irrlicht-1.8.3/0000755000000000000000000000000012574354552012055 5ustar rootrootirrlicht-1.8.3/scripts/0000755000000000000000000000000012574354552013544 5ustar rootrootirrlicht-1.8.3/scripts/packages/0000755000000000000000000000000012574354552015322 5ustar rootrootirrlicht-1.8.3/scripts/packages/OSX/0000755000000000000000000000000012574354552015773 5ustar rootrootirrlicht-1.8.3/scripts/packages/OSX/readme.txt0000644000000000000000000000166712574354552020003 0ustar rootrootThis is the source package for the Irrlicht framework installer. Build steps are as follows- 1) Remove the framework so you don't accidentally package more than one version, if you use the GUI to do this empty the trash so XCode doesn't build to the trash! It's best to run this command from the console: rm -Rf /Library/Frameworks/Irrlicht.framework 2) Build the library and the binaries. * Navigate to source/Irrlicht/MacOSX and open the XCode project * Choose release mode and build Irrlicht.framework ** For the moment it's not worth installing the sample binaries, they can't be launched due to console input 3) Build the documentation * Open the console and navigate to scripts/doc/irrlicht * Make sure you have doxygen installed. If you have Aptitude for OSX then type: sudo apt-get install doxygen * Now run the makedocumentation bash script: ./makedocumentation.sh 4) Now double click the package file and build it. irrlicht-1.8.3/scripts/packages/OSX/moveAll.sh0000755000000000000000000000036112574354552017731 0ustar rootroot#!/bin/sh mkdir -p $HOME/Irrlicht1.6.0/ chmod a+rw $HOME/Irrlicht1.6.0 find /private/tmp/Irrlicht1.6.0-install -exec chmod a+rw {} \; cp -rfp /private/tmp/Irrlicht1.6.0-install/ $HOME/Irrlicht1.6.0/ rm -Rf /private/tmp/Irrlicht1.6.0-install irrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/0000755000000000000000000000000012574354552020654 5ustar rootrootirrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/07changes.xml0000644000000000000000000000130412574354552023153 0ustar rootrootcom.irrlicht.irrlichtEngineV151.changes.pkg1/Users/gazdavidson/svn/irr1.5/changes.txt/private/tmp/Irrlicht1.5.1-install/parentinstallTo.pathinstallTo07changes-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$irrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/04examples-contents.xml0000644000000000000000000024557612574354552025236 0ustar rootrootmodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodeirrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/03media-contents.xml0000644000000000000000000006217212574354552024463 0ustar rootrootmodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodeirrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/01irrlicht-contents.xml0000644000000000000000000007506512574354552025227 0ustar rootrootirrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/07changes-contents.xml0000644000000000000000000000024312574354552025007 0ustar rootrootirrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/index.xml0000644000000000000000000001422012574354552022504 0ustar rootrootIrrlicht Engine v1.5.1/Users/gazdavidson/Desktop/installer/Irrlicht v1.5.1.mpkgcom.irrlicht01irrlicht.xml02html.xml03media.xml04examples.xml05tools.xml06source.xml07changes.xml08readme.xmlproperties.userDomainproperties.systemDomainproperties.anywhereDomainproperties.customizeOptionextraFilesproperties.titleirrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/06source.xml0000644000000000000000000002070212574354552023045 0ustar rootrootcom.irrlicht.irrlichtEngineV151.source.pkg1/Users/gazdavidson/svn/irr1.5/source/private/tmp/Irrlicht1.5.1-install/source/parentinstallTo.pathinstallTo06source-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$irrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/02html.xml0000644000000000000000000000161312574354552022505 0ustar rootrootcom.irrlicht.irrlichtEngineV151.html.pkg1../../../doctemp/html/private/tmp/Irrlicht1.5.1-install/doc/parentscripts.postinstall.pathrequireAuthorizationinstallTo.isAbsoluteTypescripts.postinstall.isRelativeTypeinstallFrom.isRelativeTypeinstallTo.pathversioninstallTo02html-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$irrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/08readme.xml0000644000000000000000000000170712574354552023010 0ustar rootrootcom.irrlicht.irrlichtEngineV151.readme.pkg1/Users/gazdavidson/svn/irr1.5/readme.txt/private/tmp/Irrlicht1.5.1-install/parentscripts.postinstall.pathscripts.postupgrade.isRelativeTypescripts.postupgrade.pathinstallTo.pathinstallTomoveAll.shmoveAll.sh08readme-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$irrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/05tools.xml0000644000000000000000000000130012574354552022675 0ustar rootrootcom.irrlicht.irrlichtEngineV151.tools.pkg1/Users/gazdavidson/svn/irr1.5/tools/private/tmp/Irrlicht1.5.1-install/tools/parentinstallTo.pathinstallTo05tools-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$irrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/06source-contents.xml0000644000000000000000000131325112574354552024705 0ustar rootrootirrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/02html-contents.xml0000644000000000000000000025756412574354552024362 0ustar rootrootmodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodeirrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/08readme-contents.xml0000644000000000000000000000024112574354552024633 0ustar rootrootirrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/05tools-contents.xml0000644000000000000000000003412512574354552024543 0ustar rootrootmodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodemodeirrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/04examples.xml0000644000000000000000000002013212574354552023356 0ustar rootrootcom.irrlicht.irrlichtEngineV151.examples.pkg1/Users/gazdavidson/svn/irr1.5/examples/private/tmp/Irrlicht1.5.1-install/examples/parentinstallTo.pathinstallTo04examples-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$irrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/03media.xml0000644000000000000000000000130012574354552022612 0ustar rootrootcom.irrlicht.irrlichtEngineV151.media.pkg1/Users/gazdavidson/svn/irr1.5/media/private/tmp/Irrlicht1.5.1-install/media/parentinstallTo.pathinstallTo03media-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$irrlicht-1.8.3/scripts/packages/OSX/Irrlicht.pmdoc/01irrlicht.xml0000644000000000000000000000202612574354552023357 0ustar rootrootorg.irrlichtengine.irrlichtEngineV151.irrlicht.pkg1/Library/Frameworks/Irrlicht.framework/Library/FrameworksparentrequireAuthorizationextraFilesversioninstallToidentifier01irrlicht-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$irrlicht-1.8.3/scripts/libIrrlicht1.spec0000644000000000000000000002175412574354552016761 0ustar rootroot# Copyright (c) 2007-2011 oc2pus # This file and all modifications and additions to the pristine # package are under the same license as the package itself. # # Please submit bugfixes or comments to toni@links2linux.de # Packmangroup: Libraries # Packmanpackagename: Irrlicht # Packman: Toni Graffy # norootforbuild Name: libIrrlicht1 Version: 1.8.0 Release: 0.pm.1 Summary: The Irrlicht Engine SDK License: see readme.txt Group: System/Libraries URL: http://irrlicht.sourceforge.net/ Source: irrlicht-%{version}.tar.bz2 BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: freeglut-devel BuildRequires: ImageMagick BuildRequires: gcc-c++ %if %suse_version >= 1020 BuildRequires: Mesa-devel %else BuildRequires: xorg-x11-devel %endif BuildRequires: update-desktop-files %description The Irrlicht Engine is an open source high performance realtime 3d engine written and usable in C++. It is completely cross-platform, using D3D, OpenGL and its own software renderer, and has all of the state-of-the-art features which can be found in commercial 3d engines. We've got a huge active community, and there are lots of projects in development that use the engine. You can find enhancements for Irrlicht all over the web, like alternative terrain renderers, portal renderers, exporters, world layers, tutorials, editors, language bindings for .NET, Java, Perl, Ruby, Basic, Python, Lua, and so on. And best of all: It's completely free. %package -n libIrrlicht-devel Summary: Development package for the Irrlicht library Group: Development/Languages/C and C++ Requires: libIrrlicht1 = %{version} # Packmandepends: libIrrlicht1 %description -n libIrrlicht-devel The Irrlicht Engine is an open source high performance realtime 3d engine written and usable in C++. It is completely cross-platform, using D3D, OpenGL and its own software renderer, and has all of the state-of-the-art features which can be found in commercial 3d engines. We've got a huge active community, and there are lots of projects in development that use the engine. You can find enhancements for Irrlicht all over the web, like alternative terrain renderers, portal renderers, exporters, world layers, tutorials, editors, language bindings for .NET, Java, Perl, Ruby, Basic, Python, Lua, and so on. And best of all: It's completely free. %package -n Irrlicht-examples Summary: Demos and examples for the Irrlicht-SDK Group: Development/Tools/GUI Builders Requires: libIrrlicht1 = %{version} # Packmandepends: Irrlicht-media libIrrlicht1 %description -n Irrlicht-examples The Irrlicht Engine is an open source high performance realtime 3d engine written and usable in C++. It is completely cross-platform, using D3D, OpenGL and its own software renderer, and has all of the state-of-the-art features which can be found in commercial 3d engines. We've got a huge active community, and there are lots of projects in development that use the engine. You can find enhancements for Irrlicht all over the web, like alternative terrain renderers, portal renderers, exporters, world layers, tutorials, editors, language bindings for .NET, Java, Perl, Ruby, Basic, Python, Lua, and so on. And best of all: It's completely free. This package contains some demos and examples for the Irrlicht-SDK. %package -n Irrlicht-doc Summary: User documentation for the Irrlicht SDK. Group: Documentation/Other %description -n Irrlicht-doc User documentation for the Irrlicht SDK. You need a chm-viewer to read the docs (e.g. kchmviewer). %package -n Irrlicht-tools Summary: Some tools for the Irrlicht-SDK Group: Development/Tools/GUI Builders Requires: libIrrlicht1 = %{version} Requires: Irrlicht-media # Packmandepends: Irrlicht-media libIrrlicht1 %description -n Irrlicht-tools Some tools for the Irrlicht-SDK. GUIEditor, FontTool and Meshviewer. %package -n Irrlicht-media Summary: Some media files for Irrlicht SDK Group: Development/Languages/C and C++ %description -n Irrlicht-media Some media files for Irrlicht tools and demos. %debug_package %prep %setup -q -n irrlicht-%{version} # only for windows-platform %__rm -r examples/14.Win32Window # avoid irrKlang %__sed -i -e 's|^#define USE_IRRKLANG|//#define USE_IRRKLANG|g' \ examples/Demo/CDemo.h # adjust media path in examples find ./examples -name *.cpp | xargs %__sed -i -e 's|../../media/|%{_datadir}/irrlicht/|g' # adjust media path in tools %__sed -i -e 's|../../media/|%{_datadir}/irrlicht/|g' \ tools/GUIEditor/main.cpp # pack example-sources tar cj \ --exclude *.cbp \ --exclude *.dev \ --exclude *.dsp \ --exclude *.dsw \ --exclude *.html \ --exclude *.sln \ --exclude *.vcproj \ -f irrlicht-examples-src.tar.bz2 examples/* %build # create shared-lib first pushd source/Irrlicht %__make sharedlib %{?_smp_mflags} popd # create necessary links to avoid linker-error for tools/examples pushd lib/Linux ln -s libIrrlicht.so.%{version} libIrrlicht.so.1 ln -s libIrrlicht.so.%{version} libIrrlicht.so popd # tools pushd tools cd GUIEditor %__make %{?_smp_mflags} cd .. cd IrrFontTool/newFontTool %__make %{?_smp_mflags} cd ../.. popd # examples pushd examples sh buildAllExamples.sh popd # build static lib pushd source/Irrlicht %__make %{?_smp_mflags} popd %install %__install -dm 755 %{buildroot}%{_libdir} %__install -m 644 lib/Linux/libIrrlicht.a \ %{buildroot}%{_libdir} %__install -m 644 lib/Linux/libIrrlicht.so.%{version} \ %{buildroot}%{_libdir} pushd %{buildroot}%{_libdir} ln -s libIrrlicht.so.%{version} libIrrlicht.so.1 ln -s libIrrlicht.so.%{version} libIrrlicht.so popd # includes %__install -dm 755 %{buildroot}%{_includedir}/irrlicht %__install -m 644 include/*.h \ %{buildroot}%{_includedir}/irrlicht # tools %__install -dm 755 %{buildroot}%{_bindir} %__install -m 755 tools/GUIEditor/GUIEditor \ %{buildroot}%{_bindir}/irrlicht-GUIEditor %__install -m 755 bin/Linux/FontTool \ %{buildroot}%{_bindir}/irrlicht-FontTool # examples %__install -dm 755 %{buildroot}%{_bindir} ex_list=`ls -1 bin/Linux/??.*` for i in $ex_list; do FE=`echo $i | awk 'BEGIN { FS="." }{ print $2 }'` %__install -m 755 $i \ %{buildroot}%{_bindir}/irrlicht-$FE done # examples-docs pushd examples %__install -dm 755 %{buildroot}%{_docdir}/Irrlicht-examples ex_dir=`find . -name tutorial.html` for i in $ex_dir; do dir_name=`dirname $i` %__install -dm 755 %{buildroot}%{_docdir}/Irrlicht-examples/$dir_name %__install -m 644 $i \ %{buildroot}%{_docdir}/Irrlicht-examples/$dir_name done %__rm -r %{buildroot}%{_docdir}/Irrlicht-examples/09.Meshviewer popd # examples sources %__install -m 644 irrlicht-examples-src.tar.bz2 \ %{buildroot}%{_docdir}/Irrlicht-examples # media %__install -dm 755 %{buildroot}%{_datadir}/irrlicht %__install -m 755 media/* \ %{buildroot}%{_datadir}/irrlicht # icons %__install -dm 755 %{buildroot}%{_datadir}/pixmaps convert examples/09.Meshviewer/icon.ico -resize 48x48! \ irrlicht-Meshviewer.png convert bin/Win32-gcc/irrlicht.ico -resize 48x48! \ irrlicht.png %__install -m 644 irrlicht*.png \ %{buildroot}%{_datadir}/pixmaps # menu-entries %__cat > irrlicht-GUIEditor.desktop << EOF [Desktop Entry] Comment=Irrlicht GUI Editor Name=Irrlicht GUI Editor GenericName= Type=Application Exec=irrlicht-GUIEditor Icon=irrlicht.png DocPath= Terminal=0 EOF %suse_update_desktop_file -i irrlicht-GUIEditor Development GUIDesigner %__cat > irrlicht-FontTool.desktop << EOF [Desktop Entry] Comment=Irrlicht-FontTool Name=Irrlicht-FontTool GenericName= Type=Application Exec=irrlicht-IrrFontTool Icon=irrlicht.png DocPath= Terminal=0 EOF %suse_update_desktop_file -i irrlicht-FontTool Development GUIDesigner %__cat > irrlicht-Meshviewer.desktop << EOF [Desktop Entry] Comment=Irrlicht-Meshviewer Name=Irrlicht-Meshviewer GenericName= Type=Application Exec=irrlicht-Meshviewer Icon=irrlicht-Meshviewer.png DocPath= Terminal=1 EOF %suse_update_desktop_file -i irrlicht-Meshviewer Graphics Viewer %clean [ -d %{buildroot} -a "%{buildroot}" != "" ] && %__rm -rf %{buildroot} %files %defattr(-, root, root) %doc *.txt %{_libdir}/lib*.so.* %files -n libIrrlicht-devel %defattr(-, root, root) %{_libdir}/lib*.so %{_libdir}/lib*.a %dir %{_includedir}/irrlicht %{_includedir}/irrlicht/*.h %files -n Irrlicht-examples %defattr(-, root, root) %dir %{_docdir}/Irrlicht-examples %{_docdir}/Irrlicht-examples/* %exclude %{_bindir}/irrlicht-GUIEditor %exclude %{_bindir}/irrlicht-FontTool %exclude %{_bindir}/irrlicht-Meshviewer %{_bindir}/irrlicht-* %files -n Irrlicht-tools %defattr(-, root, root) %doc examples/09.Meshviewer/tutorial.html %{_bindir}/irrlicht-GUIEditor %{_bindir}/irrlicht-FontTool %{_bindir}/irrlicht-Meshviewer %{_datadir}/applications/irrlicht-GUIEditor.desktop %{_datadir}/applications/irrlicht-FontTool.desktop %{_datadir}/applications/irrlicht-Meshviewer.desktop %{_datadir}/pixmaps/irrlicht*.png %files -n Irrlicht-doc %defattr(-, root, root) %doc doc/irrlicht.chm %doc doc/*.txt %files -n Irrlicht-media %defattr(-, root, root) %dir %{_datadir}/irrlicht %{_datadir}/irrlicht/* %changelog * Wed Jun 20 2007 Toni Graffy - 1.3.1-0.pm.1 - update to 1.3.1 * Sat Jun 16 2007 Toni Graffy - 1.3-0.pm.1 - initial build 1.3 irrlicht-1.8.3/scripts/doc/0000755000000000000000000000000012574354552014311 5ustar rootrootirrlicht-1.8.3/scripts/doc/sed.txt0000644000000000000000000000061312574354552015625 0ustar rootrootGNU sed version 4.0.7 - compiled for Win32. Native executable requires only the Microsoft C runtime MSVCRT.DLL, not an emulation layer like Cygwin. This .EXE file was obtained from http://unxutils.sourceforge.net on 2003-10-21. For documentation, GPL license, source code, etc., visit http://unxutils.sourceforge.net. Downloaded from http://www.student.northpark.edu/pemente/sed/ irrlicht-1.8.3/scripts/doc/irrlicht/0000755000000000000000000000000012574354552016131 5ustar rootrootirrlicht-1.8.3/scripts/doc/irrlicht/makedocumentation.bat0000644000000000000000000000506012574354552022331 0ustar rootrootmkdir ..\..\..\doctemp mkdir ..\..\..\doctemp\html copy doxygen.css ..\..\..\doctemp\html copy irrlicht.png ..\..\..\doctemp\html copy logobig.png ..\..\..\doctemp\html rem enable following line for skipping tutorial generation (can be used for faster testing documentation layout) rem goto SKIP_TUTS rem for /F %%i in ('dir ..\..\..\examples\[01]*\main.cpp') DO ..\sed.exe -f tutorials.sed %i >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\01.HelloWorld\main.cpp >tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\02.Quake3Map\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\03.CustomSceneNode\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\04.Movement\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\05.UserInterface\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\06.2DGraphics\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\07.Collision\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\08.SpecialFX\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\09.MeshViewer\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\10.Shaders\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\11.PerPixelLighting\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\12.TerrainRendering\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\13.RenderToTexture\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\14.Win32Window\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\15.LoadIrrFile\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\16.Quake3MapShader\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\17.HelloWorld_Mobile\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\18.SplitScreen\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\19.MouseAndJoystick\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\20.ManagedLights\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\21.Quake3Explorer\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\22.MaterialViewer\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\23.SMeshHandling\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\24.CursorControl\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\25.XmlHandling\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\26.OcclusionQuery\main.cpp >>tut.txt :SKIP_TUTS ..\doxygen.exe doxygen.cfg pause irrlicht-1.8.3/scripts/doc/irrlicht/doxygen.cfg0000644000000000000000000022467212574354552020304 0ustar rootroot# Doxyfile 1.7.5.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = "Irrlicht 3D Engine" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = irrlichtlogo.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = ../../../doctemp # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = YES # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = YES # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = NO # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = irrlicht # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../../../include/ \ tut.txt # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.h \ *.cpp # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to directory from which doxygen is run. EXCLUDE = YES # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = ../../../media # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is adviced to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 237 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = YES # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = irrlicht.chm # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = ..\hhc.exe # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = YES # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = YES # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = YES # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the # mathjax.org site, so you can quickly see the result without installing # MathJax, but it is strongly recommended to install a local copy of MathJax # before deployment. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES irrlicht-1.8.3/scripts/doc/irrlicht/maketutorial.sh0000755000000000000000000000011012574354552021161 0ustar rootrootcat tut_head.html >$2 sed -f maketut.sed $1 >>$2 cat tut_end.html >>$2 irrlicht-1.8.3/scripts/doc/irrlicht/maketutorial.bat0000644000000000000000000000012112574354552021314 0ustar rootroottype tut_head.html >%2 ..\sed.exe -f maketut.sed %1 >>%2 type tut_end.html >>%2 irrlicht-1.8.3/scripts/doc/irrlicht/tut_end.html0000644000000000000000000000115012574354552020456 0ustar rootroot

 


Valid XHTML 1.0! Valid CSS!


Irrlicht Engine and Irrlicht Engine webpage © 2003-2010 by Nikolaus Gebhardt

irrlicht-1.8.3/scripts/doc/irrlicht/logobig.png0000644000000000000000000001602212574354552020262 0ustar rootroot‰PNG  IHDRé< ¦ (tEXtCreation TimeÕ 1„É7tIMEÕ G$# pHYs  ÒÝ~üIDATxÚí] pTU–~îNº¢Qlu›EfB•5†ÝQÌ΃5€hœbÌÔ¬J@”¬¿ACm°Vv£Š`Øl-.au G ³þ,¨2ZЍ«KÊ¡\w%ÊêÔ1M‚ä¿ß~ïž¼“›û~úu÷k¢Sžê¼zy}ï9÷žûÝsϽ÷Üךö-}KßL ௮nÛXc,iýújÛ纮[\dåÈ“³Ë|è^fB÷ÙæR$ym“åBA!ÜutôXK¥H• pO™i!ØÚ(êÔ"þV”ü›2|áiÍžJ¥ø!c—²н;Û\Šä1¯ò­ÒpÛQ)‹ÀÕÀîĉQ»‚é )c@榤¤½µ&éEfË|­ÊÒó((Q$±°¡¡!kÃA'µ:Q. ¿2VÈHP«ôööBéÔ6Ü*ŠN5WÓË£dF4$R / %°ô´E‘ŠD® lœÃpˆO­;ë*‚g¤kµJWWµ 5 Z%b:ǬJ/ªÏ”§\’~“Z[wìßÿ_ï¿ÿßÇŽioo§,ñx|âĉçœógÓ§Oÿá@ذF£à ¬àJ­Ižh.ÕtÏ Yd\) €o»»»{zz…:›ì9xÄ.÷LðGÕF°ËvwÛ¶eÖœW^ù·bœEK£3 ÓzòÉZï²eJ&{;;“Û·?÷»ß9~|@˜p(Hüéþ¦ÔžxâÆ,¤@¡¢^½Û·?•V´ÉÊÍ,ÓîÝ»¡;jL‘Å#p3â‰b ]Ñ*<Ô¢"µµu;vÔôPR § }L@-ËÅT²‰DÄ^P4J"uH³O•Nž‚{‹‹Å&MwâD¿ðAÕ èY`ËçÄ]Y Ók5$¹›[žhõùóç;÷²Ë.»ä’Êùóçc²‚†|õÕ7_{íµÖÖ'lgrO?ý$°Ë+Á¼0ìÔKs©¦’2Ǩ[?~<¯‘¾žìnW×€°»0·1”kNvwþü¿åЉ(ù¬æŠA`êÔ ]4ùª«fEFoíYS¿r%,"œ}LÚà9@âP >‚ØìeÔ<¾.ŠÑÜÜòæ›oZ“%åË—ß4cÆwÆà¡jÀîÕW/X¼øŠ¦¦çÍ»¢­í-kÆ7®^½Zv‘€›Ö(æRMÎ À|þùç´I‰¼ÜÁ{l‰Dš}ëÖ­´X ÂÊàŠ. &bJäín‚¯iwep¶ínXä)LkwKKÃåÆCRB­|5¨½ñÆÿ¾ûîÿ­\yy"WòF£È"¯ŒØ){¾E„¿.,-åa.Ö"£V_¿¾ÑúÕÅ_¼jÕ*´"”OÀÅ•° Ò&‹öúë/Ï›7ÏŠ{xä*§ë}/Pñx'Ì ¬å0Þ£æÉy¶©„ŒÎ¨ ò¨¦òÖšiwÛ;µôvWv·ÏÅîvwÐ&¢˜ @jƒ ‰åÕQñþ—_~oùrRñx ÙaÅÞA@èZÏ£ )±ÔuuåÃ9ˈ›6=šL&-¥ßyç´I[lá˜àHS1â•W^Ab+‡ßü¦uÅŠÁËâT M R2IÞsZ@°êƒx¦ÈËvîd¿È»¥)aWŽÅѼ¬3dhw $)‹Ä:Tˆöá„T£ŽqdL΄)¥³»¾ CsË„â>ó̳ÖçUUKhg‹¶»¨-Ù”rÉiõà†nÞ¸ñ…ë¯îª¯¿ƒ†2pÀÕÅú²ÃÛ΄yC.£zÉ‹¼Ñí´ˆ£2¨ä…R”p~•”††Ð Å~a¨ “C¾Z½££Ãö9Ýdä2fá\~CÉO»›ÝsOS{ûqVÖtÅ¢îg ŽUPwŸ¸ÑèêúË©'ÛMݬÉ6A:‡ò'Bciw1å¿·qãWLJÆ/¡5ZZÓÇ‚>: ª b]Í- ô ¨ø7ªm¤mOãý͵b6xlì.ÀôË_6}ðÁ…ñ+k ƒ€¬psuZ¦õOö‚’'Éåëé囜DK§ž<N”Sò96æÃ ùè¥c²Âèg<ƒJ&{ëV¯íþÒè-¥¥a O ‡ÉÍ-¢Ø1>ð“ÉAv« äêÕ¾ü²K …G•Œ ¥ †ƒÑ¥Õ‰1·»ñxÜ>&c—ƒÓe€*“0Þ¸âí\^4W…óQÓ1™0øÏÀá]&Ä&OžTS³$‘ˆ)ib±ÈÖÍ466½ñÆÿ)óð#-/Ð C(­ÝeAee%‰Äù‚b›7ÿ½)¨`XP™‚¤N2–„š–•M´b÷ý÷”—Ÿ¯IѱÊûD¬Ä´1ÆØå³ï. {ì±Ç²°°ÐÆ%ïM؆€Ýõ3žÁï‚ú:þxâþõ¼óâ«VUYt׬¹­¾~ÝG}fnWÒ'$b,)2Á R,É::¾ÌLPqT˜^!¨¸¤ àëàéN:Ùº'|ìØ'À.—°ÈqŒ´û Yl3-æã»š0Š×Â9¶eP^€ „qQ—°S_ã©üÆrö‰“°pÉä±ÇåÆç[¯[W__ÿàŸŠ…AáïÒµß| „£"F 2ÎY3”„ˆ"SPe4‰± ô’؉Hô”)iÚ(_µ··ÿèG³)ô¶Oà(3È"(ÙôéÓ++\YY9{ö_¾5 C£“<šØxs*ŒK%ÈÇ!ʬÉO»K))&ý66Rþþ÷hm}cñâÙÖôk×ÞzóÍ==}",& Nª ŸÝ^¯£éÍUPq$¬³ ásÂ.:JÈ)>.Aƒ ÍœYÑdÙoyç}K—þ‚÷i‰ä]@yú…4k×6µ´åñÇ·À^~ÿû³g̨¸òÊùÈBþƒ{<ƒfy‹‡ÆE]N¤žzò9žÁL dô%b½6õôÓ.ü 뀎'7®©®¾[Ó £‹O(DÖ|ÂòË£|”„  âñ×ÅL¦ ä¶Wn¼c×:]ÃtsïÞ·/½ôÂîÉ“'yÄGI8ª• ¶}ûÎ £ûúë{ðyþùÖÍ›7Sô·»¯,njۆq¥Í{ŠÉ»Ë)…9," úÐ?îºë–Ë­¨ÂÔ­¼üìO>ùÒ4½2½èóôî³| *."Ó*)M{Æ]ó¨4aFi”rÑ¢k¬ochm}²²r¦.N½ŽÀ+—GáÅ¿MM›ù}92ÍœY™Åñ]§0®¯Õ qžì. ØgÊëG{ç#••Ó¬¹~¸aÉ’ºd²W˜ÞT0˜Îh‘ v³´xq}w·tR"BE÷Å#/ÁDŠéòŒd÷ßÿw¿þu‹²ÁK¼qãÆ;ñƒ¦n|’G3Ì÷oØð€-çk®¹Š½X¶£~¡glɣݥsÂEìîHJøúÂG&<ûìNž|šõ¨¼|Ò¡C*fÓ$Ó믠 /œ0"¨¸P˜Þ &@òìÇJd±ø%Kš%8PNÌVŠàâë­˜´+nmjzPIóöÛo¯[·nõêÕÀ+w!š´vwìØÝØxí®ò‚W±ÛêñÔZ.˾,5xgâÅî²s)Œœ‹ÝUR’9ä·3Á½ë.HÝ{oÝõ×7|öY·X Kƒâôo8‚Ž ÄòÈÉúvÒ,ÝJp ¬z啌[ÿ‚Ï?¿Ý:ô·µµ-Y²dÞ¼—\2ƒl0ʼk׫{÷þà¶ÇiùòëqF£t:‚ôâ7——Є$âÐrj¿§žÚµdÉå9F–]qÅÕW_} àÒ™²Ë¶Hî~”y³f’>ž!‹š‡rÑq£.ï´¦4ãRÆø»eËîåËçY³ß}wmmíZ²ˆÂ¦f5_‚n¿?0˜¢“ÆüÞ ù0wFJÏ‚€$zÓ²|€›¼páž{îµë®»2ë7;-Z´xÕª[!‚ÏÄÓ{t»NµSŠ”Ñ\3—¼Y3‰gp |éîÖ„‘Ó…': N× yKiå%s(o’ut|´hQ2· u[¸›hLd×ò%¨~¥)h  @ò‹ßlRôëû@sçÎøøãö³ëžyæÉŒäÆb1¸ K–TÑx2·üös÷cyÖ"YWúœ²{Éë/m´¿kÝ3Ï,= H»âæ‰O)9(l´xý¡‡vÜwß5ÖUØD">mZ¼³ó$L;ò:ù þ ’— ü2ºôâ7z¸m åü’qò¶å!’v¶žzêñ^¸éÑG×½øâ‹i%µ0·uu·ðv.…%ð‹¸NP°-’Çúæ’7k&£Þ{n›¢«+hþXƒ.Þ†gCSš/ª X‚ôwßýäÒK§*€±5kþzÙ²¨;9Öþ ‚Êxã×¹«ñãÇÓRï&Xð4PSÉ¿ÉCiðïÂ…³çÏ.ͦM¾õÖÛ|ðAGG;¿ü&‘Hœ}öyßýîw¾÷½‹,¨äH1~?‘9;UÐ¥H^ê›uÞ¬™Œú]K=‡ßù±¦äßÕ±íè”—VN)JùE72@æg8½HÃY}´ví5òÚ'dÑÏ{dôë4ÖmU9ò«G~mÿ¨ŽòÚ"Yœü‹Tü#?¶?P%_åí\ÙâÊAgî¿ó£)Ǽ£[$W& _-EæM³ù}5kÊ”&ÛAÊV–>ÂcôÏ­™ß¦<~ ¢þ-Ïôy­7Ó_“—uxúŃ5ŲÐïF1àÈLZ· äÖâ"Ñ ‘8$H.OõdÑrœ¤ÒüüU@¼±Aù4÷]Œ\òúÈÄÏßµtHé>âS)æ©ì¥.™ÿ‚èÅѲÁãé-{Y`—ÊÑ^JÐO@ú•FÎeËP“~yºõùí!šÔgäì¶<åjz/R.yýeâF;Ê1e¦â¬JÏ“ ŒŠ”)ù^'V~ññÎÊcÞŠ˜1W®ך¸q­‹?Íâ´Ë§³âÈ5¸²Â¸^[὎»íÞ§,¾Ln¼09e‚|—?ž~±Ê…ǼmIcŸ…{hŇFzºïÕ¢† .3^e^p†6´ô"- ”Ek~ëÎvÄŸ’l_»d}n)ë‹B3âf[rÛ¼ôP¾f] &.Ù½ë'£R)…Éšüm>…dÇ”–ܧ K<¥Ì¸ÄÚI 61˜˜X¦%búÎj}ŸÛnüvi’z’¼!É}«ººº³³ÿâ:gÎJFßrél¸êdWxº|%‹·Y³f)*–ù“PzŽ‚Cªž”——ïÙ³‡’íÛ·ÿR±¹œ«@r©¦UUUÚè—ëË*·²8J©lçÊåQáñüàÁƒrÅkkk÷ïßÏé¹x¬[°-/¯@«Ï (ܶ}e†NÍ—‘ÏÐ °Û(P»­B ¶ÊðLô¡áõ¢:{êôŽFÚm¸-#7xŽoîæjºª¹ã*¥·ªƒŸ+£‰|O_Ñ}"‘`—N¹UÐ&ÿ«X)jNybd;°bH%OîûHŒ2@éÀ.¤“9qÇ.ÝÀàͶ–Gp²‚N<É'÷†¨æÁî¢:0±BF[«ïTrï WÚÈÚ|Ííš+ P{pŽè5Ââj› §ÖhOóhÔšØíY¯lÐw ø¶ÔP.{+•gg—ˆ\^kzëÈ(߃Ì F+vAë×7+ü`A„{Eµœh Å(.²S©œ"è kJ0·—»JÅÑ£`Aaw­ qG†Õ¦€µK; ¤._m›Ï;v[ÄÕ»-»@§v;×ë‡ ì¸Ív³7'×:Wã ¸5»uü’Û€;®íWŠ8ë,ÄZN¨•n ÇaÄh6NÆ[挦R‚‚$4<}EÄþC¦Ø%ï\V¦ & òÝ‘~Ïž}rbWï±YjPJž©Â­Ý‰³XuâN²Ï°SXßž*àºÑ>ÃáFÓÓ•>=¸Âg°çn»öÄå¦êÑsî£\w¼ÊÏÑqÑZÊÐ9Òæ¿ÔõIœ \'Ç:e×…ÒLá?`ô§ÕŒ’òë´'ÏÊOZ[[5;ßNžªkæB’Ò}â1nƒâž9ù‘Ð*EÁ€@>IÒÅÂk@–eëïzQ¸í´ŒšÏ½œ¶D³4B0Yßó„×KÖ—Ìsµš«‰îÅ\-­ˆ‘¶÷œÖÛsY±·ýŠèq“%OµSžg±Õbû$b’òÄpëc/̳«~ŽJ£Õ±ZiÌÄ®˜±Ñjæa;kõýµúaB°øn°eh¿'ìïk¸]ØÒïâ\RÊ_ñ½Sú|T0­,B´”6®mZÊTá>*m4ð VIÚè×Þ’¡%{ûXÔ¸DSvbèó¥Kß’•0´%‡oÆ0Ô‘4ñÊ_t&OYD‹õæþ»;Ûÿî+á’q“ŒIEND®B`‚irrlicht-1.8.3/scripts/doc/irrlicht/maketut.sed0000644000000000000000000000014212574354552020275 0ustar rootroot1,+18 d s/src="/src="images\/tutorials\// s/href="/href="docu\//g s/\(.*\) “¦¬Feç(¡È—ˆ¯DC'$>ÀÀ…{ÚïD}.Ÿ´ 2§úè^AŠÑ HHÂHÈeùÍÒT3€PP…‚û@à#4œ §¦d-Fè²Òeª!á¹Ë‹[Z e,&@‚$$V…¯í^5 ##8lÜ¥…pWV˜õmÚ¶‡Ÿ]á\6Eçòø/KCˆ¢ˆ&éÍ”’I%ÈŒLGOðâÂùüËöÒ’SR‘Þ¼ˆàWXT0 >A³.µE‹¸kè/0¯k;óz½P¥ZwÀ˜Ò«2 uHßïÚŽCû÷š`ÊŒÇ!¤¤W[°qý§¸î²¾Ì-[aàà¡èÔí7ðJ¬†‡3§r±nõÊËZN»Ãî×õ CooO‚¤’5«1 uC%Òþûß,œ!H%’ÖG9«ºÿím­>Ñê¦( c&‘>õÇ §%¬Ù1 ~I…Mà ðœî¨²J©äBþ9¬ýèôé?CGŽ[¢åþ%”Óïóá§ïwãXöŒÏœ GZ3È&T@û*UE8pªª¢wïÞa£ÀÅÍÓ¬‰ªª ÊO›¶Rn·UUUeÙ2ßV­ZA½íìv{˜Ä£Myªªª—…ã8Øl¶‹gî2V£u3@ @ˆÿ3"¨!BÀEɨ 0$Ûy8mXÈyøK@U"»w¢izstíÝ>…tÍ8N_‚T”•៼} ~&Ô0¶XȈWy?ûì3H’„Þ½{_ô6à8Ï=÷Ün7þö·¿Õú<㈭]Ú|unn.öïßœœ\¸p@ ÖçOŸ>ºç;//ÿûßÑ·o_Œ7®Á€ÄqJJJðÊ+¯ k×®ÈÌÌÔAUlݺ?þøãEiÛ?þñ5˜a]Á òw¢qQ#@5(³%P"§› D첬FÙ¶y#ºõì Iå!†<”¼îçøå”³¨ ~ÞƒN= ‰W\GšñF#³S‚ „Qéx‹ÇãÛíÖG-ŽãL=²Ž‚ @|ÿý÷Ø´i ˜@ZZRSSa·Û-Ëïr¹ ˲žŸÆü~?cPU<Ï7x$v»Ýðù|5òä8®Nm+IΜ9ƒääd´lÙ²ÎÏVUÕÔ 23y¢™H¢¾®ß ü A` Œ ¨¶@ÑÓ_ñ¸+‘—{®Ö ½ÿ|ÈÄù%•ØÎ½À/«pˆ\„ À]eÇ5X êò}ú Gh×®œN§%x•ÓãñÀáp€çùup8 @cžŠ¢èyʲŒAƒaРA`Ìz`ä8¥¥¥xþùçѱcGL™2E­hâóù IRX{Zù;êÀ˜>7¥› `QFt" 4Ç!E­èå’‚óù¸úŠNð«‡ÈCà~™p!ÿ¨ 0\õ"¬xúÈðŽ´¿)Îæ1ŽãôÏÚ’TÒ[‰ÃáÀŽ;°fÍ(Š‚””Œ9ƒ ‚ªªðù|¨¬¬Dee¥^ÑX{–q]<AUU(Š›ÍVo4²)-OY–uÛ?€ˆ I’¥RkŒHËÃçó¡¼¼¢(Öê°Õ@ÍèЋ6ÚGg!?c*µÆ¢˜  Q0’˜¬ƒçy\Ãÿ/Õ$BiI1N=% bHŒ «ç ðÑ ]Ç ´ºªm\•[ ø‘{üJ‹ £”Ó"‚GRá´q.Ôaã I¹ãFPÑò3ŽäÆïUUjV:N|ùå—øôÓO={öÄĉÅÅźO@EÝD0Òíh¶zd5ºÞ‡°QyµKUÕùiåµÊÃív‡µÏó:k© üµ2X™f£ä{ ‹ˆT~kPTUå¡jDÌ ÜpËhäU(¡‘­á@À¸ÖÎc°·+/DUÈÎ4›­PÁ¯\öj›Úª^ºtC‡Þƒá‘TÄkþ]äFòضá_øy÷óú0F*AbÇŸO9B×F¡kË£6Æg8‘Ïß}÷Ö­[3f †Ž’’H’Qáp8ô8öºÚ×Vþ#4IJògDÖѪ¬‘>­lÆúYMwÖ¦ôµMV3€ê€s¨!…Qk±•GU……!˜Þ‚10Æ ©„¼2 É>4º5\¹Êü Z¦¤£ÏooÄÖ¯>·ôUÈ*ƒƒT‚ȇ̛(¾BŒ ¿ —âÄZÊý*nqö~¿ ªÉô[…AVÄP§T‰‹+M7‚_, @ÁµQ3Vvíy‚  ¨¨+V¬c £GÆÍ7ߌ .€1‡Ã‡Ã¡ÓâúÄ2D2€Xë_WP5*p}XT$¨˜¥µú®® `â ðY†Z…€BÑC£`çGHqpÚâçt"éW´ŠZNÍO,'؈‚3‘GšKŒkx3'ŠHmÔ¥Eݱª†Š§ÅÍ Iûkë¬F¥¯M6mÍúˆÓéÄŠ+н{wŒ9çÏŸÁårÁétš:ºj®4Ôgé㈬k¬f„±|Ѧ(kÚ‚ŸÌãB7TFP5ï~€J2Õ \V uîê€Ã¸€1²©F9ƒÂ™ë¤–æéCÀFTc‹ÃÓoE67“ƒJÁf Xƒm?©VD›"Œe´¯Ëó4 1Ö_EdeeáÈ‘#°Ûí¸ï¾ûPXXEQàr¹t/}C¶VŠÖPˆd±‚¥Ñ‘WW_‰˜)4çŸö·>úSµ’Ôb(†Îœ5 ¨ «!ÆÀ(náíNQ@^î‰(#zPéýÙ\T` A Åâ7\l<Ÿ»å%ÅmD:ÐX•´ñžŒdZGÖ<ã ±¢ÝfÔÖf³aÓ¦M`ŒaÈ!°Ùl(--…ÓéÔ•?uTüäädݬhTUU5ȯ9#™O]?9â4›^Sêhs¬I ŽêJDðYZž:7w"ÉÎëî†:m‡ÜÃûðÓέÖå$™…FVª6W¬ÓZ5²ƒQpÚ0.TŸŸ®Zf©\Œ‚ @ •SfÁèE•â; `f+ŠI’â>5Zà8~¿û÷ï 2EEEà8v»<ÏÇ­LFº¾ÿ~üå/‰Ï O¨ÝŒ3 a±æaÅ¢±óåÀZ0«¶™£¯T.E¥PG5OOŠŒ.]Tíø‹ƒR‘ÊPZ\ˆŠÒâ¨ÊÁ †€ŠJP„èÌfïîí8qôH\Áï­BÁ¹3Q§+ù‰"+ETA3Iâ7 ém–$IŸvºbæÝ6ÏóÈÎΆ¢(h×®RSSQZZŠäädˆ¢÷ø­,¨¨¨¸h`‹ÐŒ9Ô%Ú?Õæ¬¹Õ«eµz ÚH)© ŠÊ 0>jzRU?r—ClN'¼J¨zÌ‚U½Š.ä£èÂ¥_*lw:áW¨š­°p #¡±ƒùý~TVV¢Q£FmÇáÈŽÉl6N:"BFF†2¬•'žŒÄ8sбcGŒ;6.ùú|>¼ñÆ1)¯0ʆ@4 ‚0€iö2tÇ^4V)8ZÉjhÑ/ryåmÚá°[†Ë.èö5û%–óª¶(®’!« J4O' ÑYeæ”»˜ ÀÌ(,,¡uëÖðz½zt_¼ËdœoOMME›6mPPPPk$amÒ¶m[Ó:6$F¡>N@c1²¬º3€Ð‚ E»ô>р̂—JÊâ—£\Mšµ@RËv(Îr£µMÕK;Êð—Ýú@nI ¦AP‚þ•xˆ,ËúhcfŸ_LsG<¯ªª иqcH’¤ùÄ»L‘Š ( EARRRƒ¬žu5¬L 3©ë •C22tØ FA;”!êBF£« ø‹¼°$VÄ|û=8ï#ªc Â/¦œÐ¦ã5Hïx¾?RŽô ²\\ôu-ËjZ.ÞJ§î˜=Oë˜ÇÁáp@QØíö‹²_ƒ1ªN+öÜÚ'Õ%ïȰàXM£‰R×<¢ìµ€I PÐ  „æÊUFàyÁrSÍ È,8 âEÝ¡Î^wAÄ€Ñã 6¿ÙÇËÑ$ÉQàƒQŽÐEÞ¬!&êuÜ4a 6¯pØÇé>¥žáºšÍíóùÂ:Š¡¿ DA€hñ<ÆRRR $I‚ÃማÃÓJYÄÐú³˜øúæ«åi4ê:Àh@' „PÚe–G´%¾µ)¿`„›!' Â^ˆ\Ðí¿§2@´Y@CÿTGv¸’ѺSWt0ù¬6g—Ãiã‘âÁóäƒãø‹Rκ”•À š¶lƒŒ^ýТK_|•ãF¹OA³T;œ6*iοà F¬J¡ú’$Õèl¢(‚"¦›.`ŒA´Ù`³ÙL€¢(hÞ¬l6ÊËÊpe›65bâÍ´µƲ4¤þD›Í1täV¬yF–«¶÷+D²­È™‡0@¡yh)DëyA€Ý ˆƒ¬"lŽ]DÓô‚(bÄó@\ì´›pôûoqüçÝ–i’Òã–ƒœ+ `ÓY/J½Hrh’bC’S„ŠÐº"Ø9β^ÝÝ„ö×õ«W ìõ`ËŠ7Mcý5é3âN´éÞn†Ü¶î+Ï“lhœl/pa[ƒ)1®ÐF}³x"Ò 2øäb™¢(Z€,ËhsÕU°Ùl8—ŸNz`ÍÅm›.#ŠGýyƺÂPåc-W,£m«C@ÁY‰HÕ9Ž·œ"RàÊ5• ©€b féyA„bOŇ?Ã.ò¡íÆë&.»€áý‡âÌ‘}P-æÑ%¯ù'᤭=N–øáy4M³£Q’ˆ§ðЕÊΑã,ëes&á»óÀ©?D‹‰ôkŸŽö×]SöX¦9uðG¤fôÁƬ2ØDI.©.’DØm<”ˆøc™êÆ´õö‘£~d§áy¾ÆÔÓÅt <>Ô±#Ÿ'I:tèA‘““ƒÑ£G£¢¢ââ™!(2ø¦¡N@^À…è{¬+ õ˜ˆPuq$F[à-ò2Š Àâ Úó ðK¼>ŸùhÇ*!À‚—L€ßï7M/ˆbˆ%phžb‡Ë[ƒ«.´êÖǾßj™fß–õôÀŸQ)’"ì"‘çÀÀ!` mŒ Ȫe½²‚€B°ÛD4MµÅ´è‚GÁoþÏdÿ¸ L5gÞÓ'qõÉCèzeg¸%‡MÐ7V•L_VŒŠ_—=÷¼^¯½¦…ý6Ô íyžª*x<K§£ÝnGË–-‘““ƒÓ§OÃåré[•Å›(ª Ƕ}WCMm×!Í×RŸ€†æÉ«‘Õ²b5òs´Í^¬Àô`? #$Ùr÷U‰1øÀ¯2øBLÀ/I¦é•A"À¯óclo?c(á’puïÈÚö•eº7ü ·<ÞgÏಛƒŒ¼¢ZÖ+ (Áº„.!ÆŽ˜[!¡Ó #px×0ÅÜd)È;‰sÿÞƒäÖ½à–„(4#à!I$Iª×‚m{* .… `4KÌ<ï>Ÿ={öD³fͰÿ~:tqcø³šñÚ©!yZ•ËÌŒ¨mch`e:D@°Ó{U‚|²ŸUö3¯ xU‚ü ð‡Ð¾&PágŸÂàU <‹½ÁOTHèrãHüöK(§ùÎåáäOÛ‘ÒqÊ%sÅSTëzÉ |j° ¼*Å䯯D(Mn„6½úãèö¯-Óíù|5†Íê‹3ù2\kFT%3}C͆î㯙 @à’Ìü~­”ÛãñàÞ{ïÅ‹/¾ˆ·Þz óçÏ×7֌猄ƴúǃh£wCÚÔŒÔe·%+¨mea$X%xP¥@ ¨ ~•ƒ—ì*ÁGŸß~øX0®í]Å| ®º~0Ž|ý‰µb}² #ž„Óù v¡Æ¼ž2¢€‚Þˆ-ºë*9®v~³Á’øN@ÞÞHn×2ç«A¼ƒÛ¯¢Ò¯Â›ÆA¹ÊeÐ2Ò¸˜ @€hqî>Ÿ;wưaÃðùçŸcîܹ˜?>œN§å{ª¢-^õÌ3Öø-}d¹¢íù_ˆ\î]û,€¾ð0B%Ü ð$=T3R<*Á£rp1OU~ŸizÁn‡‡ÆPÉÔz"nV¹„î7ߎ}þeɪªrqtçWHê~3Jª®Xº-HxE±¬W•,ÃÃ(Ô¾‚•Ð8¥ Z_#ŽnúÌ2Ýî5ïcØü8|² 8TI U5ìtæ¶)b\§ê4p©¦#ÀÊì(++äI“pêÔ)ìÙ³øÃ0gÎddd ²²2.§ @¼ê¯ù’§‘EÔÕ7c¦ÔfŠo³Õ ÀC„RhÂî@^¯×´ª ØT‚ªeŒPåó›¦Dð¨„rSow[ )BZÝ8G?ýÐ2Ù«—aèooFv%ƒ=‚^ ¨–õª”e¸CÊoc¾ž¡AʸöÖ»qðËuP-—Þ“9غi Z D©WgboøXì@µ)¤æÿ¸Ø>mt× ÚóTUEyy9žyæÌ›7;wîÄôéÓqÛm·!33)))¨ªªª÷‘^š‡>r´Ž‡ ¡yF@,{š-ý­‹ `é¨d„b¡2 ”¨A…æÔà”a1<~k(fAÖPÆ^Vÿw—ð›ÿºu« ú}Sm¹8òõZ8®¿þp ÷岬W¹,£’ÊC›¤Ô× E‚àj Wÿa(üêck§áG‹Ñä/CQ•å煮ˆ3øý~‚€FÁårÅm9pä¦"ÆY3ïs¤È²ŒÊÊJÌ›7Ë—/Dze˰råJ¬[·ÇÇèѣѭ[7}ÿ}³u‘Š逬jÇ‹IJ¨>åŠÍ#•=’‰˜…Éj@ ‚ ‚A>rÀA¦¢‚q¨b1´Ä¶ÜïGÀ$=§2ìg·ÜLlã”îÔFÀÍ·Á·æ}Ëdûþñ®zÎT¨àÕ¼˜¥Qœ€¹²‚Rp«A3ˆ«eÞ)’˜ÌÀ5ôN¾€ÔáA_¬'[èœ9‰ªŸAîp dˆ\ˆïrà@ €’’lذ!®#}JJ Œ’’’ŒC;Š«.kÝeYFQQî½÷^ <¯¾ú*¾ûî;|øá‡øðÑ––†îÝ»£}ûöhÞ¼yؾ‘2pà@ýH0h>3Š\_€ßï¤X}Z¹´Y€ºŒÚррY_ c"(à’$Ø,e_hË0m;±R’féU†Ÿ ù7tWÐ’²ø»DÊšå€Ï|$÷ÍCág@2ðªÐ'ô‰P ¨pYÔ븬@ •±Š¶I6îÜe´zwKƒ[Wh × [a۰ʺ­ü;<‹F%>€g23¨/ȲŒóçÏã©§žŠ+´mÛC† ;¯N{žÙÈV›‚”––"55¯¿þ:N:…Ï>û [·nE^^¶nÝŠ­[·ÖZ¦%K– K—.aŠi6e×P@Có4æa¶i«Ô¶X´hÀ(€ÐÉ™ÁÿeY³˜/'UKýw’$7I¯?ÏÀ4$ Ù›À;ún,¶N÷ÞBàÖñ@… ð¢>j«Ì:@õJ@¾ð(Á«¡sÑ>øÇ> õ‹•QY¿åŸ`×Þ¸e„Í=ÆÑ dï·Nwá,0Äzd»ÁöˆŸ ´´­Zµ‚¢((++ƒßï×;V<ØÅÁƒõ}üyžGqq1Ú¶m I’päÈ‘zmö¡-©ªªBII‰^f—Ëe:ÊërìØ1(Š‚ôôtØl6TUU!##ç΃ËåjpÛ###>Ÿç΃Ýn)O"Byy92B ¡´rY@]¢Í„Ñœ¾†¯'4€öM€ÎMƒŠb㦎 2UIÐêy.Ø9+¤`g½* hìœ"j îÂé1¤×ôýBUpt»2pÙ`<’ÜŒ}èÿ›}§)|Š p‰A…õJæt\VÓ•À©ÕŠÕÜe}R°¬Æßù «h‘üMÅþ*D’pÙÕ_àž*´¢†˜üÜ4 h’–…ÞÁq?r'ÉË •7ò¹IvÀa¦è\µÓű "4M[™A\°í9Îx*hÜL€K%u]ÁöŸZžxÍØÔfµmÿ]ÛŒÁ h Û- 6bÏUWË…:©ÀW3­³r¼¯‡š `tlÅk­ÇÕ˜>«“h`v)E0€Ë%îT ùß)‘JoÆŒ¾3?‹qÄf[5ÝŒ˜ ßkÊϼ„Äor\0 jS Lù¹p§÷¬PJ_Óñ©ÈѦùjLÄp›3bdÖ>“áChÿ€ C. <ªÿÖ€‚C0g˜]—PüX„% !ÖLÀ8²G~gÆ èg!hWµÀVCBŠƒçž7aÚè¯1ý;{;!Ñà:¿Ê×N–L >NF³„jÐô›Õ…–S¸ ¯1>ÔY9# €µ€KØuc ôÖZîyIDATHùèoñ­ü‘Š™–ã8ˆBá–"µTiŽ"`Í£ß8Ãa#|ägcš(ŽÀ„ÔIò‹øÇ9òóó‘0L?•¼.k ´5!8wî8Ù®I4qBòë>Ñ IH’„$ ¦ôïßË–-Çq¸òÊ+±lÙ2´mÛ¶N™¿õÖ[:thT»¦]»vu.ìœ9spß}÷]´Æ1b6lØ€o¾ù;vlp~±Ô-2kÖ,<ôÐC¦Ï9r$^ýõKZžþýûcÁ‚øûßÿŽÑ£G‡Ý»óÎ;±lÙ2ýZºt)^zé%Üxã—])Þ{ï= 0 бcG<ðÀúÑJíÚµ [\M&Nœˆ.]ºDmè9sæÔ¹°­ZµBzzúEiˆäädüóŸÿ„ÍfÃW_}…¢¢¢å·páB¼üòË—ôeŽ17Üp`Ô¨QØ»w¯~/-- W]uÕ%+ËØ±c±cÇ\sÍ5hÖ¬>þøcÌ›7O¿ß»woÜqÇúVåЯ_?lÙ²¯½öZÜψ¸µØþ_ƒd#|­nØ5aÂ""âyž¢¥3»*++éÑGµ¼¿mÛ6ZºtiÌù^Œëꫯ&"¢¡C‡Æ%¿/¾ø‚>úè£KZ‡o¾ù†–/_NhÊ”)TUUuYÚ’ã8ÊÊÊ¢eË–éß=ñÄäv»ÉétzñÅ);;»Æoï¸ãRU•n»í¶_D¿øO¿øX‘qóæÍÈÈÈÜtaýúõÈÍÍÅêÕ«ñÈ#`ݺua¿IOOÇÊ•+‘››‹ 6è¿;w.zôèQ£FaÉ’%€wÞy3fÌÀÂ… qâÄ ìܹÔóZ´hfΜ ˜9s&-Z„éÓ§ãÈ‘#8xð 233õ´¢(bÞ¼y8zô(öîÝ‹±cÇbóæÍ¸é¦›jÔ«C‡Xµ*¸kÏßþö7<þøã€›nº 6l@nn.Ž=Š¥K—¢iÓ¦‚«Üž}öY:t'NœÀêÕ«Ñ©S'ÀO<~ýúaÈ!øàƒLÛrîܹxâ‰'°qãFìß¿W_}5\.æÏŸÃ‡#''ï¾û.®¸â ý7Í›7Ç›o¾‰Ã‡ãôéÓØ²e † V#ïâ±ÇƒÃáÀæÍ›Ñ¾}{üîw¿Ãš5k·ß~;>ýôS 2ßÿ=rrr0wî\¤¥¥aÉ’%8yò$vî܉~ýú…1¤—_~GŽANN–,Y‚æÍ››Öˆ0nÜ8<ýôÓúwuÙÄÖ­[‡õë×còäÉ–i´÷uâÄ 8pO>ù¤¾’.55›7oÆ]wÝ…O>ù¹¹¹ø×¿þ…Ö­[ë¿ïÙ³'6n܈ÜÜ\¬X±3fÌÐß?lÚ´ ·Ür `ñâŘ9s&,X ÷ÉAƒéiž{î9½,_¾mÚ´1-·Ø¼ „FÍLïÙÛ] N49´V`oßý—ÁºwïNDD½{÷¦´´4:{ö,íÚµ‹î½÷^Z¼x1ɲL%%%a ÀívÓ¼yó(33“Ξ=Kß~û­Žô¹¹¹´gÏz衇íß¿Ÿ<½þúë4qâD:tè>}šDQ$´{÷nzë­·½ýöÛäõzé“O>¡ñãÇÓçŸNŠ¢Pûöí ½ð äñxhÖ¬Y4eÊÊËË#"¢‰'Ö¨c‹-è•W^!"¢%K–ШQ£¨{÷î$I½÷Þ{ô»ßýŽæÍ›G²,Óo¼Aèá‡&ÇC3fÌ ‰'ÒÁƒé§Ÿ~"ŽãèÖ[o¥ììl:pà€%Z³f ù|>š?>͘1ƒl6­[·ŽŽ;FS§N¥û￟vîÜI‡"—ËEÇÑ·ß~KYYY”™™I<ðeeeQYY¹\®0йsgZ·nI’DO=õ5oÞœfÍšEçÏŸ'ô‡?ü$I¢;vÐý÷ßOýë_‰ˆèàÁƒôÊ+¯Ð„ èСC”M<ÏÇq´~ýzÊÊÊ¢‡~˜&MšDß}÷íÛ·GÔæÚk¯¥gžy†.\¸@Ó§O׿·bhÖ¬YtáÂÓ{-Z´ sçÎÑúõëi„ 4cÆ ÊÏϧ… jÚ´)åççÓŸþô'zôÑG©¼¼œV¬XA¨Y³fTXXH[¶l¡ñãÇÓûï¿O²,ÓéÓ§õg0Æèþûï'´oß>òx<´`Á½]òòòô>ùÁÐÉ“'iÚ´i4qâDÚ²e åääPJJJ²;»õ§«ÞÜMͦ¼Bö¶]Ãî5¹û j³p5ºíQR›V³)ÑF­_úŒZ>¿†’û"N´Å›Ô233ÉãñP³fÍtÚ·~ýú°xñbýó“O>I–&ÀþýûiãÆúç»îº‹TU¥-Z˜@aa¡N)¯ºê*""3f ‰¢H%%%ôä“Oêy1ÂŒ&ÀàÁƒ õèуž|òIýE Ÿþ™¾þúk@ , S§NQË–- eddÐÈ‘#‰ã¸:™kÖ¬¡£GêŸ{öìI’$Q§NôïRRR¨´´”î¾ûn²ÛíôÇ?þ‘úôé£ßŸ2e ‘zÑL€HPU•:wîLH*,,¤U«Véé'MšDªª’Ëå¢ë¯¿žµk×N¿Ÿ––F•••tÇwDí`S§N¥7RAA½òÊ+$B­ðûßÿžü~¿é½§Ÿ~š8ö^n¹åòûý”žž®ÀìÙ³õûo¿ý6:tˆÐôéÓ©´´”ÒÒÒô~»mÛ¶¨ ½s4nÜ8bŒQË–-éšk®!EQ¨{÷îú}—ËEùùùôàƒš›GŽ$J¹ñNjùÜjj9g%õ¹‰ÀÍk±Ù•ÔxÜLºòÕM”þûÉve¨/p9¯éKÍùoºòo©ÑèÉÄ'¥Åê½'tÏž=‘••…ââbömÛ¶ ýû÷Kwøðaýï²²²ZˆGŽ KÏó¼å.2'OžÔ·‰*--Õ©ÿÕW_¦M›bÇŽzÚºl$i”ƒÂçóáOúºté‚ë®»={öÔóùŸÿùdffâÌ™3øá‡°víZ¬Zµ*¦°ÝãÇë÷éÓ‚ àË/¿ Ë#)) ={öÄêÕ«±xñbŒ7'ND×®]õ¶®Ï4'NœܵÇëõ";;;ì¾¶pD+Û¦M›ÂÊæp8гgÏfŸQ/^ŒÅ‹###{÷îEnn./^µliii–¸öíÛíÛ·ë'6› ‡]»vÕ¿7Þ/--ÕM„ž={âÀ¨¬¬ ë·Ñfl"óÒ6'éÕ«AÀºuëÂÚ¥I“&¸îºëÌÍ£€žíkáÝ»Mî~Íÿ°çž ¥ Jñ9”¼Þ¿F³©E³É/áüó¿ Ûwô'ŽïGRÿ[‘þàÿ1†Ê ï5˜þ7hSx«m‹Œë©.±¤¯-­±|±z•ûõë‡o¿ýÇŽÞ={ðÞ{ïaúôéúý½{÷¢sçÎ?~<ÆŒƒùóçã™gžÁÀ‘••sùEQ„,ËxñÅkœ˜••Qñõ×_£k׮زe‹n»Ë‹hgÙE~gÚID@/¼ðBßÞ(6›M?+rrr°{÷nÜpà µ@ß¾}qðàA˲=z ,ˆ ¨ÑúF]úm]ú™(Š`Œaþüù5¶XËÉÉ1›÷†#£7R‡ÝGF/xv¬ÃÙ™7B­(gw"éúHz8žGÅg‹áý1x¾¤Ð´%R‡Ü…äc8q^œ)÷p\ìÿzÀÞ½{1yòd´hÑ………à8î1‡ yyy(..ÆàÁƒ±sçNÀàÁƒcÊ#33GEŸ>}ÀƒÃáÀœ9sPPP7nÒÒÒ°páB,\¸­[·Æ‘#Gpë­·Ö"•Ün·ãرcøî»ïôŽ:~üx¸Ýnôèу BÿþýñÃ?þò—¿Ô›ÄZ6—˅ÇãçŸÖŸ9aÂÓ‘:==ÇÇc=†üãºÓ´C‡ø÷¿ÿõY]ºtÁwÜiÓ¦Y–¥W¯^X»v­¾×`«V­0lØ0TUUéÛ}Eë·ãÆCãÆQ^^Þ ~›••žçqæÌ|óÍ7:˜Ü}÷Ý:Ûjî7 i£'£ò«÷QòîaÓÝôÉ/ã”}ø 9ûª1ÃîD«çVóó\xq"Ô²‚¸¾ÛzÀÇŒgŸ}6lÀ’%KЯ_?Œ1åååuÎÃï÷£k×®èÕ«öíÛ·J)Š‚W_}sçÎ…ÍfCyy9þüç?Ç”Gqq1Ú·o;ï¼ååå˜9s&Z¶l‰óçÏ®¼òJ¼üòËHJJÂÞ½{1pà@¤¤¤`Ïž=zÝ:w}ûâ§Ÿ~ªõy»víž={°jÕ*Ìž=.\Àý÷ß & _¿~(++ƒªª˜0al6  Ïˆ¤¥¥™¶­ÝnÇÈ‘#ÃL¡úÈÖ­[±ÿ~¬^½O=õŠŠŠðÀà®»îBß¾}k¤/))ÁÖ­[ñÒK/Áï÷£  ?ü0Z´hwÞyGOרQ#ÜÿýúhÚ¹sg<ôÐCضmV¬XaZ–¥K—â‘GÁÚµkñꫯÂápàùçŸGrr2Ö¬YS+¬\¹³gÏÆ† ðþûïcðàÁ¸á†pæÌ™˜Ûeß¾}غu+–/_ŽÙ³gãÌ™3¸çž{0yòä°™M¼{7£ê‡ ¦Ûו,}$Õ<ó’äÎ=q H\ž@ ÊÊJÝ6 ÈÎΆ?t ØðáÃqüøq̘1ÉÉÉxã7¨бcÇ¡¼¼GÕ?¯X±Ý»wÇÚµk¹¹¹(,,ÔïWUU!;;[§Ä§OŸÖGà‚‚œ>}:Œ¾fggë#Ò_ÿúWÌ;£GÆÝwßÙ³g€ån¸Š¢ ;;[?6ìõ×_ÇîÝ»±råJ|ðÁ8|ø0¦M›žç‘’’‚7ß|‹-œ9s°}ûvLž<S§NÅöíÛ«V­BÛ¶m±~ýzSF~~>Ξ=F3ÇŒƒ;wbñâÅØ´izôèÛo¿@nn.fÍš…ñãÇcÓ¦M6ln½õVìÛ·OŸZÍËËÓjË–-ÈÉÉÁ§Ÿ~Š>}ú ´´T§Èeee5(ê‰'ÂNöq»ÝÈÎÎÖwâ5jöìÙƒ¥K—bãÆèÚµ+ÆŒfeÒ¤IX¿~=Þ~ûm|õÕWhݺ5nºé&}‡ã¢¢"”——ã©§žÂSO=…ǽ{÷Æ /¼€Ûn»Íò=?~ÇGrr2¾øâ |ôÑG8{ö,FI’ ª*²³³ÃÎ?(**Bnn. ¢¢7ß|3òóó1sæLÞyç°çeggë#xdŸÔ|%ÚAcǎŦM›°hÑ"lÞ¼¿ýío1vìX¥…)³°Ü»ÒLùCNŠ‹¦üšì¨÷pÀ€4}úô°¡E‹Ñ?þxÙƒ8Ž£gŸ}–®½öZý»N:Ñ€ ¿âkÈ!4uêT}¶-[¶LŸžþ•]…"€o ªpáÂ…øÍo~ƒ­[·¢k×®˜©Ñÿÿ¼!®¥ j.~IEND®B`‚irrlicht-1.8.3/scripts/doc/irrlicht/irrlicht.png0000644000000000000000000000460112574354552020460 0ustar rootroot‰PNG  IHDRX쪷tEXtCreation TimeÕ%†¦¥étIMEÕ  ovìv pHYs ð ðB¬4˜ÿIDATxÚí™?h[‡Ç» Œ ©hŠ-&b\,ÈU¼B.äNê¢RWÈT,¬Šjäâ]ìR¯“ ƒ]8d1Hà€T¬Â Ä C X )¼°Ÿî‘ÆãÑhbçñXÞîÞØã™{çÜsÏŸ{νѴÿ7Õ–ø-•v~¿ rù•|.ýŸ^æwÚ‹/büÑõ¸úû†â÷?-î{ÿìzà>\ ×uu]Ÿïô†æ;£™Ì3Œ)·Aë³å=p Ѱ±'ŠH£«6/¨ŒÊªàÎÚxR*e•¿¤Ûí® Ñm»+1?AÄöF˜ìîîò’Íf+• VE\H°-!†«£b:‘ün¢ˆn·»¶¶FO>Ÿ/ ¸•8ÑÝ1'Ò¼ðWY¢×sPM*²€P˜Éw¶ô@kµZ¢©W¯^y[vk4²#È6áwxÙé KVO“·ãú·ªùÐ,O÷Þ1µxÑ`0T|uÿL³7¶ü°Çj†Íy²`Ïb„ž÷ïßÏû.ÀvHàȼ‹¢/Z’¨Ð€²ÙlÆÐúáa[Ó’Â<¶·g+Ø£!ù%ðëùUµÇΦ=~¿3\w¨§Ýî³<2h<žX´B•öúÍæöcNÑ¢·ÛߤˆEb2%›7™ÏgM3¥M⿹ØCad ò#=Ýnìá _¸¤¤Q[€¿§J:ý•’´\.ǶêíÿäWÂäGá«,ï)]UPÇqç V+¤R‰r9¸Ûu¤ òH¨ 6X©”§°yûyµà"™–——QÄ„£ëü’2”zÅb‘R‚=Ÿ§—XªIMµ(¦¢ÛŸÂ:ƒY9Z­6Â0P*­«òÁû™¬Ùl‹IuHŸba)õ¼P ÉB¤FUŠ=ÊždPÑ‘-úxÄhu\ƒ¼HIņ'ªý2„ ™Ì¶¾žQê»['ë§æ ì86ý~&Ùì:Ô‘²æ••ðŠÃã ÔŘ}‘.¼4ù(¥Ì§Oý~>3¤ÞjuäpQ(dÕfᨄ°Õê±SC_D¡äIŒÃK¥äoœ<€d{’&0 gtÑSÍãÿø…dV¸yTþ2áN&_ê àc3[¹ÊtšT‡ãñäÆS>e„=‚år°\.CLñ½CTnCeÌŠƒ,2…”LR)òL©R ƒx‡. jílv•ÝÁ;³Ñ„JȽ5ÃAøˆ¾ü‹÷f‘"ͯ£ÉÅL¹Ü¤*ñû… ø{Ÿ¾;ˆqD6Swfæ/QzHì¬2ä?n‡.:ò/Â/--…f`­©>#.`¢`†™ôÕQA»È‡#FDD( Íÿ‹mI| ü_Ùþ ?n,l•Túç}wä¦ñ,ùìçòÏãΣ8ä_å3?e.¯.GÑŸí—‹/þž¶ôjzíok§½Oº~û43bZ<¦=iæSm™ƒ¢® ý¥ùt%©—^&¿<ë]´Û>w¡a¥-Öfª9‘Jðé Ñé}Öëu»Ý¶IoìÌRÌ1 ‰Ð„{^«7êrŽÔº0[ æ@<=¶"§LDT‰Xš¢R·¬ëÙàf'i$äS— ÖV)}ÖÌ•òTÁ8˜º2u»]ο<···Iã°ì®…õB­^#{KÃâ5•ÌEh ¡r¹¼¹¹ 9Ÿ~IuhŠŠˆÔÕh4ÀйñzC&ÚV *ªò5z8 ê³X(ÊÅ$L¨8òù<+ßÙÙ¡¸@˜º›O`œA‘Âõõõjû"2$ûIJ³ ÍJ˜†¾•µúm*šîží †nÐ#hÐT7ªðEÇÌ£L6#×§¬ ‰¥‘‹Vé¿3u½ŽÀПèB´†ž1”ËÎj „èÅ/r7ÇŒx¾¦®jÐ$è‚|³Pœ?YU*Ê-Äv žbPÝáH Òƒ¦›î•M7jÙ÷µl%kÞ󈩔³‹Öyvv†@|øðíÛ·¯_¿òþñãÇX,vzzŠÖö ¥g4ñyÚ;¹£““úÉ/ |†WS“ÚGöÍøä›7o˜ æOž![ï¸su{ËËÅññîÞb#ÏË“ý+÷V»åþšÔb®ÿ×å×o¿üóÃß7?î¹ÓòÇ«#ð  ^­VíC;ë³e$5ÝUŽO( œ@¨l'×ã[EK3ôªí4[“ëåÛ?ž"4µÑà“´r9üíܤý˜d÷XœøñIEND®B`‚irrlicht-1.8.3/scripts/doc/irrlicht/doxygen-pdf.cfg0000644000000000000000000022467212574354552021053 0ustar rootroot# Doxyfile 1.7.5.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = "Irrlicht 3D Engine" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = irrlichtlogo.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = ../../../doctemp # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = YES # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = YES # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = NO # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = irrlicht # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../../../include/ \ tut.txt # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.h \ *.cpp # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to directory from which doxygen is run. EXCLUDE = YES # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = ../../../media # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = NO # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is adviced to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 237 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = YES # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = irrlicht.chm # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = ..\hhc.exe # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = YES # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = YES # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = YES # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the # mathjax.org site, so you can quickly see the result without installing # MathJax, but it is strongly recommended to install a local copy of MathJax # before deployment. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES irrlicht-1.8.3/scripts/doc/irrlicht/footer.html0000644000000000000000000000134512574354552020320 0ustar rootroot irrlicht-1.8.3/scripts/doc/irrlicht/tutorials.sed0000644000000000000000000000065612574354552020663 0ustar rootroot# Page start and end are delimited by /** and **/ # we keep the end unchanged, the header is extended s/\/\*\* Example \(0*\)\([0-9]*\) \(.*\)$/\/\*\* \\page example\1\2 Tutorial \2: \3\n \\image html \"\1\2shot.jpg\"\n \\image latex \"\1\2shot.jpg\"/ # All other comments start and end code sections s/\([^\*]\)\*\//\1\\code/ s/^\*\//\\code/ s/\/\*\([^\*]\)/\\endcode \1/ s/\/\*$/\\endcode\n/ #remove DOS line endings s/\r//g irrlicht-1.8.3/scripts/doc/irrlicht/tut_head.html0000644000000000000000000000613512574354552020621 0ustar rootroot Irrlicht Engine - A free open source 3d engine

Irrlicht Engine logo
irrlicht-1.8.3/scripts/doc/irrlicht/makedocumentation.sh0000755000000000000000000000030712574354552022177 0ustar rootrootrm tut.txt || true; for i in ../../../examples/[012]*/main.cpp; do sed -f tutorials.sed $i >>tut.txt; done doxygen doxygen-pdf.cfg cp doxygen.css irrlicht.png logobig.png ../../../doctemp/html irrlicht-1.8.3/tools/0000755000000000000000000000000012574354552013215 5ustar rootrootirrlicht-1.8.3/tools/MeshConverter/0000755000000000000000000000000012574354552016001 5ustar rootrootirrlicht-1.8.3/tools/MeshConverter/MeshConverter_vc12.vcxproj0000644000000000000000000002664112574354552023046 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 MeshConverter {E72B637E-4AA6-46F3-885F-AC67B4B470ED} GUI Editor Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled Neither false ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib %(AdditionalOptions) ../../bin/Win32-visualstudio/MeshConverter.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)TestProject.pdb Console Disabled Neither false ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib %(AdditionalOptions) ../../bin/Win64-visualstudio/MeshConverter.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)TestProject.pdb Console Full false ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ../../bin/Win32-visualstudio/MeshConverter.exe true Console true true Full false ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ../../bin/Win64-visualstudio/MeshConverter.exe true Console true true {e08e042a-6c45-411b-92be-3cc31331019f} false irrlicht-1.8.3/tools/MeshConverter/MeshConverter_vc11.vcxproj0000644000000000000000000002664012574354552023044 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 MeshConverter {E72B637E-4AA6-46F3-885F-AC67B4B470ED} GUI Editor Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled Neither false ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib %(AdditionalOptions) ../../bin/Win32-visualstudio/MeshConverter.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)TestProject.pdb Console Disabled Neither false ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib %(AdditionalOptions) ../../bin/Win64-visualstudio/MeshConverter.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)TestProject.pdb Console Full false ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ../../bin/Win32-visualstudio/MeshConverter.exe true Console true true Full false ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ../../bin/Win64-visualstudio/MeshConverter.exe true Console true true {e08e042a-6c45-411b-92be-3cc31331019f} false irrlicht-1.8.3/tools/MeshConverter/MeshConverter_vc10.vcxproj0000644000000000000000000002664012574354552023043 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 MeshConverter {E72B637E-4AA6-46F3-885F-AC67B4B470ED} GUI Editor Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled Neither false ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib %(AdditionalOptions) ../../bin/Win32-visualstudio/MeshConverter.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)TestProject.pdb Console Disabled Neither false ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib %(AdditionalOptions) ../../bin/Win64-visualstudio/MeshConverter.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)TestProject.pdb Console Full false ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ../../bin/Win32-visualstudio/MeshConverter.exe true Console true true Full false ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ../../bin/Win64-visualstudio/MeshConverter.exe true Console true true {e08e042a-6c45-411b-92be-3cc31331019f} false irrlicht-1.8.3/tools/MeshConverter/MeshConverter_v9.vcproj0000644000000000000000000001005612574354552022432 0ustar rootroot irrlicht-1.8.3/tools/MeshConverter/MeshConverter.cbp0000644000000000000000000000264012574354552021255 0ustar rootroot irrlicht-1.8.3/tools/MeshConverter/Makefile0000644000000000000000000000221012574354552017434 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = MeshConverter Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math -Wall #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lglu32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/tools/MeshConverter/main.cpp0000644000000000000000000000475212574354552017441 0ustar rootroot#include #include using namespace irr; using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; #ifdef _IRR_WINDOWS_ #pragma comment(lib, "Irrlicht.lib") #endif void usage(const char* name) { std::cerr << "Usage: " << name << " [options] " << std::endl; std::cerr << " where options are" << std::endl; std::cerr << " --createTangents: convert to tangents mesh is possible." << std::endl; std::cerr << " --format=[irrmesh|collada|stl|obj|ply]: Choose target format" << std::endl; } int main(int argc, char* argv[]) { if ((argc < 3) || ((argc==3) && (argv[1][0]=='-'))) { usage(argv[0]); return 1; } IrrlichtDevice *device = createDevice( video::EDT_NULL, dimension2d(800, 600), 32, false, false, false, 0); device->setWindowCaption(L"Mesh Converter"); scene::EMESH_WRITER_TYPE type = EMWT_IRR_MESH; u32 i=1; bool createTangents=false; while (argv[i][0]=='-') { core::stringc format = argv[i]; if (format.size() > 3) { if (format.equalsn("--format=",9)) { format = format.subString(9,format.size()); if (format=="collada") type = EMWT_COLLADA; else if (format=="stl") type = EMWT_STL; else if (format=="obj") type = EMWT_OBJ; else if (format=="ply") type = EMWT_PLY; else type = EMWT_IRR_MESH; } else if (format =="--createTangents") createTangents=true; } else if (format=="--") { ++i; break; } ++i; } const s32 srcmesh = i; const s32 destmesh = i+1; --argc; if ((argcgetSceneManager()->getMesh(argv[srcmesh])->getMesh(0); if (!mesh) { std::cerr << "Could not load " << argv[srcmesh] << std::endl; return 1; } if (createTangents) { IMesh* tmp = device->getSceneManager()->getMeshManipulator()->createMeshWithTangents(mesh); mesh->drop(); mesh=tmp; } IMeshWriter* mw = device->getSceneManager()->createMeshWriter(type); IWriteFile* file = device->getFileSystem()->createAndWriteFile(argv[destmesh]); mw->writeMesh(file, mesh); file->drop(); mw->drop(); device->drop(); return 0; } irrlicht-1.8.3/tools/IrrFontTool/0000755000000000000000000000000012574354552015436 5ustar rootrootirrlicht-1.8.3/tools/IrrFontTool/readme.txt0000644000000000000000000000124212574354552017433 0ustar rootrootThere are two tools available for creating fonts for irrlicht, both are supported. oldFontTool: only works in Windows, creates a simple image file containing all data for displaying fonts. Those file contain no alpha informations and are limited in their character set. use the IrrFontTool.exe file in this directory. newFontTool: a more sophisticated font tool supporting alpha channels, anti aliasing, different character sets, vector fonts and other operating systems than just windows. It will create multiple image files and an .xml file containing meta information for the generated font. You can find it as FontTool.exe in the /bin directory.irrlicht-1.8.3/tools/IrrFontTool/oldFontTool/0000755000000000000000000000000012574354552017701 5ustar rootrootirrlicht-1.8.3/tools/IrrFontTool/oldFontTool/source.zip0000644000000000000000000011173112574354552021731 0ustar rootrootPKAa33¡êÏ µ"IrrFontTool.cppÕksÚHò3©ÊèõÕ¹D,ÀŽ×g¯sB¶uD›Ë¦(!„ÑYH”4sIþûuÏŒ^<窮jÏFšéé×ôs&¯_ƒ.Ö‘w?c he¨W«õcüóºÞCèÛËnÜñÌŽ&ìå‹×¯a0ób˜z¾ ø½°#áØÌ…#Š|ÏA4zpïîA…Ã_‡8a0ñ˜1O¼˜EÞxI`XÆ® ±ë"\ÂI2ÏA$X+³—/2ðѼ, }˜"Ù`¢2økˆ–H¨9á|ìÇÙÊc3üLÂU,ø5`f;€QxÙs‡ÌØ0uW0÷‚%scä9ä4pµá,£È Cöc›„ÎrŽc6CŒDý‹­A«,ñÇ_âÒƒ˜MìécevŒÜ8\FŽ»1Œ°^¸=æ{c>øò*wé0°4ܳ–Íì—/¾¾|QZ9ø:b@_¶ÃÜè=ÔÞÊ›°Yò2sIû—„†¿/Âø÷Ëìù#>ç³/_ÐÖh·› í*{9¿¶çšíûMÔž¢™]kmóæÚìà•¿ð§*ˆÁþû £ú†Fãl®Bkhö[|+ëZB»×è7:à/ˆû2êñ+~J–LZþ½ÁÜyÇcûÞE¹v[e¨‚ÑÒFmÃÔEsÔhµ,¤Ò½Q¡ª‚Ò6»7eâãø­?½¶·kÏÝò%aŽ\¶Œ¨‘p$Ù—ÐC›\Lpψ©^ä~ñܧ³a0) ’bïß®åúpÛì)›qUç\Ýèí®oémÎUµœ(7~’Ú“HÆ¡?ùíV×Þ!šf‡£¡· ,³Ñƒž…§¾aš‚BBýrEëý>¦êJQ•%Òe‰ÌÐr?ÕªõÓÏ´-4ú|¥’U© ~ÚnnCezÐheÄÍ%ä"Nq[-„E!mzŠœ|ÉÚÉ'ÉÆÛ–ÒçËZÇ–Nq÷ npZ‹\iq Í•Ž;K¿å}QfUŽmÑq5{+G%ë¿ëmëcY…_ëe•¯¬ªô˹Iü®‡£¦ÙnÁÈq±Éyðä—åØï»¾kÇ®ä\EQÒ]#%î á(RR¡Ãœòz}ýƒ¡Å. „æ{û®Ã¹R…Ô,JÖìßY·à£eÌTIt0rLf¯ñþNªŸÏˆ½¡©½{% ÉìàÞxÈ!ªðZ€Æ!cá…‘6ÖY[Y‹*2œ'EõÃÍ-ÀlsŽžûº…aê5±qJ¦{¢]‰WH)–û ‡5CEÓ5{CÏ®Z`“Öv¢Ü¯JBÜøÇËé§Zýüsš¡OŸQ¬¯§ê™z®þM­UÕZM­ÕÕÚ©Z;Skçj½ªÖëjýT­Ÿ©õsõäL==Wßœ©gçê¯uµJ…S‰ÊT…gÙ«ê%áô>S6Äç£#¯¼;ÁΤ·«¾ñXh+©Jü«P«–Ë2™>oNg§Û:#[F.WW`Z*2©Ÿ3TJ_GÁßvª¤*jbCŒ€‹X¦––ñ"B˜©Â…8øëÞ£ëÇ¢X=PźÄýž’K3;MAÛ­0ÄŸxÐU”C•ÓQ]êH: ÕÅ>ö@"Þ»l ôEùû: çÖ2šbíI¯JR?æÊIS–z¬R)ZZͰKQpè·¬T¢·ß®x©š®,ÎÓç!€)^P‡˜eÍ»·,¨œ9ߎµùjVr÷ãZ4§‹½ퟣ4.ý‰kã«´6þö-ÓWa0·#W¤mY3Ë­Ï5/ápêEb_‘É“z2šv}Z¸äÅE²ûpœ­ à´k„WvìxÞÀó)Àº.ûTDÇC¤ì/_a„ˆ™…ý}p/—É™EpµÏY@ `àýVÉbb†“âåx¸:Ï6Âä@6¸“…ŸbC—Nx×΃>öë7JKWË7°cÌ4|ÁÏ–µɯXâílqþÎÓ ÎO¸u»)i¦Fø#²rHQú'Iÿ7­ÕÿAûôe½0PÇö¥’ðT øÁ&)®ÿÔ¹¾é»â<&mx]'¯òÀæqã}9Ã3üî«ìÔ(‰éœ‘^ˆˆNêCÎøaÁ-±ØÀ!ž©x^>:’ÊB—‚çèÖß †{:'YÊsÎßÖpt%—­xv”)»”E)ä¡BçU¸Ö_îœý(f×;fS% HA²°+iᙈ›â$-Y_RkI`B…¥ßÓ0.õq›,Îá,îÑqMŠsô4Œdã()6 <]¢ 3`ÿ•¥Q3ß6A§Ñƒñ|‘:£Î6ó³¦Çæö‚[M~ËUØ¢Àc("áat ÆÔ´Øq@°u>пi*Ü-Ë…éÂyÀ“Ç\°Ÿ: xöY@¾1ç:+®•!°€wôü>é‹ð;ÿ„BÆyaÍ®h%—ä–%ÌGtõrš”^óF•Ÿ²Í| GS0†m[ÈäšA¿Ñµ0!`Ó™p%¯`òsÊÁÂÓÊHE™K6LˆNŽßR\I>b˜Ã§5¾ôÀ£GmÊþuyÕPg†¾ä»SKÜRº%‰üšÛÑÃèŽèAÄŸãZŠø°ðöŒN5¡".UüpµEæ{Á©=¬†e³%ô_`Ël OI±‰¡–ÇPM×ïçoA=APÍ-ÛÎÃ}„[L¹¾X,3*öBÀBp°S'Ä'Lt-ÉSÌl'V˜Ž¥)ÚõHD»ÌA5?ŒÝüº’ˆ»üG8˜D½o:ñäý™çî‡)¸ê'\OQ‰#'œâ˜9øîC«=gV;¬Š°B²…mšf;»Yjy¶Þ÷¢Ð‘ 슑*ÜXû-;1>ŅѪ‡9Ïîø«loã•G1_¡t¥ÄC€ƒ"ð32ºÆ e40£\d½Æš;ý2…Åq§Ñm]de ¿>ë†Ì›®5º¼‚[ƒî²Á‰ˆ ÊhálÛÜžM…Òµ¹òF‹CÈp$yW/‘$qΖÑ2ß]ä_µFWÓÛb¨¤£ª¸ú”Tk9v%¥^³÷K%5y5™ØÐCFC6Ê;냼¬ß1V¿AdûžMòúc.šwƒÙ•K’ýfø˜IKWÒâ$ôéæ5¦çZ¥ŠÃ/ºOÄE÷x ÝJrÉ]ù#ø#8øC -ðÛfºaŽÁáù<†1/fxŒù½ó2¦n{JqO¼ó:óc¸Ä:?€I¸ üОðŽß+Ø6»Q9á87ì’˜b‘²c‹‹×¯½äš\\#[÷n%pYå@M ãpÉ §’:Í‘ù¾Ñ·¡™]£{mö;avŸ«¹»¥]GNéFœœ×öâû.«yì¶PÁYA,!¯mKϹS£g`ÐÿC/èØ^ Ü]k@¦X•ÅXg8.Š »~r dq?o÷°çäOþB›OÚ¸Gû@‰3ñ ¤5 W £Ozô–V…‰_¦ä¡Óx§cHëë–y××tÅhµF"(ÕʼpÌ"aÑ‘Âÿמ¿@k8²nÍ¡œ/Üä®;Ö Ìã{Rô$Lª!jÏz®ûDÃ9EÖ¬jU¡×õõŽùA/ç:µAd1µ«ùur«[^¼ J{{ê»ØcqÄ ŽWæòÀõ—+еïÀ“VPÍŸqþPKéšv.qhÞªØèIrrFontTool.dspíWßoÛ6~ÿá¦î¡-VÛq†¬ˆæ¶%»FcdzÜu-y–XK¢@Q‰Û?|OyØI²¹q'Å؃òîøÝ?ŠÏ`(˜’©œk°ð C™ Gg\H+ù ™†ž^ÁȰe ”êÉXO¥ Ž]¶p}„ËëUëן;>z¶³dçjäÐÉDÈ ìŸ 'UäjøU*d gµF#ÇyùFƒî›)tìö¤c¦öˆdÇG¹nÚžô§Æ6ïE|Ú„çË×g/ $¡`®&ËÆIã$7ïöú­Jàw¹ÈB/ó~ÚŽÓîÛ` LA¤(bðoB-|’ ÝÎ)Ð|Ì"°Uª1 1Næ¤.ê´Ð)DBÃhØ~kW ¯P]cÌÉÚùÿÎ1ÁX£.©´@…ts˜ßê΂ feX¸ƒúªS‹Ü…QÛ½ ]üDŽ롈 ¥+wWTùŽ’Gx+ã¹ð3UÜØGã Ï ¨‚s¡S¨E¥hçê "—¨UðéÜÔ¯ƒ"M†çÍ(‡ÝjÀí}4vãõnT¾Q_åC[PÌ_2•WàÚ î g§¿ †è¦hÀsÏM‹ì9¸ÙîoÆA–)< °<ô©æ«C› Æ“Ë1´ÃP^Qu‹ô-LŠfdy£76Fc³|a~ÄÁ0¶ä’¹áØÕA¡èŽÇ-Öp‰ÇGÃéE+|5›8Ý–bå˜bô(øŸÓ–½0 ÕÚ_Ç2Âe§íØð.ÅÙ°×­D¸uš]O¹j;‰Âä2ÓI¦g–P`Ü¢W-±F!ÄBû즮òq…t«ºÙþ öÆs@(w¢h[VíÔcJ_Býý)ÔûBý² u‹šf0:mÅpdÙwýr<#¹uùÞY͆n>ü©æî|Y hÖ³ ÎÖŽþ E2ÔJ·ŽªˆÑB¦¦÷š ò~7ÍzÝ–®¨O¡ÒåÀ¿@o®î×wœîi³å¥ŒÈËF¯àÚuDͶðb0zK¡ˆwÖ—:ºyTŒái³F@–¢Z }.V#J)MrNÌ'LF<ôW—_¹ÉÚ, è’Zeˆ·#7ÓkøLðRÊ=¶6 !KV“M}ÓÌK?gFçäËë”Êì²€î‰óÁéë³u"ßwÄZö…cÄ\ëçɼur?o­±÷³Ö.«oᬓœõ•—Ãx _E%Ÿ|§ð¯9eöNéÜË]ÿ®¿<6{<°d7Íà±Ùÿ<¶‹xÞÀÛTõ„{T|%0_`Ó'ö–ùC Y¡IkŠ= ÀѼMì±ò¿á¨ì–WîÁÍEEéîTò ºôÊze=\ǀʕ˜Õ1ˆL‡TMaZhjÁ·ä<:© ¦¥ãø€þLš,S¦%&4ê’&ý´é‰ØT~júbn~J|úañç‘ÝBðOJ^(Eoµ@çdzÖŽ/Â}ˆÚê!ÖôRïÁZÞr¶y þPK±Uv.܃5ä=IrrFontTool.dswµAOƒ@…ï$ü‡±^-ibõ@Š ¸n¢´Ù¥rñ²ÒÕ`W†,«ÓßSj/êɃÛ7oæå½»º²ÔÑ“¦ßµ¡V[îmS”d·]«* imô¤d_•ƒ{m»š¸ f3ß;…2ù:ÏB`%B,ä…LP ¿¾‘,.‹E ùÈ$x¸À– dxû)÷B‰‚a~â{£éÿÎÞreéEW.„ ·6¥ÆDfß0Øt-La¥ª­zÖ°üh´ó«¯ÿÃ2Z\ŒØ÷½ï ÃðC˜ÿŽP"3ô¨Lø·<çÇϳPK®Uv.œš‹n¾IrrFontTool.ico½“1hI@¿ÁqãÆ°`¸ÄU\Oåê÷†4®ÝMwµ›@T¹QöÀ0]Š;sVãH•U8Oä"ÚÊ…ÁH(N"¸ƒof-ÛŠV ×Ü_ý•ö¿ÙùogV"+OŸJŠß"›|?'cé'rE‰5WeI4ÓGšÍê+üè÷ûÒöåã_§²ºº*FCÖ××eccC677ekkK¶··eggGd_ööödwwWš/U^¼PùE¢£ &2¸¾–×´é`IGz2T—–“¥f©ÙXÓjˆ£îøá¨;êN«ÛÖqð8xÕ´mÕN¸Ô=šÅí 8úÜ~ik£kðуKÛÍM—€K@"Ð0½¸n .ñµÑ…= ¸„¸É%¾ q|z•ÅAqP‡ô:ápP‡€CzÅpPÅAq`j’:Šƒâ (ý“)7*ƒœ‹{Ä>jìçŽcœ<“ßäððPŽŽŽäøøXNNNäââBÎÏÏåòòRŠ¢««+¹¹¹‘ÛÛ[™N§òño•_ß¼áÿÑš>çMWqÞx©²–âçºX»n]<âOŠ…ÎñOÙ, SE±„gEñm~7Åï͸1¾æŸïx§ucX,áYÆ€¶a¢ùþ ¼øÏæ¸?©V-ò¬–OF£ÑxÒ^Ƴ ÞË*njy«5ã­ÿÊKø8ñw‘Ÿ~Å˲L¼kÚgïÚ…©áe9nµÛggœNy>jµ;˜NÏ󼇥Éž¿€¿]Âóî0ÿ’wMw\óR'“/D>ÎÇY WýœâQÖrÕò!23,ðGÌû·o; üa„ùðþ1¾ç³f8‡¸ÎøN<»g0Ý9¼f2ó(z=“ߣD~˜þù#ùŠÔ©¬¤üPKNa3Š"WÅÙlIrrFontTool.ncbí\MlÇ~Ë¥lIÖ¯“ø§©"Â9ÔhZ™ÔOœu*’KFlø£’”ä ª+rEn³ä²Ë¥äÄFaÄ)à"‡ €‘=$— zÈ%0» `øÜºprhQ´¨‘¢×= î{3Cj©q‘HbZÏ7xÜ™·óóffwvæ½f¬’ë4u/?ì±P¦ œ ‡‡¿¢Pðò0Ò9àx$$$þpîÜ•¸?q¤×HHHô ¨ý4ôáeÁUœðôñÑýjoÝMÆëð ûí¶xCè \Cœþ»Êy}ð°¢)¯/Þæ ÂQ˜€_¨|­ÁyC°á8òÆṅ‰7Œ¥Á2çç`y¡ÚÅÅ5ʃpŽx¿þ“ÊycðºDW¼qæþ øË=O)g•|½(ä; /Ãåv¼yª¼/Áå.™'`tÜî‡Ê àu¯à,¦-!5žGºŒôWLøK¼^Gºt)€ùíG:­òûÛéoH!bÜI_üqÿ»>ž„Ľ Þëôü‚´à—¸/pe*¢üþÕJœ¾aÙä£ÿ4Œ¾}ëêo^xob²Géµ»‚  Y¦Ž}½LBBb×±¯×HHHô N°{ý?‚î|PŒ Œ§ \'žrYðL¯w yפº@BâQœèï @ç]'ý¼Ñçÿ°ÛçÿUèGw³‹„atïvñúØxr¥‹·Ù^ïâíg¶ƒ·ºxýlŒ¹ÔÅ`î{Äçºy²NÐø4ÃeãØ¦Ç¼Û•vˆéÿ'öùë6 ‡Ð½ßo„ÙN±xc‚7 ‡Ñe0^ éÇH¿Cú ÒkHo"½ƒô2ÒN#ÆôsH‹°„Ä—²ß÷z-†„„D@Ó÷y˜í}œ}ÿ'>gF!Ž]Ü ÑO¿ÌoñçůBŸÖyšrëZEüôµJ”ŸÃ*·O~!ûîO²á O’0C˜'­‡¸‰=°C¹_ ´WaŸG®Wn¡L4oeÜÑ«øŠ¢Á`q»ï3å}¤ï:ÊÕ¿S $± 8ŠDódšÓ<˜žZÿÓþÚ·Cûthl ½/´V µ­hîOs}šÛÓ\žæî4W§¹9ÍÅi_í¡÷„ö×<Šå$¿3ù?Îüëû?ËôOBûÚ¥¥÷}ïÜ~ô -¼ð“K‚ßüöž¡ýHËÂ?\¯ÁÇ“›ûU¶·‰üD×EœºwEœ Æ¡¶ ÿúÏÛñ¬Ní±èŠˆßGr*m9yý¹ *k;òÓz£ª¶ëÅÛ•§åmNþaŒ\m× Ø>*.o_žÊÚŸË£²ýMä?¼¿È?ÐÙÏ4 ¼?9_e}ÄÛJíì[ýÏóQ¡½Ç‰F„ÚnÞç¼­T1â);6òIôÒÆ/!qÿa¤×HHHô Ÿ|ðÉôí?K“Ôø©UÍÜ0m§Q3ëÞjÃu~h>ë=½êš¶i4Íæªåº¶Uªzß OEf§ÂÿöÇn®¦\7éÔ½"V›NË-™~ÖÔF‰2¾ç™^X±ê3Ó{[´f®µ*[/ºNÅ5j5s5Ó9 ½l5[†*x­²å„¦²‰bh:žY].\Å\ŒÒ³F¥j¸˜•e{SõÒ”ö¤¥FŽ5½²±~nªz ޹&ÄÈ·œ¶Ï¶ÖÈ‹õÌV¬º ©l¡ÍÆ¡jªÞôŒzÉôó]s£ÃO/Šù݈×Êi«nRúP…ª³ Ó+šç¼–k¬çͤëÔ -wÝ(± ‹Ú$f¶SÁ.A,—KÃÂJV U7ëeÍ®ÀR*[ µ2Í ¬,FóÑLhsÑÀ~À‚YÈæ¡D½UKµ¸aÛ1lvˆçPÜP:÷T2‡É¿n7ìuÁ+&Î3‰b>'¶Wm%—×B¬åžk˜|šáPrÏñFÛV#æn6«,d\©—Y5l£éÅ«† úe);¾S§Jè3JžéÂ&yuÏsÓ*{U?£jZ•jW”†Ó<³-ü ´eÃ3I6êËÜ„¤eÛN[Mo³‚WŽâSEOØ®R…ooZõ²³Ùœª> Ñä½PÔè² ëÑoi±'f´z’š‰ha=–Ô"úìììÜÜÌÜl¡ë©l<½¤%4`%•™ÖÓ‰hVf5=ƒž]¬ÁÖ)-¥§ðé‹@$ÁPL¥Š™è"…g0¬éZ*ŠÏ*…g1×cKÅ"ûÓĈ0Æb>±œJ¬cš1â¹L,ÇR̰p:U(²àl'È’ÏñØ ‰øÓìöã[avÿ$èÑÅ‚žÅ×DÏ' ¹¥|<¡/GÓK ¼;绉f¨ù=jîH×Ýl1ŸKwR†ŸðÝ,<“I´vð/×LÞTYOIƒBš ² ’¦‡40di½ãS1vçªHŸ¸Çé&²ÌÒ©*:uEZÒ¾¼#¬µ¤¡¹+¬¸¤Å!MÂ:,¶Âݺ‡Æø¶O&:muMhƒéÖëBCFÚ$Òþƈ4't2+*´d¤Q"-䢓Zd%þè¿X~ßü+ò%ÁZ:Âe!6{c[;‘æšN - ­ã«ë䧨s.×D÷åC§×>Ü/#äØné&MYÄ?üy_=IÓDZ«í'ÕN‹pæÞM"!!ñ…ðYçÂøvž¨5³‰—ÒÚ ÏpqÚgÕ×®9å–mn…›žãú‚–…3ɲ¹.R»æºéš8±LmËàÄÞÍ›÷¦Tß4jO ¬îQq¾ù+pÃt›–Sg=O¶ú(zž~tž÷ßQ¸ á pû><·u¼©p[Åaà¶’[Àm_nס/é©Àm;Ä“[ªvdçù*Ò ß×ÿUa¶/xÿÌãõ^ÿ¬ð¾Õª ïCꯃ"Ÿ1àgë©ï¨Ÿ©Ï©_éƒNq)/ê?©s”ørà^ !!!!!!!!!!!!!!!!!!!!!!!!!!±cø7PKiXw.\„‡'Ù¾IrrFontTool.optí]påuÿv÷Ó¿;[–,Ù²-ÿÙbÀF²$ËK ÒÎÈH–- ‚)^Ý}’Ö:íjöö,‹¤±È” é¤ ¶é´!ÓN3í„L™v4 ‡fH¨ÇМPZ“6` Ü÷v÷[íéVº¸’ùöæiï}ï÷ÞûþïíÏÞ»§ž¬þéWï_ö"™vl' yïB) ”Iž8Gû… ø–Ÿñ¸ Žßªã]ÆM¡ % 8æe å  ¨7Îóá\ ²À¤d!H H-È"Wç% KA–Ôƒ,Y²d•‡ë„ójK@.ùÈË@.¹d­‡½Î ëAš@šAZ@6€´z¸MpÞ ²d+È6ß¹ ä£ÎÜvq×À¹ ¤$éI€ì¹Öá\ï»@ºAvô€ìÙÒ Òça¯‡ó^} 7€Üò1›@öƒÜìá>,G/1áeZnÀÙ"d.Çb˜1<–\ÜžˆÖÿò˜Ü/öAv‹Œ #I5éƒzh ¬ˆü*‘9J½½§˜:;õ¬õªÙM2ù¼›ûQEd ׎4‡üóù;HŠèÐVó}eǵ(K¥djß-Ægq ¿ã‡uê–5h¶mšéµ±mûãìK›c£Ì°÷wZVLý` ¾oLeÆÐõüù5œS Ÿ ¤Áê|Îßû•’Ûí0ôG°üÛ’‹U&£Ï0k\Kg¡Í n@2l2‘¬”3ÿoñ“Üa—àÏß{à ÛÙ,ÿ¨ìb•ÉŠ½š¥kif£ËÖa°¢œt¥”k‰ÑJ¹Ñ±üQ‰G/ïeCzÆfî9¸w.…T ­zÊ N}cLOç:ÑÐM9EÛ²ƒVv0Ù¦Z¢ëN°£œŸÕRþ8<eßðú)8XÞ.óq¨Šë-“a£iY0o*WfÝ ïPÞ§MÓ*·å …\Iø|šš‹ï€¼òe(CÁÑ:'a²Ê6k€év†{bsS)ÎT¬Ê¤¼~à÷«@*Ü,¹—.>¯¶H.^™Œt3ã4ÃîºZA/X¶âMþÏKîUC×O[!ÎnFÝ+—ä…Çr,«÷ÆÐÖŒ”f¥Ö‚Köñi_9-0½Ev/OÞGªI,? »X˜³T; svÄ/ÍP!û.xwÈ ¿âUG—Üþu"½*ñHÕ;4ãVf©íz:•IëÖ(.~wúpA±qëÀKöï÷š;çj»uCwûPe¼J¼ÁX%){ªò¦†ÒeRn•ð¸Ák諲{]”Ü¥4‰å÷^M¥­¿«‘¸qËœ¸a9U±Š^–ɘY+ɽæ(Øœ^¥q]K›C«œ>•šmļ šÓ§Y¿O+ûl–…‰›f¸;²:·ãp%Ù-Š;Ây‰œ·òwXÚ >ÂŒEÎÞE§Òl“¼Î;%·£¸ Ìî׉kƒ¦$4XAF] L™f/”ŒÃù ÉýL2=ÌcpþqmÐýì°Ý€›yjEyöWàUüDšÈÛŠ"íLsÖ/3x÷Ë8³ tIœ d=‡y).ÆC8ÿpe½òM’?}pàzyMÉ]/X~—?"Ñ8L…áLöTc{ FÒ¡ÙkT³' S:i¦àb× ´ ÛÞJÏßÙ‹Æg÷Ç=ùVÜÀ f¬òü–@ÞüªÛ2\T0{ wymðzexß1þcoÿ7há™^qv:oq–ßèí"ßô?Øð!>7“#ûŒ”Dô(™Äk2ßÒÜ Ëœ^ʰʼn7¥ïÅœG¦ôÇç_-¯œ”/Øæ`o󫣋ø;Öºú•Rn„çê®…г¾ÐSòê4õæíi9—ÜßÔ÷ð®Dþ¡"üÌ2Ó»‘=¿txÏL¸1ÀL» 0_(€Ã­ã‹€¹»ˆx÷æÁ"pæ;pxÏö0`Þ,÷`JÊ ·£0åe…ãUf}¸&Àl,€ÃÏÈ›/טýEä½0E´7 VD¼AÀüQ¸Ûó×Eàþ0O{0¯;˜¥å…Û» 0ËË Ç[š àpž¶fSy7fkñ¶æ/‹ˆ÷W€¹·ˆx_ÌEÄû&`*"Þ?F©(Œ£€Y[‡yצ¡ˆx€i+×­Ü`›Ì— àpûùSÀ|¹ˆx˜{0¯Ñ¯æ"â½ ˜K"…q—¦?â^f79²SF·ši¸ë¡ð3ܽ'Bq …ßàfjÇwóˆW¿? oJˆ†Ú(ëØ&I²ì¬ï_’xx»¬>U‡ŸÕ~r\Ö©Nûúåƒô ýó'¹þ¤ðC®?/¯‰®ªopý'rC´%Úô×_”7F·F8Ïõ—å«¢±¨yŠë?“¿y$rï¬Ü-í‘.õí?—E¾9ñ"×ÏÉßlŽë¿ŸŠœŒ¬>Îõÿ–ŸœŽÜÿ,×_“ÏD^ŠÜø¯\?/¿9yÀ¯ßÿʯFÎG€^æè¿–çKó¥SopýmùÓôÓô8øWxú©ŠÓ¨»öwäÓ ¯?ËõwåÛéítýøx¼'ߡܡt=Ëõ ò¸2®Túv¢|^e¾¿¤¬¦«éé纬TÓúµ“\W”ZA£¾*õ´ž<Áõå‚¢Pús®—*Qº€^v’ç+SöÑ}ôÒGy{Ê”¢:º‹/Wýàs\¯PÎ+o([Oq=¢¼ ¯ÈÕ‘jr èQåëôëô2_Ÿ§ÜGï£oý ×ç+­´•Ö}ë•ÊFº‘^÷ ®/PŽÒ£ô3¾^¥£Çè}¾^­|—~—>éë •Çècôk/s½Fy‰¾DoóõZå =CïüO®/RNÒ“ôqß¾X9GÏÑ|{ò }†^áëK”ô}ý?¸¾Tyš>Mû}ÿeÊ ôªúz½ò<}žþÈ÷_®œ¦§éÉïs}…ò¼j~Àõ•Êx?ãú*¥‘6Ò‡庪|‚~‚*Sÿ¢ƒoÿ¬½àÿˆàÿÿ'ø?Áÿ þOð‚ÿüŸàÿ¦â þ/'ø?ÁÿÁÿ þOð‚ÿü߇žÿ+‡ÛŽî®ø_[ÿ'ø?Áÿù)ÿ'ø?÷$ø?Áÿ þOð'ø¿ðx‚ÿ Ç þ/<¯àÿÂó þ/'ø?Áÿ þOð‚ÿ»xü_Øó×ûˆN ¸éÀç¢ «‰,áG‘¹<Œdþ¸“ì¹Ä‚WrâSèýÎSéé"b©î­ç…¹ä_’ÿý‘÷‘c  Z©AïgàK‡ÞŸ{ÿÏ9ÿÕüHºE¤nÙuid’«:zz·ÿÖPjjfKÄçi¼‚Z‹%=£N™<^ÆED;ãñ[âm]=;šg* âšÊâšÍt®­ÍåÕÕš®Þ¦6«»-ó ±/gWä4 Råó)· òZ¦¥˜ÕàÙ«§²§‚iCº%§Z3[fè6ÁÿÚ#ø_Áÿ þWð¿‚ÿü¯à§áÿ+ø_Žüox<Áÿ†ãÿŽü¯àÿ+øßßEþ÷ÀYwªïìíMôìêïïééRÔ}»6´¨½]m} òþÓ'ÜT8ÌYҞͯ>HsM7Ð÷ÍZ†áþ&Mâ„ïΖx·0ämçKü[Ⱦ¥åµ}}í½Ð²(‰õkÖ³;m6:[…fOšG J$âvÇËÌŽy¨’òÚøÎ}ÓøÂYùTâ,`%Å`jáÎŽžɉT[Ó fyÀŠh“I5KdA˜ÐÓìÿ/Xð¯àÿÿ'ø?"ø?ÏMðÜOð‚ÿ Äü_>Nð‚ÿãñÿOðáý'ø¿âÁÿ þOð‚ÿk$å–•†{ Êt#™Î¦šÊ‡²ºªŽ¥Q‰ÒSÌœR3If0O•Hm¬ÍÐG5›¥ºYf¸;ÞÒ˜ílaža‹å÷mˆs‡š|‹ã±,§¼³ï‚û7î¶d³ã;/Öžë·˜Žø^m<5/lM¾Åñ¨Å´Qfiy ó ^†ž¤=C†<‹ãQÛ³¡ ŸÅÇöppeN¡Ù+ ‰œgq<ªcNA·fhCÌâè¹¥rUÌwu{×´鉘n%Ó~–³aœ(+󽦭ٺið Ëg »ÝÚ‡jÛÝÓ¾“ûUM+ö°ý,cçuGÕ´b[áu¾«•é nÚÃÌò'x);l3Ë@TtPËØ·@]¯R3ÃsPx;ìö=,ª8;¤'™C&#@rú~Zù0–Îã+Ãü‚85aYJþuÖ娦:ýÿþ:ŽF“àÿÿ'ø?Áÿ þOð‚ÿü_ ½‚ÿ 'ø¿pœàÿÿ'ø?Áÿ þï·Ÿÿã¿ÿŒ· Q‹¥3‰tª/m ÆBð‚ÿüŸàÿÿ'ø?Áÿ¹þ‚ÿüŸàÿüx‚ÿ Ç þ/<¯àÿÂó þ/'ø?Áÿ þOð‚ÿ»xü_œ02@²d^ŒXsÞ?¾ï܉jÝ÷qb’$ä…ìøÍ™9æ¯%²„—hü¦ºbó÷ò_Œc®í¿ØÇÉñn– =ü\èÑi|*n™¯©Àg‡-3ÝÃR‡…‚Òù¼´ÝbÚ·à-梸fköÄS»õŒ–Ö‡ $U¼Û|Õ£UmÉ$ËdÔ½º™v¨@n„Gçwênmˆ©–eZܲ,5é4ÒÒj§‘±­l2èy'صY–6¡¶›Y#•Q;'K±G|‹iS³¡ Ó…@=cÌÒ ò9€ÔzYqu`Bý³Løü Ó`‡µ¤ßV™Mû­ûÔqÀ!h|ÊͬêSébz1k0mŽsÓÁTíšúl-9¢Æ†Yr„[ïë×z½‘Êõ¬[Å.Síf£¦5ÁK?¥Kv™FÆJ7²ø›IN¿Œë³ÆéZ¯¶q=3ffô ýnì¸NÃfCÌš¡_îÁAåéúúï¶ÀF¥ÂFï]ì·ÅÓ½7J0%â]]ê.ÓV8´ÜÒ–¥hé4 ¾Pû[nV$òQŸ$£G«ºÍTšžâkv[f’¥²Vˆ½ëÅ»æZ˜)iÆgz23úÓºn=i™sÐVcëÖå÷,yÕôXzp^àW±š ª-¹ê†\µ•jˆöŒRð¿Dð¿¹aÿ+ø_Áÿ†ãÿÞÁÿ†Çüo>Nð¿‚ÿ%‚ÿü¯àÿ+øß=ÿ[êÜÉã-¤Bþ,ggˆ­­[wÑö™vÌkÜßg§Úãw[óñ–¶Ž–Ímb Í›š›ãM m‰æö†¦¦¶¦ØÖ¦ÄÖxǦ?$³þ& Ò (7ÃæwŸ„·O¿ùÖã5³Ü;®Øz‹ytǰßúøh½e(Aëï—\ÌÌâý¬N£•Œ¸d‰øñõ¦8ËÚ™ä°zù)üÍs绯¸yÍÇ7´nÙ´ië–Ö†Ö­íP£X¢¡=Ѻ kÔÖÔÔknéh)²F_ý£C‡ýfÇã8ÈI‚ß‹0uæGuãþà7¢ÎuJâ¥] é´¡Œ{ƒ"ø?Áÿ þOð‚ÿsÁÿ þ/'ø¿pœàÿÂã þ/'ø¿pœàÿÿ'ø?Áÿý.òÿPKIXw.C‡<"”IrrFontTool.plgÅUÛn1}GâFûÔJÍ:•T(Ššˆ$T¹”V¥ªvíaqñÚ+Û›ÛC¿6R›5 D¤ÊRAÂ3žÙ¹œ³ÌÌl.뵃T±{ý1Û;ìjcQˆRf¦Ðʪ¹â€8ƒ77ÝïΆÏ@É)ÏJX®dúZ÷”´WJ Ø1—Í\ ÀÄধ]d²íãgÂ< (Ãý‰FYf@Už'’à!Ò4Æ;"`÷Žî(¤!©*5Ek4Ñy§{|}AtÒžtð…*r”v²Rídå1EP¯8PC óBéGíÔNb‘Cl4¸>ëþÙ›œó¹š Gƒ£¡×®œóäâòKëcló"‚œ[èËY",ÊzíG½F¤*S@Ά@ÆM §ß€Œ@:ûçÍF´—u{ù—»ïŒÆ—A;;>ñb¯xê{¥™¸ 3gü^FƲdz{­÷ ‘רšÖB]Ïÿh5>-Ѝ^ûù*?T,øùüvˆ¶ƒwëÿâM·‰÷¥eG.Ô¡nmêýW ž£–(šXðJƒ:ˆãAºåÒ5¯¸f˜È‚%a7I±t33Wb•Àg))í2|ÉYuËRºtp"-‚òÄ»)SsïšÎÛ.;S·—T£G=mé\ –¶7“ËRGYžÐ™¼Ýo~jQ¥Ýìì¸ðÇ“`\ûÛ¨ô÷ª)0üâvm~-˜_§«“‹) ‘{æoæ¿¢¬¶G¥É’Ô…’.¶ÓöYä–p‹š¹c®ò‚ ŽÚÆq\¯ –ª[ Ëiuýüª¾êòbzÔkCW9ê¯JgÉšgõõ5vu†©äÆ`¨ïÐnÃìBÏúƒ“Ɖ–.é;”ïý^ ‹, ›ï/PK]a3Œv&TIrrFontTool.slnAo‚0ÇÏ’ð'—)Š;”‹‡%ËX¶3B5]ºÖ´Ålq~÷­:æ’©‡¦ïý_ßïýûH%¸äså¼Ù”Ô)TSîœ6Špæä„â“sñ^ê7XÈVŒ|lëQð7\©¾»Ž£,‰¼( ¡)ð¢4< @q «ápãÞ8wŽ;"çL=sNÝA'õWÕR[uâ Á0Ž=€²Ì Û(ÂÜ Àä¢1OÀhãÚVÏx(ôÑÆú&Mñ³³Š`ÙN]r©LI÷d¬î¶ÙÖQ²­{Êg%ÕïvÁ½ßâlN(Ûd x_ÓM½Ïš…–·w+f’Ì%êsW’ìú2¬ë);sPlëPK‚I¨.«oQ^PšIrrFontTool.sln.old‘Áo‚0ÅÏ’ð?N.Ò**v€‹‡-Ë\¶3§éR[SŠÙâüßWçÐÃÔ[û^ù½÷}<Ò\ŠRÌ•õFË*cÖTUÖT°JQÁ­”2èY©ËL¿YÖâØEÈ4ž¥ø€\uí‘€$‘ïø‘:ÇÈñcŒ„BD¬]¯¿µï¬{ËžH™ ®^…`v¯uu×ùJkuC‚„„^8ˆ$‰ãÕ§{©ƒÑh’a8¡ÁÖ6„M Óx`b–1ÓèìS-ê®ÝÃ$Dð9]T2«/u••„ƒ§?êìý§l .Òn ³jq¢c­¿ƒ¬íèìVÒYrÓ,†ðxN¡ÜåŠRý ¾sÞ¿Íé\¶4w7˜jöÈ|qõûòAÿjNTQVv5¥Yg«O£ÝÌ:v:%ý»ëäS/éŒ2ª¾öÖMÿ¬Å ‹bÂ/Ãü*¦ñPKNa3ëh‘ü$IrrFontTool.suoíYolSU?Ýlƒm0q Ö¿ÂJ÷S±k»‰0þlƒ‘X?tÝ[)t}M×ñ'£Ÿ4úÅû¦¢&ÿ!â$$&òA!&£å111h‚‚ ›¿sÞík;ÚµoA§9ïÝ{ß}ïœ{ï9¿sîí¹³ó~~󓪋4Žž B+¡™)m6ÅBs‰ T}tll,ÑØ} üö©ï)¼d+emV˜¡éãgNé;QÌõYl'0™ÛsÝŒ»É…׌47Z¼(5šmÍÛPªÃóup/z5áÚ„š‰ß¸óf ŽmÊH)½Á8`ßa”oON>+Íø[™uö è$ ß—ud<®( cþe¶€;m†2}õ^cåå“\ø!¥œÉºäsC¦~ÖZP”ð›O2ÓšIøß"ðw ¸¶}öu³ùøD´dñ·|Ê´ÿ°,ï  ¼¯³¦öŸ‚'”¿ÿ§î¿(Ç8“Œ‰Ïw‰ÇÇsîA—ªù¯´ ¸JÍ?cQV:,ëlHIt‹šºñ­Pz·Èk:]×è88NîvɾR¥òìfÖ͈Ü·˜–O³n-²3ÞÑ&ãí°Âúì_ð¸V3ónÅjô¥Ó´ëÑ™mVt1,À…žm¼u/$Õ¢'—DnÆéDÉ%Ï\¢©w§ŒÁ‰7ùçFoÎÅË·uýxòòœŽW–|^ðú‚k8~™¿ì›jjÚ_ºxdEï@£4–Ÿ© _/©ÙþÚØK×Ξ~Û+GI '™Q’èÕJóa”‰üUš=*õ!Zuî³?ö¼\}ÂûþÆo#W-/ŒyÚµjdß–wÏ¿ñbçè§Çø‚vÚ‰¾¿m»¿[XRC¦±¿ý?aŒÏ•²Û³ñ<éw|´ã<†ñ½PᢠrÅa”‹éO³ô—*ͦkR*¤«ã­BúÛìõYú×,]7K7ÌoŒ©ŸfµËjgÃi±÷f-qìF¯VÔ@mÞ%k)Æ>›ŽVp(¦·*ŒÓ0f+}fÖŽ[÷]¸òzúáå8WsÇàêIÄÿÔø—Íqó¥E“ˆÿ«ÁWTüþÜëÓ%Ê$+Ê'þ[•¿ž’ûÿNñ¯ì%ãX/]Å> ã·ñY ŸËNfþ“~ß+VÅÄç®^ÉþS-2ý|:¤Î‡|3Ç´»Õïœdø]räk³bíäæ<•öœÍõ¯ËÄ4•bP¢>ˆïÄd4¼ÇkÅhÚñmªWüŠ7j]x´ÛÈ3%Ý…†‘Œp²a$M˜¾u’Œ4 Ü,‰‘\'‰Q«$@µxÖ€?¯ÇÏ vIéOH}CcÓº¼÷ùf°¼J.ÁÔ¼èÆ ÉÈ[ù<0¥[ø˜ZèX}ëÍ”ŠG±¿õ2 N©œSï ¼ß,6§Ë>Ä -TøÏûˆ|ñçI2Î`˜²ŸF†Ñ›3Læüu#%ÏŸ§ƒ¬ÊŸnšŠü¯­nùmöQÏ;¿>;:ê'Ú ‹Ë”:Òl¶_"/Å!߉ËøVPe‘Á4ÜÎô½¨àvYAÅjÚ ŒÓ­t02¡Ô´TEëT#{Þ9ôPK]a3–á߆¸ÒIrrFontTool.vcprojíXYoã6~Îû½î®8Ýn[Ù]8>²ìĵ¤ 5–™P¤@Q®]ôÇw(Ò±|;º=ÐÕoßœ¸Ñhž@ͳ"§wï<ܺ[˜þT:?3 ×$F¡ŽRm)ôHJn‡”:vÛ­u%%¼OôWðô“jŸ=–*NÍl95g]¾¨xå\º¼"^mH1fQ¦ˆF‡œ…•µ‚™p )üaÍå7™N2Ýd ½”j^óJ_”Ýï *† »¥V´€ÛÛnƽv£æÙ…ú¨Ûc‚ÅìwHƒLŒX ](¢æ·)‰P³]ï[Îî„(Bу!èšWÉáÂû€ó‘»×]£ÑmÈ8aÔüÜwδ3A[­YB„K'ÐW(I!M¥jÂÝÊAD¼;ו÷×ÍÖåíÕûœ5oî‡Ni¨¦Qɳi4¸uΞàmôò65ï;·Þ$àÏ~ta ¼ËÄÓº:B…Q{ð TÍ»Xúºº5š(™E˜D©ÉxVšìlã°±r!KK ]¨ÕÓbtSuYªÑ5“¥:Gk©éDo“ÓëfŸ—‘"q“hr‰ËFÊiCòž(a2x,ï9Ì’DaD†š(%—DCŽSywü³TËø2c<Ì`·¤A~%Kêa˜‡ð›Ä…¿Ü«7¾t®[?u.~ø~C¬ ˆû ”•a@/*%΂S3¤‰, ÊËk_`æjèÄxÖTA B¾LÓ}l€8ÐwF< žÍÃyª!6•µ°^§Ù-Àµ³flµ8©Þv,S•˜Fñ§àïሊ@·Ä”)) K8Lq5¶žYÅ‹jì¹U_¦:O—Ö\ÇÞ#¬à%²&Lj •™¢°¥u‡r#ã:ShëâìÓ{º‡`jÊ(69›_¢M°‘ðï×^×dÔ±âx –—óøðÕ{D`¯ïIPÇžPÏfŒ3Œûaõjy…“öób‚,:ÀйÌN,Èü3Ñt8<Ç5ö³ãhða+ bsgÔ1^cô)]öðu"üø.Çÿüfõ¶²ÛÊÖn[‘{9³Y‰ÜHG˜Ç]î[;˜‡Ä¿ù6#³‡÷*Gæ*Ö;†·$Ë_E#5n^ó¿IŒÿãk‰qmÉ~W` Kì´¼67Uä¾6qˆ|T Ó_2à¿¶!ÄÒd lP¬XÍ£IâSŸÎf¾¢~c_ù2ä>Ãß$yô¢¤fÎp„øÍ˦`¿šK_‹éŒö e£qPÙ°‡É®´¤èË4‡:¬#-O´Â›ÏŠíÜN§À|½‹2Ϲà<ß|ët­øæù¦Ž°Î‡˜;òÈýÐÜ–EL–ÄŸ`MbŸ ~8g”k*øŒxMзhp`š”9Ql­F¥O3åqâ‡<Âj¨àOû¾ŠR?bcÿ1‰ðùŸ—UZÙ5™RœÑ‰æ2’¥Ë^ÿˆëZK놵”ôÌÕñÒ‚ÙþqÅe@¸ë-ËIµ¼åq¸þ'PK‚I¨.»Í/­mIrrFontTool.vcproj.oldÝXÛnã6}Îû†^w×vìn·­ì._²ìĵäe€¢Æ2Š(ʵ‹~|‡"ß/)Ðí¶J(rf8sær¢Ô>Ïc^˜J™uï²Xö ¨ ™ˆ õ‚÷ÀD(O?\V>V¼Ï¿¾}S»giFøHg!“%Ÿ€ê·o.Üj¼H îY‘BóÝ;î—Æ?Ëe³qCbê*Õ‘B¥äfsD©³aÝ^ORÂDOqo¿¨ 8Ñ©âÔ¼­^Í‹3Œ.W+^)—.mˆ×šRLX”)¢Ñ!gacoÍÌ8þ´æòƒÛL'™n1…^Jµ¨{ůNÊžw…CȈ†ÃRZÀ.íÉ] ·“~§Y÷Êv£1îõ™`1ûÒæ0cCЍÅ]J"Ôì4z£¶³;%ŠPô`ºîUr¸0>p¾rqÝ7›½¦ŒÆA-ÁÏ}çL@'Ô¸Õž'D¸’p‰’ÒTªLЭDÄ»{S­¼¿iµ¯î®ß?â[ëöaä”FZa! ðüU÷ÆÃ;çìF£WÑÔ½Ü~[€¿øÑƒðÏÛê:Dmá !¨ºW]ùºy4ž*™EXD©Éd^œìàr-c¥µ*-&t©ÖHSˆÑMÕc©F×L•ê­•¦½ LMo›}¹^FŠÄ-¢Én)›¤É¢„¹Èొs”%‰ÂŒŒ4Q:K®ˆ†§Òáüg©–ñUÆx˜ÀaIƒüF•4Â0O;á·‰K©ßh~éÞ´éVúqG¬ ˆ' ”•a@«•"gAÁ,ib_–Påíu,0w=ta<ë ª ¡ _•é1Hv@è3/fƒÑ"Õ›Î: X¿Ûê­Áu°gl·8©þ3NlÓ•XFñgÍßÓ‰Š@·ÅŒ)) +8Ì|q=¶]Yëj‰j S—K{nbVðY“ÈsD‡ÊLQØ3ºÎC¹™q)´U-úùÈEŒ@ÍÅ#ç‹k@´ òþ¡Ö:—‹x3–ZicÞçœYt‚qr™|³&ó}²™xšåó(æq/ÅààdÔ±Is ô9]ÍÇm’ùøØ#Çÿop‡ÕÛËGGxcCîõ¬a%r#]aþpÊ}ëä CÒÿuVÙÍÌN©œ ˜›° Ü9ij§Xþ)Úyüig7Ìÿ'é<~Ÿ¤³µe¿‡L ºÏ \â0_ã¢ß2à?!ĺf lDV¬îÑ$ñ©Oçs_Q?„‰¯|rŸá3Mžü€è%#˜;Ü4üc3°Ÿsů뵀ö– %£qRy¤ÃŽâ•žÞeÖýßsNgÔ”uˆ5.—ùqžïÒýI×Öiÿ›:v&ÖÆ¶iƒ´¨èn–ò%Å:²î|hí«¢)KâO±Š¦±Ï?]3.íÓ׋r}¼Oï„ûCÓáFWìíF¥O3åqâ‡<Ân¨à£ý€ _E©±‰ÿ”Dø@þãu]Ö_(SŠ3:Õ\F²xÕœ®µ´mhˆYëCQÏ]¯,Ø•×\„ÛuiõR+íù'îÿPKa3Ɖg¼ . irrlichtlogo.BMPí˜TTÇÇm‰ˆ hìÏ;bb/ÑØEXzYXdˆ51F,Hï ˆ4{,Ø–ˆb»‰XAQšÊ}?vâÍfQ_8ïå$9çÍ™Ý3óÝoîÌüç+ÿ¹ƒLŒ›WДüÚñSðkƯb…y!Ãêâ÷ºèUyïW[¶lÙ±cÇÆÿå+ù «ÏåË—7mÚ”••õå—_"©\Y¯B•šUôêUÑk\Uߨš~«ê5ŒkÔìW£®¹aÓ‰M£›tR7ï¦6 ÌS¤îÊ©uê¿ ÀéÓ§ËòÉ'“&MêÞ½;m„'N:t¨J¥úè£PkÒ¤IÏž=½½½ûöíKWŒ­W¯^ÿþýèªÕêÎ;Óøâ‹/Û¾}{í‰lmmÇ÷ÁÐf”‡‡Ç!C¦M›ÖºukYgàÀ,àã?¦B×®]i°æeˆ«««““Óúõë{õêE÷Ã?d UõÛ6kÖŒ8(•J—Ö½£›wV·í«vÛ ù\‘ææIÓ.Ý2yvƒÊ‚`hh(IRïÞ½i›˜˜Ü¼yó믿޽{7¯Ý¾}û?ü°zõêW¯^a¨g‘’’booO·E‹üÏ™3çèÑ£¼á—_~qvvöòòºråʬY³RSS剂ƒƒÓÓÓcbb8@wË–-;wî )))5j”ÐQ(?ýôÓ7ß|³cÇŽFÑöôôD~áÂ…É“'õ;w¦L™Â?«¢qîܹ#F°†êµ{4ˆ ¤¥¥­\¹réÒ¥ÀÒ¾¯ºó0õ̳RÔK)®DŠ-‘Bó¥ñ[¯õµ 0¨×êm8DFFž:uÊÚÚšõ°Œ]»v}ÿý÷´å-ƒÃ­[·ÜÝÝ9îwà°mÛ6£Ðy¢V­Z s***ä‚‚±}@–qHHHøñÇÅ0ؤ˪tp¨]÷sCóæÍ gϞ͆ f3¤q§È&Õ-º©G,L$óµ×:+<êÔoö_¦-‘/DÇÙE¾(W%_L˜0A;;Puòů"_T¬R½Â{µÞÓkRU¿£^µfzúmõjöªQgxºV†-ç5ê¢nØIÝ¢ÿ’f=¿ªö¾þ_žúÿÎJ¹ÄÉùÏ«'6¥Jû‚ýÙ8dþspH7.iܸ%nnq*5ÁÍ-ÑÝ=áu9O“_W-V©b]]Å£_G¹º¾MmWL ©œLö$K>~üø‘V¡›››Köái^^ ´‰™%šBd`~~>rÔø§]\\Œ\(ð}äŒE.bƧšBC(³Ù7ê ÄU+I¥ºwõêÓÎ<`kíät~ï^º÷oÞô·±‰ptŒwqA‡š¾téÓ‡Ÿ{ö (Xðò””‘#F´Ñ$ ýúÍš9óÌéÓ4¡púôiΑQ 'e”ÐÒÒ’·A<ȧÙÙÙ@!ö{öìY¡ÏŠÈú¿áà¢Ì{øîÅÌÌcÆY[_=vŒn~^Þ´Ñ£XYÅ8:&(•«  ¹¹ÈŸ=y¬Vϱ°¸žN·¸°5?…B¨­œ8ñÙ£GÈŸçå…{OLðõ%ï³° o)Ò‡hGGGCKÀ-ûöíáÆ•UˆÄõë×9P¸«r[Ù¿ÿÝ»wÅsÍAH.†ÐBAMlöĉBßÍÍM[ÿ7ÜÝó4+ÏÊÌœlf`gw5#ClÄ{̘y66±´»û•Ç…mHLœ6v,j—Ž8µÚÅ„ÚÖe˦™]ˆ „p;àÞ›¢)01–[+ ¤{ëæÍáÇӭT©R×.]T®®žð¡cÜ©Óî´´Ÿþš$$ܹ¸AHàŸ2ÌׂV1;®ÁzŽ?.ôˆ7ýßpps8\ÈÌœ4fŒ¿­­ŒÃDSÓ¹ÖÖ1JåΈð—/^ ¼wçÎd _…"ÊÉ鲇¢Â¯LMçXY-R*·‡†¼(.Fx?;{šBák¥Ø‰e  6Ë—/ÇàípN.J v÷+^Â?ã/®\©ÝÑ£G¯[·Žs¿zõjÖùóƒ àÌñõ…(B8å}áPb_l8¬Zµ B[ÎBÖׯc~qáÄ ïQ£(W4~_ékaïå•“]zôEEqsæ”úFâè(,&Œ9ÛÂ"ÎÓóÑ;HGKüüf˜¡f¶p!n(ã Îßd Åš‚2f ÃÐÏ>£]]_?%9¹Ôþ¥&TruŸii±!"ŽT.Z·jE»cûö؃vâö@Ô…M±9oBbccɧÜúÎEUØ×ðòáð–ø@œœ`j:K¡st\¨T.ruͽwùå3g¦˜™ÙÛ_z/JÕ,-C…š‹ËÃÛ·‘_ÏÊBmup0ùã8'­¥Úñޤ¤$À¢ØËõk׆ ìâä„ÀIä¼É¾áüùó÷ïßG¹OŸ>:ñô.ÛúÄÕ7np@¯4E‡G•Íj“oÇŽ &0:;o‹Š‚*”ª?îcjŠk\:tHà€ÚLÚBg§­áaEùùȯœ>íc:jU€?».k׬yÿý÷é0`óÆp?¢âƒÆŒ°råÊáaapE¼ e_lYäM9_äääàYd(LEèÛÙÙ$o e‹§:~òѲ\‘û@^NÎ3”a¡§`ÙÉÁÁ3ÌÍCíí…_ y£ÚŠˆˆæc×…†bÆ2¤ ›ºûöíƒTxzz IÓ&M,,,ìíÛ¶n]Q#éÑ£»&~‚˜Ì£´y‘̣ćÁ6mÚÔ«W¯nݺµk×úzzzµjÕ200044†¡ãOžœnnŽÁ¿1_”ÞSŠ‹÷oÚ8ÝÂÂÏÖû¿ò¦|!ÔlÝ:Ãҵ틒XFFFÌ[6ô‹•„‡‡>|˜£Ç˜½Æ¯¤aSÚß_¶lYFFG)çM•J…mLµyuÆ 7nÜÝb³ï§ ðÑNT*Ó¢£wÆÆ.Ÿ;wÐÎnÓ‚iqq›.LŠZÿº® õW© UÖÖQöö‹œ6¿E-ÐÝZ`e…Úž˜wˆŠŠŠ‰‰äC#å»À ‰‹‹ƒ`º—.]âž(âááC‡&xy¸441FB«p+@Àˆñññ!!!pN„"Œð6lƒ{JDDpa$)))‘‘‘óæÍûî»ïfý¾ aFîh¿ÚƒJ•¨R-vqh$¸ºÆkºçHGG¹ÒE§T¢ F¡¶èjûããEœÇ>|Èjqù¢'§BLWEKÇŠ‘„ýrw€ŠÃqFºŒb¬,wU&BΤÈy 6»ûû‚„—Ë×ñÅ IóÑIzÝ¥X¦"LÖúÎðÕ&&È›}©)òmWO9Pùãƒ,GÈ^0,„Ë ¢È£´¿3èÌ%^B)þ}B™öÿ¹ßå6¦Jû"pø¡üPKuUv.O£Cïr ReadMe.txtµSÁnÚ@=‰å$ R{CÊZÔ6DH¹-ì/^Ϻ»ëò½ý†žrÈŒ©£67²›™7ï½™¹º:Ïév >«ùâã‡Áx±š.&w‹ÁÜûÏŽâÒ9Û휩דkb0`»À`L{$]ÒRA£‡Ó›0‡`BDŠo–úþºº–S眪®xþ<ö˜ü±½~Ö`¡[Qä€ýÍgý{GF{Þ¸çØ½'·çø“ŽLöí‹÷R½wï±GîÛsôÞ“÷½çÄCö +‡Ùõ]#êÀOnê{¡ú}ßžчüàK“(Y$až9à x‹ ©g¬ "~Š¢E”°4_¥" ¢pÌëZ>8ÀãÍ2—Êx‚,+J¾‘ðM*sቲ,ÌgA.õàI²(MªZ”øðd]"ªÂS¬¨ßU/J^åó2ä‹ –Î9 †ðL“cå3–E ûjËmAV—yº|~0‚g™¼ÚšñhIx¶½£Ž9PŒÝÊ á^w¼ü×XÙ¨¼¬’<[$YœƒÏ€êFU³: á ƒ°“ž¢gà¬,MV³EÊã§Ð0¦ph ÕyÄdÐ"e²ºFOù‚9-ä8 3„ÝdÙ’XO‘ /#^6 8Ćm&[2p Ú¨iÊÀ'8nÃe[¢“6•Ä„¦ ÕyžÖIQÀ¦¤ðbât+rlE /Y–æ¬^ÌæøŒ`>²—¶ßâE‚L¼L‘µ$â8MEÊB.à`’Âˬ’Ý|mel†Ó& ŸÂa&Œ“]\V:pS`fS’lU'Å¥(Áj™/Uûbì#Åò2áY½XËËÝpP{êOíÌéNˆÛ¡ÅÕ­ÇhOµíd'¬¶£q?È~ý©vÅ;ÑŸ4¦“ªÆÇø+…ÃUy–‹·È«ŽåŠ kêoši8;¡XN|Ñ?-SÚ G(½´»ƒìΞj›ôN(—ö Œñ Î¸žj™úN¨hí¢…DIÈê¼\ [À^ò1ºº- …L+2v[,›Ï$rá÷-T…e*™GZ,ß(%òá*y(Ñ^i¡u–1ÉF°¬â+‰¡÷8 VX¼k‘DØõ¢XÔI’ésòÞ§i–D)Ÿñªb«Š:ðM×xZÌò¨­páƒ=u/ø,àQ$×'GºV¡‹.иÆT%>œ¡q®*Ñk”S8Kt+NdR°œ­Kó‚g²Øéâ0Í+.Ë]ø¸.¯Ø†*öàœvñ‚U’øp®&ö‡µžá,\:Á'-*ËÇð)û©(Á™UxŸ¶qDŸÂyšÏ‹ˆÕª η:æÅÖ²'\``Ž!rÆ’T²>ÓÛE\ª¹q|V³Y9Ç¿”•l«3€ÏÙ,åNÃ>ße®d\Øežd.\Ôe¾d|¡Ë†’ùðÏ]6’lwÙX²|±Ë&’áK]6•lÿÒÓ÷„SørT#Ãà+=P M—ô@56!\ÚÕàDpYT£Ãáò¨†'†+Ú0eÍ Çp¥@AD!FÔp÷‹br£F±H«ÏËf‘q®ôh ‹Tá 5“…0<´db~Éú*ÉøI›aoš!w1ôüÔ¢k4Ïb&<ÜV%F´²N¸z,Xq ]±‹ŽçÑ&„6ñB>ÛýXc~R¨8îaãa¥#P‰‡_éPúSRvôPðÓ²]-¡ªõ@ñÌ=0ùÕÆ4Åa}ŽIšp0Å!}® ™¢<ÏmLÑ6ž¿ÒÙ ÿöÊ2Û«BÚT‘7‚ð"Ìò 8¸¨Û˧\8¤©«KèÁ¡&¤KŸ'1†NS³M<ÇÄËõ£Iº&)y…‰¶d8åžÉjV­7öã¬ûÎ0{_KÒH¢FE¼Zgaˆ©v^ŠG &šS®KñZíçáÅÆ+1÷ÓÈ—h„æ¤î8¦äý¥šÍ3‘uGyð²n*˜Ç”±¿\cÛßÄ”­fÖLÖ&ó ‰GÀ4¦ý¸(Æ54Åî/¼,qkÃ6pѰ@=‹©×Ïf9†åyQäe/à»B^Ô‰X’¨t ÖÊåÁ‘%raÕ˜>Ãá¶%¬Á€` |HÌÑ@Ï—gÔ$A1v¦Æ¼e\9]$Ì4©7sM\Ȭ‰É%bòÎð“­&”  «/å’EÅŽèWH<‚Ò†å`¨­,Š;á倸¨-\çËÙ÷§0_1·{”TͰsIÍeÿ&¸ÑÖ  )ÞI†màÃ:ÙÀ-Áq·­¹ ²*GDŠûmãitþ²÷Ú†°l.rF¸ÓÖ .óÝ\vq‚ÛìÖºÖ]I6†WµèždxµaLbÿfÐ)m=É*3x…ÕÏаÇ;ÌÕ Â1ÖË1[и«–GðZs5ÔLì dŠ$^gx©$hÁþPCy’lòé^¯¹Häš45k´ŸÎZØ…ã Ó¢$ŸêáQ½UHóšú°×ô=ëY¾™i:„ §PÇ­ÊGðcARiÒ1ìÓ4É6XJ)ë¼,yJ¿8ÀI] ÍqÌT¦pòö’ óS)cðFí ͆Êb:üx“–Äè$q¨ê\„†E”‡RäÀ›ûDÂx–"Þ¢E¯…¤œÚWF=2Þe%>ü±!#»Á\M¦IR0„·ö6¥fe½Lc:9ù“>]ÊæY¸Öäû1¤ü©9Dèœ2–Šæ¥zåÞ¦%Í·–b Öy™ ¸ª›¾1øs­šg%_Å~gªŠÞnÃÖ+Bø Í#tiÎ"õ.©ˆàmE€õEA*8¼S+ VV´7‘ã…ié_Ù §&•пîypÑd¼1¸üMßã¦Äƒ¿µ%U]’ïPÙ[L0ïêTâ$Wß…¤hï¶EÁV­jÁ{l8_vr ﵡ¹®è@æ}¶À\›t(sš-X'rï·¡®:€ô½[Âþ®c@Ëõºôtdrú¶º‚ÕkRåÀ‡:ª(ÁÏS9£˜±œÑ‘ÈT‘æMös–3·m–‰j;&.guÛÔä]º²!|x{™QÝ>¢u˜'E-E{øhcß°ó¸¬[)|œmhÅÞA¥ ‚c†pN¯Oʳl©qà\£^nЇ„y%Íó„OhªÖ[ ‘Ÿl§˜èãÌ—û𩾗£2‰UíCøôö>LJFp^Çé.t‘áü¾*LÉ.è“  ‡ÌÕÌ)>Ó'¢äÇR2øì6ƒªÎ1PÀ?iÍ*¯Û)¸Ô„ð9sà{5|¾Ó{4†•JÀáÂí£Ž”ÄpQ×w³"VH0㸸F…&Rë Ž/ö×B§äR◬Ж5ÞŸ àËÃD—‰Œ̯t¥´b®êf.\b È—ypiOXÑõÁE>\f‰Ôbx–¨!gC¸Ü™y…ÔŒà KSrÚˆ+_*€áJK%¥vQl_íéSÅùºäSøšÅ×pÞѧHÌà* WÈåi!â®¶0Æéõ%ášNãªuݸ®µ8Ïc‰8\ge‰ni9ÏÁ®·˜9Ï7X˜ügž¥Ò!.Ühq´®<^Ž|àÁM–@xV]ƒ7[ÔæÔùnéò0eU%ùníò*\ã3&cø†±/ CôÑ,åó,©1ÓNvñTVà6c"OÝÔñi좗¿ÝÈ¡å};ð]3;OÂ<âvá{Æ$Ƀyð}í‘6Þ^,Z!A—G["¤Èa,Þ$#kÔÅpg[ÌgE½…µ¦óYÖœá¡Îƒ»Úº8á)š³:ld5£&µ>ÜÝÖ&iÊW1›¢/§R2„{Úq¡ ¥–oâ^2ޱOrͺ$~Øgy³Uߤn ÷vt=ÕMà¾íÆÇ4WƒÆµ…ªÎ:¯™kÿÝ–äQÚ¹­‹ãþ¶ŒnWôÇÖ[3VTky¯8‚ÿi‹Ég£Iˆ¤+ ÕhsøßnG:ªì †Y¦µ‹¡äGÖØå›Í¾Û< +?îž úˆyR62꼹ȫ„R! D²þJj=øI[K~OXV_|ø©5ðÔ¡ºÄ „-ECx¸Û©˜7öŒ;âG,{ÎÐ`èsµèáѶHJÄSŽÖ€äŸu­a†ÉuE—&ºý˜ÂÏû–_+Œº¸_þE[äùúŒ•ëU_üòÿSã&;X69„_™ç²Ô%E"XÙ¡·m 3âl5É(¬âôa`ÝÍš„ÖÅðq@[á߃D5ÃÇãÛX‹Qkš0ïbyB[…³….WˆLÏ\Œ"Om+ÐÇÓ[ĵ4¡ðáim…ôwó¬uÎêb8yúŽe·×êZ_‰ÝÈgY|ƒ:[t#žmaŠÿdø\9Õȃ߰$˜®µGäÃs,.Û ‰"5 ÑžÛi‡iÑžg ÔF`¹/q£1<¿§’dVÐm˜¬™íh¿©eèûCq¬ä»”Óã?…Œ;ð‚md†È…n#š©ëe(òà·‘¼‰œn,ÂAºXpŠ›Š;ui@®³z:Ùù]]¬n›ä¡8C¢/–ÛPüN)BàÂ!šš¢ڡꔚ>Vv¨/Æé(}RñèLÞÛ!¿<ï˜ Øý¦P}RòèP}ØƸ ª5Y<„‘~iÍ‚æB§¤7”>OmÒ¹_”®‚7ã«×Lx+âºIxëC# äšÊ ሠ¡0˜ÚHÁÆ;é³¹«@t ¥¦t.¿3š@¥¥r²›B­™Øêb)fds]*Ûm|Z&… ›väɬ ì2 N~¢§pÞ`:ÑÎØjF[`x…âË$+©¥Ná•®‰ûr¬§¸³_h´ÑB¼J£,°aYIæÂQ†]”h[™•)æo¯¶¯6òáh‰b’ö lÊÊF°Çþ&=Æìc(pÓ´$x­Iæ]&Ë™hÆÄ×÷R§pl/ÄÖˆË×ÇõÑM8¾®mêÂÞ>*ëõà„>XÉŠ}xC/pûz¡¬x'ö¶‰.®ÃI}\.ä8Ùæy¹ªŸŸÂ)}¼yÞÀ›zŸcâ8ðf›ÎXµ.˜ oiX v&â’œü¸BåÃ[5o¹tL²H0‚·5‚réeh›ž <†·78Á]UD_‡å=<Ï¡½Ï;ÛT#þR7švK´¸åÍüwµùíJÞÏw›TõV*‘ ï±P²[Þk,èºLÖ9]Ñöð>Mæt݇î3ÈÛû§Ï0 ©*ˆàý¦SI1÷ RŠE¸ÚlsNŠso3J u§Ûdµä˜)8ô ãCÝ·ÍE…>œa£-ž¦°údq¦ gâjFtgÙ4Übâ…cøp·1è ú&ñ¥ty¹áSø›G˜™Ê^¢ÿcmzŠ&üÑ>®z‹V|vïË)ˆˆç=øXßóº×ŽïS¨ž;C8ÇÂÒé|ÿ\ö0äͯŽáf2‘"Ép(Iù´’°¦ï*å&çÙ {p¾ñzqcÑ¡lä3Âç…¸Ë+ÞžëÇpaG„'pQnCŠ)|A¯~ÜcqñÅÑs= 1ëToù¬ú.I‰Ç.^bdƒrDyµ.ÿßr.µ9¦U›9nW yUEC¸Ìmf%Y«2æh¯—÷Hš´£Ñ^asroòæò \ÙÇuSøj§¡ô…ž/«`ð5[‘d–&€«úkÑ/ áêíªÑ¢®Ù¦5ⲿq¸vÛ²®ëºæžtL7¿n ªóRÊ!+)qàz[ÔYÜÌ ®ÍzxµÆä…¤˜îߨ£Xö—æM=| xªþ£NLW‚oîX[R‰ ¯®i·Ø"«š1ܺ­B×3ohUÉW穚eg ÿªI§ÒF·éâ¤Æ]t(AßlëM·4”qF·!‚okHœR¶¥>_6‡‹ÜáðíDÒMU ·o§j¼épò]cÑK¢ïÏpÜ‹|¯ÍÑ[´|îI¾ßU4§Ñw$ÿÖÅòÆ…øðï]As£CJ†ð]‰ºÑˆxÿiOpQ¬J6ô°…q ˆãfä­¡Ö3¸³‹ÚOpWgu!ÜÝKÛuDpOG%#Åò(ƒãî臦]Ñ’ÙÐb ¹÷ösGrîÓ\\Ë¥ýš`þî·XëN/*x@ŸÆ¨&†,«›3Ž»—{Í7.ŽæGí^››w3?î(è¼WŸÌqÜØ<¤5¼9·ŽçYHÊ[ï1gxØÔá6§ŒSå ˜´à¼Îcy›Br5y”l$tÇ!ØÚÍË\J<øY§ ¹Ät°c>ü¼G„±ÎÐ á¦&Àîªë3y™ÍgZ‹l¿4uB”×Ë3$ÎÆð«žŠš}Î&ð˜]Kix·–³È¦û™Çì?äI¾<…âŒÁÊ~ýµð]¸‘öÂر_»-òÛ¼*¿rÂ~­w_¿è“þþ½üsçe•Þñ;$Hƒ„-ºIÖîdÏ‘-Ãȸʮ‰A ’p"M&FÇÅ$`2Aw‹UvKm+)¶,Õ-­n-®Û5žª¤[J³¥[¦:É:“¡y ÿø­…“uå<§=çí÷Þwæ}Ÿ{ïóNìé9=}Ó™÷ù>ï½Ï{ßûþ˜{3h‹4‰Ù%|ËyúzqÕÑ×ät¤ÿpMr°ÓÞ[c„±IŽyÒ(œ›6l•Ý!˜´l’CžæÎàè¨vñbb®VÊÝÛîSm§æ?ƒöm¸]Ì3ã´ÃܰJDi@~nqr<Ìë^àj1Ÿ ćÅÖõ-…vnX#®g‚dfÁ…45¬ ¸:½‹ÄNï[È*°^T ”Á¾ÓŸ Ä“”XH£q½Ã®úCàwË9€Â_·454ˆ/ öbůј–¦¦Ðºï‹ìâÔ±Ýæ×$n 1÷Ío½¸±H°Ši¼M|Q;¸ùÜ´ÜX'*™6l¼Ãæ†Ö»·ÜCŽKãJQÅ57¹Å7ÆDµ^¥8 :\ãíâK4@^³ H½­Ÿ}¼uã*q“Þ^rjV>¼èɯ¿NÃòßR’ãÓ[åµ¾5ß9׈/—DÔ7ÖåïÁv‹;ðÏ'Àu¯‡= ÏÑŸõb¯Ø#Ä6¼î=¢Vì]x'#gÁCänÙ£”o!¶úc°ZÔ²IlVå~/bÖýžU·Üå -÷?€Ëjò,Eõ®d½1ß‹Ç_9>` >/B¡^m¾R1(áónÿMµý*H À„Ï»ý½SáßJ(MáßKÄlA¾@Ẕ«ðq !*üGIÀR¸ì¿_)®”Èôð‰rý-jHþÙ›ü³Y\® m·T±*Þ±úÈ §¸­"`SÝ)/ÑxÇ®Íý{ëïìí}tצÝ]ý{“{‹·ïNîëìY¼u`ß#»÷.®miÚ¶k{ך]=½‰®]»÷tõì{äÑ>háUŠhâ;Ö~Ýêï×,¾ÿÏèqVW³;ÝÂ@ßf~µV~Ÿš_êVÖ³Û"P(¹QNq+ „\»»AÎƼ<#â©ìö<äÞùý•UÞÚN¤µÚ{ÛÒ*©ª(õ펵ފþ¯—ï¹ù)‹-"©¢Ô%“V‘bì Og´"6©DU0Û¢•(÷uÅñ!¤{~,bŠæü˜@çÇl•ÌE”J>a~47ÂpV˜ È(o„¡°0[ÐÑ߈ iá¶…#Âň7†Š#àň7IÈ…TåX{çšåå»U k î"˜µ´XÃÑS#ÃÑ–æG[ ŽŽØµ†£-‰G[¢6m©Áp4“La8Ú’ŒáhK׆£Y• G³z0ÍWN†£Ùíµáh6"Ž6å`8šv-k8Z;wép4èptļZyÃÑ´ú`8šx™IlÕ³í©sÏmLûN:uî;õ©s¿VfrœhÆä¸¦p“ã$€™'ª59N5mrœÖiOŽÕœ'’59N429N¼!“ãÖh“ãZÿ2'lj¨OŽÓ¾gMŽÑœ'’99N$krœö7crÜ’‚ÉqK*LŽ›‚?9n drœ6…>9î+!«Dç'Vý~bU«Ùš|çÕüä;/&ßYµ0ùΊþä;«&ßYÑŸ|çÕüä;/&ßùœ‚ÉwV'“ï–nL¾³:™|ç·/L¾[*™|÷5vrÜPéä¸võb&þ8Lüq²>ñGz§1ñ™‰Lç?s0\¦H 1\&¢†p™"LÙ6—‰Dq\&"‡r™¼{Ée"^Êe"nËDü”Ëd¸ —‰(6—‰Š6—ÉTEžËdm¥s™,Ùà2]ç2™;ap™¨lr™ô¶Õ¹LD³¸L–F¸LŒæs™Íç21šÏeb4ŸËÄh>—‰Ñ|.£ù\&Fó¹Lܾû\&Nô¹Lœès™8Ñç2q¢ÏeâDŸËĉ>—É)—É“l.“é§\&ª.u\&â¥\&âÖ¸L¦_ã2Y¢Áe"ºÎeÒÊe"ŠÍe""å2i¥\¦ÂòÉeÒü—IÓ .“¦Y\&[¥\&MÕ¸Lþg˸)—ÉóÚ\&â×¹LDиLžŸã2[ˆ<—Éóp\&O±¸LžÛâ2å{½ÍeòžËh6—ÉÐ .“©Ú\&#Âæ26—É¿…ò\&[6¸LLå2Y*å2q*á2Ù²ÎeâuÂeòö›%eš%eš!eš%eš!eš!eš%ezÇ•"ŠÍ•"¢Æ•"~†+E‹4¹RD³¸RT#\)â6¸RÚ”+E+å JS(J(J(Ši²M}Òdú¤)õIÓLêMê‘Xê}7¨O´JƒúDÿMêÑLêS"¥>™¥>i%ÛÔ'ú©…PŸ|w1êÙvê‰ §>ÑB}¢;ÃRŸ´Ö°¨Oô¸éÔ'¢Ô'³Dƒúd7¿I}2 °©O!ž¼Ú’uê“©Ô'SÖ©Oú‡IŽúD",êíÐõ‰~’µ©OtkB}¢½@£>A§>éç•N}2NúD;“M}2·4¨O¦ÌQŸhÛ™Ô'³r‹ú¤ ,õ‰^¥,êYêÑC©O4†úD»O}Ò®=õ‰^,ê=!mê‰ ¡>1!&õ©H¥>‘kaõ‰„„SŸØ “úD‚ê[„M}¢a,õ‰OŦ>±q õIk"žúDBB¨Oveõ‰DÙÔ'K4¨OD¡> õ‰DXÔ'K£Ô'nCúÄn®SŸ¬†údÃPŸ¬ J}²DJ}²D“úd˜Ô'+€RŸ,‘RŸØº=±‘é@<õ)<ŽRŸì(‹úd‡0Ô§Ð úÄäÄQŸŠ„iÔ'ÇQŸl9œúDc9êMÒ©O´ ›úDT“úd±!&õ‰ b©OaJ©O$&”ú¤5|õÉÞ{ƒúTä®ã…¬ç®Ý&õ‰¹šÔ§R(õɼµQê“©Ô'{Sƒúd˜Ô'î¶jQŸÌ –údqÔ'3†§>™Q&õ‰Û'J}2uƒúdÊõÉ” ꓜN}2uB}¢Ò¤>™šA}2e“údêõÉ °¨Of€I}btúÄè:õ‰~.+F}¢ŸBlê}†f¨OÚÓ¹M}¢@L꽬„PŸŒâÔ'#8”údÄ¥>±õÉ)N}2‚C©OvK} m“údrÔ'#$Œúd„¥>™µ¥>Á!Ô'fGê“Ý|6õÉl»¨O\ó0Ô'»æpê“;õÉlx–úÄì”F}2û3K}2‚ŠQŸ˜Þ0õ‰=ý,ê“5õ©h´A}ÒÆeuêùØ6õɈ5©O†B}2¢ê“ÁPŸŒˆPꣵ¨O¦hPŸL™¡>™!,õÉ ²¨OvõÉ à¨O\! õIX §>……iÔ§° ú¤¢ò¼ZÇ °tŽ`Ù¼.„ò,Ýà°:å؉š¼+‚á„”By¡ÅP^@X6/ þøcñÉ'ŸˆÏ>ûLüò?]ñ—¯¼‚óXžÑ®ú'aêEþH~ÍUK/·Ìõ—an!úœ)kùPÓUUX¦Ê½e*D¯šš*®ç‹ÐôS½¼ü„\Sÿ4¯Ÿ8ôš\>œ Ñ«ª0TŽ‚ôú-}j½JÓË¡ÏñZMêU¬>}ùòå+ÓCazUôSUž^Îê‡ôCÿSý*ô+JWê¯úÕ«W•>\>ôÆ»CSåŒ~õê•Co ½ñ~½fëÃÐ/:qBÚ‰œ~äÈ‘SȲ¼ÊÚÿ)èSžþIˆ~døÃ#׎ —_aôª«îôô5,G®¹RÅè®û©Z~…å*«»îÕ`©*Ÿ˜°tPžyç–D”;*ûz! üCMt· k²Ò•߇òaMž[^UN–S§ÊøÒ ñ•Ïþïì°gaîg"¢l‘(<ÇxŒ&ó9ÆÃh,^ì=Åȧžˆ8w}aÖÄ=ûì€}…<û¼>—ò‘j¬V[«Ë eÞùƒ‡õüS«)ËoUV!***D¥´¯”ÊJX l™WbM%¬¦F,ƒm©ñjXV³L4ú`òÙ©Ö ÛkƒuI_]>“²:¬×‰n˜ü¸X3l ¬ Öë–¾zé«Çz½zþj†mµÁº`ݰ$LˆõŒ&D3ÒoËêšEss³Ø;b ^·ˆAØQØ1Xó–-b ¬ –„퇄 ŽºÛàƒ Ñ­ Z´6hmâì8¬­­ qm" Û;„…“þ.øaaƒ]r».Äv!¶ ±]ˆíBlb»ÄqØ,Ùv6; ;;’þnøa5݈éFL7bºÓ˜nÄt‹ýÝÐ`GaÇ`Cr=ÙcıMŠd2)öïß/†`eeñzP<ˆWØ0ìØàAø;(±Ž×£GÅQØ0ìØ1iÇÄYXMåqô XÝqqüøq1 MCCCb6›€UV £ß ‹ŠeÃ(wXàÖßÖGÄÈȈ8 ›€]<;".Á*——FΊ³gχ÷°iØøø¸¸›†UVNˆ‰‰ 1 »&_/NˆšŠ‹Èë¢X»xñ¢pa—ÄÈÙKâž×§a.¬¦bZ\šžÓ0W¾^›×`®´ékX¿†õkXÇ«‹Wi×\1gŒkò¹ãÿ¡ \1z—¨|/ WïýÜÀ\ŽhØ«™Ñ†hÔÛVú,Z°`¼ ÌÁGÌ|Ð<üDÄ|(Od.ÞjŒ ZA´…wþ{ýýïåroµöãBõ¿JîeìÀÑ1çU§Ð™äëòü%ã‚~ëù'YtÉwÏ;:곪˜ì{§ td³äÚøß¾ÐêµoЄê^/!åèÆWƒæÌÈ|3ï¹Gå;»£~S]Ï×’õí+:¾žÄ-"Þ™LÆŸì÷op_çÀ#…+w¦Ðµ2Á•Üï×r…öºJõìŽýu;VÆoþöm­«Zzp÷iMölØÛ“èÙ±/±I¿û8…;NþuŒÜ+œŒw¥VRuI_¬ïŽøý·>Q‹û\K2Ù2ÐÑ×ñL¼¿½£÷·og ÷Ÿ ©eŒäL™ê’’ȬÒÙ¥%¸—`)-={vI‰´’ÒëàŸïßÂE”ÞƒÉý>eîÓ—#…Ï»³aßR>úy7¢Fó¼åtÙèrõniä¼zå™Ç"ÿ¹x“ØŠ²·ŠN¨IõîQDïVcÓþ²ø¿ÇÀTiÍ`Äð‚䎆d ªT ® ©ÀÔQ äyiP»À¦¦iÐéÊ •@V âƒNV.ê˪)ªA ûšöñ ÛçV[ Ô~0•| ¬ÀF” ƒtL³ :&`b7N€ hÞ  F#†WÌ5È€™Ah†Ð>3†×`ùVTyÆ…n ¬ ³zÞ€å›Q] ””7Ê¿Å"Ï ö!Ð.†wPÿ8c!‹:;y º÷Puž@'BÏ¡ vcW`\y2¸3øçŒÜü¢î ¡@HÎ, RÀ%½ ÒH4RaÄ ù&v¨w –…L+1°² ÄA'&Ÿ‚²c˜ÐÏ÷e‚ûÆÒº¡†É$¨{€µ:Šš7#£ :ç{þs¾Açq[8â?tô'ügAƒÎUÞáŒÿ\eÐÙÆ.øÏ6Í324’6Ïš[th$mn4CØÓHÚ"h$mC#îùCи\Eîq9ÐÜš.Ücp 2kÎLÜe(Ÿ™MY:PK}J¨.5Ü G$/ recources.rc½VYo«8~”ÿàá¾´ºV¤™¶,Nj•¦‹T QBZ$»Hýñs „Þ6šqÓÄ>öÙ¾óyÐ<‰Š¼Ì—ºMÊM˜"ãûwôgqVñq™oŠ(FeT$ëêl8†ƒoI¥›EŒ¤íüÙ‹4ÀÄ"^&YŒ4—qߤNàÍtlë!`sݱ˜ÐÿÂÖ„3¡Yñ²ÈW¨z‰'÷œÚ†å›©]"d.Á\ÿ÷m“ ‡Ð8€E± 3t¢mʪHÂÓ.÷².Q²D5eZœhÓ{Š9¾gÀ´¬SôúŠú“\ófI´ÓZQ$ÜQ{¬–fÏ|mFè3âÍ5#æë½q ùŒ{T³A{]„Ï«Eù"Öás|¢¨U˜³„4m wž:ب}ëÜóXÜ饑 Ê{†Ì($ õ(ÿ(iˆm õ€ÆŽl;¶IÅc&µ ú†Æ }¤Ób Òù¶£Ð¬†ŽFy¶Å¬¢ŸIõ‚Òüg\VˆšèG˜nb´NÃHlΤi•£8+7EŒÂõ:M¢°J@/im]Wa’•@•¬LÊ*Î*Óaš¢ò7 W%ìajÒ€Ž­ ý&dè&Ñ¢˜æYÅó<=OÇØí-&zR­ÂõjêNù\s÷Cmdïš@òR¥ùs~¦ÏÝ#Fj&!xÙEj&Õ,g¦ æ—Ü#‹z¥Â—|50þ`d²€>ulŽ^Å`5õ´9iƱ9ñ Ç×q}·éšË)Ôç5{`sbûÃÁv®_(H½öq‰‘4gˆ…@ ÉRÂm`ò/yo‡¸>»Ö}η$¢"†[=Õ5AK0ŒÂlÔZÿ4ŒÒdý”‡ÅBÂÔ4‚FUÁ¸1÷¶]\àÉžÈX‡œ}‹S‹ÚäÏÚS¾©úfU0«ŒaA9o”€¬Üs¬Î¾"kÆ5N ,± ¶F$aÆZtÐg¾}Cl<ƒËX•c–87úLjœ»¹¥äN8Ÿ¨X½”Eü‘mpéÎ}·‹@¯–A´x,×IŸc²6=Ç5;Û¢Œ7E½e¤`uE}Û` ×tÆ· 4{®j_B¨ƒ#þÏel3æx‰èÚJÍ<ͺ&tv͹ÛEôo}."KÜóýŽÃÿìÛKzž¶\3®‰q£`IßTUžI‚RšÏZ,bìGÿñù•("àVa*øÓùSùû,%A7ƒ…¿öæ9ÚÑDÙÔž:ÛãéÃGÁ̧&‘õ´ö/ÎÞц۳­™è­©ùA¦°Ë~ûx?ÆK½x–WïVåPK}J¨.Ó7ìMTŽ resource.huÒ[kƒ0ð÷B¿Ã=Zµí¶W5a ÕDêeëS°‡C¼ìBéw_*Œª˜¼r~ ÿœd³¹\(ã{˜"Lm‚ýëu¹ØlÀÍ“ºjª¬…(oº¸{µ‚QŠ:nE y™]* Ë ±î7„\>ÿB-’ª«ѬëäVX.R‘奂'6£:Ì]Ó‡Øâ \ÓÓx;Ĉ#b:ìE…wCls+ U]Ó´9m¨´>ÖÞG¿©´1Ö6s-¦èˆÔÛ±vˆ¨Û7½åMj½Ÿ$yÅöAäqFJý´\ô¿‚ŠŸ䶸+ZøŠ‹N4U5”âªó§HÚ¦wòð<“LÏBD'4bŒúB9ª±‰uNÜ?ÉÞ9þ=—†SüHã³ðhc™NˆïÁösX¾kR4¶°ÓFO;ä482gÂå¥Ÿç´ ‰§GÿÿuQ¦yvŸÿPKuUv.¢‘þªéO StdAfx.cppm±NÃ@ †g"嬲ÒÜÞ )i©B‚„Ø.9‡˜^}ÑJŸ·ÏÀL’vAb°,ýö÷û·RÄèÃ+xŒh­àqÔé !pôs¯D³ÑÞ,Knm4‰bƒ’&JݔޯKíœÍ†¶ 2sŸÎïÝa Kèa‹Ú _æÓ™»pÍ K¶ÿbõ÷@Ü9ÐBŽÓ$Mné’W‡~1ÉJÁÛ3O»"/7Åà ^Ð!бm-Â)†³œ,µ=òŸ8È—«±ˆ¡ªóûõk¶=#à‘i2.ô0CÐ ÿ½ãêPKuUv.6ö ×DStdAfx.h­RËnÚ@]‰¸U7­ Ú¨ŠdÓX§Â„TÙŒæÚ¾=Fãqi‰ò­Ýð ]uÑ»Ñ.ÛÙ܇ÎÜÇ9·×ƒÒHê¦p Úd•Ä âo"#”Zv¢Ï¥Á¼s„@uÖnõz…D []|ÀSnqO1•›áO4HBHUL ¬QUfoÎ@¬Q7eÜ#•Ò˜`–¾P‚ ¼uiJZ/Agµjwݯv«ÝzN1<““Bù›¾çÑ’9s͹÷š_ ØØ:SÆû}vÎÇSÖçÃáp4Œ†çöq„“Ù-ói‹5…àŸêüœŠÏ£ _ù ¸‚¾EØäV‹$P¨ Ú•´(»û_À߃Üáà‚Ï|/ä^ÈøÜ:''öK„™±¤üàa‰”!8%îHÉbWv®Q¸PÑ&5€¤Öählfk”7»ÛM¯\¾ÖáþüÅÌgÁ[?¼„êRi;EN<²Eþ*fŸ‘“¹és¬rjx§‹D‹ #include #include "CFontTool.h" #include "CVectorFontTool.h" #include "ITexture.h" using namespace irr; using namespace gui; #pragma comment(lib, "Irrlicht.lib") const s32 texturesizes[] = {128, 256, 512, 1024, 2048, 4096, 0}; const wchar_t *fileformats[] = { L"bmp", L"ppm", 0 }; // bitmap font formats const wchar_t *alphafileformats[] = { L"png", L"tga", 0 }; // bitmap font formats which support alpha channels const wchar_t *vectorfileformats[] = { L"xml", L"bin", 0 }; // file formats for vector fonts const wchar_t *warntext = L"Legal Notice\n" L"------------\n\n" L"When making bitmap and vector fonts, you should consider the potential legal " L"issues with redistributing the fonts with your software; this tool basically " L"copies font data and some authors might not like this!\n" L"If you purchased fonts or they came with an application or your OS, you'll have" L"to check the license to see what restrictions are placed on making derivative works.\n\n" L"PD and the OFL\n" L"--------------\n\n" L"You'll find lots of fonts on the web listed as Public Domain, you can do what you like " L"with these.\n" L"Many fonts are released under the Open Font License, which is a 'viral' open source " L"license like the GPL. It's worth reading the license here: http://scripts.sil.org/OFL\n" L"The most important restrictions are- you must include the original font's license, you " L"can't stop your users from using or distributing the font, the font must have a " L"different name the original.\n\n" L"Some free fonts can be found here- www.openfontlibrary.org\n" L"http://savannah.nongnu.org/projects/freefont/"; const wchar_t *helptext = L"This tool creates bitmap fonts for the Irrlicht Engine\n\n" L"First select a character encoding from the list, then choose the font, " L"size, and whether you'd like bold, italic, antialiasing and an alpha channel. " L"In Windows, antialiasing will be ignored for small fonts\n\n" L"Then select a texture width and height. If the output exceeds this then more than " L"one image will be created. You can use the scrollbar at the top of the screen to " L"preview them. Most modern graphics cards will support up to 2048x2048, " L"keep in mind that more images means worse performance when drawing text!\n\n" L"If you want a vector font rather than a bitmap font, check the vector box. " L"Vector fonts are stored in system memory while bitmap fonts are in video ram\n\n" L"Click create to preview your font, this may take lots of time and memory " L"when making a font with a lot of characters, please be patient!\n\n" L"Now you're ready to give your font a name, select a format and click save.\n\n" L"To load your font in Irrlicht, simply use env->getFont(\"Myfont.xml\");\n\n" L"That's all, have fun :-)"; #ifdef _IRR_WINDOWS_ const wchar_t *completeText = L"Font created"; #else const wchar_t *completeText = L"Font created\n\n" L"Please note that anti-aliasing under X11 is controlled by the system " L"configuration, so if your system is set to use anti-aliasing, then so " L"will any fonts you create with FontTool"; #endif enum MYGUI { MYGUI_CHARSET = 100, MYGUI_FONTNAME, MYGUI_SIZE, MYGUI_TEXWIDTH, MYGUI_TEXHEIGHT, MYGUI_BOLD, MYGUI_ITALIC, MYGUI_ANTIALIAS, MYGUI_ALPHA, MYGUI_VECTOR, MYGUI_FILENAME, MYGUI_FORMAT, MYGUI_CREATE, MYGUI_SAVE, MYGUI_IMAGE, MYGUI_CURRENTIMAGE, MYGUI_HELPBUTTON }; // event reciever class MyEventReceiver : public IEventReceiver { public: MyEventReceiver(IrrlichtDevice* device, CFontTool*& fonttool, CVectorFontTool* &vectool) : Device(device), FontTool(fonttool), VecTool(vectool) { device->setEventReceiver(this); } virtual bool OnEvent(const SEvent &event) { if (event.EventType == EET_GUI_EVENT) { s32 id = event.GUIEvent.Caller->getID(); IGUIEnvironment* env = Device->getGUIEnvironment(); switch(event.GUIEvent.EventType) { case EGET_SCROLL_BAR_CHANGED: if (id == MYGUI_CURRENTIMAGE) { IGUIImage* img = (IGUIImage*)env->getRootGUIElement()->getElementFromId(MYGUI_IMAGE,true); s32 i = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos(); img->setImage(FontTool->currentTextures[i]); return true; } break; case EGET_COMBO_BOX_CHANGED: if (id == MYGUI_CHARSET) { IGUIComboBox* cbo = (IGUIComboBox*)event.GUIEvent.Caller; FontTool->selectCharSet(cbo->getSelected()); // rebuild font list cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_FONTNAME,true); cbo->clear(); for (u32 i=0; i < FontTool->FontNames.size(); ++i) cbo->addItem(FontTool->FontNames[i].c_str()); return true; } break; case EGET_CHECKBOX_CHANGED: if (id == MYGUI_VECTOR) { IGUICheckBox* chk = (IGUICheckBox*)event.GUIEvent.Caller; IGUIComboBox *cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_FORMAT,true); cbo->clear(); if (chk->isChecked() && VecTool) { // vector formats for (s32 i=0; fileformats[i] != 0; ++i) cbo->addItem( core::stringw(vectorfileformats[i]).c_str()); } else { // bitmap formats if (!FontTool->UseAlphaChannel) { // add non-alpha formats for (s32 i=0; fileformats[i] != 0; ++i) cbo->addItem( core::stringw(fileformats[i]).c_str()); } // add formats which support alpha for (s32 i=0; alphafileformats[i] != 0; ++i) cbo->addItem( core::stringw(alphafileformats[i]).c_str()); } } break; case EGET_BUTTON_CLICKED: if (id == MYGUI_CREATE) { // create the font with the params IGUIComboBox* cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_CHARSET, true); int charset = cbo->getSelected(); cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_FONTNAME,true); int fontname = cbo->getSelected(); cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_SIZE,true); int fontsize = cbo->getSelected(); cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_TEXWIDTH,true); int texwidth = cbo->getSelected(); cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_TEXHEIGHT,true); int texheight = cbo->getSelected(); IGUICheckBox* chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(MYGUI_BOLD,true); bool bold = chk->isChecked(); chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(MYGUI_ITALIC,true); bool italic = chk->isChecked(); chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(MYGUI_ALPHA,true); bool alpha = chk->isChecked(); chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(MYGUI_ANTIALIAS,true); bool aa = chk->isChecked(); // vector fonts disabled //chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(MYGUI_VECTOR,true); bool vec = false;//chk->isChecked(); FontTool->makeBitmapFont(fontname, charset, FontTool->FontSizes[fontsize], texturesizes[texwidth], texturesizes[texheight], bold, italic, aa, alpha); IGUIScrollBar* scrl = (IGUIScrollBar*)env->getRootGUIElement()->getElementFromId(MYGUI_CURRENTIMAGE,true); scrl->setMax(FontTool->currentTextures.size() == 0 ? 0 : FontTool->currentTextures.size()-1); if (FontTool->currentTextures.size() > 0) { IGUIImage* img = (IGUIImage*)env->getRootGUIElement()->getElementFromId(MYGUI_IMAGE,true); img->setImage(FontTool->currentTextures[0]); scrl->setPos(0); } // make sure users pick a file format that supports alpha channel cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_FORMAT,true); cbo->clear(); if (vec) { // add vector formats for (s32 i=0; fileformats[i] != 0; ++i) cbo->addItem( core::stringw(vectorfileformats[i]).c_str()); } else { if (!alpha) { // add non-alpha formats for (s32 i=0; fileformats[i] != 0; ++i) cbo->addItem( core::stringw(fileformats[i]).c_str()); } // add formats which support alpha for (s32 i=0; alphafileformats[i] != 0; ++i) cbo->addItem( core::stringw(alphafileformats[i]).c_str()); } if (VecTool) { delete VecTool; VecTool = 0; } if (vec) { VecTool = new CVectorFontTool(FontTool); } /* Message box letting the user know the process is complete */ env->addMessageBox(L"Create", completeText); return true; } if (id == MYGUI_SAVE) { IGUIEditBox *edt = (IGUIEditBox*)env->getRootGUIElement()->getElementFromId(MYGUI_FILENAME,true); core::stringc name = edt->getText(); IGUIComboBox *fmt = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_FORMAT,true); core::stringc format = fmt->getItem(fmt->getSelected()); // vector fonts disabled IGUICheckBox *chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(MYGUI_VECTOR,true); bool vec = false; // chk->isChecked(); if (vec && VecTool) VecTool->saveVectorFont(name.c_str(), format.c_str()); else FontTool->saveBitmapFont(name.c_str(), format.c_str()); return true; } if (id == MYGUI_HELPBUTTON) { env->addMessageBox(L"Irrlicht Unicode Font Tool", helptext); return true; } break; } } return false; } IrrlichtDevice* Device; CFontTool* FontTool; CVectorFontTool* VecTool; }; void createGUI(IrrlichtDevice* device, CFontTool* fc) { gui::IGUIEnvironment *env = device->getGUIEnvironment(); // change transparency of skin for (s32 i=0; igetSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i); col.setAlpha(255); env->getSkin()->setColor((gui::EGUI_DEFAULT_COLOR)i, col); } IGUIWindow *win = env->addWindow( core::rect(10,10,200,500), false, L"Font Creator"); win->getCloseButton()->setVisible(false); s32 xs=10,xp=xs, yp=30, h=20; env->addStaticText(L"Charset", core::rect(xp,yp,50,yp+h),false,false, win); xp+=60; // charset combo gui::IGUIComboBox* cbo = env->addComboBox( core::rect(xp,yp,180,yp+h),win, MYGUI_CHARSET); for (u32 i=0; i < fc->CharSets.size(); ++i) cbo->addItem(fc->CharSets[i].c_str()); yp += (s32)(h*1.5f); xp = xs; env->addStaticText(L"Font", core::rect(xp,yp,50,yp+h),false,false, win); xp+=60; // font name combo cbo = env->addComboBox( core::rect(xp,yp,180,yp+h),win, MYGUI_FONTNAME); for (u32 i=0; i < fc->FontNames.size(); ++i) cbo->addItem(fc->FontNames[i].c_str()); yp += (s32)(h*1.5f); xp = xs; env->addStaticText(L"Size", core::rect(xp,yp,50,yp+h),false,false, win); xp += 60; // font size combo cbo = env->addComboBox( core::rect(xp,yp,xp+50,yp+h),win, MYGUI_SIZE); for (s32 i=0; fc->FontSizes[i] != 0; ++i) cbo->addItem( ((core::stringw(fc->FontSizes[i])) + L"px").c_str()); xp = xs; yp += (s32)(h*1.5f); // bold checkbox env->addCheckBox(false, core::rect(xp,yp,xp+50,yp+h),win, MYGUI_BOLD, L"Bold"); xp += 45; // italic checkbox env->addCheckBox(false, core::rect(xp,yp,xp+50,yp+h),win, MYGUI_ITALIC, L"Italic"); xp += 45; // AA checkbox env->addCheckBox(false, core::rect(xp,yp,xp+50,yp+h),win, MYGUI_ANTIALIAS, L"AA"); xp +=40; // Alpha checkbox env->addCheckBox(false, core::rect(xp,yp,xp+50,yp+h),win, MYGUI_ALPHA, L"Alpha"); xp = xs; yp += (s32)(h*1.5f); /* // vector fonts can't be loaded yet env->addCheckBox(false, core::rect(xp,yp,xp+200,yp+h),win, MYGUI_VECTOR, L"Vector Font"); */ yp += (s32)(h*1.5f); env->addStaticText(L"Max Width:", core::rect(xp,yp,50,yp+h),false,false, win); xp += 60; // texture widths cbo = env->addComboBox( core::rect(xp,yp,xp+70,yp+h),win, MYGUI_TEXWIDTH); for (s32 i=0; texturesizes[i] != 0; ++i) cbo->addItem( ((core::stringw(texturesizes[i])) + L" wide").c_str()); xp=xs; yp += (s32)(h*1.5f); env->addStaticText(L"Max Height:", core::rect(xp,yp,60,yp+h),false,false, win); xp += 60; // texture height cbo = env->addComboBox( core::rect(xp,yp,xp+70,yp+h),win, MYGUI_TEXHEIGHT); for (s32 i=0; texturesizes[i] != 0; ++i) cbo->addItem( ((core::stringw(texturesizes[i])) + L" tall").c_str()); // file name xp = xs; yp += (s32)(h*1.5f); env->addStaticText(L"Filename", core::rect(xp,yp,60,yp+h),false,false, win); xp += 60; env->addEditBox(L"myfont",core::rect(xp,yp,xp+70,yp+h), true, win, MYGUI_FILENAME); // file format xp = xs; yp += (s32)(h*1.5f); env->addStaticText(L"File Format", core::rect(xp,yp,60,yp+h),false,false, win); xp += 60; cbo = env->addComboBox( core::rect(xp,yp,xp+70,yp+h),win, MYGUI_FORMAT); for (s32 i=0; fileformats[i] != 0; ++i) cbo->addItem( core::stringw(fileformats[i]).c_str()); for (s32 i=0; alphafileformats[i] != 0; ++i) cbo->addItem( core::stringw(alphafileformats[i]).c_str()); xp = xs; yp += h*2; // create button env->addButton( core::rect(xp,yp,xp+50,yp+h),win, MYGUI_CREATE, L"Create"); xp += 60; // save button env->addButton( core::rect(xp,yp,xp+50,yp+h),win, MYGUI_SAVE, L"Save"); xp += 60; // help button env->addButton( core::rect(xp,yp,xp+50,yp+h),win, MYGUI_HELPBUTTON, L"Help"); // font image gui::IGUIImage *img = env->addImage(0, core::position2d(0,0), true,0, MYGUI_IMAGE); img->setRelativePosition(core::rect(0,20,800,600)); // font scrollbar IGUIScrollBar *scrl= env->addScrollBar(true,core::rect(0,0,800,20),0, MYGUI_CURRENTIMAGE); scrl->setMax(0); scrl->setSmallStep(1); yp += h*3; env->getRootGUIElement()->bringToFront(win); win->setRelativePosition( core::rect(10,10,200,yp)); } int main() { IrrlichtDevice* device =createDevice(video::EDT_OPENGL, core::dimension2du(800, 600)); video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment *env = device->getGUIEnvironment(); // create font tool CFontTool *fc = new CFontTool(device); CVectorFontTool *vc = 0; IEventReceiver *events = new MyEventReceiver(device,fc,vc); createGUI(device, fc); while(device->run()) { if (device->isWindowActive()) { driver->beginScene(true, true, video::SColor(0,200,200,200)); smgr->drawAll(); env->drawAll(); driver->endScene(); } } // drop the font tool and resources fc->drop(); device->drop(); return 0; } irrlicht-1.8.3/tools/IrrFontTool/newFontTool/irrFontTool_vc12.vcxproj0000644000000000000000000003050312574354552024446 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 FontTool {4D53E40F-37E3-42B1-8848-F4C6F8313A17} Win32Proj Application MultiByte true Windows7.1SDK Application MultiByte true Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\..\bin\Win32-VisualStudio\ ..\..\..\bin\Win64-VisualStudio\ true true ..\..\..\bin\Win32-VisualStudio\ ..\..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ../../../include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib %(AdditionalOptions) ../../../bin/Win32-visualstudio/FontTool.exe ../../../lib/Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled ../../../include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib %(AdditionalOptions) ../../../bin/Win64-visualstudio/FontTool.exe ../../../lib/Win64-visualstudio;%(AdditionalLibraryDirectories) true Console MaxSpeed false ../../../include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib %(AdditionalOptions) ../../../bin/Win32-visualstudio/FontTool.exe ../../../lib/Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true MaxSpeed false ../../../include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib %(AdditionalOptions) ../../../bin/Win64-visualstudio/FontTool.exe ../../../lib/Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true {e08e042a-6c45-411b-92be-3cc31331019f} false irrlicht-1.8.3/tools/IrrFontTool/newFontTool/irrFontTool_vc11.vcxproj0000644000000000000000000003050212574354552024444 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 FontTool {4D53E40F-37E3-42B1-8848-F4C6F8313A17} Win32Proj Application MultiByte true Windows7.1SDK Application MultiByte true Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\..\bin\Win32-VisualStudio\ ..\..\..\bin\Win64-VisualStudio\ true true ..\..\..\bin\Win32-VisualStudio\ ..\..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ../../../include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib %(AdditionalOptions) ../../../bin/Win32-visualstudio/FontTool.exe ../../../lib/Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled ../../../include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib %(AdditionalOptions) ../../../bin/Win64-visualstudio/FontTool.exe ../../../lib/Win64-visualstudio;%(AdditionalLibraryDirectories) true Console MaxSpeed false ../../../include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib %(AdditionalOptions) ../../../bin/Win32-visualstudio/FontTool.exe ../../../lib/Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true MaxSpeed false ../../../include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib %(AdditionalOptions) ../../../bin/Win64-visualstudio/FontTool.exe ../../../lib/Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true {e08e042a-6c45-411b-92be-3cc31331019f} false irrlicht-1.8.3/tools/IrrFontTool/newFontTool/irrFontTool_vc11.sln0000644000000000000000000000157312574354552023553 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2012 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Font Tool", "irrFontTool_vc11.vcxproj", "{4D53E40F-37E3-42B1-8848-F4C6F8313A17}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.ActiveCfg = Debug|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.Build.0 = Debug|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.ActiveCfg = Release|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/tools/IrrFontTool/newFontTool/irrFontTool_vc10.vcxproj0000644000000000000000000003050212574354552024443 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 FontTool {4D53E40F-37E3-42B1-8848-F4C6F8313A17} Win32Proj Application MultiByte true Windows7.1SDK Application MultiByte true Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\..\bin\Win32-VisualStudio\ ..\..\..\bin\Win64-VisualStudio\ true true ..\..\..\bin\Win32-VisualStudio\ ..\..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ../../../include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib %(AdditionalOptions) ../../../bin/Win32-visualstudio/FontTool.exe ../../../lib/Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled ../../../include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib %(AdditionalOptions) ../../../bin/Win64-visualstudio/FontTool.exe ../../../lib/Win64-visualstudio;%(AdditionalLibraryDirectories) true Console MaxSpeed false ../../../include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib %(AdditionalOptions) ../../../bin/Win32-visualstudio/FontTool.exe ../../../lib/Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true MaxSpeed false ../../../include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib %(AdditionalOptions) ../../../bin/Win64-visualstudio/FontTool.exe ../../../lib/Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true {e08e042a-6c45-411b-92be-3cc31331019f} false irrlicht-1.8.3/tools/IrrFontTool/newFontTool/irrFontTool_vc10.sln0000644000000000000000000000157312574354552023552 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Font Tool", "irrFontTool_vc10.vcxproj", "{4D53E40F-37E3-42B1-8848-F4C6F8313A17}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.ActiveCfg = Debug|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.Build.0 = Debug|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.ActiveCfg = Release|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/tools/IrrFontTool/newFontTool/irrFontTool_v9.vcproj0000644000000000000000000001102412574354552024036 0ustar rootroot irrlicht-1.8.3/tools/IrrFontTool/newFontTool/irrFontTool_v9.sln0000644000000000000000000000157512574354552023341 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 10.00 # Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Font Tool", "irrFontTool_v9.vcproj", "{853A396E-C031-4C26-A716-5B4E176BE11D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.ActiveCfg = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.Build.0 = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.ActiveCfg = Release|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/tools/IrrFontTool/newFontTool/irrFontTool_v8.vcproj0000644000000000000000000001024412574354552024040 0ustar rootroot irrlicht-1.8.3/tools/IrrFontTool/newFontTool/irrFontTool_v8.sln0000644000000000000000000000157412574354552023337 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C++ Express 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Font Tool", "irrFontTool_v8.vcproj", "{853A396E-C031-4C26-A716-5B4E176BE11D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.ActiveCfg = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.Build.0 = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.ActiveCfg = Release|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/tools/IrrFontTool/newFontTool/CVectorFontTool.h0000644000000000000000000010066012574354552023122 0ustar rootroot/* Vector font tool - Gaz Davidson December 2006-2012 I noticed bitmap fonts were taking massive amounts of video memory at reasonable sizes, so I decided to make a vector font. I always wanted to try converting pixels to triangles... And I failed! This is a collection of the ugliest, bloated, most inneficient algorithms i've ever written, but its kinda working so I'm not changing it. */ #ifndef __VECTOR_FONT_TOOL_INCLUDED__ #define __VECTOR_FONT_TOOL_INCLUDED__ #include "irrlicht.h" #include "CFontTool.h" #include using namespace irr; using namespace video; struct STriangleList { core::array positions; core::array indexes; // for adding one triangle list to another, // these triangles share positions, but dont share triangles STriangleList& operator+=(STriangleList &other) { core::matrix4 m; core::array map; map.set_used(other.positions.size()); for (u32 i=0; i positions; bool isMember(s32 x, s32 y) { for (u32 i=0; i h1((f32)(positions[i-1].X - positions[i].X),(f32)(positions[i-1].Y - positions[i].Y)), h2((f32)(positions[i].X - positions[i+1].X),(f32)(positions[i].Y - positions[i+1].Y)); h1.normalize(); h2.normalize(); if (h1==h2) // erase the current point positions.erase(i--); } // level 1- if point1 points at point3, we can skip point2 // level 2+ allow a deviation of level-1 } }; // contains an array of lines for triangulation struct SLineList { core::array lines; SLineList() : lines() { } void addEdge(const SEdge &edge) { // adds lines to the buffer for (u32 i=1; i 0 && lb.getPointOrientation(l2.start) > 0 && lc.getPointOrientation(l2.start) > 0) return true; //if (la.getPointOrientation(l2.start) < 0 && // lb.getPointOrientation(l2.start) < 0 && // lc.getPointOrientation(l2.start) < 0) // return true; core::vector2df out; //if (la.intersectWith(l2,out)) // if (out != la.start && out != la.end && // out != l2.start && out != l2.end) // return true; if (lb.intersectWith(l2,out)) if (!out.equals(lb.start) && !out.equals(lb.end) && !out.equals(l2.start) && !out.equals(l2.end)) return true; if (lc.intersectWith(l2,out)) if (!out.equals(lc.start) && !out.equals(lc.end) && !out.equals(l2.start) && !out.equals(l2.end)) return true; // my shit intersection code only works with lines in certain directions :( if (l2.intersectWith(lb,out)) if (!out.equals(lb.start) && !out.equals(lb.end) && !out.equals(l2.start) && !out.equals(l2.end)) return true; if (l2.intersectWith(lc,out)) if (!out.equals(lc.start) && !out.equals(lc.end) && !out.equals(l2.start) && !out.equals(l2.end)) return true; if (lb.isPointOnLine(l2.start) && l2.start != lb.start && l2.start != lb.end) return true; if (lc.isPointOnLine(l2.start) && l2.start != lc.start && l2.start != lc.end) return true; } return false; } }; // an area of adjacent pixels struct SPixelGroup { SPixelGroup(IrrlichtDevice *device) : triangles(), pixelWidth(0), pixelHeight(0), Device(device) {} core::array pixels; core::array edges; STriangleList triangles; core::array ll; core::array isMemberCache; s32 pixelWidth; s32 pixelHeight; IrrlichtDevice *Device; void triangulate() { // find edges in this group makeEdges(); // triangulate the group makeTriangles(); } void drawTriangle( core::line2df line, core::vector2df point) { //const u32 endt = Device->getTimer()->getTime() + t; f32 scale = 5; //while(Device->getTimer()->getTime() < endt ) //{ Device->run(); Device->getVideoDriver()->beginScene(true,true,video::SColor(0,0,0,0)); for (u32 v=0;vgetVideoDriver()->draw2DLine(st,en, SColor(255,255,255,255)); } // draw this triangle const core::position2di st((s32)(line.start.X*scale)+50, (s32)(line.start.Y*scale)+50); const core::position2di en((s32)(line.end.X*scale)+50, (s32)(line.end.Y*scale)+50); const core::position2di p((s32)(point.X*scale)+50, (s32)(point.Y*scale)+50); Device->getVideoDriver()->draw2DLine(st,en, SColor(255,255,0,0)); Device->getVideoDriver()->draw2DLine(en,p, SColor(255,0,255,0)); Device->getVideoDriver()->draw2DLine(p,st, SColor(255,0,0,255)); Device->getVideoDriver()->endScene(); //} } void makeTriangles() { // make lines from edges, because they're easier to deal with ll.clear(); for (u32 i=0; i < edges.size(); ++i) { SLineList l; l.addEdge(edges[i]); ll.push_back(l); } // add an extra one for inside edges SLineList innerlines; ll.push_back(innerlines); // loop through each edge and make triangles for (u32 i=0; ibestScore) { bestScore = score; bestEdge = k; bestPoint = j; } } // hopefully we found one if (bestEdge >= 0 && bestPoint >= 0 && bestScore >= 0.0f) { //assert(bestEdge >= 0 && bestPoint >= 0); //assert(bestScore >= 0.0f); core::vector2df point(ll[bestEdge].lines[bestPoint].start.X, ll[bestEdge].lines[bestPoint].start.Y); // add it to the triangles list triangles.add(currentLine.start, currentLine.end, point); // add inner lines to the line buffer, but only if they arent in others core::line2df la(point,currentLine.start); core::line2df lb(currentLine.end,point); bool found = false; for (u32 lineno=0;lineno= 3); // all edges should be closed assert(edges[i].positions[0] == edges[i].positions[edges[i].positions.size()-1] ); } } // adds a line to the edges arrays void addToEdges(s32 x1, s32 y1, s32 x2, s32 y2) { bool found=false; // loop through each edge for (u32 i=0; ipixelWidth || y>pixelHeight || x<0 || y<0) return false; else return isMemberCache[pixelWidth*y + x]; } void refreshIsMemberCache() { isMemberCache.clear(); pixelWidth=0; pixelHeight=0; for (u32 i=0; ipixelWidth) pixelWidth=pixels[i].X; if (pixels[i].Y>pixelHeight) pixelHeight=pixels[i].Y; } pixelWidth+=2; pixelHeight+=2; isMemberCache.set_used(pixelWidth*pixelHeight+1); for (u32 i=0; igetTimer()->getTime(); const u32 endt = stt + t; while(device->getTimer()->getTime() < endt ) { const f32 phase = f32((device->getTimer()->getTime()-stt) % 500) / 500.0f; device->run(); device->getVideoDriver()->beginScene(true,true,video::SColor(0,0,0,0)); for (u32 g=0;ggetVideoDriver()->draw2DLine(st,en); device->getVideoDriver()->draw2DLine(st,ep,video::SColor(255,255,0,0) ); } device->getVideoDriver()->endScene(); } } void drawTriangles(IrrlichtDevice *device, u32 t, s32 scale) { const u32 stt = device->getTimer()->getTime(); const u32 endt = stt + t; while(device->getTimer()->getTime() < endt ) { const f32 phase = f32((device->getTimer()->getTime()-stt) % 500) / 500.0f; device->run(); device->getVideoDriver()->beginScene(true,true,video::SColor(0,0,0,0)); for (u32 g=0;ggetVideoDriver()->draw2DLine(st,en, SColor(255,255,0,0)); st = core::position2di((s32)(t.positions[t.indexes[v+1]].X*scale)+50,(s32)(t.positions[t.indexes[v+1]].Y*scale)+50); en = core::position2di((s32)(t.positions[t.indexes[v+2]].X*scale)+50,(s32)(t.positions[t.indexes[v+2]].Y*scale)+50); device->getVideoDriver()->draw2DLine(st,en, SColor(255,0,255,0)); st = core::position2di((s32)(t.positions[t.indexes[v+2]].X*scale)+50,(s32)(t.positions[t.indexes[v+2]].Y*scale)+50); en = core::position2di((s32)(t.positions[t.indexes[v+0]].X*scale)+50,(s32)(t.positions[t.indexes[v+0]].Y*scale)+50); device->getVideoDriver()->draw2DLine(st,en, SColor(255,0,0,255)); } device->getVideoDriver()->endScene(); } } void drawTriLines(IrrlichtDevice *device, u32 t, s32 scale) { const u32 endt = device->getTimer()->getTime() + t; while(device->getTimer()->getTime() < endt ) { device->run(); device->getVideoDriver()->beginScene(true,true,video::SColor(0,0,0,0)); for (u32 g=0;ggetVideoDriver()->draw2DLine(st,en, SColor(255,255,0,0)); } device->getVideoDriver()->endScene(); } } void drawTri3D(IrrlichtDevice *device, u32 t) { for (u32 g=0;g verts; verts.clear(); for(u32 v=0; v< t.positions.size(); ++v) { verts.push_back(S3DVertex( -t.positions[v].X, -t.positions[v].Y, -100, 0,0,1,SColor(255,255,255,255),0,0)); } device->getVideoDriver()->drawIndexedTriangleList(verts.pointer(),verts.size(),t.indexes.pointer(), t.indexes.size()/3 ); } } // process all pixels void findGroups() { for (int y=0; y0) // look one behind { grp = getRef(x-1,y); if (grp) found=true; } if (y>0) // look above { if (x>0) // top left { g = getRef(x-1,y-1); if (g) { if (found) { mergeGroups(grp, g); } else { grp = g; found = true; } } } if (x groups; core::array groupRefs; core::array refbuffer; bool *mem; IrrlichtDevice *Device; }; // creates a simple vector font from a bitmap from the font tool class CVectorFontTool { public: CVectorFontTool(CFontTool *fonttool) : triangulator(0), FontTool(fonttool), letterHeight(0), letterWidth(0), triangles() { core::map::Iterator it = FontTool->CharMap.getIterator(); while(!it.atEnd()) { CFontTool::SFontArea &fa = FontTool->Areas[(*it).getValue()]; if (fa.rectangle.getWidth() > letterWidth) letterWidth = fa.rectangle.getWidth(); if (fa.rectangle.getHeight() > letterHeight) letterHeight = fa.rectangle.getHeight(); it++; } // number of verts is one more than number of pixels because it's a grid of squares letterWidth++; letterHeight++; // create image memory imagedata.set_used(letterWidth*letterHeight); // create vertex list, set position etc verts.set_used(letterWidth*letterHeight); for (s32 y=0; yCharMap.getIterator(); while(!it.atEnd()) { addChar((*it).getKey()); it++; } } ~CVectorFontTool() { if (triangulator) delete triangulator; } void addChar(wchar_t thischar) { const s32 area = FontTool->CharMap[thischar]; const CFontTool::SFontArea &fa = FontTool->Areas[area]; const s32 img = fa.sourceimage; const core::rect& r = fa.rectangle; // init image memory IImage *image = FontTool->currentImages[img]; for (u32 i=0; i < imagedata.size(); ++i) imagedata[i] = false; for (s32 y=r.UpperLeftCorner.Y; y < r.LowerRightCorner.Y; ++y) { for (s32 x=r.UpperLeftCorner.X; x < r.LowerRightCorner.X ; ++x) if (image->getPixel(x,y).getBlue() > 0) { imagedata[letterWidth*(y-r.UpperLeftCorner.Y) +(x-r.UpperLeftCorner.X)] = true; } } // get shape areas triangulator = new CGroupFinder(imagedata.pointer(), letterWidth, letterHeight, FontTool->Device ); wprintf(L"Created character '%c' in texture %d\n", thischar, img ); //floodfill->drawEdges(FontTool->Device, 500, 3); //floodfill->drawTriangles(FontTool->Device, 500,30); //floodfill->drawTriLines(FontTool->Device, 200,3); /* if (area==32 && map == 0) { scene::ISceneManager *smgr = FontTool->Device->getSceneManager(); smgr->addCameraSceneNodeFPS(); while(FontTool->Device->run()) { //floodfill->drawEdges(FontTool->Device, 100, 30); FontTool->Device->getVideoDriver()->beginScene(true, true, video::SColor(0,200,200,200)); smgr->drawAll(); floodfill->drawTri3D(FontTool->Device, 100); FontTool->Device->getVideoDriver()->endScene(); } }*/ u32 lastind = triangles.indexes.size(); // loop through each shape and add it to the current character... for (u32 i=0; i < triangulator->groups.size(); ++i) triangles += triangulator->groups[i].triangles; // add character details charstarts.push_back(lastind); charlengths.push_back(triangles.indexes.size() - lastind); chars.push_back(thischar); } bool saveVectorFont(const c8 *filename, const c8 *formatname) { IrrlichtDevice *Device = FontTool->Device; if (triangles.indexes.size() == 0) { Device->getLogger()->log("No vector data to write, aborting."); return false; } core::stringc fn = filename; if (core::stringc(formatname) == core::stringc("xml")) { fn += ".xml"; io::IXMLWriter *writer = FontTool->Device->getFileSystem()->createXMLWriter(fn.c_str()); // header and line breaks writer->writeXMLHeader(); writer->writeLineBreak(); // write info header writer->writeElement(L"font", false, L"type", L"vector"); writer->writeLineBreak(); writer->writeLineBreak(); // write each letter for (u32 n=0; nCharMap[chars[n]]; CFontTool::SFontArea &fa = FontTool->Areas[i]; wchar_t c[2]; c[0] = chars[n]; c[1] = L'\0'; core::stringw area, under, over; area = core::stringw(fa.rectangle.LowerRightCorner.X- fa.rectangle.UpperLeftCorner.X); area += L", "; area += fa.rectangle.LowerRightCorner.Y- fa.rectangle.UpperLeftCorner.Y; core::array names; core::array values; names.clear(); values.clear(); // char names.push_back(core::stringw(L"c")); values.push_back(core::stringw(c)); // width+height names.push_back(core::stringw(L"wh")); values.push_back(area); // start names.push_back(core::stringw(L"st")); values.push_back(core::stringw(charstarts[n])); // length names.push_back(core::stringw(L"len")); values.push_back(core::stringw(charlengths[n])); if (fa.underhang != 0) { under = core::stringw(fa.underhang); names.push_back(core::stringw(L"u")); values.push_back(under); } if (fa.overhang != 0) { over = core::stringw(fa.overhang); names.push_back(core::stringw(L"o")); values.push_back(over); } writer->writeElement(L"c", true, names, values); writer->writeLineBreak(); } // write vertex data core::stringw data, count; data = L""; count = core::stringw(triangles.positions.size()); for (u32 i=0; iwriteElement(L"Vertices", true, L"count", count.c_str(), L"data", data.c_str()); writer->writeLineBreak(); // write index list data = L""; count = core::stringw(triangles.indexes.size()); for (u32 i=0; iwriteElement(L"Indices", true, L"count", count.c_str(), L"data", data.c_str()); writer->writeLineBreak(); writer->writeClosingTag(L"font"); writer->drop(); Device->getLogger()->log("Font saved."); return true; } else if (core::stringc(formatname) == core::stringc("bin")) { FontTool->Device->getLogger()->log("binary fonts not supported yet, sorry"); return false; } else { FontTool->Device->getLogger()->log("unsupported file format, unable to save vector font"); return false; } } S3DVertex& getVert(s32 x, s32 y) { return verts[letterWidth*y +x]; } core::array verts; core::array inds; core::array imagedata; core::array charstarts; // start position of each char core::array charlengths; // index count core::array chars; // letters CGroupFinder* triangulator; CFontTool* FontTool; s32 letterHeight; s32 letterWidth; STriangleList triangles; }; #endif // __VECTOR_FONT_TOOL_INCLUDED__ irrlicht-1.8.3/tools/IrrFontTool/newFontTool/CFontTool.h0000644000000000000000000000316712574354552021743 0ustar rootroot#ifndef __IRR_FONT_TOOL_INCLUDED__ #define __IRR_FONT_TOOL_INCLUDED__ #include "irrlicht.h" #if defined(_IRR_WINDOWS_) #ifdef _MBCS #undef _MBCS #endif #define UNICODE #define _WIN32_WINNT 0x0500 #include "windows.h" #else #ifdef _IRR_COMPILE_WITH_X11_ #include #endif #include #include #endif namespace irr { class CFontTool : public irr::IReferenceCounted { public: CFontTool(irr::IrrlichtDevice* device); ~CFontTool(); virtual bool makeBitmapFont(u32 fontIndex, u32 charsetIndex, s32 fontSize, u32 texturewidth, u32 textureHeight, bool bold, bool italic, bool aa, bool alpha); virtual bool saveBitmapFont(const c8* filename, const c8* format); virtual void selectCharSet(u32 currentCharSet); struct SFontArea { SFontArea() : rectangle(), underhang(0), overhang(0), sourceimage(0) {} core::rect rectangle; s32 underhang; s32 overhang; u32 sourceimage; }; /* struct SFontMap { SFontMap() : areas(), start(0), count(0) {} core::array< SFontArea > areas; s32 start; s32 count; };*/ core::array FontNames; core::array CharSets; //core::array Mappings; core::array Areas; core::map CharMap; core::array currentTextures; core::array currentImages; const int *FontSizes; IrrlichtDevice *Device; bool UseAlphaChannel; // windows #ifdef _IRR_WINDOWS_ HDC dc; #endif }; } #endif // __IRR_FONT_TOOL_INCLUDED__ irrlicht-1.8.3/tools/IrrFontTool/newFontTool/CFontTool.cpp0000644000000000000000000006341212574354552022275 0ustar rootroot#include "CFontTool.h" #include "IXMLWriter.h" using namespace irr; const int fontsizes[] = {4,6,8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,56,68,72,0}; inline u32 getTextureSizeFromSurfaceSize(u32 size) { u32 ts = 0x01; while(ts < size) ts <<= 1; return ts; } // windows specific #ifdef _IRR_WINDOWS_ const DWORD charsets[] = { ANSI_CHARSET, DEFAULT_CHARSET, OEM_CHARSET, BALTIC_CHARSET, GB2312_CHARSET, CHINESEBIG5_CHARSET, EASTEUROPE_CHARSET, GREEK_CHARSET, HANGUL_CHARSET, MAC_CHARSET, RUSSIAN_CHARSET, SHIFTJIS_CHARSET, SYMBOL_CHARSET, TURKISH_CHARSET, VIETNAMESE_CHARSET, JOHAB_CHARSET, ARABIC_CHARSET, HEBREW_CHARSET, THAI_CHARSET, 0}; const wchar_t *setnames[] = {L"ANSI", L"All Available", L"OEM", L"Baltic", L"Chinese Simplified", L"Chinese Traditional", L"Eastern European", L"Greek", L"Hangul", L"Macintosh", L"Russian", L"Japanese", L"Symbol", L"Turkish", L"Vietnamese", L"Johab", L"Arabic", L"Hebrew", L"Thai", 0}; // callback for adding font names int CALLBACK EnumFontFamExProc( ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme, DWORD FontType, LPARAM lParam) { CFontTool* t = (CFontTool*) lParam; t->FontNames.push_back( core::stringw(lpelfe->elfFullName)); return 1; } // // Constructor // CFontTool::CFontTool(IrrlichtDevice* device) : FontSizes(fontsizes), Device(device), UseAlphaChannel(false), // win specific dc(0) { // init display context dc = CreateDC(L"DISPLAY", L"DISPLAY", 0 ,0 ); // populate list of available character set names for (int i=0; setnames[i] != 0; ++i) CharSets.push_back( core::stringw(setnames[i])); selectCharSet(0); } void CFontTool::selectCharSet(u32 currentCharSet) { if ( currentCharSet >= CharSets.size() ) return; LOGFONTW lf; lf.lfFaceName[0] = L'\0'; lf.lfCharSet = (BYTE) charsets[currentCharSet]; // HRESULT hr; // no error checking(!) // clear font list FontNames.clear(); // create list of available fonts EnumFontFamiliesExW( dc, (LPLOGFONTW) &lf, (FONTENUMPROCW) EnumFontFamExProc, (LPARAM) this, 0); } bool CFontTool::makeBitmapFont(u32 fontIndex, u32 charsetIndex, s32 fontSize, u32 textureWidth, u32 textureHeight, bool bold, bool italic, bool aa, bool alpha) { if (fontIndex >= FontNames.size() || charsetIndex >= CharSets.size() ) return false; UseAlphaChannel = alpha; u32 currentImage = 0; // create the font HFONT font = CreateFontW( -MulDiv(fontSize, GetDeviceCaps(dc, LOGPIXELSY), 72), 0, 0,0, bold ? FW_BOLD : 0, italic, 0,0, charsets[charsetIndex], 0,0, aa ? ANTIALIASED_QUALITY : 0, 0, FontNames[fontIndex].c_str() ); if (!font) return false; SelectObject(dc, font); SetTextAlign (dc,TA_LEFT | TA_TOP | TA_NOUPDATECP); // get rid of the current textures/images for (u32 i=0; idrop(); currentTextures.clear(); for (u32 i=0; idrop(); currentImages.clear(); // clear current image mappings CharMap.clear(); // clear array Areas.clear(); // get information about this font's unicode ranges. s32 size = GetFontUnicodeRanges( dc, 0); c8 *buf = new c8[size]; LPGLYPHSET glyphs = (LPGLYPHSET)buf; GetFontUnicodeRanges( dc, glyphs); // s32 TotalCharCount = glyphs->cGlyphsSupported; s32 currentx=0, currenty=0, maxy=0; for (u32 range=0; range < glyphs->cRanges; range++) { WCRANGE* current = &glyphs->ranges[range]; //maxy=0; // loop through each glyph and write its size and position for (s32 ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++) { wchar_t currentchar = ch; if ( IsDBCSLeadByte((BYTE) ch)) continue; // surragate pairs unsupported // get the dimensions SIZE size; ABC abc; GetTextExtentPoint32W(dc, ¤tchar, 1, &size); SFontArea fa; fa.underhang = 0; fa.overhang = 0; if (GetCharABCWidthsW(dc, currentchar, currentchar, &abc)) // for unicode fonts, get overhang, underhang, width { size.cx = abc.abcB; fa.underhang = abc.abcA; fa.overhang = abc.abcC; if (abc.abcB-abc.abcA+abc.abcC<1) continue; // nothing of width 0 } if (size.cy < 1) continue; //GetGlyphOutline(dc, currentchar, GGO_METRICS, &gm, 0, 0, 0); //size.cx++; size.cy++; // wrap around? if (currentx + size.cx > (s32) textureWidth) { currenty += maxy; currentx = 0; if ((u32)(currenty + maxy) > textureHeight) { currentImage++; // increase Image count currenty=0; } maxy = 0; } // add this char dimension to the current map fa.rectangle = core::rect(currentx, currenty, currentx + size.cx, currenty + size.cy); fa.sourceimage = currentImage; CharMap.insert(currentchar, Areas.size()); Areas.push_back( fa ); currentx += size.cx +1; if (size.cy+1 > maxy) maxy = size.cy+1; } } currenty += maxy; u32 lastTextureHeight = getTextureSizeFromSurfaceSize(currenty); // delete the glyph set delete [] buf; currentImages.set_used(currentImage+1); currentTextures.set_used(currentImage+1); for (currentImage=0; currentImage < currentImages.size(); ++currentImage) { core::stringc logmsg = "Creating image "; logmsg += (s32) (currentImage+1); logmsg += " of "; logmsg += (s32) currentImages.size(); Device->getLogger()->log(logmsg.c_str()); // no need for a huge final texture u32 texHeight = textureHeight; if (currentImage == currentImages.size()-1 ) texHeight = lastTextureHeight; // make a new bitmap HBITMAP bmp = CreateCompatibleBitmap(dc, textureWidth, texHeight); HDC bmpdc = CreateCompatibleDC(dc); LOGBRUSH lbrush; lbrush.lbColor = RGB(0,0,0); lbrush.lbHatch = 0; lbrush.lbStyle = BS_SOLID; HBRUSH brush = CreateBrushIndirect(&lbrush); HPEN pen = CreatePen(PS_NULL, 0, 0); HGDIOBJ oldbmp = SelectObject(bmpdc, bmp); HGDIOBJ oldbmppen = SelectObject(bmpdc, pen); HGDIOBJ oldbmpbrush = SelectObject(bmpdc, brush); HGDIOBJ oldbmpfont = SelectObject(bmpdc, font); SetTextColor(bmpdc, RGB(255,255,255)); Rectangle(bmpdc, 0,0,textureWidth,texHeight); SetBkMode(bmpdc, TRANSPARENT); // draw the letters... // iterate through the tree core::map::Iterator it = CharMap.getIterator(); while (!it.atEnd()) { s32 currentArea = (*it).getValue(); wchar_t wch = (*it).getKey(); // sloppy but I couldnt be bothered rewriting it if (Areas[currentArea].sourceimage == currentImage) { // draw letter s32 sx = Areas[currentArea].rectangle.UpperLeftCorner.X - Areas[currentArea].underhang; TextOutW(bmpdc, sx, Areas[currentArea].rectangle.UpperLeftCorner.Y, &wch, 1); // if ascii font... //SetPixel(bmpdc, Areas[currentArea].rectangle.UpperLeftCorner.X, Areas[currentArea].rectangle.UpperLeftCorner.Y, RGB(255,255,0));// left upper corner mark } it++; } // copy the font bitmap into a new irrlicht image BITMAP b; PBITMAPINFO pbmi; WORD cClrBits; u32 cformat; // Retrieve the bitmap color format, width, and height. GetObject(bmp, sizeof(BITMAP), (LPSTR)&b); // Convert the color format to a count of bits. cClrBits = (WORD)(b.bmPlanes * b.bmBitsPixel); if (cClrBits <= 8) // we're not supporting these cformat = -1; else if (cClrBits <= 16) cformat = video::ECF_A1R5G5B5; else if (cClrBits <= 24) cformat = video::ECF_R8G8B8; else cformat = video::ECF_A8R8G8B8; pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER)); // Initialize the fields in the BITMAPINFO structure. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = b.bmWidth; pbmi->bmiHeader.biHeight = b.bmHeight; pbmi->bmiHeader.biPlanes = b.bmPlanes; pbmi->bmiHeader.biBitCount = b.bmBitsPixel; // If the bitmap is not compressed, set the BI_RGB flag. pbmi->bmiHeader.biCompression = BI_RGB; // Compute the number of bytes in the array of color // indices and store the result in biSizeImage. // For Windows NT, the width must be DWORD aligned unless // the bitmap is RLE compressed. This example shows this. // For Windows 95/98/Me, the width must be WORD aligned unless the // bitmap is RLE compressed. pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 * pbmi->bmiHeader.biHeight; // Set biClrImportant to 0, indicating that all of the // device colors are important. pbmi->bmiHeader.biClrImportant = 0; LPBYTE lpBits; // memory pointer PBITMAPINFOHEADER pbih = (PBITMAPINFOHEADER) pbmi; lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); GetDIBits(dc, bmp, 0, (WORD) pbih->biHeight, lpBits, pbmi, DIB_RGB_COLORS); // DEBUG- copy to clipboard //OpenClipboard(hWnd); //EmptyClipboard(); //SetClipboardData(CF_BITMAP, bmp); //CloseClipboard(); // flip bitmap s32 rowsize = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8; c8 *row = new c8[rowsize]; for (s32 i=0; i < (pbih->biHeight/2); ++i) { // grab a row memcpy(row, lpBits + (rowsize * i), rowsize); // swap row memcpy(lpBits + (rowsize * i), lpBits + ((pbih->biHeight-1 -i) * rowsize ) , rowsize); memcpy(lpBits + ((pbih->biHeight-1 -i) * rowsize ), row , rowsize); } bool ret = false; if (cformat == video::ECF_A8R8G8B8) { // in this case the font should have an alpha channel, but since windows doesn't draw one // we have to set one manually by going through all the pixels.. *sigh* u8* m; for (m = lpBits; m < lpBits + pbih->biSizeImage; m+=4) { if (UseAlphaChannel) { if (m[0] > 0) // pixel has colour { m[3]=m[0]; // set alpha m[0]=m[1]=m[2] = 255; // everything else is full } } else m[3]=255; // all pixels are full alpha } } else if (cformat == video::ECF_A1R5G5B5) { u8* m; for (m = lpBits; m < lpBits + pbih->biSizeImage; m+=2) { WORD *p = (WORD*)m; if (m[0] > 0 || !UseAlphaChannel) // alpha should be set *p |= 0x8000; // set alpha bit } } else { cformat = -1; } // make a texture from the image if (cformat != -1) { // turn mip-mapping off bool b = Device->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); currentImages[currentImage] = Device->getVideoDriver()->createImageFromData((video::ECOLOR_FORMAT)cformat, core::dimension2d(textureWidth,texHeight), (void*)lpBits); Device->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS,b); } else { Device->getLogger()->log("Couldn't create font, your pixel format is unsupported."); } // free memory and windows resources // sloppy I know, but I only intended to create one image at first. delete [] row; LocalFree(pbmi); GlobalFree(lpBits); DeleteDC(bmpdc); DeleteObject(brush); DeleteObject(pen); DeleteObject(bmp); if (currentImages[currentImage]) { // add texture currentTextures[currentImage] = Device->getVideoDriver()->addTexture("GUIFontImage",currentImages[currentImage]); currentTextures[currentImage]->grab(); } else { Device->getLogger()->log("Something went wrong, aborting."); // drop all images DeleteObject(font); return false; } } // looping through each texture DeleteObject(font); return true; } #else CFontTool::CFontTool(IrrlichtDevice *device) : FontSizes(fontsizes), Device(device), UseAlphaChannel(false) { if (!XftInitFtLibrary()) { core::stringc logmsg = "XFT not found\n"; Device->getLogger()->log(logmsg.c_str()); exit(EXIT_FAILURE); } /* Get a list of the font foundries, storing them in a set to sort */ std::set foundries; Display* display = (Display*)Device->getVideoDriver()->getExposedVideoData().OpenGLLinux.X11Display; XftFontSet* fonts = XftListFonts(display, DefaultScreen(display), 0, XFT_FOUNDRY, 0); for (int i = 0; i < fonts->nfont; i++) { char *foundry; XftPatternGetString(fonts->fonts[i], XFT_FOUNDRY, 0, &foundry); core::stringw tmp(foundry); foundries.insert(tmp); } XftFontSetDestroy(fonts); /* Copy the sorted list into the array */ CharSets.clear(); for (std::set::iterator i = foundries.begin(); i != foundries.end(); i++) CharSets.push_back((*i).c_str()); selectCharSet(0); } /* Note: There must be some trick for using strings as pattern parameters to XftListFonts because no matter how I specify a string, I end up with an intermittent segfault. Since XftFontList is just calling FcFontList, that's what I'll do too since that works OK */ void CFontTool::selectCharSet(u32 currentCharSet) { /* Get a list of the font families, storing them in a set to sort */ char foundry[256]; sprintf(&foundry[0],"%ls",CharSets[currentCharSet].c_str()); std::set families; XftPattern *pattern = FcPatternCreate(); XftPatternAddString(pattern, FC_FOUNDRY, &foundry[0]); XftObjectSet *objectset = FcObjectSetCreate(); XftObjectSetAdd(objectset, XFT_FOUNDRY); XftObjectSetAdd(objectset, XFT_FAMILY); FcFontSet *fonts = FcFontList(NULL, pattern, objectset); for (int i = 0; i < fonts->nfont; i++) { char* ptr; XftPatternGetString(fonts->fonts[i], XFT_FAMILY, 0, &ptr); core::stringw family(ptr); families.insert(family); } XftPatternDestroy(pattern); FcObjectSetDestroy(objectset); /* Copy the sorted list into the array */ FontNames.clear(); for (std::set::iterator i = families.begin(); i != families.end(); i++) FontNames.push_back((*i).c_str()); } bool CFontTool::makeBitmapFont(u32 fontIndex, u32 charsetIndex, s32 fontSize, u32 textureWidth, u32 textureHeight, bool bold, bool italic, bool aa, bool alpha) { if (fontIndex >= FontNames.size() || charsetIndex >= CharSets.size() ) return false; Display *display = (Display*) Device->getVideoDriver()->getExposedVideoData().OpenGLLinux.X11Display; u32 screen = DefaultScreen(display); Window win = RootWindow(display, screen); Visual *visual = DefaultVisual(display, screen); UseAlphaChannel = alpha; u32 currentImage = 0; XftResult result; XftPattern *request = XftPatternCreate(); char foundry[256], family[256]; sprintf(&foundry[0],"%ls",CharSets[charsetIndex].c_str()); sprintf(&family[0],"%ls",FontNames[fontIndex].c_str()); XftPatternAddString(request, XFT_FOUNDRY, &foundry[0]); XftPatternAddString(request, XFT_FAMILY, &family[0]); XftPatternAddInteger(request, XFT_PIXEL_SIZE, fontSize); XftPatternAddInteger(request, XFT_WEIGHT, bold ? XFT_WEIGHT_BLACK : XFT_WEIGHT_LIGHT); XftPatternAddInteger(request, XFT_SLANT, italic ? XFT_SLANT_ITALIC : XFT_SLANT_ROMAN); XftPatternAddBool(request, XFT_ANTIALIAS, aa); /* Find the closest font that matches the user choices and open it and check if the returned font has anti aliasing enabled by default, even if it wasn't requested */ FcBool aaEnabled; XftPattern *found = XftFontMatch(display, DefaultScreen(display), request, &result); XftPatternGetBool(found, XFT_ANTIALIAS, 0, &aaEnabled); aa = aaEnabled; XftFont *font = XftFontOpenPattern(display, found); // get rid of the current textures/images for (u32 i=0; idrop(); currentTextures.clear(); for (u32 i=0; idrop(); currentImages.clear(); CharMap.clear(); Areas.clear(); /* Calculate the max height of the font. Annoyingly, it seems that the height property of the font is the maximum height of any single character, but a string of characters, aligned along their baselines, can exceed this figure. Because I don't know any better way of doing it, I'm going to have to use the brute force method. Note: There will be a certain number of charters in a font, however they may not be grouped consecutively, and could in fact be spread out with many gaps */ u32 maxY = 0; u32 charsFound = 0; for (FT_UInt charCode = 0; charsFound < FcCharSetCount(font->charset); charCode++) { if (!XftCharExists(display, font, charCode)) continue; charsFound++; XGlyphInfo extents; XftTextExtents32(display, font, &charCode, 1, &extents); if ((extents.xOff <= 0) && (extents.height <= 0)) continue; /* Calculate the width and height, adding 1 extra pixel if anti aliasing is enabled */ u32 chWidth = extents.xOff + (aa ? 1 : 0); u32 chHeight = (font->ascent - extents.y + extents.height) + (aa ? 1 : 0); if (chHeight > maxY) maxY = chHeight; /* Store the character details here */ SFontArea fontArea; fontArea.rectangle = core::rect(0, 0, chWidth, chHeight); CharMap.insert(charCode, Areas.size()); Areas.push_back(fontArea); } core::stringc logmsg = "Found "; logmsg += (s32) (CharMap.size() + 1); logmsg += " characters"; Device->getLogger()->log(logmsg.c_str()); /* Get the size of the chars and allocate them a position on a texture. If the next character that is added would be outside the width or height of the texture, then a new texture is added */ u32 currentX = 0, currentY = 0, rowY = 0; for (core::map::Iterator it = CharMap.getIterator(); !it.atEnd(); it++) { s32 currentArea = (*it).getValue(); SFontArea *fontArea = &Areas[currentArea]; u32 chWidth = fontArea->rectangle.LowerRightCorner.X; u32 chHeight = fontArea->rectangle.LowerRightCorner.Y; /* If the width of this char will exceed the textureWidth then start a new row */ if ((currentX + chWidth) > textureWidth) { currentY += rowY; currentX = 0; /* If the new row added to the texture exceeds the textureHeight then start a new texture */ if ((currentY + rowY) > textureHeight) { currentImage++; currentY = 0; } rowY = 0; } /* Update the area with the current x and y and texture */ fontArea->rectangle = core::rect(currentX, currentY, currentX + chWidth, currentY + chHeight); fontArea->sourceimage = currentImage; currentX += chWidth + 1; if (chHeight + 1 > rowY) rowY = chHeight + 1; } /* The last row of chars and the last texture weren't accounted for in the loop, so add them here */ currentY += rowY; u32 lastTextureHeight = getTextureSizeFromSurfaceSize(currentY); currentImages.set_used(currentImage + 1); currentTextures.set_used(currentImage + 1); /* Initialise colours */ XftColor colFore, colBack; XRenderColor xFore = {0xffff, 0xffff, 0xffff, 0xffff}; XRenderColor xBack = {0x0000, 0x0000, 0x0000, 0xffff}; XftColorAllocValue(display, DefaultVisual(display, screen), DefaultColormap(display, screen), &xFore, &colFore); XftColorAllocValue(display, DefaultVisual(display, screen), DefaultColormap(display, screen), &xBack, &colBack); /* Create a pixmap that is large enough to hold any character in the font */ Pixmap pixmap = XCreatePixmap(display, win, textureWidth, maxY, DefaultDepth(display, screen)); XftDraw *draw = XftDrawCreate(display, pixmap, visual, DefaultColormap(display, screen)); /* Render the chars */ for (currentImage = 0; currentImage < currentImages.size(); ++currentImage) { core::stringc logmsg = "Creating image "; logmsg += (s32) (currentImage+1); logmsg += " of "; logmsg += (s32) currentImages.size(); Device->getLogger()->log(logmsg.c_str()); /* The last texture that is saved is vertically shrunk to fit the characters drawn on it */ u32 texHeight = textureHeight; if (currentImage == currentImages.size() - 1) texHeight = lastTextureHeight; /* The texture that holds this "page" of characters */ currentImages[currentImage] = Device->getVideoDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(textureWidth, texHeight)); currentImages[currentImage]->fill(video::SColor(alpha ? 0 : 255,0,0,0)); for (core::map::Iterator it = CharMap.getIterator(); !it.atEnd(); it++) { FcChar32 wch = (*it).getKey(); s32 currentArea = (*it).getValue(); if (Areas[currentArea].sourceimage == currentImage) { SFontArea *fontArea = &Areas[currentArea]; u32 chWidth = fontArea->rectangle.LowerRightCorner.X - fontArea->rectangle.UpperLeftCorner.X; u32 chHeight = fontArea->rectangle.LowerRightCorner.Y - fontArea->rectangle.UpperLeftCorner.Y; /* Draw the glyph onto the pixmap */ XGlyphInfo extents; XftDrawRect(draw, &colBack, 0, 0, chWidth, chHeight); XftTextExtents32(display, font, &wch, 1, &extents); XftDrawString32(draw, &colFore, font, extents.x, extents.y, &wch, 1); /* Convert the pixmap into an image, then copy it onto the Irrlicht texture, pixel by pixel. There's bound to be a faster way, but this is adequate */ u32 xDest = fontArea->rectangle.UpperLeftCorner.X; u32 yDest = fontArea->rectangle.UpperLeftCorner.Y + font->ascent - extents.y; XImage *image = XGetImage(display, pixmap, 0, 0, chWidth, chHeight, 0xffffff, XYPixmap); if (image) { for (u32 ySrc = 0; ySrc < chHeight; ySrc++) for (u32 xSrc = 0; xSrc < chWidth; xSrc++) { /* Get the pixel colour and break it down into rgb components */ u32 col = XGetPixel(image, xSrc, ySrc); u32 a = 255; u32 r = col & visual->red_mask; u32 g = col & visual->green_mask; u32 b = col & visual->blue_mask; while (r > 0xff) r >>= 8; while (g > 0xff) g >>= 8; while (b > 0xff) b >>= 8; /* To make the background transparent, set the colour to 100% white and the alpha to the average of the three rgb colour components to maintain the anti-aliasing */ if (alpha) { a = (r + g + b) / 3; r = 255; g = 255; b = 255; } currentImages[currentImage]->setPixel(xDest + xSrc,yDest + ySrc,video::SColor(a,r,g,b)); } image->f.destroy_image(image); } } } /* Add the texture to the list */ currentTextures[currentImage] = Device->getVideoDriver()->addTexture("GUIFontImage",currentImages[currentImage]); currentTextures[currentImage]->grab(); } XftColorFree (display, visual, DefaultColormap(display, screen), &colFore); XftColorFree (display, visual, DefaultColormap(display, screen), &colBack); XftFontClose(display,font); XftPatternDestroy(request); XftDrawDestroy(draw); XFreePixmap(display, pixmap); return true; } #endif CFontTool::~CFontTool() { #ifdef _IRR_WINDOWS_ // destroy display context if (dc) DeleteDC(dc); #endif // drop textures+images for (u32 i=0; idrop(); currentTextures.clear(); for (u32 i=0; idrop(); currentImages.clear(); } bool CFontTool::saveBitmapFont(const c8 *filename, const c8* format) { if (currentImages.size() == 0) { Device->getLogger()->log("No image data to write, aborting."); return false; } core::stringc fn = filename; core::stringc imagename = filename; fn += ".xml"; io::IXMLWriter *writer = Device->getFileSystem()->createXMLWriter(fn.c_str()); // header and line breaks writer->writeXMLHeader(); writer->writeLineBreak(); // write information writer->writeElement(L"font", false, L"type", L"bitmap"); writer->writeLineBreak(); writer->writeLineBreak(); // write images and link to them for (u32 i=0; igetVideoDriver()->writeImageToFile(currentImages[i],imagename.c_str()); writer->writeElement(L"Texture", true, L"index", core::stringw(i).c_str(), L"filename", core::stringw(imagename.c_str()).c_str(), L"hasAlpha", UseAlphaChannel ? L"true" : L"false"); writer->writeLineBreak(); } writer->writeLineBreak(); // write each character core::map::Iterator it = CharMap.getIterator(); while (!it.atEnd()) { SFontArea &fa = Areas[(*it).getValue()]; wchar_t c[2]; c[0] = (*it).getKey(); c[1] = L'\0'; core::stringw area, under, over, image; area = core::stringw(fa.rectangle.UpperLeftCorner.X); area += L", "; area += fa.rectangle.UpperLeftCorner.Y; area += L", "; area += fa.rectangle.LowerRightCorner.X; area += L", "; area += fa.rectangle.LowerRightCorner.Y; core::array names; core::array values; names.clear(); values.clear(); // char names.push_back(core::stringw(L"c")); values.push_back(core::stringw(c)); // image number if (fa.sourceimage != 0) { image = core::stringw(fa.sourceimage); names.push_back(core::stringw(L"i")); values.push_back(image); } // rectangle names.push_back(core::stringw(L"r")); values.push_back(area); if (fa.underhang != 0) { under = core::stringw(fa.underhang); names.push_back(core::stringw(L"u")); values.push_back(under); } if (fa.overhang != 0) { over = core::stringw(fa.overhang); names.push_back(core::stringw(L"o")); values.push_back(over); } writer->writeElement(L"c", true, names, values); writer->writeLineBreak(); it++; } writer->writeClosingTag(L"font"); writer->drop(); Device->getLogger()->log("Bitmap font saved."); return true; } irrlicht-1.8.3/tools/irrEdit/0000755000000000000000000000000012574354552014617 5ustar rootrootirrlicht-1.8.3/tools/irrEdit/irrEdit.txt0000644000000000000000000000077212574354552016770 0ustar rootrootirrEdit is a free scene graph editor for Irrlicht Engine .irr files and is capable as being used as world editor, particle system designer, meshviewer and more. It is a visual front end for the Irrlicht Engine, and thus has a lot of impressive features like importing meshes of every format Irrlicht supports, simple but powerful material system and lots of special effects. For package size reasons, irrEdit is not included in this SDK, but you can download it from http://www.ambiera.com/irreditirrlicht-1.8.3/tools/irrEdit/irrEdit.jpg0000644000000000000000000012120212574354552016721 0ustar rootrootÿØÿàJFIFHHÿÛC     ÿÛC  ÿÀ¸þ"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ê|Iû+|~ø¿y?“öxðdv:e­¥ÅŸ…>"éö6–æÊÉ#¬rò‰QNìg` Æ6òÞ+ý¿h½wá–›âᾕ£Y‹–x©~.XIãყÍ2ĘpÇî„Ç&¿[†¡á/ Zköo P³ƒDšò-*ÎÕá“QºŠ(Œ®Æ) ’4ÈÇä®rÇšx¯ã'ÄῃaÐb›%‹^Õo-õ/ ÇiÒè¨$ìóN±Ý,qÆñ‚î»Ø1Œyx-Ó07ñ6Ut(Ó§h%kº­Yw¼ì÷>áÆI‹œçRR¼·²Šû­Í›ø&ßí]eá›mVçáü)osdöVº»üSÓ¼™nDï#M»ÌØ\F¯Ü€g–7,`ßÚÂþ>6ñ/½&]UšÖ Bóâî%QHh£˜Éƒ$¡X³˜;Bò+õëÄÒxhêºg„4Ÿ†þ¹ðßœ¦úæ˜y`ÌàùQª4E‚üß1^§Ö¨iMáËßûá߇­+cÓ_Av·‡i—î·9%Q•Á\ yPAǤüxãñ”eNš_÷^öz{ç4ýëÇþ&~ÔµFðÚ/üý‰ÄÚÑñÅÆ˜úV¯âHt–:J*ìÔ½ěC±`#-»Ž˜;«–>3qtåeìõï*«§øÎ™xu+o§”?ùá‹Ïø&/í¾Þ+ØÿT•"@³»|c¶„Ïó`¶>Ó´ Ä$õÌx›þ KûmjVooá¯ÙþçKÍ)ŽâO‰V· m3:& ¨ªâ>`»° ~¾Çã]? }6'²šÊYãxìn`)Ê)þ¹ù5ÿ€ÿ‚‹u> Ÿÿ þH¤ÿ‡?ÿÁE¿èI¸ÿÂÆÇÿ’+öAø•¬ÿÂu¤hz烴£¤ÝéqÉyoª<æÞä¬í*ùèV&HÊÛÆÐÒË"zÒÑþ C¬ZÁqwá{;iå"'¾m²Ã°[nQó+0V½Yý#øæ½*ø ¿ù#†>ðÛûu>õþGãaÿ‚?ÿÁEHÀðMÇÔø¾ÄÿíÅ!ÿ‚>ÁFèM›ÿ ÛþH¯Óß~ѵU‡Â? x£Hý‘ô ¿j>=M?ľ‹ÆK·LÑv˺õ]¤@îdHÓ«/™µ‚•­ˆµýLJüeãxWöUñ^¡‡4®ôï¬2=¶«pˆ‡É·XÌB¨u.P¨À;„Çé%ÆòQµ*ÿr_üß„\9ñÔû×ù•_ðçïø(¿ý óá[cÿÉß¿à¢ÿô'Mÿ…mÿ$W覗ûR~Ú^/øMðÿÄþýšt 7\×üS<*±ñ=µÕ³éúZOi7·¬awF–LÉ)â!ò|ø‹ðÛö‹øâ‰_4ŸþÏé~ðÁeðmòÞÊ.5¦ŽYã YO1bIP¦D¨…˜ÂßÒ;Ž£&*uÿò@¼$á·öê}ëÿ‘?)¿áÏßðQúæÿ¶Çÿ’(ÿ‡?ÁEúÿÂ7þ¶?ü‘_´ñø¿G¸ŸFhü=a1–Ö Ú‘ßmò''vëýkȼCñÓö ¼}ªø[öfÑÅú7‹ÖÓÀútþ#­õÍ'íQ#]×±[™¤òE’r)?¤‡%eCÿ—ÿ$?ø„|9{sÔû×ÿ"~[ß?à£øCeúÂ[cÿÉŸðçßø(¸ò'Íÿ…mÿ$WêJ~Ó-ÿio|&ÔÿfX‡…u_™|eâØ/¦xtÍ@Úy»#ucfN %· 6}ïˆ_>&øwá ¯Š¼%ðÃRñ<ºÛA>‚ÚÎV;=²²Í¹%<åc\g«d…蹿¤§ªŠÊ…Þ¿­¥·|Úo ×„:âß=K/8ÿ‘ù1ÿ~ÿ‚‹ÿП7þ¶?ü‘Gü9÷þ -ÿBtÿøWØÿòE~¯Eñ‹ã…Ïí3âßÅðwÉðûOÑ£“¾$¹ÔçYïïšÕ]‘ÊÈʱ Ï–NÕ~áX ÕÛ|$ñˆ|_àû;ÏøfËN×#· ªÚØHÆ0’E/e„`ªFXœëZ¿¤¥eCÿü‘ñ 8sùê}ëÿ‘?Ûþùÿ#ÁWøWØÿòEðç¿ø(×ý 3áceÿÉû}ö;/ùô_ûé¿Æ±ÙÏ¢ÿßMþ5ñ2|sÿ>hàÿäŠÿˆGÃkþ^Tû×ÿ"~ ÿÞÿà£_ô$Íÿ…—ÿ$Qÿ|ÿ‚ŒÿГ7þ6_ü‘_¸Ùö_óê¿÷Ó/ö}‡üú/ýößãGüL—ÏŠø¿ù ^pãûu>õþGá÷ü9ïþ 3ÿBLßøXÙòEðç¿ø(×ý 3áceÿÉû„švžsþŠ?ï¶ÿ™§©ÇÙýôßãOþ&Kޝü ø¿ù"âðçüü©÷¯þDü=ÿ‡=ÿÁF¿èI›ÿ /þH£þ÷ÿÿ¡&oü,¬¿ù"¿pÆ™¦÷´÷ñ¿ÆŸý“¦ÿÏ ÿ¾ÛüiÄÈñßüø¡ÿ€Kÿ’+þ!' /ùySï_ä~Ÿø#çühœÿÂ7áã/þH«:ü#þ #¦ë–z•ç€gš{¨å–#âû½U+ƒqƒ1_·£HÓ7ö5ÿ¾ÛüiÿØú_üùûí¿Æ¦Hþ9©B†¿Ü—ÿ$ð›‡#$ÕJšy¯ò?/ü?û~Üš‹.üN~‹õ¹‚KMGÆ:|©„“ÎÚC.Õi' ´ñ›š&ý’?lm+ൖ‘­~Í:Mõ·¨Å¨êºÇŠ´ß²ÍR ¥YQå*éÒs»>mß©ÿÙ_üø'ýößãTTèß4û];Nš;TF…"IŠÞRžI`y-™âÿø'ÿÇñ/†¼J>iú&u«üe±Û­)Û°¤ÒL8aÊ’㎂¿UüSâ? øWá÷‰¡Ó¿gÍ/Äñi³FúG†4ûo³µëIu,/Ììb•„&2 2œÏ+©üQñÄž=øsð÷Wý“´é4=kIµ›\¹[$¹¶ðô¾ký¢ÞIÖØŠ ·1ìIC&J…\ýÇ.)À¨Ñ¥NŸ»•ý«Vµ·çµìš¯á¶Gˆ”¥9KÞwzEk{ÿ.Çç.±û|]ðöœuösV÷Ö >y?Ç[HР*Í*³² Œ cûÀóÒ¢ñWì)ñkÂóYë)øa¥ÚêïæØ$ÿ¬áK¥, f“æpA±•ê8?¬)ŸGÖ5ì+…¾Ô4+]=þÇÿ$«0¶Üª±²ùA7…Bƒ‚8â›y„üMá 6Ã[øyáé–5*týCAwHÕ’1å,he‡¤Bû™HLŽÏLÐòI¼4¤…Àƒ´£l¾‘œsÏËì°ÿø ¿ù#á' ¥w:Ÿzÿ#ò‹þÿÿëÿLÿøXØÿòEþÿÿÇ> Ÿÿ þH¯Ø=âÔ>1×4ÍsÁ–3i:{O¥^ZÝK¾ä¬0 ‚VF’F¸P¨ ¨· A¥;Zø…®ÁàÛ½_Bð6™u®Ûh—Ûh²êæ8o/SpD¥Ï–’`  €Ø ÖsúHqÄ~ʇþ/þH¨øEÃr·¿Sï_ä~;·üÿþ *G Ÿê|_böâøsçüdÌ›7þ¶?ü‘_ª2üxý “Ĭ‡ìË¢¾›âxîÛâ}ä^*R|0Ëå}ZE2nW•Ù€|<¼"°Âø‰ûqxºÇÂ^:¾øûxÀÞøjî+}ï4é®N°fŒÍ²IHƒ°%#n$ckúHñÄÜR¥C_îKñ÷øEÃqûu>õÿÈŸ™cþûÿÿ¡6oü+l¿ù"“þýÿÿ¡>oü+lù"¿M<7û@þÕ^%ñ·ÂKgø á½/@ñ‹ïÄɵF¸[½&Wó“­ÑŽUH²¬ÓÓc¤ïÙóö’ø¥ñá÷ˆ|cñsöoO ^[x†+hñ_J'žÊEˆ–‘ft%¢20iÕmŒU~\5¿¤Å¿ÝaÿðòB^pãO½ò'åoü9ûþ /ÿB|ßøVØÿòE/ü9óþ 3ÿBlßøVØÿòE~Õ\x£Eþß6öš.›ýž4ç=õ6Ünr6¦7ýÞ¼ã·QÐø†¡ñ÷ö¸»øá?øöVÐ ñÕç‹ ¯‹<9yâx-+lø»‰þÝ$°·R7»€ÎÂ7À/é!Ç þ]PÿÀ%ÿÉ xGßÏSï_ü‰ù‡ÿ~ÿ‚ŒgþDù¿ð­±ÿäŠSÿ}ÿ‚Œ“ÿ"lßøVØÿòE~¦è´×ÄíWö ñ‡Â˿٣ìÞ Ò<35׆¼W5ôÈ5-B9V äù{e J㔂Ko;:_|añÞsðþÛDø3cyý¹z±xÕÿµüI£ó S"씆ù^gÆX/'¬ÿÄÊq¿µö~Ê…í‚Véך×+þ!òóóÔ¶ÛÆÿuÈÏøs÷ücþ„ù¿ð­±ÿäŠ_øs÷üWþ„Ù¿ð¯²ÿäŠýIð—ÆŸÚgÄÇÅ7Uø'á-2R¹ƒáÕÞ¥qVÝ&Û× LGÏ\e'7—¸W®ø+U)ðõ®³¨èkes-¼&êÏÌ'ȔČé÷F-üGÓ5¤¾‘ür•ý•ÿn?þHø„œ9üõ>õÿÈŸ‹'þûÿnž Ÿÿ ûÿ·Ÿðç¿ø(×ý 3áceÿÉû}ö;/ùô_ûé¿ÆedOüz/ýôßãQÿ%Ç?óâ‡þ/þH¯ø„|6¿ååO½ò'âü9ïþ 5ÿBLßøXÙòEðç¿ø(×ý 3áceÿÉûö?þ}—þûoñ¥þϰÿŸEÿ¾Ûühÿ‰’ã¯ùñCÿ—ÿ$ñ 8nßÄ©÷¯ò?¿áÏðQ¯úfÿÂÆËÿ’(ÿ‡=ÿÁF¿èI›ÿ /þH¯Ü%Ó´üsj¿÷Û ¥éÿóê?oñ£þ&Kޝü ø¿ù!Ä%á»ÿ§Þ¿ùð÷þ÷ÿÿ¡&oü,l¿ù"øsßükþ„™¿ð²²ÿäŠýÃf›>È?ïã?û'MÿŸAÿ}·øÑÿ#Çóâ‡þ/þHñ xkþ~Tû×ù‡?ðçÏø(ÈÏüQ3áceÿɹðÛþ EÿðWŽtßß|=–â;3ÊØ0-´…$Èàz ~Õ.‘¦ÇØ×þûoñ§#Lëö!ø»g[éÇ5éJœ¨P´“OÝ—_ûxª^pí)Æju.š{®Ÿ#òÞÃö/ýº4[ÙéßEÃêÆål§Ôüca4–q¼q¬CÌWMÍïlã+ã¯ì5ûc|Døyáÿ X~Í$ÚKí¹™¼Q¦7ÚR¨Lfà*• IÉ'°_Õßì}3þ|SþûoñªzÞ“`–ŠÑY¨>` }ýëâ1¼}›q7U8.I]8ó'µµ÷Òø/.¡ÂùŠ©†wæ²|É=/.§ÍzÞ©á{¿KãH¿h[;5žÁ¢†Åu¤Y ime '–·*CðÒà®AŒ‘´‚Áè°jZxOý¨æžkFæy'ƒX.c¢ª©d½ÈX¬Í¹œ¹·c’Û´—Åíö>ðþ)ø×„¬-忆;Ž).<èUd$©’ÝP%°_™Ž] GÒ>"~ÊžÓF™ãŸxz=jÝ^}zH žÌ1©žãkµAÀ,XኦâØð°UjÓŒÚq]Ÿ;AÙjpžñEŠþ+jz΋ñÊÏ[“^kÛ{ -b2Ñ2Ȳ0T7l®Ñlq•NÃÔç×nÓâmÍ–³iî§ j@ 9îÓ:h¤x‹ “ó)“æ'æsŒ+>?ˆÿ²'‡î#²·ñ™fñL–±¬"tZåUF˜š!é’«÷°+д¯ xZÓmõ.=­Ü 5´ñÞÌVHØV7B4ýŒûî vèxßǯ†?þ/ø Kð„¾%jþ¼°½‚kjÔÛO5Ú%¼ñ4l¦t±•dÝÎ1œË꿳í©øãYñoü/Ï%®­ K§G¤¬Ñˆíä}*;/8:݆$J†èÌsó䯥áð¯ý¤ÿÀÉøº€ü*N?³¤ÿÀÉøª‰|AÌ»êß³7ÄÏø3 |[ûSx¥®ÛĺխÅΠâ}Y¥†'û2´wªè"X$“j¶0ÒTuÒ¾"Z]ØÃ#h×ÁÌK¼l®ֻϊ> ðîŸàëBÎÉÒh§·òÜÜÈq™ã«w‹áO«[Bà^ÞÕãf•káåoÐõòºx*›¯}-k;z™°x¡']Ñè—˜ÿv?þ.žž"‘†á¡Þqׄÿ⫽Óü güñŽ…Z‹ÁúräyYϵyð«›ÑièiRyT]’üÌ®|okjs>‰Ç¢FöjÇÔ¾8xkI ö½Tùzí·Cÿ³×¬ê_l.xHÀ⸟üŽIÒTƒÚ¦u±”þ%ø†–C]òÔr_3Ë5ÿÛ›àÏ…‹ _N×—o]šrŸýž¸OÿÁ^¿d¿u¤ñJ㯗¡îÿÙêÏÆß6÷–óºZÊF+âoÚ3à¬PZÊÏiÏ9â¶¡”ݤ{•8g.pçƒm??øÒúŸü ÿúÒ§6×·þ1V^¿ñMþ9T×þ&ÿ‚t¢Ú§Œÿ þ9_´Ãû}>òI!ƒ¬Hâ¼;QÝh‰Æ>÷<ƒ^µ%N¬nxõ²|5=5ûÏßøˆËþ ÆöŸp?êW?ür¡ø9þ ±Lš¯†?êU?ür¿™Ü! ä ÉÔ$˜.Ñ0?Q]+ mL=.@ú¯üËÿÈÑì[Q½Õür"F¶øI‰Éÿ¶•Ÿðtïü¦O»­ø÷ú“›ÿŽWóÇñ6êTð¨F#ç½AÀí²OëŠà,Ðc'¿zë¡‚¥8ÝÜá©N”^Œþ˜£ÿƒ£¿à–R°)­xó“ÿB{ñʳüÿ¸”á5ÿá ßür¿š«L.ŠÙУ’æä8ÍzÊpò¶æ-EjJ:gü¡ÿÓÕñö-OÇ=7xLý©]“ÿÿÿ‚êÄ}ŽïÆGpãw†ˆÿÚ•üòü=Ñ(JzWº|:Ð ˜É‹ô¯w¸E¹¹¾ÿø3šKC÷ÛàWü#öZý¢6{“PË1þÆ•ídõó3…FÑÚ,z‚Œ8ÿàD_üU.Ûÿú7ýÿ‹ÿНñçĈ¾ñ&¹m¥\L¶v±]Kf·>¿xÇ—! EÒK±ãÇ …½Ær*Œ^?ø¹§hqkö«/—.›osq†º¬>Nè·Ió=Ç¬ŠHc´î%Añ|翪ê yÓÛþÿÅÿÅS³ÿ@öÿ¿ÑñUáž ñÅ™%Ó.|Wy+Çy¬×ÇðÛW@Šé–Ræu1v2¥Šòv“¹ðÓâ Ò¼'·ñ_ÃÞ$ÕMäÐÛÚǤøR·žÝ…¼nï:•g‘T:…E!”ýÒÔþ¬g¬fûþÏÿâÿâ«–ø¥ñþÒÓÅ:‚ØM©Ç:iÁæBÒ´q4²m¹+<„uÚŒGC^†¾ð«Ì:Oü —ÿ‹¬‰ßti|!4zF›¼’âÞoµÜJÑî{ˆ×2~Sœ/⃜ùfTЉ5›ˆ?hû(dÖ † &ë?ßÀåŽív€ ÆHÚ@›¨)Ôðî¹e%߇5+Ú^MB 7rj.äGsö’dt»ØGq_>àFÐû¢¯íñ‚ïàG‰|!ð×ĺ„´x³_v•‚K  ÄÃhì|Ø0ÆåeÊ¢¾UðW'×4?ˆ_±šh1hš¯ˆ¼>Í[nb *ÄiLXÁ5ËòÓæ#pɧkVͧ®£iCDqŸ5?íbñtŒöÞ1¸Ôc·Ôa·ƒWž("‘ǘîäÀa"£2…” RÔìþ*_xnçD‡ZÕฟQ{˜õº³ÃNd. ФF Ëm’j~)~Éš~£ö8¼]§[\I%ÄL|ÉãËC3$Š[Ž’#Ÿ›k0È×£xTÿÌ>_ü —ÿ‹ªtg®»‹Úyñßá_Ç‹¾$ðæ¹á‰º·„ Ñ.f’úÒÀÛËý¤®Ö̪Íö„1íòerq3`ŽsÆø‡öXý õÁã¨ÓöŠñD1ø¾YŸOŽ9b_ì}úšÞ/—¶ìòãÝxaäJŸ¨ÿáð¯ýåÿÀÉøº€¼+ßO“ÿ%ÿâ¨Tª.¡ÌŸCâOxij姅õŸˆÿ´o‰®£øsà«OPÒžòI'Ö-mne¸šåŠÞî‘!*æA,6U¶Ÿvý›>0x_ö®øA¦|pø;oww¡j²N¶Ív‰ ¡¡™áutfÊñ·Ô`ô5—ÿ)𦉣þÆo´ÛFŽoøDut.gvÊÿf]œ|Ì{Šùçþ ¹ø’|Iû&x—áÍÕÆé¼7ã ZÏ݂⤜‚jñ1™Ç;¥„“ÒQoÎéÿ•ÏѲþÃã|3Æq /ípõéA®œ“Œ®ßý½Ëf}­ÿ‡‹?èÿøÿJ%ø©àßxžûG›áOˆžQ,%ïô¯ ´ðݳ„ù–HÁÎÁ'Ì[Ãc85×Ùø_ÂrÛ‹‹ XÆ'hçe6¤¸1Y†>ð|0'Üõ¯ëh×*n?‰þ€ÅJQNçh!Ô]<ÿàDüUF¡œgŸûÿÿX"iW¬­ÿ}Vg‰¼Iuáû'¾KÕïü¸YͶ‹¥½íÃÈ ,hÀã-Éè:œ ‘tê)Ë–1üJk•nvk ?³þEÿÅQ¶ÿþ|[ÿ"ÿâ«Ì—âÓˆ™~üBÃʱɻÀ“ƒDØ$¹‰A# yÑ“€Iâ{Èè±ü?ø…ó.ì·€']¹gU3u>Y?ì†BÛw®zŸËø™Þ'¦(¿\çNoûÿÿK›Ïú¿þEÿÅW¯x—Uо)§Ã“m5ÄFÛÍ“SX6E’…‚¼üÜzcZÙóeþùüébaS (©«s$Ö½SqªŸ+ÙØèóyÿ@÷ÿÀˆ¿øªæ|iãÿhÚÕ¿ƒ5•U¹µ{Û{*$·FXÞ@9UgE'±uÏÞÿ2OùèßaøìoÓ#‘¹o=FO¦Ö®Œ¦¬e˜ÓMu=\¦„jf4¢ölà?à©ß²óþÔ_ü)áɼc¦h–úwެe7Ú‡†"ÔeIâH|‚èZ7/òŒ2‡fEs·5ÔxïÆž$Ó|}¤Ø|Cñò+ê“oÓ¬| ͬp©•8’N @¼{ŠžÑ–1Ï—ÿÁh|/ñÆ_ ü#áÏxKÇÔÓøæÍ¦Ó¼!tbYU^û×òߨö0F&CÄx>•ã4¾‡â¥zš?Ä1×%cu£xÞmŽÑr òd*T Œ d$æ3·~dž¬ñL´ø;ñÛÄ–úËþÐzÕÅœ:”w-¦ÜéV{^0Ioæ$jâ7Ãg •äíçÑ•vŒWÏ:„¼[¬/á_üJŠÜx’ÒäÜ?ëOmŒŒeË䇈(.GEÇÐõ`QErÿÇü[ë¿úø¶ÿÒˆëcH±Ž;v¨Ä½°¬Œò!]ÿ×{oý(Šº+øòƒþ¸¯òÉWJ½Dæ¶dÒ²$X‘z vè(¢º#¢„/R*9­£™Jº‚\Ô´…€8&¦t©ÔV’¸ÓkcϾ%ü4‡W´’kXAb§+Šø«ö¯ø5,Zd÷+fG'økôRH–Tè9×ο¶]·…´O ÞÉ{wÚ £\%’¶ee…à·ã¯ò¹–_,5EVžÍŸkÙÔù¾­YéÑö?ÿj‡r@.3×Éí_øÎ/Z–ÑÉyê:×Ö¿·‡í#ã]\i~ øYâ}2â BHäšóDERAÆPgÖ¾1ñ%ÿ‹õ;ÿ·kMè”óóÚ²ÿ1^®_N¤iÞzÙ†&“›Pw%ûAhA~Õ™q™ n«öòfÀy:IŸºÊAªÓ}Æ %½z¾ï-­7)lqˆ‡E´ˆËK‡<ÿ²«ÿÅWfŒ+²ø· ÔÖ–Gi#lóYŠÆN7¿Ý®JҘʫÛ8ïÊ^žZòë?{SBÑ  ®·Àš[\H¯·©®fšhÞŽ¤gó¯Gøqj¥S Üv¯o OšiòœOSøqáçqòøâ¾ƒøeás#D«§jòφ6+/–›ké/„Ú4LbʃÓ2±ÉR¢gØ?ðJï ¾›û@éó"|Íjr™&êßø‡+õŠý5¾økâ‰Â"ivd ‹–;µÛ Ë|³tæ.§‡8Î1ƒùßû]GáOŠ6Zù´ó X¼À˜Ý@,xQœdžä×Ýžý¶üãŸÞxWÃuÍå„ÒEp[Ž5†0ÁYÔæE)<ƒé_Ç”•,ï•*&”×-ÙÎøûöbø™®x›[×´¯ øfDÔbº0ÈÞ'Õ!¸gi @ê­åÁÿZeã T:§ì¯ñA¼1…·…<)öˆth­ˆ‡ÆZÙo1ae*­#àÄïó¾pꢽsEøÎúÎi¬ÅáµU¼µŽtV¾…u !0zö«_ðµ®?è_ÿ¿û]|#ÄR‹³’:dÕÒ<§Jý˜þ#Xe4¾ð˜k+Xå1xÓ^ ­eX+;€8œÜ3r U=#öPø‡aðÚÿÂ×ð‡ÛfKo^6×¾ÎDH¡ó#1–/™T&ΛC“DZÂÖ¸ÿ¡~?üÿítÂÖ¸ÿ¡~?üÿít¾µCùùcWá¾…ái>Ôí­á¸²°Š¢µ¼šâ$ePIgý㯣?Ì{Ôž8?ñ'ƒþÂöúY bÿÂÖºÿ¡}?ð;ÿµÕ=[ÇÓë‹i¥É£,"]ZË2 ­ØÅÔG¦ÁéëÞœ+Ñ”’R&Q’W±ñÿürÓ@Ô?à¡¿²ò]É,—ðxî ‚ÛÂ0ÜÜGÚ_,.$D®ü‘‰eÚYjÒ¼[ãIu¨­%ø…ñ ÄòÊÂÞ_Ã$Aƒeù±É!î ““qñ€â×¼C¢x†=~úÏûöYäµ·*c¼„yrnRB†Úÿ!S•Á;KÍi?³Ž›¦xªÓÅ/ñGÆwMc2IκM¶AË+FS„=69$UúÆ|'ñ‹/>)éZ~¥ãOˆ·0›B)­(‹P‘#:uË*±òµ™c'+ŽaùëìFG\ÎxGá¿Ä­T´¿Ö¾=jZÅ´*¢{Iô›T[€–EÈ$`¸Ë ñœWGâ+(ï.m”ê÷6ŒíkK¥…ßîñ–F{cÐö®Œ5½¼E?”4Xoä×£_øWALd‡ÌkYïÚeo3÷œ.6tÁ<óíNøc kºT 4HÚÀ—þÖ’àÌxùvá¹ÆAãÛOá‚5_>¾£Ä^"†îÌ$qêúŠÏÒæE•1ù°q‘Á\qÀ®ØëÚ§ýAþí•{T¦©ÊöO}Öšœ2ƒ¦þÊß l|G¬\x®ÎâòkíQí㳂#$8Wtn7+üøò÷Œ1 VwŽ¿dëß|I¾ñ\ÿt-Z)õin"»ºñuÕ¼ ‘Ä¢07îòðFÀ’§ø¾™Lã­-wÊœ%º<'cÍtKö‘°Ölô{¯ø[û*=F–þß_˜Ê,È]ø‰¢Ê¤·ñà…ã®+Ò¨¢©$•‚Š(¦-ñð€ÝàË{oý(Šº ~Ç;B¿ÈW?ñˆøW÷cþ›ÛéDu{À'Ѽmà­#Æ>»[‹ ON†êÎté$R"º°ö ƒQuÏn¶ 8¹[M¯æmÑE`QE4Žy=z×a¿íc©ù®¼2ñ‚GQÙÇáæþµß@$Wã[_>¸vŸ¨ÂNÞ¹û;à&¸±¶öI¾’_š:ðMº’K¬eù3´–Ú Ô¤Ð«)*Ëšæu¿‚ÿ|P‰>øsPV2ßhvò†ä½CÏÖº¼ä5.@à·5Ùdr©K£<{Äß°7ìA☥“^ý~ܳow•ü`™‡ÌÅ„@’}kÊ~Á7?b›Kk{­CöJøy;Cµ£k¯YÉÈägtg?}S¯êš^…y¨]\"E ´Žìí€RkÁ>þÙ¿ôXg‹Ç¿|-¢GmÃK[·ƒí†`kÌÇ_ž h¿áG *ÞÆj7gw¥~Ʋ‰3\hß²§Ã{Iv¼–¾Óãb3œ°ŒŽœ{VîŸðàVkö-'à·„íaŸ*ßÖȹ=N`W‘ø›þ ½ûxbf¶Ú#LÔdRF4[K‹ÀpqÃÅ)úçsÀßðSÏØŸÇ¤GañžÚÁÙ¶ªk’Û~;võ5èF¤µÎW‡Å5w÷3ðþ¥ñ¦‘®ÿÁV%ð&emkoàï‡ú>–ÖÖ‘""É'|IU+xœžp°ñ—à rÞPí^±ÿ«ñoˆ¾0ÁR~2ü]F¾“G¾ñœ–šFªlÜ[ÞZÙÅœRÅ&6É$ ÊÀÊAkÊ~N—ÏLWØåE'ÑÕ9ã£V>†ø_€/Ls_Lü€±‹1þ•óWÂû…ýØ=ñ_N|¸E1e‡jýC%ŠæZœ5%£>Üý‡¬d¸ñ³Ú[AnòͤËit…¢,ÅÞ%rFG¥}*Ÿ ~%Ë¥\y‹ðþïµÆö¢? M$>R‰•£|Ì­óæÝò9R²($aó§ì˜¢8jtµ©;KF“[Ýôÿ3)Uœ—º®µ¾»ö½ÒŠ úQ] a…QLŠ( Ÿà§Ÿòd~>luð¦¯ÿ¦»ºþz¿gˆ'á7íà‰¦sh>+Óï§pzGÂ;¡PÃñ¯èWþ {ÿ&Iãÿû5oý5Ý×ók_’x…QÑ̰Ó[¥¹£ýú`(朞`ê«Æ£Q~’„“üÏë L¸ŠïO†â6<*AÆ*rÛr¡r1Ö¼öøª~0~É>"ÏsçOªxJÆ[·Ý’fòPH¸pÀý+â?ø*§üö»ýŠkØþü3Õ4)ü=á‹MJÎÏWѼ݌Ò\E'ï‘ÏÍzñǾ~÷û{GEKÙÛmw?Œ²nÎxŠ*äx>UZzIò§ÈìÕìõ?O~QÔæ€GcÓ¶kòá÷ü)û@l‰¼iðoÊ ý†ê{V=¼d·jýSøCãø~*|/ðïÄ»[?"=DµÔ å¼±4K \3ØÎÒºrìãšs,<®Õ¯tÖãâÿ8£½›Í©(ª¨µ%$Úµö~}N¢Š(¯Tø¢Š(¬0sï_ž¿ðTÍX]üwÓ4µlý—AV#?ß•ÇþÉ_ óK²3ŸJüÔÿ‚‹jƒSý§/á'?eÓ „sÓ‚ÿû=~ãÎ>4x.TÖrŠûÿCùóé5‰ú¿…õ!ÿ?*SãÍúEWñþkt¿øø»á£ÿQ»oýµÍWMð[þJì9mÿ£½¾ÿ’‡ ÿ_!ÿ¥#ê8/þJì¿þ¿SÿÒÑõ÷ň?dKŸ]XüUkHõÛ¡ݬ—Q4Ê-ÙSw”À2ùR2äñ“ýà1†5ØKÄ7éQx†ÖWµ·ŒÄ‘jȪ“ËFr}æ1žÒÍÏ©x›ÆÞ,ÑüM‘¦ü"Ô5[W¸DmJÖêDB€—"FSÃap2p ö®r×âÇÄëŸ"ßQý•õ¤yµ — º•“Ĉ¬vM“ 'cnTc83þ‰Cà_æ±´Òä^‡mே¾øw`úgƒt…²¶‘•Œ)+²Œ7^:’Iäšw‹Ï†£‰.¼Rý–%žâÕæD,ñ %R9Wà3“SøC]»ñ7†lµëïÞiS]@$};PP&ƒ?Âàö횣ãsĺ#ÚIá½K§8–HÒBP ¿)ØAþ<¨ã¸×+ULUZTîÎÇþ-ñ?Á/Ú_êWñ­ŒrEekoarœa(ƒ…ÐqVl|{âËË(oY‘DÑ+í0Äq‘œ}Ê˼°¶Ôbê ÷BÍ+8ÏLàŸÖ¦…(–(Ð*¨TttÙ_ RЦš–·wÑ®šS¥56äîºÝ]]^ÞI}{tÓK+ÌÊ£¢Œ( Ê(¯:R”ÞçBI+ ¬È/úù_ý«b±üuÿ x¿ëåô¯G'ÿ‘/SÕÉäkKÔö%ñ_†vÿÈÃaÿ‰þ4xdœŸØàZ|›áý_Ä~*°[ÏüSˆiÏe[Ý^xæyI½ÝT©æ`/ð7A^ŸðçOÔbðÌð‘ø`øŽàÈßñ4²ðêÁò• ŽÃ!•³Ï\ŽÕÒ«¶®‘àr[©ìŸð•øoþ†+ü Oñ£þ¿ ÿÐÅaÿiþ5çaÓÿèÝÿà«ÿ¯U¯îü9¥“ý¥ð²[|&âfÓ‚¾¹'ÚŸµ—f>O3Ô?á+ðßý VøŸãGü%~ÿ¡ŠÃÿÓükÍ¡ƒJ¹…n-¾ÝI¨dtÒòAÏ"œl¬@Éø7yÿ‚¯þ½/k/åaÉæt?gèÚš(¢¾œü€(¢2°ÊGµ9çÿnáÒ¼eà]XŒoñ–yÁÈZLß—î‡é]ù$‚Gá\§Ä߇³ü@)ƒWûiÜWêÞNýû#‘6c#yúW&2ž¨+˧Þta'uÔ¤ìµOæ¬y‡íϨ~Ò–>…ÿf¿Œ¶Õv97Z†¢Ôc˜ñ€C°Ùõõ"|yñ~ºÄãZñÍÇ~F$síXúOÄ-BIK´5öOíð+ágŽïn/u¿ [ÇxÄæþÍDSgžK/Þÿ_*|@ýœuoÏ$ÞÖVî%'Î6H?ºJèÁçx\R´ß+óÛï>‹9àLnZß²Šœ|´q{Cø­"ä¯ü »o|[¸]¸¾?÷Õ|ów³¡Oö}RÊH\vuÆ~ž¿…ZÓ¼U-¹g Šö¢ã8Þ; _ *Rq”lüÏ®¼=ñ’wˆAqr$†ÀÖÄ6ß¼W'›â…~¹‘‡Ï0Ó£ŽCï½lþ5òžñâ ¸Ïã]v‹ñ^EÚ<ÿÖ®+S•àÚ~LójáéIZQLúoDø#û3ß8“NÒ5 %Ï#ì:“2ƒþì»ÿ¥zƒ¾ ø3NtüGp8ÄwÖƒ?÷Ò·ô¯•ü=ñfbê‘ÌÄö rkÑü%ãÿÜ2”.ƒý£ý+ÚÁñ6}—É:Ÿ£×ó<œFY—J?¼Š^š~Gègì%¡]é`ó5K;˜þÄÃu´¤Ÿõ‘ö W·ë~4ý‹gñEðñ—zÍÄÍ5ìsh7‹<æ@¹r<ººÓ!€î+äïø%þ³«êã÷ È4‰H^Ùóa¯¸uˆ¿í5§³‡öy–òÝ.%ò¯ ñª†‰wù\†Äg ´‚X¨ãÎsœvw‹XŒU¹ì–šh®†Ÿ%òùœÅ‹c jÖÞ/Ò­­!¼²Ó£76úMÙ)o {cù6€6àuÛƒÒ½Àÿ¾üFº~×dº”Ä$Øú|ñaH$s"žÍdj_¾0iâK=öv»¸d³Y!?ðZGša.c'9“÷yŒüÜ í4 CRÕ4¸ïµmôùÜe­d•]vÉ^3íÚ¼²f`|@¹šQâO ÝjqÙéŸkX¡Ñ¾Ø ãM¨»NdË+…‘Èç_ெ-üI$¾6ðV‡&‡sn>Ì“jš [NcuW!T©*½©Áq€1–j¬ÿn²°³{skén/Víæ6$LÍÇñ*Œ|Ù®Àh? {øºOûê?þ7^½ ûÿ™Ç/‰”®þÞê7oˆ—úœº»D"{³Vh•J¨;FIÇLóÞ©¢K«km>Òðk¶ñ1N„¥Ú.Gײt…½¼]'ýõÿ®CÅs^iž½ºðͼ—sZÝ™4äIÒ”¤û£;Êí\áIb1ß§>yBrwi¥½ô]J6RK­þóÜ× úQ_3Þü|ø ]GcáÌÖ®¨éh³ò™ØL¼ðǨ•#=ÇqáÏêÖ‰oªjµ]2âe&K ¦µi!9#¡*xà÷­½¼+=‚Šòßí¦ÿ¢Ñ{ùAþm7ý‹ßÊð£ëÃ’G©Q^Yý¶èµ^äð¥þÚoú-¿”áGÖ)’G!ÿ=ñ„~>ÿ±SWÿÓeÝ6’ùrÏýÈØþB¿ ŸÛûÄÚ¤ÿ³ü<Úí¿Ãràj2ÝÛ¬qÜ­Œê°˜×çfdi0Ê€œ¹þ{|M)ƒÃײúZÉÿ ‘_“øƒË[0Ã¥Ú߉þƒ} ª¼7 çSfQtd}gûÁm?h_ƒ²N“ð3ÀV\7šîÖ^î3+²´Í2å,» ׊þÑßµßſګÆö:øÉâêj¶FÖÞ_,(Ž0åÂ: ÎÇñ5òÇÁï˧jÚÞˆeÂùÑ\ ú‚­ü–·´ÿ‘ª›f—”ÏL÷q}:™Eâº/Àü_!Î)å*U©$¹¥RWvW|×{ï»>ðŽ¯¾Ö0[†àþuýÿÁ5üDž'ý†>êjἿ [Z’=a_'ÿd¯æËÀzÂËm‚Üþ`WôÿMñ9ñü¿Áp´ÆI4ë½JÒV=WӲޕÔ}sðjt³ ïɯó>«é(ãøO ˆKà«oü 2ÿ$}kEWéGñ €į֚̂2W#Ψ0ÇšÈÖ|A š[$f¼¬Ã4Ãài9IëØRq„y¤ì†ø‹\ŽÊf|p+óöÅÖ·ûJx£PIw/ÚbEöÛo?®kî‰m´è&¸¹º ¨ 9jüÞñ÷Œ­|oñ7ÄÚµ´¡À×®£È'¢ÊÊ:ÿ»_Ê^2æõs² ÷\éýɯÔþBúRg‹Ã0´þU?º2_©›EWó‰ü"Òüÿ’»á¿û ÛèÅ®jºo‚ùÿ…¹á¬ÐrÛÿF öøoþGø_úùý)OÁòWeÿõúŸþ–¼üK¦|l›_¸¹ð‡‹<=o¦µ¬‚ÞÛQÒ%–T›ÈaITfÉE*'#7MÐiDÖþÑ«|Eð¬–j…ÚÞL²yA£óP9œ€YD˜$1].‰ sÅâo øŠâïí·$Ík¨\ˆÚ33˜öˆæ –P`ïÎk'áóÞE¡¸ø£á}J]LÞJQ´[ýEanýØ>dùÝŽ½³Ò¿ÑÊxdà½ä°ôêû‹BO…šGÇ 0Ê~/øËBÕsX†¦=¾ÇWa¼–cɱŠãåbÀ1[~&ÓüE|ñQòÁ*°ùy”…òØŸ-òîÊñœõ¬¦[è¡·–÷GÕå·0jf†;ɃÄÍ:›o4Ç(v<ŽIÇ9æ¸?í-%ßàý̳f êºÞÖN‰x8Ëd¼cÕÂ…¥Ì¤¾â¥S™ZÇi–©ýœ4é<wöÐëÿí$#“&<ìíÛÎ6ç¶ÞÕׯAô¬—“P³’ÛIÔ-6é®5Cuu;Å%Á1m1‰¤rÄ¿í[ù¡¬ñR”¦“¶Š¢’W (¢¹M‚±üuÿ x¿ëåô­ŠÄñïü‚"ÿ¯…ÿÐZ½,ŸþFt½OO%ÿ‘­/SÀ¾ Añ‡QøX4=^O 5¥Õõ¹··Ôg…ìVä“çu˜ùÛÆ z¯ƒ­?kí3Ãúo€-<:¶&Èíô¹mÖÞ,Yö„wgo'©Í`|Ò´ oáÞ‰¤xƒKðµåµÄšb_Câ„?"C?†—x¸üz+Ü9ÿ§ßÒ°|GâáýrÀÝjZÚÜ;-Û_\‘•ažAås†`S$v@ǵkõoï?¼ž#Îmì¿jkKtµµIcŠ$ h-@UØO0þÕÄpÓþvÕÞY|^øU©êé:wĽ2{¹níbÕ¡iSŒ PÙ,w:ò*ÅÿÄivrjŸí-àŠy –i¯ãUISÐ’pr2:ŒŠ>«ýç÷‡?’>føók®§Œ|+uãK(޶Þ!³Žîá£O3r£+Æ1·_ˆŸ²GÆ»¿ÙÓöªðgÆ{[†‰4?Â÷¬3jÏåÜ/ãÈ?ýÈý¦5íÄÿ<5­øsX‚þÎYˆnígYQö†VÃ) áÜ_ÏmèÍäßõÑ¿|GŠ5e…Ä`jAë§óVgö¿Ð×,Ãç™gåø…xV„ ×”•EúŸÕ¾‡¬Ùëz5¦·a0’¨HNA õ«êÙã9ñÏüöªƒãìám[Q½Yu_ Ûdj[›,Z‘½ÙŸÆ¾“Ðþ'éZ„aÞáA#Œö¨q *”á6®¤“ûÑü›Ÿð¶c‘ç¬ H;Ñ©(?ûuÛñÜì_æÓ?Ãé_~Ìß·ÌŸkß~Ãÿ´²ch|Ur¾Ö®ÎÁ,†Xl$cüB9DßÄΡsöøËHXüƾPÉ×ãü¿ÁÐÙþÖמ;ðüçþ'E¥çŸ`¬È 9tqä©õäæÎ3øáéS­AÝÆZ®Ž-kúiáG `x»7ÄdØôãíi·NvøjE§÷^ýÑûU¬ƒrœç¥fr1ô¯€?à?ðTûÚ#Ãiû;ü}ñPxûE´'OÔn¤Tõ¤kÌ™8|j>uþ%ÇñíöÚ{þ !ÿÛý‘-î#øÁûSxxêûƒèž˜ê—¡×9C¨,äó•ï_GÌ0¸ü4kÒ—ºÿÕ?4|?ð–u¹Ý\³Mª}jK¤“êšÕ?“ÔõÿÚU³±ðwÙ®Àýù`=ˆùåñöh¾Ûs$DÏ5á¿àêÙ§ö˜ø½¦|"ø;ð«ÄºN…k$’Kâ_I&õ¾UX’Þ6rƒ’Û™óòãhë]?‰þ6øcâ~ý¹áÍI%IcÜP8%s_ÅTçõ×+hÒÔý¯Áê0¡…”Û´®îø§03Kó–5á8žN}kÙ>%ê!ä”繯ñ¥À%ÈnµááâÓGìxÚÊ{žo⤂嘖E'î¸ÈýkÎ|Aáû%s%¦bÀÎÐr+¿ñ4ß3~5Åës ¶|WÐa«Õ£¬‰Í0XEIõï^¡àþT k}[Ðù¹IÞíŸfÿÁ0­Ä_"e_ù„È?ò,Uöþ¥á_Ú)µ;™´_‹ZVŽëöho<6exÓÎvl²Ê€Ÿ-‘òÌ’M|SÿÏ0ÅñÊwPï¥É±sÉÄ‘_]jþý›¯.õK½Wâ±„ÝØµ®¡oÿ ‹ÃÅsÆ3Ì.«’ì­’À檚™ÅYÞgCá?~Ðzv¾—~/ø• ê:{ßÈóÚÛh-nñÛí4Gó-‘–$Ž{Êð[ ~ÉâÑo´ú‚‹{CSÅñyZÚ7¾pò°@V?0ÆÐÙàšöxÇÁÞ2Ñ’ûÁ>&´Õm#H×í—BQ‚—$¥H?b÷3â85ËFÞ-ÄvZ{–O´%Ö‹oxÓÄ %TJÊcn¸a‘ó©ÀÅ/øsÅ:Ìžk ûX_N¶1ë2E§Cn5 JãÌÚ€ùx8l)ÿëVñ}¯„ì¼^¾2Õ¿´ZïKÓUÙmÓ0„̬»²0•‘éÀcž–kÍ[O»¶¶Õü?%ºÝÎaŠAw €8äÁÄŽ#oƽ:ŒE'¦­ÕtkSŽQ…Fã=5èÿ>ÅÀË|oüñJ‘t ¼ûdÕÔ×1ñ³þHïŠì_»ÿÑM^t]掷¢–žeÛ•¶BK“€r —áî‰y¯Í¢èZ|M¢Ï¨ê7![H²†[BÇ®'ycqpv)àžvò ïá? ÍáïZhÚ¾²šÍͼ[fÕ/â‰f¸9's‘Pß*ÇJôiB¬©¦¥o‘„œyµG‹hŸµWÃza—ÁXÑŒFOô?Ê e¡<ôë×Ò Öþ*xkVÔMõŸ‚Å€`¡¢´ò6œy Á8ÆF ü>‚ûŸüùéÿ÷À¬ÈîôÅñ#x|éqe…î¿e>Jª”©|cq.^¸ñÆoØ×þoÀ\ÐìxZüJðê^¥ÙðÔ¥AŒÉû1G*ÙÿžPx‚oÚÁ ÿ…9§~Qÿñºö°Úÿχýð(ûŸüùéÿ÷À¡R¯ü߀^=†à ôüÖôýÁÚSEðÿÅ2<¶û2ãû.AƒµG®kð[ÆñÉ7…o£‡ïyþ“úWôKÿ]·‚/:‹Eon„ø#Å\À£?ò—­=wvéui-´ƒå’2Œ=ˆÅ~YÇŽTó,<¤ïoóGú ô;¡õ¾ΨÇNg÷ÆGÌžÕ•ñ(!|-Õœ‰·Õ†#[kooâÍ»¸g~"¸ÿ¼¾ñÕÛ¦ àô'iþuc_ÖrÚñAþóèkî0U²´¼™ü¿Æu'”ø*F¤ŸÜõ>øe¬y˜Ù¸*§ô¯Þïø7Åg[ýеmÛ'KñÕÜJ=íí¥ý]«ùëøS©äª†ÎT:ýÇÿƒi¼Z.¾|L𜠲Öì/62<øeLã¯ü»þ•ó¹mOìüÓìÓGèÞ%c?µ¼;o~IÂ_/ê~¤nUµ2YUW&«ùã×ñ¨®®±Ëvï_UˆÎèÓ¤Ú?•U7ÔæõßGiq,àr¿‘ÅygÄŒºf‡“]j «Ä¾<~Õ¿ØŸ¼Aá9æž[ VâŠÙÊ•¯Aô¬Ø«Å?¿héü%ñ?ÀMs¢É ]º­±òÌÁãÛ´7|oÁôÎ+ó •+æÙŠÃÊ¢‹›Òï¥÷ô>[1ÍqWŒ­f¼´ÿ€+ýªÿl+{Hn¡V ¡Z¾Jýœ>1Áã SS¼šëÌz„Òd¶OÍ#6Zý¯×àŸß±Š¿ˆfÿ Þ19&{ ÙýkIÿ‚`~Á^Dß³'†ôÀŒYFŸlÐóï´Œþ4ø§Â¬F}•,5:‘Œ“½Ýíø#á}#6|Ã?/Sï/þ<0}@þwã/8ƒ²åŽ«(Õ§{IÂï—³wKN—?<@ð‹x)Y•iµ$í' ¾[ìÚihû­Üòšéþ 1O‹þuê5Ëb?ïâ×1zé~ ÿÉ]ðÖè7mÿ£¾‡³ü/ý|‡æÌx1Û‹0õúŸþ”X³ÿ‚™ü'×5›‹O ø‡Ã·VÍtEŸÚü%ªG*Cåœo+)Vmøèw'K‹ö§ðwˆ´ wð\ú<º Y¼å½Ð¯’ÚLÈ dbB˵2\“_þÏ?–êD¹{]Å›'ŠûGàÏÁØ"Š0m{«_Ü®)ÅaÕ£÷ê^%ÄÓ‚äKñÿ3è-3âgÁaCÙxnr÷¢”Z؇Tøc: #ð«cݤÿæ|9à›Bˆ@äâº;] |©ÇÒ¼ú|[›Ô–‘½?àœôøƒ9­¬b­èÿ̰nþ¾?÷Ûÿy¯ÿkßÙ'ᧈgð·Šm®òÛrAk4IÆTõ®»â½¢ü<ðv£ã l„¶ÓìÞi ïÓñÕÐéºÝ¶©HÁfö¨æ V”WÜpá¸ç5©UFq_s?Qµ_ø(ì7¥@n® èKA¦Ü?ò5æ>,ÿ‚®~ÅÚ§‹"³ðÖ»$zt6Oö»KŸ ]´íq¼lurJªÞ à’JWi ð§oq M5­ÄŠNsƒŽ+“µð]ÍÕëk7ÀyÊUH\d9ý+èøˆ«ÔÍ(©¥¿o#ô®Í«âs:<éjÖ×ÿ3ö/à•õïÂËkK;/ Ü ô»HšßÅŒV9XÛ³"¡í f9 zõoñŸ­¿ˆô¿ø ÇF¾3 Ô¼!#¥…Oî“p@­† ¸dx­|çð^×ã ÏÃT Éno¡k(õ9¡HþÉäb ùÝfÉœzã#5éSö¦ÿ„I,~§…cÒ-æ‘ M æÙ­âc—#l`I`Äq÷³ÏýM Ü”’ålî”n÷>œÇµïç^sñÑõhcŽçN‹ÂäYØËsæøÆR±ÀàˆÖPGDýë#žÞbóΣ¯íÄu¹¨¶.f¶¹„³>9ùHàdzô=kâf«ñ"ÇVÒü5ñJKW¹×ì:eµý¬-É’X“Êû¥@i!†À'•¯Öoö_ÜO/™/„Rëľ4µÒµ;„:Š>¦aÒ®K_oU“k®X‘"yhF9Än0*_ëñ]ɤÝÜ|HæÒ⺺¶Õ/ß{ÜË O,¬»±ä3ÁºíÛ×­]ÓþüUÒõõ}/À]µÜ3 ¢º‚ÊÍ$Y$6à3Y¿ï£êj;¿ŸõÍÝ÷í"yMºÀd—O²f1*…’FJ€ÛÓŽ”þ²ÿ•ýÃå}Î âFLþb¾øŠ×#ÂÇ:~wIþ¤÷__|×à3N·2<Êå£3_ÐÅ¿j>ÖüáíKH‚Æ[oÚ‡¶¶#Ér¬`(#§­=ÔÖðOnVVþf¾Åx¹Ç 5Ò ô?·¾ƒø¨QÌ3zOíû?Ûüϼ¿àÿ´OŒ| â_|Ñ4[ÍR=vÙolí-Yp“&˜î#nÚý økáoÚ7ÅÓ,.,4xË|Û‹\Hþ: þuùEÿvñ¥Ÿƒÿà þQu[}Zy´ùwô>dLT«"Æ¿¡]7Ã:V›tÓØÛ*àW‡ÃxZ™ž__°ù_æ¿ÀúJÕx‹ˆT©&±1TÚº½¹_â®y·…?ftXVóÇ.Ôõ{€™Ktc„6;¤{A\×ç‡üÛÂÞ5Õ</†üg ØZ &QÓí6+Û±È$òXƒÁ>õúÜÇ•òGü›à~©âï‚ËñwÂS\ê>—í¶±G—»± ‰£äð;²(¯¬Í²*Tòç*{­ÿ¯#ño ¸¾¦(UÅIZo•=”[Ñ[¢Ocð7ö„ðýÞ“áýeìÞHeK)Ìme`‡ŒŽpz} |1ãMVk¨ ´™úWê'íà‹ WK“RÓ™f³¾µ-©ÈxÝx?‘¯ÊïÇ$ %¼ËóG!V„q^G ®ER›èÓþ¾ã÷_jC,&-}¨¸¿•ŸêqV2ɈXå*Êr¬§û«ö"ý¨¼[¤\ÛøO^Õ$–¡b‘Û·¡¯…mÂqŒÇ5í_ uù¼9{o©ÂN$WÑg4£W“Gã|‰–0šOv~•x¿\]BÐ]†ÿX³õ¯$ñ}Ê–|õÔ¾ ø¿¦xÇÃ6Ñ5ʉV3»¯•â›Å=M|T)û9XýÂxˆÔ†§â7·N•ÄëR•bsÀ$šê¼GvWp-ø×¬ÜÎOzôè]Ÿ;¨é¦Ë~"8°ä’I®çÃä9^sÍpš# „ô íü4ùu×ÛѧÉN+²?›³ D±8êµ?šMþ'¤ø\… H¯Pðß*±õ¯*ðüꊊ'ìŸt OÄúöŸáÍÕ§½Ô.â¶´:É+°UQîXZ-;ŸKÁ<îükeûqèâûÂÚ„^·ðôˬ}œ›yn ;è÷Ž7*G Ëb¿Hîü9áë}.jà†Ð'Ûn®îa°EP¿¼óšQ¸Ý¸ôÆkð×ìÙ ü ð¦™$Vট§­­Ä¾Q&lG—õgO½ðÏ…´y[ÞŠ×K±0Á4Ößfµ‚)—ó?†HÀã0ž+…Ó~$|=¶Ól<¦xãW¶¶–ØZiút:§ˆ<{VTDÃŒÇgÑ5Ÿ‚ók¶7ZMö¿§ +à‚öÄM7“>ÕU‚ʈ=QY:Xk­ßèf¥Uø—Á*?>oxníUÇ­Ø,O¸(¹äσêN+GEðö˜š¤·3XjpÝØ]âHµ EåÛ!ˆØ:±Ù/^¿1¬›OÙ?Â/±Ã D!pñ‰€F³‚®»Jðˆ4Ÿ´<~(Ó§{©üé幚gfmˆHàmEö¢j ›TÛûÅÜõDÕÌ|lÿ’;âŸûîÿôSWYÿLjÿè;£~rÿ…p´=åç†~êz>«wÃjÚ6¡O³žEFKY$&GÆØ— @g–Âçs(lmûÆ'ô~Ÿ&ÓÛ+CEý´ôMzæ{[‡— Öçñ ñдc=GçX>:ø³wã=TßYjZöˆ¥bž«¬I¹ Ç1œ– Tö /uR5úÅ9$VðN¿º DÂñy·hw¿.³¤aÛÆÑø¿y9"AŸH|s®„ñWˆTøÿãL{/ÈÆ‹£n·‹ç?ñéòñŸø>íSѵC¿õ÷’g ÿ¿ûoÁXoëw˜øe®äj¶»cFœ|§œÊ:MÉùÿ!øI_¸?·¯¼Iðƒ\°¼Ô5 üŸ†Þ$_ôÛ¡ ýÞ“*(;Ø6]²w0Ï+ðú¿$ñq–6‹ŽÖgú)ô'‹þÀÍþx~R>Zý¨´¦Ó|W|#Ì‚T#ý úÕ[úµöŸm9´1¾ÐÌ$ A®óö±ðù¾Öìe‰NëÄXN:–ÝåŠè|GàÛk[ë‹yeÊÆålÇô¯°áœJ­”B^_–‡óÒ(ž]â6"”U½æ×£w_ƒ(ü!ÔfŠ9-Œ7=ñ_³ÿðmGŠ~Åñâ_…^PûAÓîÂsÏ“4©ŸOùoúýkñ—Máï K‚R3(19èÃ5úÕÿ÷x±4oÚËPµi5/]¼™–âÚ_åW™›Ñ”$ç–®2xþ ¯†“ÕÅ?¹§ú¸þ~ä ¹ªz­êÅnNü u¬˜µ±ö?1œ€õ¯>ý ×V4Ü­ÌÒ¿kõ?ÅÁуAâÏ€Z_‰-o¯´*Ýn5 —šYJ͹‹1Ï©&°4/ Z|“CñV¢ ‚ª¨’ãºBÃç$ŽÀsŠà¿à•_ÿjo€šoŒüûW|@Ônu[èìït-QÖûìÖËç$—Ì]”îrˆÈ§äòаýâgÒ?lÉ×Møa¢ÆX†u“§²(þ£ó¯35ðâŽQâ<Þ‰ÍÓ§¥ŸîÞ©--Ýêoø\4Ü0Ò‚´›oMog­ÏR·ý¤~\2¤_4ÀO÷¥*?21VãøûðZVÄ_tb}òÿ~yÏ«ÛXZIyst#Š/+¹ÀU$ŸlV_Âÿ¿ ~'Û½ÿÃÿ麪ªëit ‰þò2þ Wéqâ Ûr£è*p§î%ZŸ3„mwmö»µ•ÏÒ¦øÃð¨ÿÍEÑ¿ðaø×-ñŠÏàGÇO]ø'Å^3Ñe·¹CäÌ5(ƒÃ Î×ROžA5ñ[kŠ:ËÿUsâ%3“ŸZË›C† E8ÊM8½SOF™ó™àqØ:˜|Jæ§4ã(´šièÓG‘|aðMÇÁ¯^xZÔ­®Œ8{;ëIU㺉Ù"•'ÆÎAvÍMðVúÒo‹ÞD˜Úå¶ÿ®‚¼Kö®øÍu/ÇýSMs$qYGûÁ” $Q¼¿åZß²ÇÄuÕþ?ø2ͧËIâ+EÆé ¯ãzü3 Åa“TÕUÊž¶JJÚŸåöaÀÔr?UjŒ1)Fûò©«k×ËÈúwöiøoæC }›®¯¯<áah‹ n•ã?³5 µ·—„¬fº”¤4Ï!‹Ð øë⎕ã/ÁFõ_ŠŸ>kÚÖƒð¢Ú×W]BÓšê{ÇyVßNXÓ¹óK¢GAfÕú! yˆ²yÁ5ö+|(X4ëkP«ظнŸöø.|O©j/`Í®“ŠÕ›¡™Î>‹ÿ¡T¿´ÿ‡--'Fö°8÷V5ùîKgŸR‚{3ØÈrG‚Í©o£GÒ dGø% œÖ ºŒÙÙK47ºò튥¤ÁYX;!$ÿñÕáÿøÛÀ3 x&ßá6‰m-çÚomlõ·ŸÌÛ¹Bƒ#0_˜çvݽy¯!øKñÁW¿ -tû9<%©J—VVW°xš$…pq÷ÊLd)àãœc#V?xe7Íkào„BîôI-Æ °\2n¤h>B€¬ÈIÏœ€3ú¶­8RI´ˆœ[–‡°xCã'Äk¿E¥xƒÅ¸Ò5 ]aÓSLñkß³ù$d©;^F›fIâP2q“7Ç#MÔ>*xöûKÔ&–ËPŠ[9b·Y<‰ õšf*Å£²ä9uÆqÄ|+ñgÁ›¯KªøßÁ¾‚âÂãÍÓ¦ðî™$—ºH 23: ŽåèO ɮׯŸþxÅN°ú­ü‚ÂHÙ^3"m"âaüKû°Øþò­jñ¿™Ë'Ðõܱ{ÿ}ÿõèÇû¿÷ßÿ^¸Ïøh…ô1Þà<¿áGü/ÿ…øI/ð_ð§íèÿ2ûÕž1ûV‚>.ømpãþ*?ýaçîþfü®ùZ´±»pÓ0#ñ¯écöŽ×t¿üF𶻡ܼ¶·(±1I"N”ðyê /žÕ¾³!ßÒá¿ô#_/â5ˆ¥‡_ÜGõ7ÑC3–Uœc'{^PüÙô¿À?Ëð¿ãw„>#Ã1A¢x–ÊñØe#‡Ð¨#ñ¯ê3ÃZ¬:æe¬Û°d¹µŽD õ  ÿZþNt;ſӒ@Ù!q_Ò×ü[âàøÇûxÆs]y×-áëxo¶Hš4àý5òâ• ÕèMôOî?Rúgd±Äá2¬ò’ÓÞ§'ꔣù3ßAãŒUwD²ñ‘s£j0¬\ÂÑIŒ†V"¥ûZuÞãOûj‘Œ×éK0ÂUƒŒÚ³Ðþ Š©NjQÑ£ðëöäý.?goŽïÁ{›r4}I¦Ôü!+•U›tÖ£ýÒÛ”uð>å~&üzÐÿáø—âM ¦Ñm­\Æ ÿtJØý1_ÕwüöboŽ_OŒ¼- Çâ/¸¼Òî€åd@H¾Ö‘¿Ùs_ˇí¿{o'Ç¿]‹F¶{™c–{Wᢔžju“xü+ä²ÊQÃæµatÕ×¥Ïè¬Ûˆð7ûÊo’~¶ßçkž +Ö#bÎ+Ô¼~«n°JÜ`×”K ÕÍï› D᳚ô/L^Æ9W9ìké3óQGÁð¥WO1’ks×¼+âíS· -­ÃyG¨5ë7ļA¦+I.[o\×iZ˜’1 ǵu>ÕšÊq¹ÚOL×ÉÖ¦¹Úሽ4w~"¹ [?Jâµ[“çˆÇsÚ·u-LJ‡qê8æ¹­IÁºV€ÕÕ‚XÇÌð³ÌW±ËêÎûEþZ~&Þ‹.æ§CŠî|3/θ®B$Jí¼?t°…$òzWØ­tGóÝIëdzW†dT½+ïŸø#'Âþ&~ÔV^-Õ¬÷é¾´mNVoºn?ÕÛ¯×{ýq5ù÷àÙÌó¦Ozýƒÿ‚>x~ÃáoÀi|O{ŽÿÅWÿhvn¶‹1Ä¿ŸšÿILÕ£ts¦å+rüw¶ÕõOÛXøSSZ…ƯoÈeòäbBÃrqƒŽ½GZâü)ðãöŒ±ñ _xËÄ–ú†ž¶®ae¡¥¹iJŶMæw<ãýf;WIªøŠTh$Áü$¶ €騯Z§NŒ+E¶q׿§RÈò•ðŒ@´‹âÀuÄ5©àß\ióDš¡)d ÃöˆâóuÞ§rg¦áÈÎkÖÇ<â‘sƒº¯êt¿«‘Œ¦å3ç+ï„ß´³‹)|%âÕÒ`M%mçÒµ 15þac(¥I$`˜æ88ÝŒšíl|!ãäµ/ô맘/ïâPÇ'œ=±ùW¬Ÿ¼($(Î)ýN£7’<°øKÆ[äÿkϾ6x3ƃݫ’J²Xø¢wŸý'ã'Æ)®/;©mÇ…k ˆekpC/˜Þ_;•˜‚#8¬:‹¢½ ŸÄÏ_øoñÛÁ5q¡é¾ÖtÛ†k¿$k¾žÍeKyE2([ÌF^ä7@A‡ñ£Û§íÑá í Å¢Êÿ`‚,_÷¿¼•÷œt ÎíÁ¶¶ÍÑiüðýï‰üAÄKŒîl­ÐîÑü_§Gi ÒHŽ4On’„†ÈÚr«’Êq]6¯¡IqñßO×WUÓÕ!Š0m™ vŽèùO˜Sæß!æ4çÓ_q©Ýý–Ûþ}¬?ï‘GØíOü»Øß5'þÐFF?Ðè´CSåø*ô1Gð'Q1Ål¿ñDx«˜WþA2u¯çº¿¡?ø+àF¡ü‰*ÿUÿ`™kùì¯È|Fÿ}£èÏô[èMÿ"Óþ¾Cògñ[ãÄ^1𕪦âuûuaŒü¦E'ÿA®Pðkê÷ò˵ö'ügRñÂÛAµñ†ƒ¨%”ÖWÐŨ-”ŒŒÖ]¨ØSóîHÇ¥~|1ý•~ èžI±ø_¢«‰lg¦HÍ}7ð—ÀðÔq+Dµ·Àò`UþB·Äf°Åûœ·?Ì1ô2œé¥w$×ÞRðo‚¾%|Bµ[]çðæ— ùC¨7³)îåaÿßìŠôïø Ã´6žÒÖ'3Îî^Y<»¶Y'©ãµ_µr¸íWT‚8¯¯Èð˜8QçŒ}îïsñÜUj•ª^Gñ[Á:·ˆ­ì|QàÙ"Ä: Á›Ly‰ qan-$#þYËÂȱI‚c¾lýºbü¿C_°\~*©}I4Öû¦.càsÌÊñ÷ã5%%¾;>èúãöt½º¶··ŠâÒTùGÞŒŒ}+éï j1”F9Œœ×àGÃÿÛcã˜ikãÛ¸F †Â‘ô=«Ý¿gŠß·Ÿí#©·„~_øÛÄÎXCw-•ë­®ç½Ã‘\s†`O`OëR˱.½é«¾ÇÝÃÚÑÅ'N ¾ÇíΛ¨Yù4è8î¨øó⇅¾hÖšî¿¡qî¯k¦Â4­2kÆ\J±!q ¶Ä Ãs¶{œÈÿ³çüëã6¥c¥û`þÒšî¡©™üáMbx­Ýšì•–_qÇÏñ0ëö‚~ø;áW‡m¦ºµ»¸D=»H„dúî [eWk PíÂŽ&8©O™{6’QKTîîÛ¾·Ó¡Ú¦¹mýhQ»×ô‹=6çWº¾H­ìáin¤‘°"E³6z?…~2|cñƽûJ|yñÆ;ø% ­êý™ ¹Ý ¢b;xñ؈•3êÄžõû=©éf©m-¦£eñMŽXåŒ0u#H=AEq~Í¿ ¸‚âÓá. ¶ó,°É›aÈ<šòó¸â'A+«/Äô²Ì^ )Jqm½‘æ_¾Z|ø ¥øQíŠ^Íl.u=Ó;Œ²ÿÀx_¾fý¯4•âaŽo‡oö^¾÷ñ¦Ø¬ˆP0€+áŸÛ“,yÇü/þ€õðù-6¸‚•ûŸ[¯¬ciM­yŽ÷á/„¼¥ü%‚ÿû Á0ù‚Öêôø¦ùí"™¤·`̾_-+J ËðÁ,1ÔÙ|2Ó ²ø›ÃZZË:Cµp –Tò܆q±Y·îàãQø8'ÂÍ:+-;Á×w†-= µñ”â8RvhÎr £ðg‚w:€üEã'žÿCøgð’þÎæ(šökkƒ;XnÂãnâøÜOÝÎ2p?NÃÓ§:I´“j['Â_€>“ÃQêþ(ø ®£)(ÓøbòW·‘@áÙ?8n;`wÍ|}ÿŸøcÿ$Ñî>i?ðJ£iw· «MãXµ«®ÌÑ!³[bž|3mÚ^`q·;—®8ûÃáN•ã­‰¥øïCÒln `°[ørI¸MŠXáðA28¦Óœ“ŽWãn—¦êü=m¨êúõ¼’iב[A¢ëö–—3ÈÒÛ`(žT2/!3‚Ëž«WRŒy}È«ù­{ÞõìyÇ„4K«_ xN×Å‹à©5mCúdšŒWúÌ–óÜݵ´/rQ¨ËHçh «¡ÀÎÓÛx/Gø<-|BÕ<0ºÅ¡XõŸìÏ£Ã+3Q¾m˸/¹$mÿ‰¯“€ü%s ®g øÖ y.f qºG Ĉ 6²aJ´3|!ø¹4—RŸ†ß ¯ä‹›L˜ˆ‘ ™IüÈv´j¬ íö`ƒEFµŠû…Íær<#¥=ï…•¡ñfÎyî+§. þ´¼•âÜc§”J7øš_οJ»UÀSéžkªÑnö€ìßpº=Æ03ÏjêâÖ´ éŸÛþ%œ¬Kþ¦ûó7`}2IJZ³àCIÑm£ÖüK~–¶¢ETÞpdbxP;×é·ìÏûPxz éšN…:Coigè­ÀDP ~B¿-õÿ|Oñ Z¦°LvзúŠ’þ§Þ¾³ýþ#]xNŠo\€Ô-Ò¯“š,Â=ãö³ö~ø°Þ6ñÖ‹£µÆíº¥¤˜Ï¥Äcú×Úïü‘ÿ‚]|_oþÑzVn÷íH¤ÛŸK»qýkõ¸ ïNŒ\bÓîsâê/Ah£ ô4VÆEdzÐWûTþΞ2?õ¸ÿÐk¿?xWûHØWàWŠ4´”!¹Ò$ˆ9Û»8ük:‰ºoÐ:£åOü'ÿ„oÁfsñâ ÊÅ<öÇU²ÑäÔÝ‹o”Ý õU;p¡P7 úg†ÿd}sÄÚâoÚåŠ]XE#ZjjG:óbDbv8ÎÖÓ¯¯¥~Ξ Ò´ÿ±i?uÍ)Á“'GX6ÜÉŽhå†Ñ†öÇ®Cû6ø‘­!²—ö†ñÁT’áÆ¥yòUÜ"(9\pYqƒ\ÔðÐä\ËSGRWÐç4?Ø÷SÑVU›ã÷¾kn_¶A»Ëä’qÏè+œñ×€ì<­a_êþ!Ô.$’&Ñ|#suîB™ìFýÙ3 nL‘¸W¤ZþÏ7€[‰¿i_MäܤÒy’X8 Ä£bÔ|¥ˆ$ }У •=ÿÃ+ûï‰ö—S³DµÚ5“³¶Ø®Så“ÌAû@$91/>—õj}¿1{Iáû¦Ûç‹ÎYUCxõX–Çð± £‘ó¯?+b­Î…xšÌ‘Úøé›Üxî/·þàJØdä˜þm¿8#¦ ú×ì×_óÆÛþø£È¹ÿžß÷ìÒú­.ÁÏ#óóöÙðõŸÁm{Y³Õu97ø ÅP˜5=k6ñ*îgÞO_c_ˆý ÁX£–?€úƒ¼qø¡üUþ¬cþa×óÏq(Š"Äö¯É¼C‚Ž6ŒcÙŸèŸÐªváìÖOùáù3Ü¿à–: ×ÿkÝCWh·G£ø6úR}Ú(‡èí_© ìbˆF>ü`Wæ÷üÃMøÛ⇋dL}›G±³ñÔË4ŒÃò:ý'øiu a??ʸ(EÓÁÂ+±ùg‹—ö‡‰Xé7¤\c÷E~¬öï C^[ݫּx›WÀÅxdžõ8ÊFêǃƒšôo êi‡ÀïÍ*2÷ijì<ªÄõ;YU”6zÕÈ&Áí\Æ®G*ˆòGA[±NæS_c”fN“gæøŠ§&š/nÆÚòOÛOá«ñ§à.­á¯]I¥lŸlÓÄJ¤Ë,jÄGóŒ `ש ‰ã&›,…Õ”‘ȯ¢Äã¨â0î{™PœèVHî™ø!â üIMBXµMAw¤…]|§R<Œnâ°ÛKñTˆšá[ÉÃ5ú9ûZþÁ_|SñGPñwÃO ÛÜXê“™LJ¨bvûÇ ''ñ5â÷üãöŒ³Ž{•ø+¤-ÝJ¤¹ÿdgŸ­|ÖáMY³î%ˆÃW¦œ^¯Ìù"çLñtŠ99ô7øS-<9âMH‹kö ¸gbÙÇAŒÿʾºý>„ÖUÇìÝñoL}×_oã$n(Ðs·×é\˜¬ljRqVÔù,ò”«a§Ií%cÈaÓ>ÏÄŒd¸é]ìÞ²7íà§Ý´Údg¯ïV¬ø‡áOŽôÔ2xBùQÛjŸ³·&¦øáívÇöˆðcÝèÓÃåø–ÓÌßzµâ`í\ú¯Ìü¾†S6*UùŸ“zÿÆ ‹H'·Ó.цðyý>Áj߇¿¶'ü³À<  éšEæŸcý‹â½H²ŠÚMZÕU'"(”* FË…P8K„ï_ÉTú„3«1àÍ~ŸÁ©?·°øûaꟲ7Ž5µƒÃ_ A£ùòa-õëecá|øL±îén;Wë9](Q»î}ΨÒnÚŸÒ6qœÖ›; .Z°i —kލßßÁn†IXÞ±5Ú™‰Ôç¾kŽñGÄVØÈó/~}+ÃÇg³ÄÅ££“â1JÚüGñÍ„ò~ð ö¯†jßY\Ý"f"ìGû/þ5îþ)-­¼È“©à÷¯‡þ<|I}S]0 ÁÄ»ˆˆ®~\ùÝyŸ£e8X*ô`·¹õݯÄ?øa.¼…µ;ý §²î5=èOkHeI¢'0ß?ͼëi_|G¤x2kÏ„7WžÕæ¾íZ\Ø©ö´ !,d‚ÎPXŒ3&Il`nÍlkšö£áHN“íeœb-Ú¼ ÛÄ|¡œÇd7aQÔôÆ9ŠéôA¢ø¢Øø‡ã™{k`NŸ©é·~xMÕꄌ¿˜¶£ ÒJ„,!ÆpÆ¿BT+EY7ý|ÏÈ9àÏ>OÚ7ö•uW“Å*Lܪ0ŽŒÄG¹²ÿò …Œõqèiþ.ø§ñv?Ú\ø‡]Œo©Èš,rA»s–_N%q¶0y±+í÷ŸþéÀµòèÐs“IºP#pbM·œò¸lãiÅ1ñóàɸ†Ôßhk$ìË>•t¬H¾é¶+qƒå¿?)£Ùb;¿ëæð<¯Ã?>;ë…ã×>)x§Ge]é#I¤\+bHò¸]5pLm!Ïc0r3ROÚ#öˆ}õÌ^6ñaš €±¯4pn»|Çþ%¸IÁbq“ë‡íðWMK×–ïEu°‚I®Z-*é†Ô.oú7Ï‚˜ùsÊG5f/Žß% ýYvô»¥uf(6Ù ™+ÔnÉSöXŽïúù‡4ðdž'ø¥âÛŠü{«fÆkO&Î÷û73Iò¨O28ÓfÇ 1ƒ!Ï5üÄ‚_SŸoÁ¿ãÏrü#×?Þ?ìWõÕ࿉> ëpøoÂ’xzãPšÖ+ˆí ´¨û$·Šásºò¦Š“‘»®Ëþdýï è?çþÙW./_ny7ee}tí¹õœ)Åo…êNTé©s[«[|žçò áï„­§Fo„)õðýÏÿ_IþÅV¿>ünÐõÉ>xŽÝ<ï.Y$Ñnyä”õ¿¦aà­\ò<+ þŸüj”ø3YŸ è?Ÿÿj¯|,¥Z59šißeþgë Çügö-|ºXDãV.-ó=.··/G©ùù­xû]»Ób»UÛ"VÇÙÛ##8é\'ˆ+‡Œxzçür´­> |mÖì?Ò> x­.b6|;r7{ýÊýëñGü÷öCð·ˆî|&~5øÂ l§û<¾_ÃÍ>éce(]L¬Hf;YrÙÛ½½:'þý‚<3ðÖ÷Ä> ´ñF·.‰åý¾sàûH.nD· :B%U* Š8Ç OZ§‚ºÝýÄC*ÂWTV»ëÿþz?áH|sŠN> ø¯ ÿнsÿÄV½‡Á¹ŒŸƒ¾*ɃáûŸþ"¿~$ÿƒ’?`(­¾Õ/ÁŸªìGü"¶$¶OAþ—Œû_^+GÁðqìãt¾6? |kjú}ÄpÏ ÷†lRMî®Ê­Ñ=õÇQ]jŒß.¯Ðñóž%«šÑŒ%÷¿è~ Að—â׆4ÿí]Gà÷Цñ¼zÉfoûã­eZ|ý ø¥âË1_Zæ:ïhàvÏJæ¾#ÿÁǰ½V-#Å_ ¼n$šÒ+ˆÚßÃ.»dEuñô8aGZí½Xý—÷7*ªZ‹^ øñWGE‘þøˆÐaÏÿÄWy¥x â;þ¯ˆ†:Äšqÿ²Wêåü¯ÿöÔlbÔ øKã¯*fÚŒÞÓÁú‘öÌÿú«°—þ ËûÅò¯Â¸¶—Ë'‡ls»yN3uÏ þ=9ªŒª½¢ÄêE+3ã?ø$<¿<ûSkÄš­¢ÚÛè{¤ÔnôÇU€}ºÌbífU,ÁprF0zWê.û[ÝÜøõü?{ñ#V·Ðu^ݧ1%wà˜Ežà¬ps‘¼duÇ‚ÅÿèýЧtHþø¸y¯±èL˜È@MÖ ¹ÅVŸþý‡á´kÆøQã ‹˜D¾²‰º—l—JAç#<@$‚(x•EÚqwþ¼ŽZÒŒå~d¾ÿø¼kµïŠ4 éú…¿5 GQš ¤Ô,-M…¨ƒn<•_:Õ÷4ŠC}ì ™®øƒö±Õ4Õ[½â^¡¨Ãö wh–¤[§™VHŒ­m³jDZO¹–(@>Ÿ0xþ=ý‚|'¨YizÏÁÿ¥Æ $kT‡ÃZ|ÂmÜw-áùÆ9äsЂ`ºÿƒ“?`«NàÄWnÌQxJĸ©ÇÚùõãµRÆCuø’º—çþgÖ~ý§õ/éZ{ê/mõë™âI´Yã±–m¬±Û¡$G—ì3ÇÍÒ½ üG×_/ýû‡ÿˆ¯Ž¾ÿÁv¿b‰3øvÇGðGˆ­î|R›´{[íÑ^Aæ4c%geRYH5ÞØÁP~ê?ÚÍÁ¯"è׿e¼gÒ,±¿ü¸¸9#®:ŠáÄciÊ¢ŠŸ+ìwCˆ§KžQvÞúíóó=òóã:é·BÇPø—eÍõŠi-‘Šç°W8ϬŸ|UÐj}2Ð~>|sÔì^ó[ø©âm6k}¬ÖË9JÊT5@!–,g¨“¶Œßøi?ÚLé]ÿÂYâ!x÷B9¬þÓ£HöŒË¿û/¦â@@è3Ç©MûI|ŠÑïRm*XÒXc>V‰vÌÍ)AÕû6æÉ~ÃŒôæÍçíðZÊÊ{ù5=’ß~ñ™tÌJ¬ŒÁ@¶ù°"“8èWH{HÝâŽÙ”2äg¦E}·à)5 `žuŒàãø¢aý+ï3à­hÌ­ ÿß_ýª¾zý¥þ7xcàÞ‰ñ⇈õ«¸t¯xZâï\Ò´}.76Ëkoqs-ÄÖ34­Û±¤òó°ï$JTŸ,Ý¢•ôùw>7ñ¶k×ÌjRJU¤Ý®ô¿KÛ[#'ÃzÑ#GVääîô?ÅÐnT×-ŠüëÔ¿ààß{õEÓÛãlsiö"c·á‡æŽ4q\dצø9ö„º\ÿ²ßÆ^Üâåçð%‚$'vÒ¬ÆûÎW;€V$|§.³º›û¿àž}^/öÑ´©/¼ûßAñuŠJ%}B!Û™uwŽô¬€ú¥¿ã:ÿ~TÄ^ŸðJOú$ÿð‹°ÿäÚQÿyÿÁ)OO„ÿð‹°ÿäÚÞ1(}·÷Á<,FiKîáoŸüõÂø}×öÕ¨Èïp¿ãO>(ÐxÖìÿð%Æ¿"ÿâ/Oø%'ý?‰øEØòmñ§ü“þ‰Ä¿ü"ì?ù6·þÀ­ks¿»þ çûXv?Zæñw‡×*ºÍ©>¿h_ñ¬«ïhù êÖäz ×ükò«þ"óÿ‚RÿÑ"ø™ÿ„U‡ÿ&ÒÄ^ŸðJOú$ÿð‹°ÿäÚäŸ NkZîÿ‚mON›Øý-×¼Q¦ùlEô ; 5Àø—ÄÖw¼e•‰9¯ˆ|ÿeÁ.üqâÝ/ÁZ‰ûXÔ`²²x;OU2Ë"Æ€Ÿ¶ð70æ¾×ñ/á&×~×µ§Y\ÛiËk§°³Gc˜¤e4–ò3‰NFóŒ‚qσZ¯î*¾a °jJÈóOêwFÞU£63…Xó^gáÛN_‹~™tIÂmÛ³?ÙÛ ûÁÎq_Sèú/ÅgHµñm§Ä©ÖÅÁyO iÌ?(ÚÙn6ž»ž1Óë_<=¢é7Çü+‘t¶Ã/ ½³Èßî®ñšÒª5c56ìÓÛþ âÕú£jr’]w?“IcÏÚPÜ€¾9÷>¼¦çl|;ý•k?x¿Høà߆~9ѵSƒPÒ58¼/t²[]A"Ë‹˜þòº«¥N‘þÝ_ e“Éõ€Ààƒ¥Úqÿ‘«¨ðŸí%à/Éyo¦|=1MbÄIow ¤nøà”_˜WØB…X-ûŽÚY¦+s'ó?%ÿkOø-¿ü—ö…ÑÓÁ þ ë¿ t·²Ž-FóÞ¼—Rº—h:Ý<`Û©`Jˆ•]AÁ‘«ãÍàÇís[›Äþ0ð'Œ¯õ+ÙŒ·—ÚŽ‘w,Ó99.îêY˜žäæ¿¢cöðŽƒ(·Ô¾Ý*íµ-¬˜€ªIàM‘À§xOöŒðŒµôÝá%é–V ,m@?ùÖu°Õ«üWû[/â¬.\íJ1Wó×üÏŽÿà›qËð“öuÒ4 ZÖ{+¹[‹ˆîà18gr@!¹à`WÔ6tô€×"äã]íûJx#öZðå‰þ*|.-µ Z8>Ãgi#UÜr «Ž+æI¿à¿_°Äƒér|/ñ_š´áûgÿ«çkpº¯QÏ«ùÝ^6…gj”¢Úó=ÛQø»§*–Mb6>‹ ÿá¼eñi¥ÅµÁ~6 çò¯Gø?ûf|"øÝðºËâç„>M—æýž;û+XçýÜeD„™9éQê¶—ÂM:so?Ã[ÆaÆVÂÐýY.ŠÞoî0\u†¤íqO×þò?ůxÿR¶‘ôß ê÷ë˜Ú 6W{¦¾VñW†~5k~(™‡ÂÏ´a2ûr ÈîSúúŠýñüçö#ð~¿{áoøsS±Ô4ûƒÕ¤ú]˜xÜc~?1XºWüwàOí{âù´o€ž(Õ¡—NÓRkÍ!¬­"@‘”Ͼ'i Ÿ1iù0™ë×ÕÈrœ,Ò—,îïØô0Î+šRnW]O]ø—âû‹mRÞÚ_\AþŠ¥c—㥽—?e¹Á¬D©ã«0üµ&ñ•®j§Žü±‰.Ñ~8G Æ>Ñl 2DêC4€Èÿ1Qõ*ýC Ö¹ðGÆ8õ»¹×Â^3òÿá#’H^4ÐfÄF{r¯‘A+µ\ï—÷ˆ¶¾ ø±G_ñKÆbñ¬¨ÇM³`#øÏ1%# €Ñá‰à‰¾ëð[ø«—1š]wKš/ˆ2²&H¿h ic9øóZÇŸ»ã-°ýÑ-z½à¿‹BË„üW m2ØmŽ `©½Heàä6c#69 ÍŽro|g“_Óî%ðg’ID’\i>,†`2ñ˜9 ·:ûÕ Íë.’ëTÖ ñä’˜c›~~5Ãuå2Í0ù•a nËœ« !C èLj¤¼×¥¶ƒÇ—{]5&v²ø¹o¨:F,äÝ ·òÔìP™  Œ‘_ ~1ßk“5ïƒ#YÛEv ݸ8·–?6ô  ”]¯¥ëç_ h?®µkH¼cðw_i,ôÃ{g¯jÖºd·z·±\Ghÿgy³ß¼Q H AÆWÂ]oã‚uˆ~øûIñ/‰VêéXxªöÖÖ(í“Ë–=Ž!lZ×ÎÈ/ÛcC¸Ìët`¢Š(¢Š(¢Š(®zWœümÓ4æð¾­ª5Œ&ån,•n cx|<ëŠôgÇ_Jò¿Ž>/Óm¬u Oââw³”Jì &ˆžKg·¥.Jµ.¡ÙßЉJ·1üÃx­¬Ç~%+§3'ü$·Ì¢Ýö—È8軳ï‚+sáù´íf sG–çN…R9ØìM·pn‘ÈköKŸðDÏø'ÏÆKÍOÇž(ø—âÍî}Vw’Öéáe8“ä€ †ÆN22MjÜÿÁ¿ðNYô[ý/ÚÅ}»Êón“ÆZq–0’,ŠšÜ€ (Ï‚k ЫJ£„–«æo ôåÑùuà“ðU~êz¥ñŽy™r¢2‹5ªª6ÓÀ9ëžÜŠä¾é¾Õ5Mdj))qªXÏÔD´“)KÛŽÐw—¿×ëÿÙÁ<.¬î´OþÒ<Ý¡{±mâÝ.Wãþ†xû½°8Æ8®£Áßðn¿ìcà¸mãÿÄT{™‘žy|G§nÈ-´ YÕÏoJŠ/ØÔ».¬£V›z´¿âðö£eáô:eÏÙøh—Í ÉPz)ÉÉÝúŠùkö¾ðî½ñ O°Ñ•3‡tÆ™œü¥þÉí¥þ"x¯Ý¨?àߟت8ÞÖ‹¾2œÍ¸¿®iä±àŨöüë'Ä¿ðnì9â^=gRøÏãô–;(m‘`ñ‚¨Ž$¼}“®uÔÅBkúÿ3žpgà†t)­´Û- U„¢ðE»qÚñ×®2}? úPûm®‘x%´)pÓ…ÚÐq1ëÔÿõ«õrø6ö·ž;…øÕñ´WeÝâ[7Ÿùô®³Tÿ‚~ǺÄÞ÷ã'J³î}ºÖŸóÛ¹ÿDõ¥OJ7¹SŒ¬~0n^hñØk7 4@%›Í*„Ç$c¢úôÉÈjÜÀ4¸ôýOÊû]ݪÚÚÉ$ÒIó|ÂBx$…D‹k0À `µû"ßðowìZì7ü\ñ›¦Í²FúÎžË Æ>lÚsÇJŽø7“ö,µóßã/ŽÑåyŽ5û“VÚ§'’ qÒ¸±W«Í¬rKRLüA™-¥×4½_Æú=“G¹‚ßQŽGVÁWÞ²@Ī2UIT\Œ©5ëàíÃm&ì=ë†EÔmdU¾ÎD¸É#:c¶?I>.ÿÁ½ÿ±ßZh¯ão‰RÇ«ƒ>™â ĪïŽE“ghP ðqÔ’I<åÇüýûËkm¥Ãão‹ÛÛ0ʼn4੸m#<ž˜ü†zWM¯R”eYù¯ó7§Š£FÎ{¯&|Ùû üðž»àÏ‚¿~Çn²ÛÜß5Ź—÷dEw(Œ¸ÀÆ8aÇQŸZú²‡z'ˆ¼M©Ù_êío±þÖ ÓÃF“J7šÄa†:/ãÍ{Àø%À_ xzÇáÎãïÚiÚ,O%œÚޱdÄ38%r-–füëÒn¿à˜ß .of¾üY’Ä#_+T±5”}›ùæ¼ZÙCÃcäæ“M¦ÕÓ¶–{>úž¼³J˜¬$cÌïÒÓÏCù¾Öãµ]~÷Ε]ÅÜ„£ÀæB;w' ú×Ñ_ðGå·ÿ‚|9¸7‡ 6­²Qqä²ÿĦøýì‡ݺö¯Ó[Ÿø6cö ¼Õ$ÕgøÓñ ¥–Bì?á!Ӏ䓸óéÍZøOÿWý—ÿbïÚ;Âß¾ ëþ?×µËind¶’ó\Ó¤¶ŠI ’Ô# µBĬϷ0û »«è©U_v+ϧO™ãÍrêÏ¿ñt­ñnÒÊLÇûI[Íñ¾'3Ùå~É\ç<ܶp¿{†è3 ¥X:üA%9›þôL­ÿ˜V‡sr8Qʆùcçuüñ‘þ#Û^AàŸ‹¨ÆÏ(µÐmíÂy¶§'`3p«!È9]¬r¦¤xãUµ•ŠÝx?Æë"G2HZÈêquÁ%B…!“ç¼}ʘÔ-¼gâ¶·Ôu%_<>^¦ù𺢵 Ãç*ѳŒg=F +ÎÊÁÐ|[tþ5¶1øòå·Ø‘ÏŽÖs>dx ZÎ~þp?y»ïE]Ç‹<ñj[ûæ±ð¯‹dS¨‰­bÑç †eËHÀ~“ÉDJðÅôñdwW> ñ~Ãbë+Ï¢h<þòUö ¤aA¹TÎM[@ñÚ®¢¼>ó_Ù~ü|oŽõ|qq䙯7c÷˜ a’º_ø‡íZŒ‹7ĈàŠÁ$¸>*Á©¤Ju0ÒˆãS1Ú¾be˜R9’¡±øwñº+–Ôo¼ãï:I #ûΑÖ0áT@Få/+ÍÄúoÃߎ:~›"Âãs-½Ëµ´±§‡¤ ÈϺ32mO0 '%À3Úd`À:•õ¯í¢éø‹P1K§’Ðü@³1J lXéâ14˼‚\Cm mF¯¢+çÂ?5k«ûK¯‡ÚάYÙZ[è~){ n.í®-dŸ)$JL’ ‘¤eUûÀ÷Ÿü[ñ.;´øãßkóËn“LÞ)Ôb#›w•2ÂDGAqän6ÎÀ€Òö¯?౺^kÿäøÕ}ma sMðßÅ>tÉ ÿñ)»êGZûBÎzWÇ¿ðUyïþ&~ÄŸ>x/A¼½×.¼ â;8Õ7]ÜO¦ÝGQÙ,ÎÊ£ d‘K–¤“qÙo÷‘'kŸÆ’júœhɧp¡ŠîfçnvçžÙ8ôÉ¥‡YÕíî~Ù¯r“`5&`Ø<žsžkßüOþ L:þÆÞ7ÿÁ`ÿâ©?áÒŸðRm»¿á|oÿ‚ÑÿÅUYš=Ϩކ¾Š?ðIOø)(ëûxÜÜ4ñUwOÿ‚9ÁQuh Ö•û |C¹Œ1S$:çŽ2^GçIé¸îš(¯§áÌðUŸú0‰?øN½ðæø*ÏýGÄŸü'^—4;ŒùŠŠúwþÁÿYÿ£ø“ÿ„ëÑÿ`ÿ‚¬ÿуüIÿÂuèæ‡pÇþ›Ç¿¸–ŒHu›H¥8"Û®|Sµý4|vý‹>~Ó^Ó¼3ñkãF§«[é’æÀýºÇ)!NOúœ1*9ŽkÀîÿàߟؚóS{óñCʼn1;ŠÅ«éà.sÛì½8?•G¶¦zV¨ê9%¹‘ûø?Jñ/üKÂ~%{²ß¨ÿ¤#‘´%ìüÜŠâ|=o¨x߯ÑxvÇUŠ!qs²9îdÚ¸ÏS_h|0ý~|&ømû9xKâÕÿö©ŸÊ{‹Û7¹d¯# >ó7ððs¶_ðNOëp^Ëâî²d‰²|½JÏ(}ñX¦ãcέ•ו^h¤~Tköš-·Æ>³¦Âá¼O/—”Å—'©í÷:ô¯Ø®ßHÿ…û}¨hö0Âà¦G* oau == #?á_iêðEÙWÖ¥ñÿÆ=Ä×/päêš~ ±$Ÿøõ÷ÇÒ¸‹¿Øá'ìã ëÿ†ïâ}BCo ›jz•í¤°Ì²n‘ÑV#pÊaŒî$©ó:g§“‘eX¹ç0’¶º?Hʱ´cŽ£·Kcìy¡5’ÚKrºDHæÁ¼½ÊÁ‚ägã<ÑEWµ­IË–Oktÿ#/vkTr²~ÌÐÝjú®µ¨|tÖ®fÖ,$³¼ʬ« H’íˆnýȰٴ÷ŽU?fœK4³|ñÆ`ÜK¨11b|ÈÆüFã$\03ÀÁEd±ÿ™‡,9vFÑø8—Z=LJµÏ‰‡RÓî…Ç™g{n6‡žà\Í (êÊÍ0ßx=0.óöYøU¨ii¢ßE£KkfXdµ”‚Z8ã$þÿ,vEÉÉù}ÎJ+&]dÙp—,tF¿ƒ> x_áæ·'ˆ¼ªév7³@ðËp–nÅ‘™]Ý1²)Ï^+©Ûâ_ú(:þ ÿ¢ŠŸd»³^yßÿÑAÓÿðX?øå|KÿEOÿÁ`ÿã”QSìâò ¾%ÿ¢ƒ§ÿà°ñÊ6ø—þŠŸÿ‚ÁÿÇ(¢g=¬Ão‰¿è ißø-ür¾%ÿ¢ƒ§ÿà°ñÊ(§È…í$|MÿENÿÁhÿã”mñ7ý ;ÿ£ÿŽQEÎ%*³ ¾%ÿ¢ƒ§ÿà°ñÊÛijÏ>#ÙÆc™%GL\†F½d#ªŽÝ(¢ªœTjÆÝÅ)¾VlÉâωÑò¿ìÿðIÿQÂkñSþŠå—þ !ÿ⨢»ê)Åé'ø‘”XÂkñSþŠåþ !ÿâ¨ÿ„×â§ýËüCÿÅQEcÍSù™­ÂkñSþŠåþ !ÿâ¨ÿ„×â§ýËüCÿÅQEÕ?™…ÂkñSþŠåþ !ÿâ¨ÿ„×â§ýËüCÿÅQE>jŸÌÂÈCã?Šg“ñnÇÿÿñUÄ_|+ûn¿}â³ñÖ-JþúÛ‹Û}&‘®!`ÑHHo˜©Q€Ù㢊j­h%'®û‘Œ¤®‘Ïë?³¦§¯\ÝÝj_´‡ŠÞ›“㪀p;QED”ê{²“·Ëü‚-FZ"ÖßÿÑAÓÿðX?øå|KÿEOÿÁ`ÿã”Q\¾Î&Üì6ø—þŠŸÿ‚ÁÿÇ(Ûâ_ú(:þ ÿ¢Š=œC†ßÑ@Ó¿ðZ?øådx»ÁšÇŒ-R ¯‰ñÚKÊ »°²T–/2'…Ê’äRGÆFr0@4QZF¶’nâr控gû,ÚØéIƒãƽ•¼¸¹[ÖºÍÏ™:¢ÌLÛ·¾áyÜOÜÀÈ6bý›aDòî~8ëW*Í(”\Ýó"al¿ú ¶§EÏË«‚Šèö•¯ñ?ÃüŒ9`ÖÈÖñÁÆ’ÃwãßZë·VòÌðÞj6¼S,I €äQƒj½:zÍ›ö]øcq´Ï&˜å\¾çŠbÌ|ß4&ã-‡ù†~ïAÅV‹oVÍTíØ¿e¯†Vþ—Â÷bi7/µi˾TþPÄ{Ÿ'nNpKsšDý•¾ÅzúŒ2i±ÌàÈ“€ª7|ª¿h¯ÌxÈQEB¦»²ùØíö\øiá‰ôÛ¿ ]éºtú0oì©­a”Vo4Pg ·ï¥ä‚xÞ´‡öYøb¨ >_0¢Â“ª«I»s…Ýó±Î8'=h¢f»°ö²,\þÍ¿¯'77—štÒnv,S1À ôŽ2×=+kÁß ôßê:ž­áOiö·:Ì©.§1´yáÐ¬Ûæ<àž{÷¢Š=’¾ì9äoíñ/ý?ÿƒÿŽV|ãm&=+Zñô(îeû-ˆFÜ—Ÿœä`žÞ”Q]ù #include "driverChoice.h" // include the gui creator element factory #include "CGUIEditFactory.h" using namespace irr; using namespace gui; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; IrrlichtDevice *device = createDevice(driverType, core::dimension2du(800, 600)); video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment *env = device->getGUIEnvironment(); device->setResizable(true); /* first we create the factory which can make new GUI elements and register it with the gui environment. */ IGUIElementFactory* factory = new CGUIEditFactory(env); env->registerGUIElementFactory(factory); // remember to drop since we created with a create call factory->drop(); IGUISkin *skin = env->createSkin(EGST_WINDOWS_METALLIC); env->setSkin(skin); IGUIFont *font = env->getFont("../../media/lucida.xml"); if (font) skin->setFont(font); skin->drop(); // change transparency of skin for (s32 i=0; igetSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i); col.setAlpha(250); env->getSkin()->setColor((gui::EGUI_DEFAULT_COLOR)i, col); } /* now we add the GUI Editor Workspace */ env->addGUIElement("GUIEditor"); while(device->run()) { device->sleep(10); if (device->isWindowActive()) { driver->beginScene(true, true, video::SColor(0,200,200,200)); smgr->drawAll(); env->drawAll(); driver->endScene(); } } device->drop(); return 0; } irrlicht-1.8.3/tools/GUIEditor/GUIEditor_gcc.cbp0000644000000000000000000000460712574354552020114 0ustar rootroot irrlicht-1.8.3/tools/GUIEditor/GUI Editor_vc12.vcxproj0000644000000000000000000003064312574354552021121 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 {853A396E-C031-4C26-A716-5B4E176BE11D} GUI Editor Win32Proj GUIEditor Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled Neither false ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib %(AdditionalOptions) ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Neither false ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib %(AdditionalOptions) ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Full ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ProgramDatabase ../../bin/Win32-visualstudio/GUIEditor.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console true true Full ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ProgramDatabase ../../bin/Win32-visualstudio/GUIEditor.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console true true {e08e042a-6c45-411b-92be-3cc31331019f} false irrlicht-1.8.3/tools/GUIEditor/GUI Editor_vc11.vcxproj.filters0000644000000000000000000000601612574354552022564 0ustar rootroot {f6ad9df9-ebaa-4c0f-997b-c8101c1fc669} {7fd14cb1-d2e7-4fd0-85c1-68fc9d1249f7} {ab2c3f3a-1d99-4619-b5df-47fdd9449f3f} {740a4255-37cc-4ac4-94e9-f2f0970491a8} {a28a0b21-3336-432f-9759-ff2dc064874a} gui gui gui gui gui\GUIAttributes gui\Useful GUI Elements io gui gui gui gui gui\GUIAttributes gui\GUIAttributes gui\GUIAttributes gui\GUIAttributes gui\GUIAttributes gui\GUIAttributes gui\GUIAttributes gui\Useful GUI Elements gui\Element Editors io irrlicht-1.8.3/tools/GUIEditor/GUI Editor_vc11.vcxproj0000644000000000000000000003064212574354552021117 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 {853A396E-C031-4C26-A716-5B4E176BE11D} GUI Editor Win32Proj GUIEditor Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled Neither false ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib %(AdditionalOptions) ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Neither false ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib %(AdditionalOptions) ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Full ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ProgramDatabase ../../bin/Win32-visualstudio/GUIEditor.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console true true Full ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ProgramDatabase ../../bin/Win32-visualstudio/GUIEditor.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console true true {e08e042a-6c45-411b-92be-3cc31331019f} false irrlicht-1.8.3/tools/GUIEditor/GUI Editor_vc10.vcxproj.filters0000644000000000000000000000601612574354552022563 0ustar rootroot {f6ad9df9-ebaa-4c0f-997b-c8101c1fc669} {7fd14cb1-d2e7-4fd0-85c1-68fc9d1249f7} {ab2c3f3a-1d99-4619-b5df-47fdd9449f3f} {740a4255-37cc-4ac4-94e9-f2f0970491a8} {a28a0b21-3336-432f-9759-ff2dc064874a} gui gui gui gui gui\GUIAttributes gui\Useful GUI Elements io gui gui gui gui gui\GUIAttributes gui\GUIAttributes gui\GUIAttributes gui\GUIAttributes gui\GUIAttributes gui\GUIAttributes gui\GUIAttributes gui\Useful GUI Elements gui\Element Editors io irrlicht-1.8.3/tools/GUIEditor/GUI Editor_vc10.vcxproj0000644000000000000000000003064212574354552021116 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 {853A396E-C031-4C26-A716-5B4E176BE11D} GUI Editor Win32Proj GUIEditor Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled Neither false ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib %(AdditionalOptions) ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Neither false ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib %(AdditionalOptions) ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Full ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ProgramDatabase ../../bin/Win32-visualstudio/GUIEditor.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console true true Full ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Level3 ProgramDatabase ../../bin/Win32-visualstudio/GUIEditor.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console true true {e08e042a-6c45-411b-92be-3cc31331019f} false irrlicht-1.8.3/tools/GUIEditor/GUI Editor_v9.vcproj0000644000000000000000000001365512574354552020520 0ustar rootroot irrlicht-1.8.3/tools/GUIEditor/GUI Editor_v9.sln0000644000000000000000000000160012574354552017774 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 10.00 # Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GUI Editor_v9", "GUI Editor_v9.vcproj", "{853A396E-C031-4C26-A716-5B4E176BE11D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.ActiveCfg = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.Build.0 = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.ActiveCfg = Release|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/tools/GUIEditor/GUI Editor_v8.vcproj0000644000000000000000000001357012574354552020513 0ustar rootroot irrlicht-1.8.3/tools/GUIEditor/GUI Editor_v8.sln0000644000000000000000000000157112574354552020002 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C++ Express 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GUI Editor", "GUI Editor.vcproj", "{853A396E-C031-4C26-A716-5B4E176BE11D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.ActiveCfg = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.Build.0 = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.ActiveCfg = Release|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/tools/GUIEditor/EGUIEditTypes.h0000644000000000000000000000221512574354552017545 0ustar rootroot#ifndef __C_GUIEDIT_TYPES_H_INCLUDED__ #define __C_GUIEDIT_TYPES_H_INCLUDED__ #include "irrTypes.h" namespace irr { namespace gui { enum EGUIEDIT_ELEMENT_TYPES { // GUI Editor EGUIEDIT_GUIEDIT=0, EGUIEDIT_GUIEDITWINDOW, // Generic EGUIEDIT_GUIPANEL, EGUIEDIT_TEXTUREBROWSER, // Attribute editors EGUIEDIT_ATTRIBUTEEDITOR, EGUIEDIT_STRINGATTRIBUTE, EGUIEDIT_BOOLATTRIBUTE, EGUIEDIT_ENUMATTRIBUTE, EGUIEDIT_COLORATTRIBUTE, EGUIEDIT_COLORFATTRIBUTE, EGUIEDIT_TEXTUREATTRIBUTE, // Dummy editor stubs EGUIEDIT_CONTEXTMENUEDITOR, EGUIEDIT_MENUEDITOR, EGUIEDIT_FILEDIALOGEDITOR, EGUIEDIT_COLORDIALOGEDITOR, EGUIEDIT_MODALSCREENEDITOR, // Count EGUIEDIT_COUNT }; const c8* const GUIEditElementTypeNames[] = { "GUIEditor", "GUIEditWindow", "panel", "textureCacheBrowser", "attributeEditor", "string_attribute", "bool_attribute", "enum_attribute", "color_attribute", "colorf_attribute", "texture_attribute", // dummy editors "contextMenu_editor", "menu_editor", "fileOpenDialog_editor", "colorSelectDialog_editor", "modalScreen_editor", 0 }; } // gui } // irr #endif irrlicht-1.8.3/tools/GUIEditor/CMemoryReadWriteFile.h0000644000000000000000000000442112574354552021144 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_MEMORY_READ_WRITE_FILE_H_INCLUDED__ #define __C_MEMORY_READ_WRITE_FILE_H_INCLUDED__ #include "IWriteFile.h" #include "IReadFile.h" #include "irrArray.h" #include "irrString.h" #include "memory.h" namespace irr { namespace io { //! Provides write acess to an array as if it is a file. class CMemoryReadWriteFile : public virtual IWriteFile, public virtual IReadFile { public: CMemoryReadWriteFile(const c8* filename=0); //! Reads an amount of bytes from the file. //! \param buffer: Pointer to buffer of bytes to write. //! \param sizeToWrite: Amount of bytes to wrtie to the file. //! \return Returns how much bytes were written. virtual s32 write(const void* buffer, u32 sizeToWrite); //! Changes position in file, returns true if successful. //! \param finalPos: Destination position in the file. //! \param relativeMovement: If set to true, the position in the file is //! changed relative to current position. Otherwise the position is changed //! from begin of file. //! \return Returns true if successful, otherwise false. virtual bool seek(long finalPos, bool relativeMovement = false); //! Returns size of file. //! \return Returns the size of the file in bytes. virtual long getSize() const; //! Reads an amount of bytes from the file. //! \param buffer: Pointer to buffer where to read bytes will be written to. //! \param sizeToRead: Amount of bytes to read from the file. //! \return Returns how much bytes were read. virtual s32 read(void* buffer, u32 sizeToRead); //! Returns the current position in the file. //! \return Returns the current position in the file in bytes. virtual long getPos() const; //! Returns name of file. //! \return Returns the file name as zero terminated character string. virtual const io::path& getFileName() const; //! Returns file data as an array core::array& getData(); private: core::array Data; io::path FileName; long Pos; }; } // end namespace io } // end namespace irr #endif // __C_MEMORY_READ_WRITE_FILE_H_INCLUDED__ irrlicht-1.8.3/tools/GUIEditor/CMemoryReadWriteFile.cpp0000644000000000000000000000322312574354552021476 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CMemoryReadWriteFile.h" using namespace irr; using namespace io; CMemoryReadWriteFile::CMemoryReadWriteFile(const c8* filename) : Data(), FileName(filename), Pos(0) { } s32 CMemoryReadWriteFile::write(const void* buffer, u32 sizeToWrite) { // no point in writing 0 bytes if (sizeToWrite < 1) return 0; // expand size if (Pos + sizeToWrite > Data.size()) Data.set_used(Pos+sizeToWrite); // copy data memcpy( (void*) &Data[Pos], buffer, (size_t) sizeToWrite); Pos += sizeToWrite; return sizeToWrite; } bool CMemoryReadWriteFile::seek(long finalPos, bool relativeMovement) { if (relativeMovement) { if (finalPos + Pos < 0) return 0; else Pos += finalPos; } else { Pos = finalPos; } if (Pos > (s32)Data.size()) Data.set_used(Pos+1); return true; } const io::path& CMemoryReadWriteFile::getFileName() const { return FileName; } long CMemoryReadWriteFile::getPos() const { return Pos; } core::array& CMemoryReadWriteFile::getData() { return Data; } long CMemoryReadWriteFile::getSize() const { return Data.size(); } s32 CMemoryReadWriteFile::read(void* buffer, u32 sizeToRead) { // cant read past the end if (Pos + sizeToRead >= Data.size()) sizeToRead = Data.size() - Pos; // cant read 0 bytes if (!sizeToRead) return 0; // copy data memcpy( buffer, (void*) &Data[Pos], (size_t) sizeToRead); Pos += sizeToRead; return sizeToRead; } irrlicht-1.8.3/tools/GUIEditor/CGUITextureCacheBrowser.h0000644000000000000000000000430012574354552021556 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_TEXTURE_CACHE_BROWSER_H_INCLUDED__ #define __C_GUI_TEXTURE_CACHE_BROWSER_H_INCLUDED__ #include "IGUIWindow.h" #include "CGUIPanel.h" #include "IGUIImage.h" #include "EGUIEditTypes.h" namespace irr { namespace gui { //! Texture cache browser const u32 TEXTURE_BROWSER_TEXTURE_SELECTED = 0x5E1EC7ED; // custom event number for texture selected class CGUITextureCacheBrowser : public IGUIWindow { public: //! constructor CGUITextureCacheBrowser(IGUIEnvironment* environment, s32 id=-1, IGUIElement *parent=0); //! destructor ~CGUITextureCacheBrowser(); //! event handler virtual bool OnEvent(const SEvent &event); //! draws the element virtual void draw(); //! update absolute position virtual void updateAbsolutePosition(); //! this shoudln't be serialized, but this is included as it's an example virtual const c8* getTypeName() const { return "textureCacheBrowser"; } //! Returns pointer to the close button virtual IGUIButton* getCloseButton() const { return CloseButton; } //! Returns pointer to the minimize button virtual IGUIButton* getMinimizeButton() const { return 0;} //! Returns pointer to the maximize button virtual IGUIButton* getMaximizeButton() const { return 0;} //! get draggable virtual bool isDraggable() const; //! get draggable virtual void setDraggable(bool draggable); //! not used virtual core::rect getClientRect() const; virtual void setDrawBackground(bool draw) { } virtual bool getDrawBackground() const { return true; } virtual void setDrawTitlebar(bool draw) { } virtual bool getDrawTitlebar() const { return true; } void setSelected(s32 index=-1); private: void updateImageList(); core::array Images; core::position2d DragStart; IGUIButton* CloseButton; CGUIPanel* Panel; s32 SelectedTexture; bool Dragging; bool IsDraggable; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/tools/GUIEditor/CGUITextureCacheBrowser.cpp0000644000000000000000000002037012574354552022116 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUITextureCacheBrowser.h" #include "IGUIEnvironment.h" #include "IGUIButton.h" #include "IGUISkin.h" #include "IGUIFont.h" #include "IVideoDriver.h" namespace irr { namespace gui { CGUITextureCacheBrowser::CGUITextureCacheBrowser(IGUIEnvironment* environment, s32 id, IGUIElement *parent) : IGUIWindow(environment, parent, id, core::rect(0,0,300,200)), CloseButton(0), Panel(0), SelectedTexture(-1), Dragging(false), IsDraggable(true) { #ifdef _DEBUG setDebugName("CGUITextureCacheBrowser"); #endif IGUISkin* skin = 0; IGUISpriteBank* sprites = 0; video::SColor color(255,255,255,255); if (environment) skin = environment->getSkin(); s32 buttonw = 15; if (skin) { buttonw = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); sprites = skin->getSpriteBank(); color = skin->getColor(EGDC_WINDOW_SYMBOL); } s32 posx = RelativeRect.getWidth() - buttonw - 4; CloseButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close" ); CloseButton->setSubElement(true); CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); if (sprites) { CloseButton->setSpriteBank(sprites); CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), color); CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), color); } CloseButton->grab(); // window title Text = L"Texture Browser"; // panel element Panel = new CGUIPanel(environment, this); Panel->setRelativePosition( core::rect(1, buttonw + 5, 151, RelativeRect.getHeight() - 1)); Panel->setAlignment(EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); Panel->setBorder(true); Panel->setSubElement(true); // some buttons // add images from texture cache updateImageList(); } CGUITextureCacheBrowser::~CGUITextureCacheBrowser() { if (CloseButton) CloseButton->drop(); if (Panel) Panel->drop(); // drop images u32 i; for (i=0; idrop(); Images[i]->remove(); } Images.clear(); } void CGUITextureCacheBrowser::updateImageList() { if (!Panel) return; video::IVideoDriver* Driver = Environment->getVideoDriver(); // clear images u32 i; for (i=0; idrop(); Images[i]->remove(); } Images.clear(); u32 count = (u32)Driver->getTextureCount(); s32 h = Panel->getClientArea().getWidth()-10; s32 hw = h/2; core::rect pos(Panel->getClientArea().getCenter().X - Panel->getAbsolutePosition().UpperLeftCorner.X - hw, 5, Panel->getClientArea().getCenter().X - Panel->getAbsolutePosition().UpperLeftCorner.X + hw, h+5); core::position2di moveDist(0, h+5); for (u32 i=0; igetTextureByIndex(i); details = L"File name: "; details += tex->getName(); details += L"\nFormat: "; video::ECOLOR_FORMAT cf = tex->getColorFormat(); bool alpha = false; switch (cf) { case video::ECF_A1R5G5B5: details += L"A1R5G5B5 (16-bit with 1-bit alpha channel)\n"; alpha = true; break; case video::ECF_R5G6B5: details += L"R5G6B5 (16-bit, no alpha channel)\n"; break; case video::ECF_R8G8B8: details += L"R8G8B8 (16-bit, no alpha channel)\n"; break; case video::ECF_A8R8G8B8: details += L"R8G8B8 (32-bit with 8-bit alpha channel)\n"; alpha = true; break; default: details += L"Unknown\n"; } core::dimension2du osize = tex->getOriginalSize(); core::dimension2du size = tex->getOriginalSize(); details += "Size: "; details += size.Width; details += "x"; details += size.Height; if (osize != size) { details += "\nOriginal Size: "; details += osize.Width; details += "x"; details += osize.Height; } details += L"\nMip-maps: "; if (tex->hasMipMaps()) details += L"Yes\n"; else details += L"No\n"; IGUIImage* img = Environment->addImage(tex, core::position2di(1,1), alpha, Panel, i); img->grab(); Images.push_back(img); img->setRelativePosition(pos); img->setToolTipText(details.c_str()); img->setScaleImage(true); img->setColor( SelectedTexture == (s32)i ? video::SColor(255,255,255,255) : video::SColor(128,128,128,128) ); pos = pos + moveDist; } } void CGUITextureCacheBrowser::updateAbsolutePosition() { IGUIWindow::updateAbsolutePosition(); updateImageList(); } //! called if an event happened. bool CGUITextureCacheBrowser::OnEvent(const SEvent &event) { switch(event.EventType) { case EET_GUI_EVENT: if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) { if (event.GUIEvent.Caller == (IGUIElement*)this) Dragging = false; return true; } else if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) { if (event.GUIEvent.Caller == CloseButton) { remove(); return true; } } break; case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; if (getElementFromPoint(DragStart) == this) { if (!Environment->hasFocus(this)) { Dragging = IsDraggable; //Environment->setFocus(this); if (Parent) Parent->bringToFront(this); } return true; } else { if (Panel->getAbsolutePosition().isPointInside(DragStart)) { // select an image IGUIElement* el = Panel->getElementFromPoint(DragStart); if (el && el != Panel) { if (el->getType() == EGUIET_IMAGE) { setSelected(el->getID()); } } else { setSelected(); } } } break; case EMIE_LMOUSE_LEFT_UP: Dragging = false; //Environment->removeFocus(this); return true; case EMIE_MOUSE_MOVED: if (Dragging) { // gui window should not be dragged outside its parent if (Parent) if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 || event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 || event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 || event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1) return true; move(core::position2d(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y)); DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; return true; } break; default: break; } default: break; } return Parent ? Parent->OnEvent(event) : false; } void CGUITextureCacheBrowser::setSelected(s32 index) { SelectedTexture = index; updateImageList(); printf("Texture %d selected\n", index); } void CGUITextureCacheBrowser::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); core::rect rect = AbsoluteRect; core::rect *cl = &AbsoluteClippingRect; // draw body fast rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER), AbsoluteRect, &AbsoluteClippingRect); // draw window text if (Text.size()) { rect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X); rect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y); rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5; IGUIFont* font = skin->getFont(); if (font) font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true, cl); } IGUIElement::draw(); } bool CGUITextureCacheBrowser::isDraggable() const { return IsDraggable; } void CGUITextureCacheBrowser::setDraggable(bool draggable) { IsDraggable = draggable; if (Dragging && !IsDraggable) Dragging = false; } //! Returns the rectangle of the drawable area (without border, without titlebar and without scrollbars) core::rect CGUITextureCacheBrowser::getClientRect() const { return core::recti(); } } // namespace gui } // namespace irr irrlicht-1.8.3/tools/GUIEditor/CGUITextureAttribute.h0000644000000000000000000001020412574354552021152 0ustar rootroot#ifndef __C_GUI_TEXTURE_ATTRIBUTE_H_INCLUDED__ #define __C_GUI_TEXTURE_ATTRIBUTE_H_INCLUDED__ #include "CGUIAttribute.h" #include "IGUIEditBox.h" #include "IGUIImage.h" #include "IGUIButton.h" #include "EGUIEditTypes.h" namespace irr { namespace gui { class CGUITextureAttribute : public CGUIAttribute { public: // CGUITextureAttribute(IGUIEnvironment* environment, IGUIElement *parent, s32 myParentID) : CGUIAttribute(environment, parent, myParentID), AttribEditBox(0), AttribImage(0), AttribButton(0) { IGUISkin* skin = Environment->getSkin(); core::rect r = getAbsolutePosition(); s32 topy = skin->getFont()->getDimension(L"A").Height + 10; s32 h = skin->getFont()->getDimension(L"A").Height + 5; AttribImage = environment->addImage(0, core::position2di(0, topy), false, this); AttribImage->setRelativePosition( core::rect(0,topy, r.getWidth() - 5, 100+topy)); AttribImage->grab(); AttribImage->setSubElement(true); AttribImage->setScaleImage(true); AttribImage->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); topy += 105; core::rect r2(0, topy, r.getWidth() - 15 - skin->getSize(EGDS_CHECK_BOX_WIDTH), topy + h); core::rect br(r.getWidth() - 10 - skin->getSize(EGDS_CHECK_BOX_WIDTH), topy, r.getWidth(), topy + h); AttribEditBox = environment->addEditBox(0, r2, true, this, -1); AttribEditBox->grab(); AttribEditBox->setSubElement(true); AttribEditBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); AttribButton = environment->addButton(br, this, -1, L"..."); AttribButton->grab(); AttribButton->setSubElement(true); AttribButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); //AttribButton->setSpriteBank(skin->getSpriteBank()); //AttribButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_FILE), skin->getColor(EGDC_WINDOW_SYMBOL)); //AttribButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_FILE), skin->getColor(EGDC_WINDOW_SYMBOL), true); } virtual ~CGUITextureAttribute() { if (AttribEditBox) AttribEditBox->drop(); if (AttribImage) AttribImage->drop(); if (AttribButton) AttribButton->drop(); } virtual bool OnEvent(const SEvent &e) { if (IsEnabled) { switch (e.EventType) { case EET_GUI_EVENT: switch (e.GUIEvent.EventType) { case EGET_BUTTON_CLICKED: // button click: open file dialog if (e.GUIEvent.Caller == AttribButton) { //Environment->addGUIElement("textureBrowser", Environment->getRootGUIElement()); return true; } break; case EGET_FILE_SELECTED: // file selected: change editbox value and set event return true; case EGET_FILE_CHOOSE_DIALOG_CANCELLED: return true; default: break; } break; case EET_KEY_INPUT_EVENT: return true; default: break; } } return CGUIAttribute::OnEvent(e); } virtual void setAttrib(io::IAttributes *attribs, u32 attribIndex) { AttribEditBox->setText(attribs->getAttributeAsStringW(attribIndex).c_str()); AttribImage->setImage(attribs->getAttributeAsTexture(Index)); CGUIAttribute::setAttrib(attribs, attribIndex); } //! save the attribute and possibly post the event to its parent virtual bool updateAttrib(bool sendEvent=true) { if (!Attribs) return true; Attribs->setAttribute(Index, AttribEditBox->getText()); core::stringw tmp = Attribs->getAttributeAsStringW(Index); AttribEditBox->setText(Attribs->getAttributeAsStringW(Index).c_str()); AttribImage->setImage(Attribs->getAttributeAsTexture(Index)); return CGUIAttribute::updateAttrib(sendEvent); } //! Returns the type name of the gui element. virtual const c8* getTypeName() const { return GUIEditElementTypeNames[EGUIEDIT_TEXTUREATTRIBUTE]; } private: IGUIEditBox* AttribEditBox; IGUIImage* AttribImage; IGUIButton* AttribButton; }; } // namespace gui } // namespace irr #endif irrlicht-1.8.3/tools/GUIEditor/CGUIStringAttribute.h0000644000000000000000000000352512574354552020770 0ustar rootroot#ifndef __C_GUI_STRING_ATTRIBUTE_H_INCLUDED__ #define __C_GUI_STRING_ATTRIBUTE_H_INCLUDED__ #include "CGUIAttribute.h" #include "IGUIEditBox.h" #include "EGUIEditTypes.h" namespace irr { namespace gui { class CGUIStringAttribute : public CGUIAttribute { public: // CGUIStringAttribute(IGUIEnvironment* environment, IGUIElement *parent, s32 myParentID) : CGUIAttribute(environment, parent, myParentID), AttribEditBox(0) { core::rect r = getAbsolutePosition(); core::rect r2(0, Environment->getSkin()->getFont()->getDimension(L"A").Height + 10, r.getWidth() - 5, Environment->getSkin()->getFont()->getDimension(L"A").Height*2 + 15 ); AttribEditBox = environment->addEditBox(0, r2, true, this, -1); AttribEditBox->grab(); AttribEditBox->setSubElement(true); AttribEditBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); } virtual ~CGUIStringAttribute() { if (AttribEditBox) AttribEditBox->drop(); } virtual void setAttrib(io::IAttributes *attribs, u32 attribIndex) { AttribEditBox->setText(attribs->getAttributeAsStringW(attribIndex).c_str()); CGUIAttribute::setAttrib(attribs, attribIndex); } //! save the attribute and possibly post the event to its parent virtual bool updateAttrib(bool sendEvent=true) { if (!Attribs) return true; Attribs->setAttribute(Index, AttribEditBox->getText()); AttribEditBox->setText(Attribs->getAttributeAsStringW(Index).c_str()); return CGUIAttribute::updateAttrib(sendEvent); } //! Returns the type name of the gui element. virtual const c8* getTypeName() const { return GUIEditElementTypeNames[EGUIEDIT_STRINGATTRIBUTE]; } private: IGUIEditBox* AttribEditBox; }; } // namespace gui } // namespace irr #endif irrlicht-1.8.3/tools/GUIEditor/CGUIPanel.h0000644000000000000000000000616112574354552016674 0ustar rootroot// Copyright 2006-2012 Asger Feldthaus // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef _C_GUI_PANEL_H_ #define _C_GUI_PANEL_H_ #include "IGUIElement.h" #include "EGUIEditTypes.h" namespace irr { namespace gui { class IGUIScrollBar; class IGUITab; enum E_SCROLL_BAR_MODE { //! The scrollbar will only show up when needed. ESBM_AUTOMATIC = 0, //! The scrollbar will never be visible. ESBM_ALWAYS_INVISIBLE, //! The scrollbar will always the visible. ESBM_ALWAYS_VISIBLE, //! just a count of how many are in this enum ESBM_COUNT }; const c8* const GUIScrollBarModeNames[] = { "automatic", "alwaysInvisible", "alwaysVisible", 0 }; class CGUIPanel : public IGUIElement { public: CGUIPanel( IGUIEnvironment* environment, IGUIElement* parent, s32 id=-1, const core::rect& rectangle = core::rect(0,0,100,100), bool border=false, E_SCROLL_BAR_MODE vMode=ESBM_AUTOMATIC, E_SCROLL_BAR_MODE hMode=ESBM_ALWAYS_INVISIBLE ); virtual ~CGUIPanel(); //! draws the panel and its children virtual void draw(); //! returns true if it has a border, false if not bool hasBorder() const; //! sets whether the element draws a border void setBorder(bool enabled); //! returns a pointer to the vertical scrollbar IGUIScrollBar* getVScrollBar() const; //! returns a pointer to the horizontal scrollbar IGUIScrollBar* getHScrollBar() const; //! returns the vertical scrollbar visibility rule E_SCROLL_BAR_MODE getVScrollBarMode() const; //! sets the vertical scrollbar visibility rule void setVScrollBarMode(E_SCROLL_BAR_MODE mode); //! returns the horizontal scrollbar visibility rule E_SCROLL_BAR_MODE getHScrollBarMode() const; //! sets the horizontal scrollbar visibility rule void setHScrollBarMode(E_SCROLL_BAR_MODE mode); //! returns the visible area inside the panel, excluding scrollbar and border core::rect getClientArea() const; virtual bool OnEvent(const SEvent &event); //! adds a child to the panel virtual void addChild(IGUIElement* child); //! removes a child from the panel virtual void removeChild(IGUIElement* child); //! updates the absolute position virtual void updateAbsolutePosition(); //! returns children of the inner pane virtual const core::list& getChildren(); //! Returns the type name of the gui element. virtual const c8* getTypeName() const { return GUIEditElementTypeNames[EGUIEDIT_GUIPANEL]; } virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0); virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); protected: void moveInnerPane(); void resizeInnerPane(); void calculateClientArea(); private: IGUIScrollBar* VScrollBar; IGUIScrollBar* HScrollBar; IGUITab* ClipPane; IGUITab* InnerPane; E_SCROLL_BAR_MODE VScrollBarMode; E_SCROLL_BAR_MODE HScrollBarMode; bool NeedsUpdate; bool Border; }; } // namespace gui } // namespace irr #endif irrlicht-1.8.3/tools/GUIEditor/CGUIPanel.cpp0000644000000000000000000002201512574354552017223 0ustar rootroot// Copyright 2006-2012 Asger Feldthaus // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h /* Originally Klasker's but I've messed around with it lots - Gaz */ #include "CGUIPanel.h" #include "IGUIEnvironment.h" #include "IGUIScrollBar.h" #include "IGUITabControl.h" #include "IVideoDriver.h" const int SCROLL_BAR_SIZE = 16; // Scroll bars are 16 pixels wide const int BORDER_WIDTH = 2; namespace irr { namespace gui { CGUIPanel::CGUIPanel(IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle, bool border, E_SCROLL_BAR_MODE vMode, E_SCROLL_BAR_MODE hMode) : IGUIElement(EGUIET_ELEMENT, environment, parent, id, rectangle), VScrollBar(0), HScrollBar(0), ClipPane(0), InnerPane(0), VScrollBarMode(vMode), HScrollBarMode(hMode), NeedsUpdate(true), Border(border) { #ifdef _DEBUG setDebugName("CGUIPanel"); #endif s32 width = rectangle.getWidth(); s32 height = rectangle.getHeight(); core::rect rct = core::rect(width - SCROLL_BAR_SIZE,0, width, height); VScrollBar = environment->addScrollBar(false, rct, 0, id); VScrollBar->setSubElement(true); VScrollBar->setTabStop(false); VScrollBar->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); VScrollBar->grab(); IGUIElement::addChild(VScrollBar); rct = core::rect(0, height - SCROLL_BAR_SIZE, width - SCROLL_BAR_SIZE,height ); HScrollBar = environment->addScrollBar(true, rct, 0, id); HScrollBar->setSubElement(true); HScrollBar->setTabStop(false); HScrollBar->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); HScrollBar->grab(); IGUIElement::addChild(HScrollBar); rct = core::rect(0,0, width - SCROLL_BAR_SIZE, height - SCROLL_BAR_SIZE); ClipPane = environment->addTab( rct, 0, -1); ClipPane->setSubElement(true); ClipPane->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); ClipPane->grab(); IGUIElement::addChild(ClipPane); InnerPane = environment->addTab(rct, ClipPane, -1); InnerPane->setSubElement(true); InnerPane->grab(); calculateClientArea(); resizeInnerPane(); } CGUIPanel::~CGUIPanel() { // because the inner pane has the list of children, we need to remove the outer ones manually IGUIElement::removeChild(VScrollBar); IGUIElement::removeChild(HScrollBar); IGUIElement::removeChild(ClipPane); // now we can drop the others VScrollBar->drop(); HScrollBar->drop(); ClipPane->drop(); InnerPane->drop(); } void CGUIPanel::draw() { if (NeedsUpdate) { calculateClientArea(); resizeInnerPane(); NeedsUpdate = false; } IGUISkin* skin = Environment->getSkin(); if (Border && skin) { skin->draw3DSunkenPane( this, skin->getColor( EGDC_APP_WORKSPACE), false, true, AbsoluteRect, &AbsoluteClippingRect ); } IGUIElement::draw(); } void CGUIPanel::addChild(IGUIElement *child) { // add the child to the inner pane InnerPane->addChild(child); NeedsUpdate = true; } void CGUIPanel::removeChild(IGUIElement *child) { InnerPane->removeChild(child); NeedsUpdate = true; } //! returns children of the inner pane const core::list& CGUIPanel::getChildren() { return InnerPane->getChildren(); } bool CGUIPanel::hasBorder() const { return Border; } void CGUIPanel::setBorder( bool enabled ) { Border = enabled; } IGUIScrollBar* CGUIPanel::getVScrollBar() const { return VScrollBar; } IGUIScrollBar* CGUIPanel::getHScrollBar() const { return HScrollBar; } E_SCROLL_BAR_MODE CGUIPanel::getVScrollBarMode() const { return VScrollBarMode; } void CGUIPanel::setVScrollBarMode( E_SCROLL_BAR_MODE mode ) { VScrollBarMode = mode; NeedsUpdate = true; } E_SCROLL_BAR_MODE CGUIPanel::getHScrollBarMode() const { return HScrollBarMode; } void CGUIPanel::setHScrollBarMode(E_SCROLL_BAR_MODE mode) { HScrollBarMode = mode; NeedsUpdate = true; } bool CGUIPanel::OnEvent(const SEvent &event) { // Redirect mouse wheel to scrollbar if (event.EventType == EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_MOUSE_WHEEL) { if (VScrollBar->isVisible()) { Environment->setFocus(VScrollBar); VScrollBar->OnEvent(event); return true; } else if (VScrollBar->isVisible()) { Environment->setFocus(HScrollBar); HScrollBar->OnEvent(event); return true; } } else { if (event.EventType == EET_GUI_EVENT && event.GUIEvent.EventType == EGET_SCROLL_BAR_CHANGED && (event.GUIEvent.Caller == HScrollBar || event.GUIEvent.Caller == VScrollBar) ) { moveInnerPane(); return true; } } return IGUIElement::OnEvent(event); } void CGUIPanel::moveInnerPane() { core::dimension2d dim = InnerPane->getAbsolutePosition().getSize(); core::position2d newpos(HScrollBar->isVisible() ? -HScrollBar->getPos() : 0 , VScrollBar->isVisible() ? -VScrollBar->getPos() : 0); core::rect r(newpos, newpos + dim); InnerPane->setRelativePosition(r); } void CGUIPanel::updateAbsolutePosition() { IGUIElement::updateAbsolutePosition(); calculateClientArea(); resizeInnerPane(); } void CGUIPanel::resizeInnerPane() { if (!HScrollBar || !VScrollBar || !InnerPane || !ClipPane) return; // get outer pane size core::rect outerRect = ClipPane->getRelativePosition(); // resize flexible children depending on outer pane InnerPane->setRelativePosition(outerRect); // get desired size (total size of all children) core::rect totalRect(0, 0, 0, 0); core::list::ConstIterator it; for (it = InnerPane->getChildren().begin(); it != InnerPane->getChildren().end(); ++it) { core::rect rct = (*it)->getRelativePosition(); totalRect.addInternalPoint(rct.UpperLeftCorner); totalRect.addInternalPoint(rct.LowerRightCorner); } // move children if pane needs to grow core::position2di adjustedMovement(0,0); if (totalRect.UpperLeftCorner.X < 0) adjustedMovement.X = -totalRect.UpperLeftCorner.X; if (totalRect.UpperLeftCorner.Y < 0) adjustedMovement.Y = -totalRect.UpperLeftCorner.Y; if (adjustedMovement.X > 0 || adjustedMovement.Y > 0) { totalRect += adjustedMovement; for (it = InnerPane->getChildren().begin(); it != InnerPane->getChildren().end(); ++it ) { (*it)->move(adjustedMovement); } } // make sure the inner pane is at least as big as the outer if (totalRect.getWidth() < outerRect.getWidth()) { totalRect.UpperLeftCorner.X = 0; totalRect.LowerRightCorner.X = outerRect.getWidth(); } if (totalRect.getHeight() < outerRect.getHeight()) { totalRect.UpperLeftCorner.Y = 0; totalRect.LowerRightCorner.Y = outerRect.getHeight(); } InnerPane->setRelativePosition(totalRect); // scrollbars if ( HScrollBarMode != ESBM_ALWAYS_INVISIBLE && (totalRect.getWidth() > outerRect.getWidth() || HScrollBarMode == ESBM_ALWAYS_VISIBLE) ) { HScrollBar->setVisible(true); HScrollBar->setMax(totalRect.getWidth() - outerRect.getWidth()); bringToFront(HScrollBar); } else HScrollBar->setVisible(false); if ( VScrollBarMode != ESBM_ALWAYS_INVISIBLE && (totalRect.getHeight() > outerRect.getHeight() || VScrollBarMode == ESBM_ALWAYS_VISIBLE) ) { VScrollBar->setVisible(true); VScrollBar->setMax(totalRect.getHeight() - outerRect.getHeight()); bringToFront(VScrollBar); } else VScrollBar->setVisible(false); // move to adjust for scrollbar pos moveInnerPane(); } void CGUIPanel::calculateClientArea() { core::rect ClientArea(0,0, AbsoluteRect.getWidth(),AbsoluteRect.getHeight()); if (VScrollBar->isVisible()) ClientArea.LowerRightCorner.X -= VScrollBar->getRelativePosition().getWidth(); if (HScrollBar->isVisible()) ClientArea.LowerRightCorner.Y -= HScrollBar->getRelativePosition().getHeight(); if (Border) { ClientArea.UpperLeftCorner += core::position2d( BORDER_WIDTH, BORDER_WIDTH ); ClientArea.LowerRightCorner -= core::position2d( BORDER_WIDTH, BORDER_WIDTH ); } ClipPane->setRelativePosition(ClientArea); } core::rect CGUIPanel::getClientArea() const { return ClipPane->getRelativePosition(); } void CGUIPanel::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) { IGUIElement::serializeAttributes(out, options); out->addBool("border", Border); out->addEnum("horizontalScrollBar", HScrollBarMode, GUIScrollBarModeNames ); out->addEnum("verticalScrollBar", VScrollBarMode, GUIScrollBarModeNames ); } void CGUIPanel::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { IGUIElement::deserializeAttributes(in, options); setBorder(in->getAttributeAsBool("border")); setHScrollBarMode((E_SCROLL_BAR_MODE)in->getAttributeAsEnumeration("horizontalScrollBar", GUIScrollBarModeNames)); setVScrollBarMode((E_SCROLL_BAR_MODE)in->getAttributeAsEnumeration("verticalScrollBar", GUIScrollBarModeNames)); } } // namespace gui } // namespace irr irrlicht-1.8.3/tools/GUIEditor/CGUIEnumAttribute.h0000644000000000000000000000564412574354552020432 0ustar rootroot#ifndef __C_GUI_ENUM_ATTRIBUTE_H_INCLUDED__ #define __C_GUI_ENUM_ATTRIBUTE_H_INCLUDED__ #include "CGUIAttribute.h" #include "IGUIComboBox.h" #include "IGUIEditBox.h" #include "EGUIEditTypes.h" namespace irr { namespace gui { class CGUIEnumAttribute : public CGUIAttribute { public: // CGUIEnumAttribute(IGUIEnvironment* environment, IGUIElement *parent, s32 myParentID) : CGUIAttribute(environment, parent, myParentID), AttribComboBox(0), AttribEditBox(0) { } virtual ~CGUIEnumAttribute() { if (AttribComboBox) AttribComboBox->drop(); if (AttribEditBox) AttribEditBox->drop(); } // save the attribute and possibly post the event to its parent virtual void setAttrib(io::IAttributes *attribs, u32 attribIndex) { if (AttribComboBox) { AttribComboBox->remove(); AttribComboBox->drop(); AttribComboBox = 0; } if (AttribEditBox) { AttribEditBox->remove(); AttribEditBox->drop(); AttribEditBox = 0; } core::array outLiterals; attribs->getAttributeEnumerationLiteralsOfEnumeration(attribIndex, outLiterals); core::rect r = getAbsolutePosition(); core::rect r2(0, Environment->getSkin()->getFont()->getDimension(L"A").Height + 10, r.getWidth() - 5, Environment->getSkin()->getFont()->getDimension(L"A").Height*2 + 20 ); if (outLiterals.size() > 0) { AttribComboBox = Environment->addComboBox(r2, this, -1); for (u32 i=0; iaddItem( core::stringw(outLiterals[i].c_str()).c_str()); AttribComboBox->setSelected( attribs->getAttributeAsInt(attribIndex) ); AttribComboBox->grab(); AttribComboBox->setSubElement(true); AttribComboBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); } else { AttribEditBox = Environment->addEditBox( attribs->getAttributeAsStringW(attribIndex).c_str(), r2, true, this, -1); AttribEditBox->grab(); AttribEditBox->setSubElement(true); AttribEditBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); } CGUIAttribute::setAttrib(attribs, attribIndex); } //! save the attribute and possibly post the event to its parent virtual bool updateAttrib(bool sendEvent=true) { if (!Attribs) return true; if (AttribComboBox) Attribs->setAttribute(Index, AttribComboBox->getText()); else if (AttribEditBox) Attribs->setAttribute(Index, AttribEditBox->getText()); return CGUIAttribute::updateAttrib(sendEvent); } //! Returns the type name of the gui element. virtual const c8* getTypeName() const { return GUIEditElementTypeNames[EGUIEDIT_ENUMATTRIBUTE]; } private: IGUIComboBox* AttribComboBox; IGUIEditBox* AttribEditBox; }; } // namespace gui } // namespace irr #endif irrlicht-1.8.3/tools/GUIEditor/CGUIEditWorkspace.h0000644000000000000000000001072312574354552020400 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUIEDIT_WORKSPACE_H_INCLUDED__ #define __C_GUIEDIT_WORKSPACE_H_INCLUDED__ #include "IGUIElement.h" #include "CGUIEditWindow.h" #include "EGUIEditTypes.h" namespace irr { namespace gui { //! Adding the GUI Editor Workspace to an element allows you /** to create, edit, load and save any elements supported by any loaded factories. When you add it without a parent (to the root element) it will also allow you to edit, load and save settings in the current skin. */ // custom events enum EGUIEDIT_CUSTOM_EVENTS { EGUIEDCE_ATTRIB_EDITOR = MAKE_IRR_ID('g','A','t','t'), EGUIEDCE_OPTION_EDITOR = MAKE_IRR_ID('g','O','p','t'), EGUIEDCE_ENV_EDITOR = MAKE_IRR_ID('g','E','n','v') }; class CGUIEditWorkspace : public IGUIElement { public: //! constructor CGUIEditWorkspace(IGUIEnvironment* environment, s32 id=-1, IGUIElement *parent=0); //! destructor ~CGUIEditWorkspace(); //! called if an event happened. virtual bool OnEvent(const SEvent &event); //! Removes a child. virtual void removeChild(IGUIElement* child); //! draws the element and its children virtual void draw(); //! Updates the absolute position. virtual void updateAbsolutePosition(); //! Sets the menu command id's /** The GUI editor defaults to command ID's from 0xED17 to 0xED17+EGUIEDMC_COUNT In the rare case that these are already in use and you wish to use menus while the editor is present you can set a new offset here. */ virtual void setMenuCommandIDStart(s32 id); //! grid drawing... virtual void setDrawGrid(bool drawGrid); virtual void setGridSize(const core::dimension2di& gridSize); virtual void setUseGrid(bool useGrid); //! returns the first editable element under the mouse virtual IGUIElement* getEditableElementFromPoint(IGUIElement *start, const core::position2di &point, s32 index=0 ); //! selecting elements virtual void setSelectedElement(IGUIElement *sel); virtual void selectNextSibling(); virtual void selectPreviousSibling(); //! returns the selected element virtual IGUIElement* getSelectedElement(); //! copies the xml of the selected element and all children to the clipboard virtual void CopySelectedElementXML(); //! copies the xml of the selected element and all children to the clipboard virtual void PasteXMLToSelectedElement(); virtual const c8* getTypeName() const { return GUIEditElementTypeNames[EGUIEDIT_GUIEDIT]; } virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0); virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); private: enum EGUIEDIT_MODE { // when we are currently selecting an element EGUIEDM_SELECT=0, // selecting a new parent for the selected element EGUIEDM_SELECT_NEW_PARENT, // moving the selected element EGUIEDM_MOVE, // resizing the selected element EGUIEDM_RESIZE_TL, EGUIEDM_RESIZE_T, EGUIEDM_RESIZE_TR, EGUIEDM_RESIZE_R, EGUIEDM_RESIZE_BR, EGUIEDM_RESIZE_B, EGUIEDM_RESIZE_BL, EGUIEDM_RESIZE_L }; enum EGUIEDIT_MENUCOMMANDS { //! file commands EGUIEDMC_FILE_NEW, EGUIEDMC_FILE_LOAD, EGUIEDMC_FILE_SAVE, //! edit menu EGUIEDMC_CUT_ELEMENT, EGUIEDMC_COPY_ELEMENT, EGUIEDMC_PASTE_ELEMENT, EGUIEDMC_DELETE_ELEMENT, EGUIEDMC_SET_PARENT, EGUIEDMC_BRING_TO_FRONT, EGUIEDMC_SAVE_ELEMENT, //! grid EGUIEDMC_TOGGLE_EDITOR, EGUIEDMC_INSERT_XML, //! number of menu options EGUIEDMC_COUNT }; EGUIEDIT_MODE getModeFromPos(core::position2di p); EGUIEDIT_MODE CurrentMode; EGUIEDIT_MODE MouseOverMode; core::position2di DragStart; core::position2di StartMovePos; core::rect SelectedArea; core::dimension2di GridSize; s32 MenuCommandStart; bool DrawGrid, UseGrid; IGUIElement *MouseOverElement, *SelectedElement; CGUIEditWindow *EditorWindow; core::rect TLRect; core::rect TRRect; core::rect TopRect; core::rect BLRect; core::rect LRect; core::rect RRect; core::rect BRRect; core::rect BRect; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/tools/GUIEditor/CGUIEditWorkspace.cpp0000644000000000000000000006305212574354552020736 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // Thanks to Midnight for all his testing, bug fixes and patches :) #include "CGUIEditWorkspace.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IOSOperator.h" #include "IReadFile.h" #include "IFileSystem.h" #include "IXMLWriter.h" #include "IGUISkin.h" #include "IGUIElementFactory.h" #include "CGUIEditWindow.h" #include "IGUIContextMenu.h" #include "IGUIFileOpenDialog.h" #include "IGUITreeView.h" #include "CGUIAttribute.h" #include "CMemoryReadWriteFile.h" namespace irr { namespace gui { //! constructor CGUIEditWorkspace::CGUIEditWorkspace(IGUIEnvironment* environment, s32 id, IGUIElement *parent) : IGUIElement(EGUIET_ELEMENT, environment, parent ? parent : environment->getRootGUIElement(), id, environment->getRootGUIElement()->getAbsolutePosition()), CurrentMode(EGUIEDM_SELECT), MouseOverMode(EGUIEDM_SELECT), GridSize(10,10), MenuCommandStart(0x3D17), DrawGrid(false), UseGrid(true), MouseOverElement(0), SelectedElement(0), EditorWindow(0) { #ifdef _DEBUG setDebugName("CGUIEditWorkspace"); #endif // this element is never saved. setSubElement(true); // it resizes to fit a resizing window setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); EditorWindow = (CGUIEditWindow*) Environment->addGUIElement("GUIEditWindow", this); if (EditorWindow) { EditorWindow->grab(); EditorWindow->setSubElement(true); Environment->setFocus(EditorWindow); serializeAttributes(EditorWindow->getOptionEditor()->getAttribs()); EditorWindow->getOptionEditor()->refreshAttribs(); if (EditorWindow->getEnvironmentEditor()) { Environment->serializeAttributes(EditorWindow->getEnvironmentEditor()->getAttribs()); EditorWindow->getEnvironmentEditor()->refreshAttribs(); } } } //! destructor CGUIEditWorkspace::~CGUIEditWorkspace() { if (EditorWindow) EditorWindow->drop(); } void CGUIEditWorkspace::setMenuCommandIDStart(s32 id) { MenuCommandStart = id; } CGUIEditWorkspace::EGUIEDIT_MODE CGUIEditWorkspace::getModeFromPos(core::position2di p) { if (SelectedElement) { core::rect r = SelectedElement->getAbsolutePosition(); if (TLRect.isPointInside(p)) return EGUIEDM_RESIZE_TL; else if (TRRect.isPointInside(p)) return EGUIEDM_RESIZE_TR; else if (BLRect.isPointInside(p) ) return EGUIEDM_RESIZE_BL; else if (BRRect.isPointInside(p)) return EGUIEDM_RESIZE_BR; else if (TopRect.isPointInside(p)) return EGUIEDM_RESIZE_T; else if (BRect.isPointInside(p)) return EGUIEDM_RESIZE_B; else if (LRect.isPointInside(p)) return EGUIEDM_RESIZE_L; else if (RRect.isPointInside(p)) return EGUIEDM_RESIZE_R; else if (getEditableElementFromPoint(SelectedElement, p) == SelectedElement) return EGUIEDM_MOVE; else return EGUIEDM_SELECT; } return EGUIEDM_SELECT; } IGUIElement* CGUIEditWorkspace::getEditableElementFromPoint(IGUIElement *start, const core::position2di &point, s32 index ) { IGUIElement* target = 0; // we have to search from back to front. core::list::ConstIterator it = start->getChildren().getLast(); s32 count=0; while(it != start->getChildren().end()) { target = getEditableElementFromPoint((*it),point); if (target) { if (!target->isSubElement() && !isMyChild(target) && target != this) { if (index == count) return target; else count++; } else target = 0; } --it; } if (start->getAbsolutePosition().isPointInside(point)) target = start; return target; } void CGUIEditWorkspace::setSelectedElement(IGUIElement *sel) { IGUIElement* focus = Environment->getFocus(); // we only give focus back to children if (!isMyChild(focus)) focus = 0; if (SelectedElement != Parent) { if (SelectedElement != sel && EditorWindow) { EditorWindow->setSelectedElement(sel); SelectedElement = sel; } } else SelectedElement = 0; if (focus) Environment->setFocus(focus); else Environment->setFocus(this); } IGUIElement* CGUIEditWorkspace::getSelectedElement() { return SelectedElement; } void CGUIEditWorkspace::selectNextSibling() { IGUIElement* p=0; if (SelectedElement && SelectedElement->getParent()) p = SelectedElement->getParent(); else p = Parent; core::list::ConstIterator it = p->getChildren().begin(); // find selected element if (SelectedElement) while (*it != SelectedElement) ++it; if (it !=p->getChildren().end()) ++it; // find next non sub-element while (it != p->getChildren().end() && (*it)->isSubElement()) ++it; if (it != p->getChildren().end()) setSelectedElement(*it); } void CGUIEditWorkspace::selectPreviousSibling() { IGUIElement* p=0; if (SelectedElement && SelectedElement->getParent()) p = SelectedElement->getParent(); else p = Parent; core::list::ConstIterator it = p->getChildren().getLast(); // find selected element if (SelectedElement) while (*it != SelectedElement) --it; if (it != p->getChildren().end()) --it; // find next non sub-element while (it != p->getChildren().end() && (*it)->isSubElement()) --it; if (it != p->getChildren().end()) setSelectedElement(*it); } //! called if an event happened. bool CGUIEditWorkspace::OnEvent(const SEvent &e) { IGUIFileOpenDialog* dialog=0; switch(e.EventType) { case ATTRIBEDIT_ATTRIB_CHANGED: { switch (e.UserEvent.UserData1) { case EGUIEDCE_ATTRIB_EDITOR: { // update selected items attributes if (SelectedElement) { SelectedElement->deserializeAttributes(EditorWindow->getAttributeEditor()->getAttribs()); EditorWindow->updateTree(); } return true; } case EGUIEDCE_OPTION_EDITOR: { // update editor options deserializeAttributes(EditorWindow->getOptionEditor()->getAttribs()); return true; } case EGUIEDCE_ENV_EDITOR: { // update environment Environment->deserializeAttributes(EditorWindow->getEnvironmentEditor()->getAttribs()); return true; } } } break; case EET_KEY_INPUT_EVENT: if (!e.KeyInput.PressedDown) { switch (e.KeyInput.Key) { case KEY_DELETE: if (SelectedElement) { IGUIElement* el = SelectedElement; setSelectedElement(0); MouseOverElement = 0; el->remove(); EditorWindow->updateTree(); } break; case KEY_KEY_X: if (e.KeyInput.Control && SelectedElement) { // cut CopySelectedElementXML(); // delete element IGUIElement *el = SelectedElement; setSelectedElement(0); MouseOverElement = 0; el->remove(); } break; case KEY_KEY_C: // copy if (e.KeyInput.Control && SelectedElement) { CopySelectedElementXML(); } break; case KEY_KEY_V: // paste if (e.KeyInput.Control) { PasteXMLToSelectedElement(); } break; default: break; } return true; } break; case EET_MOUSE_INPUT_EVENT: switch(e.MouseInput.Event) { case EMIE_MOUSE_WHEEL: { f32 wheel = e.MouseInput.Wheel; if (wheel > 0) selectPreviousSibling(); else selectNextSibling(); } break; case EMIE_LMOUSE_PRESSED_DOWN: { core::position2di p = core::position2di(e.MouseInput.X,e.MouseInput.Y); IGUIElement* newSelection = getElementFromPoint(p); if (newSelection != this && isMyChild(newSelection) ) // redirect event { Environment->setFocus(newSelection); return true; } // hide the gui editor if (EditorWindow) EditorWindow->setVisible(false); if (CurrentMode == EGUIEDM_SELECT) { if (SelectedElement) { // start moving or dragging CurrentMode = getModeFromPos(p); if (CurrentMode == EGUIEDM_MOVE) StartMovePos = SelectedElement->getAbsolutePosition().UpperLeftCorner; DragStart = p; SelectedArea = SelectedElement->getAbsolutePosition(); } if (CurrentMode < EGUIEDM_MOVE) { // selecting an element... MouseOverElement = getEditableElementFromPoint(Parent, p); if (MouseOverElement == Parent) MouseOverElement = 0; setSelectedElement(MouseOverElement); } } break; } case EMIE_RMOUSE_PRESSED_DOWN: if (CurrentMode == EGUIEDM_SELECT_NEW_PARENT || CurrentMode >= EGUIEDM_MOVE) { // cancel dragging CurrentMode = EGUIEDM_SELECT; } else { DragStart = core::position2di(e.MouseInput.X,e.MouseInput.Y); // root menu IGUIContextMenu* mnu = Environment->addContextMenu( core::rect(e.MouseInput.X, e.MouseInput.Y, e.MouseInput.Y+100, e.MouseInput.Y+100),this); mnu->addItem(L"File",-1,true,true); mnu->addItem(L"Edit",-1,true,true); mnu->addItem(L"View",-1,true,true); mnu->addItem(SelectedElement ? L"Add child" : L"Add" ,-1,true,true); // file menu IGUIContextMenu* sub = mnu->getSubMenu(0); IGUIContextMenu* sub2 =0; sub->addItem(L"New", MenuCommandStart + EGUIEDMC_FILE_NEW ); sub->addItem(L"Load...",MenuCommandStart + EGUIEDMC_FILE_LOAD); sub->addItem(L"Save...",MenuCommandStart + EGUIEDMC_FILE_SAVE); // edit menu sub = mnu->getSubMenu(1); sub->addItem(L"Cut (ctrl+x)", MenuCommandStart + EGUIEDMC_CUT_ELEMENT, (SelectedElement != 0)); sub->addItem(L"Copy (ctrl+c)", MenuCommandStart + EGUIEDMC_COPY_ELEMENT, (SelectedElement != 0)); sub->addItem(L"Paste (ctrl+v)", MenuCommandStart + EGUIEDMC_PASTE_ELEMENT, (core::stringc(Environment->getOSOperator()->getTextFromClipboard()) != "")); sub->addItem(L"Delete (del)", MenuCommandStart + EGUIEDMC_DELETE_ELEMENT, (SelectedElement != 0)); sub->addSeparator(); sub->addItem(L"Set parent", MenuCommandStart + EGUIEDMC_SET_PARENT, (SelectedElement != 0)); sub->addItem(L"Bring to front", MenuCommandStart + EGUIEDMC_BRING_TO_FRONT, (SelectedElement != 0)); sub->addSeparator(); sub->addItem(L"Save to XML...", MenuCommandStart + EGUIEDMC_SAVE_ELEMENT, (SelectedElement != 0)); sub = mnu->getSubMenu(2); // view menu if (EditorWindow) sub->addItem(EditorWindow->isVisible() ? L"Hide window" : L"Show window", MenuCommandStart + EGUIEDMC_TOGGLE_EDITOR); sub = mnu->getSubMenu(3); s32 i,j,c=0; sub->addItem(L"Default factory",-1,true, true); // add elements from each factory for (i=0; u32(i) < Environment->getRegisteredGUIElementFactoryCount(); ++i) { sub2 = sub->getSubMenu(i); IGUIElementFactory *f = Environment->getGUIElementFactory(i); for (j=0; j< f->getCreatableGUIElementTypeCount(); ++j) { sub2->addItem(core::stringw(f->getCreateableGUIElementTypeName(j)).c_str(), MenuCommandStart + EGUIEDMC_COUNT + c); c++; } if (u32(i+1) < Environment->getRegisteredGUIElementFactoryCount()) { core::stringw strFact; strFact = L"Factory "; strFact += i+1; sub->addItem(strFact.c_str(),-1, true, true); } } sub->addSeparator(); sub->addItem(L"From XML...", MenuCommandStart + EGUIEDMC_INSERT_XML); // set focus to menu Environment->setFocus(mnu); } break; case EMIE_LMOUSE_LEFT_UP: // make window visible again if (EditorWindow) EditorWindow->setVisible(true); if (CurrentMode == EGUIEDM_SELECT_NEW_PARENT) { if (SelectedElement) { MouseOverElement = getEditableElementFromPoint(Parent, core::position2di(e.MouseInput.X,e.MouseInput.Y)); if (MouseOverElement) { MouseOverElement->addChild(SelectedElement); setSelectedElement(0); setSelectedElement(SelectedElement); } } CurrentMode = EGUIEDM_SELECT; } else if (CurrentMode >= EGUIEDM_MOVE) { IGUIElement *sel = SelectedElement; // unselect setSelectedElement(0); // move core::position2d p(0,0); if (sel->getParent()) p = sel->getParent()->getAbsolutePosition().UpperLeftCorner; sel->setRelativePosition(SelectedArea - p); // select setSelectedElement(sel); // reset selection mode... CurrentMode = EGUIEDM_SELECT; } break; case EMIE_MOUSE_MOVED: // always on top Parent->bringToFront(this); // if selecting if (CurrentMode == EGUIEDM_SELECT || CurrentMode == EGUIEDM_SELECT_NEW_PARENT) { core::position2di p = core::position2di(e.MouseInput.X,e.MouseInput.Y); // highlight the element that the mouse is over MouseOverElement = getEditableElementFromPoint(Parent, p); if (MouseOverElement == Parent) { MouseOverElement = 0; } if (CurrentMode == EGUIEDM_SELECT) { MouseOverMode = getModeFromPos(p); if (MouseOverMode > EGUIEDM_MOVE) { MouseOverElement = SelectedElement; } } } else if (CurrentMode == EGUIEDM_MOVE) { // get difference core::position2di p = core::position2di(e.MouseInput.X,e.MouseInput.Y); p -= DragStart; // apply to top corner p = StartMovePos + p; if (UseGrid) { p.X = (p.X/GridSize.Width)*GridSize.Width; p.Y = (p.Y/GridSize.Height)*GridSize.Height; } SelectedArea += p - SelectedArea.UpperLeftCorner; } else if (CurrentMode > EGUIEDM_MOVE) { // get difference from start position core::position2di p = core::position2di(e.MouseInput.X,e.MouseInput.Y); if (UseGrid) { p.X = (p.X/GridSize.Width)*GridSize.Width; p.Y = (p.Y/GridSize.Height)*GridSize.Height; } switch(CurrentMode) { case EGUIEDM_RESIZE_T: SelectedArea.UpperLeftCorner.Y = p.Y; break; case EGUIEDM_RESIZE_B: SelectedArea.LowerRightCorner.Y = p.Y; break; case EGUIEDM_RESIZE_L: SelectedArea.UpperLeftCorner.X = p.X; break; case EGUIEDM_RESIZE_R: SelectedArea.LowerRightCorner.X = p.X; break; case EGUIEDM_RESIZE_TL: SelectedArea.UpperLeftCorner = p; break; case EGUIEDM_RESIZE_TR: SelectedArea.UpperLeftCorner.Y = p.Y; SelectedArea.LowerRightCorner.X = p.X; break; case EGUIEDM_RESIZE_BL: SelectedArea.UpperLeftCorner.X = p.X; SelectedArea.LowerRightCorner.Y = p.Y; break; case EGUIEDM_RESIZE_BR: SelectedArea.LowerRightCorner = p; break; default: break; } } break; default: break; } break; case EET_GUI_EVENT: switch(e.GUIEvent.EventType) { case EGET_TREEVIEW_NODE_SELECT: { IGUITreeViewNode* eventnode = ((IGUITreeView*)e.GUIEvent.Caller)->getLastEventNode(); if(!eventnode->isRoot()) setSelectedElement((IGUIElement*)(eventnode->getData())); break; } // load a gui file case EGET_FILE_SELECTED: dialog = (IGUIFileOpenDialog*)e.GUIEvent.Caller; Environment->loadGUI(core::stringc(dialog->getFileName()).c_str()); break; case EGET_MENU_ITEM_SELECTED: { IGUIContextMenu *menu = (IGUIContextMenu*)e.GUIEvent.Caller; s32 cmdID = menu->getItemCommandId(menu->getSelectedItem()) - MenuCommandStart; IGUIElement* el; switch(cmdID) { //! file commands case EGUIEDMC_FILE_NEW: // clear all elements belonging to our parent setSelectedElement(0); MouseOverElement = 0; el = Parent; grab(); // remove all children while(Children.end() != el->getChildren().begin()) el->removeChild(*(el->getChildren().begin())); // attach to parent again el->addChild(this); drop(); break; case EGUIEDMC_FILE_LOAD: Environment->addFileOpenDialog(L"Please select a GUI file to open", false, this); break; case EGUIEDMC_FILE_SAVE: Environment->saveGUI("guiTest.xml"); break; //! edit menu case EGUIEDMC_CUT_ELEMENT: { CopySelectedElementXML(); // delete element el = SelectedElement; setSelectedElement(0); MouseOverElement = 0; el->remove(); break; } case EGUIEDMC_COPY_ELEMENT: CopySelectedElementXML(); break; case EGUIEDMC_PASTE_ELEMENT: PasteXMLToSelectedElement(); break; case EGUIEDMC_DELETE_ELEMENT: el = SelectedElement; setSelectedElement(0); MouseOverElement = 0; el->remove(); break; case EGUIEDMC_SET_PARENT: CurrentMode = EGUIEDM_SELECT_NEW_PARENT; break; case EGUIEDMC_BRING_TO_FRONT: if (SelectedElement->getParent()) SelectedElement->getParent()->bringToFront(SelectedElement); break; case EGUIEDMC_SAVE_ELEMENT: //TODO: add 'save' dialog. Environment->saveGUI("guiTest.xml", SelectedElement ? SelectedElement : Environment->getRootGUIElement() ); break; //! toggle edit window case EGUIEDMC_TOGGLE_EDITOR: break; case EGUIEDMC_INSERT_XML: Environment->loadGUI("guiTest.xml", SelectedElement ? SelectedElement : Environment->getRootGUIElement() ); break; default: // create element from factory? if (cmdID >= EGUIEDMC_COUNT) { s32 num = cmdID - EGUIEDMC_COUNT; // get index // loop through all factories s32 i, c=Environment->getRegisteredGUIElementFactoryCount(); for (i=0; i Environment->getGUIElementFactory(i)->getCreatableGUIElementTypeCount(); ++i) { num -= Environment->getGUIElementFactory(i)->getCreatableGUIElementTypeCount(); } if (num < Environment->getGUIElementFactory(i)->getCreatableGUIElementTypeCount() ) { core::stringc name = Environment->getGUIElementFactory(i)->getCreateableGUIElementTypeName(num); IGUIElement *parentElement = SelectedElement ? SelectedElement : Environment->getRootGUIElement(); // add it IGUIElement *newElement = Environment->getGUIElementFactory(i)->addGUIElement(name.c_str(),parentElement); if (newElement) { core::position2di p = DragStart - parentElement->getAbsolutePosition().UpperLeftCorner; newElement->setRelativePosition(core::rect(p,p+core::position2di(100,100))); //Environment->removeFocus(newElement); } } } break; } EditorWindow->updateTree(); } return true; default: break; } break; default: break; } // even if we didn't absorb the event, // we never pass events back to the GUI we're editing! return false; } //! draws the element and its children void CGUIEditWorkspace::draw() { video::IVideoDriver *driver = Environment->getVideoDriver(); if (DrawGrid) { // draw the grid core::rect r = getAbsolutePosition(); s32 cy = r.UpperLeftCorner.Y; while (cy < r.LowerRightCorner.Y) { s32 cx = r.UpperLeftCorner.X; while (cx < r.LowerRightCorner.X) { driver->draw2DRectangle(video::SColor(40,0,0,90),core::rect(cx+1,cy+1,GridSize.Width+cx,GridSize.Height+cy)); cx += GridSize.Width; } cy += GridSize.Height; } } if (MouseOverElement && MouseOverElement != SelectedElement && MouseOverElement != Parent) { core::rect r = MouseOverElement->getAbsolutePosition(); driver->draw2DRectangle(video::SColor(100,0,0,255), r); } if (SelectedElement && CurrentMode == EGUIEDM_SELECT) { driver->draw2DRectangle(video::SColor(100,0,255,0),SelectedElement->getAbsolutePosition()); } if (CurrentMode >= EGUIEDM_MOVE) { driver->draw2DRectangle(video::SColor(100,255,0,0),SelectedArea); } if ( (SelectedElement && CurrentMode >= EGUIEDM_MOVE) || (SelectedElement && MouseOverElement == SelectedElement && MouseOverMode >= EGUIEDM_MOVE) ) { // draw handles for moving EGUIEDIT_MODE m = CurrentMode; core::rect r = SelectedArea; if (m < EGUIEDM_MOVE) { m = MouseOverMode; r = SelectedElement->getAbsolutePosition(); } core::position2di d = core::position2di(4,4); TLRect = core::rect(r.UpperLeftCorner, r.UpperLeftCorner + d ); TRRect = core::rect(r.LowerRightCorner.X-4, r.UpperLeftCorner.Y, r.LowerRightCorner.X, r.UpperLeftCorner.Y+4); TopRect = core::rect(r.getCenter().X-2, r.UpperLeftCorner.Y,r.getCenter().X+2, r.UpperLeftCorner.Y+4 ); BLRect = core::rect(r.UpperLeftCorner.X, r.LowerRightCorner.Y-4, r.UpperLeftCorner.X+4, r.LowerRightCorner.Y); LRect = core::rect(r.UpperLeftCorner.X,r.getCenter().Y-2, r.UpperLeftCorner.X+4, r.getCenter().Y+2 ); RRect = core::rect(r.LowerRightCorner.X-4,r.getCenter().Y-2, r.LowerRightCorner.X, r.getCenter().Y+2 ); BRRect = core::rect(r.LowerRightCorner-d, r.LowerRightCorner); BRect = core::rect(r.getCenter().X-2, r.LowerRightCorner.Y-4,r.getCenter().X+2, r.LowerRightCorner.Y ); // top left if (m == EGUIEDM_RESIZE_T || m == EGUIEDM_RESIZE_L || m == EGUIEDM_RESIZE_TL || m == EGUIEDM_MOVE ) driver->draw2DRectangle(video::SColor(100,255,255,255), TLRect); if (m == EGUIEDM_RESIZE_T || m == EGUIEDM_RESIZE_R || m == EGUIEDM_RESIZE_TR || m == EGUIEDM_MOVE ) driver->draw2DRectangle(video::SColor(100,255,255,255), TRRect); if (m == EGUIEDM_RESIZE_T || m == EGUIEDM_MOVE ) driver->draw2DRectangle(video::SColor(100,255,255,255), TopRect); if (m == EGUIEDM_RESIZE_L || m == EGUIEDM_RESIZE_BL || m == EGUIEDM_RESIZE_B || m == EGUIEDM_MOVE ) driver->draw2DRectangle(video::SColor(100,255,255,255), BLRect); if (m == EGUIEDM_RESIZE_L || m == EGUIEDM_MOVE ) driver->draw2DRectangle(video::SColor(100,255,255,255), LRect); if (m == EGUIEDM_RESIZE_R || m == EGUIEDM_MOVE ) driver->draw2DRectangle(video::SColor(100,255,255,255), RRect); if (m == EGUIEDM_RESIZE_R || m == EGUIEDM_RESIZE_BR || m == EGUIEDM_RESIZE_B || m == EGUIEDM_MOVE ) driver->draw2DRectangle(video::SColor(100,255,255,255), BRRect ); if (m == EGUIEDM_RESIZE_B || m == EGUIEDM_MOVE ) driver->draw2DRectangle(video::SColor(100,255,255,255), BRect); } IGUIElement::draw(); } void CGUIEditWorkspace::setDrawGrid(bool drawGrid) { DrawGrid = drawGrid; } void CGUIEditWorkspace::setGridSize(const core::dimension2di& gridSize) { GridSize = gridSize; if (GridSize.Width < 2) GridSize.Width = 2; if (GridSize.Height < 2) GridSize.Height = 2; } void CGUIEditWorkspace::setUseGrid(bool useGrid) { UseGrid = useGrid; } //! Removes a child. void CGUIEditWorkspace::removeChild(IGUIElement* child) { IGUIElement::removeChild(child); if (Children.empty()) remove(); } void CGUIEditWorkspace::updateAbsolutePosition() { core::rect parentRect(0,0,0,0); if (Parent) { parentRect = Parent->getAbsolutePosition(); RelativeRect.UpperLeftCorner.X = 0; RelativeRect.UpperLeftCorner.Y = 0; RelativeRect.LowerRightCorner.X = parentRect.getWidth(); RelativeRect.LowerRightCorner.Y = parentRect.getHeight(); } IGUIElement::updateAbsolutePosition(); } void CGUIEditWorkspace::CopySelectedElementXML() { core::stringc XMLText; core::stringw wXMLText; // create memory write file io::CMemoryReadWriteFile* memWrite = new io::CMemoryReadWriteFile("#Clipboard#"); // save gui to mem file io::IXMLWriter* xml = Environment->getFileSystem()->createXMLWriter(memWrite); Environment->writeGUIElement(xml, SelectedElement); // copy to clipboard- wide chars not supported yet :( wXMLText = (wchar_t*)&memWrite->getData()[0]; u32 i = memWrite->getData().size()/sizeof(wchar_t); if (wXMLText.size() > i) wXMLText[i] = L'\0'; XMLText = wXMLText.c_str(); memWrite->drop(); xml->drop(); Environment->getOSOperator()->copyToClipboard(XMLText.c_str()); } void CGUIEditWorkspace::PasteXMLToSelectedElement() { // get clipboard data const char * p = Environment->getOSOperator()->getTextFromClipboard(); // convert to stringw // TODO: we should have such a function in core::string size_t lenOld = strlen(p); wchar_t *ws = new wchar_t[lenOld + 1]; size_t len = mbstowcs(ws,p,lenOld); ws[len] = 0; irr::core::stringw wXMLText(ws); delete[] ws; io::CMemoryReadWriteFile* memWrite = new io::CMemoryReadWriteFile("#Clipboard#"); io::IXMLWriter* xmlw = Environment->getFileSystem()->createXMLWriter(memWrite); xmlw->writeXMLHeader(); // it needs one of those xmlw->drop(); // write clipboard data memWrite->write((void*)&wXMLText[0], wXMLText.size() * sizeof(wchar_t)); // rewind file memWrite->seek(0, false); // read xml Environment->loadGUI(memWrite, SelectedElement); // reset focus Environment->setFocus(this); // drop the read file memWrite->drop(); } void CGUIEditWorkspace::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) { out->addBool("DrawGrid", DrawGrid); out->addBool("UseGrid", UseGrid); out->addPosition2d("GridSize", core::position2di(GridSize.Width, GridSize.Height)); out->addInt("MenuCommandStart", MenuCommandStart); } void CGUIEditWorkspace::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { setDrawGrid(in->getAttributeAsBool("DrawGrid")); setUseGrid(in->getAttributeAsBool("UseGrid")); core::position2di tmpp = in->getAttributeAsPosition2d("GridSize"); core::dimension2di tmpd(tmpp.X, tmpp.Y); setGridSize(tmpd); setMenuCommandIDStart(in->getAttributeAsInt("MenuCommandStart")); } } // end namespace gui } // end namespace irr irrlicht-1.8.3/tools/GUIEditor/CGUIEditWindow.h0000644000000000000000000000507112574354552017711 0ustar rootroot#ifndef __C_GUI_EDITOR_H_INCLUDED__ #define __C_GUI_EDITOR_H_INCLUDED__ #include "IGUIWindow.h" #include "CGUIAttributeEditor.h" //#include "IGUIStaticText.h" #include "IGUIButton.h" #include "IGUITreeView.h" #include "irrArray.h" #include "IAttributes.h" #include "EGUIEditTypes.h" namespace irr { namespace gui { class CGUIEditWindow : public IGUIWindow { public: //! constructor CGUIEditWindow(IGUIEnvironment* environment, core::rect rectangle, IGUIElement *parent); //! destructor ~CGUIEditWindow(); //! this part draws the window virtual void draw(); //! handles events virtual bool OnEvent(const SEvent &event); //! change selection virtual void setSelectedElement(IGUIElement *sel); //! get draggable virtual bool isDraggable() const; //! get draggable virtual void setDraggable(bool draggable); // not used virtual core::rect getClientRect() const; virtual IGUIButton* getCloseButton() const; virtual IGUIButton* getMinimizeButton() const; virtual IGUIButton* getMaximizeButton() const; virtual void setDrawBackground(bool draw) { } virtual bool getDrawBackground() const { return true; } virtual void setDrawTitlebar(bool draw) { } virtual bool getDrawTitlebar() const { return true; } IGUITreeView* getTreeView() const; CGUIAttributeEditor* getAttributeEditor() const; CGUIAttributeEditor* getOptionEditor() const; CGUIAttributeEditor* getEnvironmentEditor() const; //! Returns the type name of the gui element. virtual const c8* getTypeName() const { return GUIEditElementTypeNames[EGUIEDIT_GUIEDITWINDOW]; } void updateTree(); private: void addChildrenToTree(IGUIElement* parentElement, IGUITreeViewNode* treenode); IGUITreeViewNode* getTreeNode(IGUIElement* element, IGUITreeViewNode* searchnode); // for dragging the window bool Dragging; bool IsDraggable; bool Resizing; core::position2d DragStart; IGUIElement* SelectedElement; // current selected element CGUIAttributeEditor* AttribEditor; // edits the current attribute CGUIAttributeEditor* OptionEditor; // edits the options for the window CGUIAttributeEditor* EnvEditor; // edits attributes for the environment IGUITreeView* TreeView; // tree view of all elements in scene IGUIButton* ResizeButton; }; } // end namespace gui } // end namespace irr #endif // __C_GUI_EDITOR_H_INCLUDED__ irrlicht-1.8.3/tools/GUIEditor/CGUIEditWindow.cpp0000644000000000000000000002450612574354552020250 0ustar rootroot #include "CGUIEditWindow.h" #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IGUIElementFactory.h" #include "IAttributes.h" #include "IGUIFont.h" #include "IGUITabControl.h" #include "IGUITreeView.h" #include "CGUIEditWorkspace.h" using namespace irr; using namespace gui; //! constructor CGUIEditWindow::CGUIEditWindow(IGUIEnvironment* environment, core::rect rectangle, IGUIElement *parent) : IGUIWindow(environment, parent, -1, rectangle), Dragging(false), IsDraggable(true), Resizing(false), SelectedElement(0), AttribEditor(0), OptionEditor(0), EnvEditor(0) { #ifdef _DEBUG setDebugName("CGUIEditWindow"); #endif // we can't tab out of this window setTabGroup(true); // we can ctrl+tab to it setTabStop(true); // the tab order number is auto-assigned setTabOrder(-1); // set window text setText(L"GUI Editor"); // return if we have no skin. IGUISkin *skin = environment->getSkin(); if (!skin) return; s32 th = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); setRelativePosition(core::rect(50,50,250,500)); setMinSize(core::dimension2du(200,200)); IGUITabControl *TabControl = environment->addTabControl(core::rect(1,th+5,199,449), this, false, true); TabControl->setSubElement(true); TabControl->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); TabControl->addTab(L"Tools"); //L"Texture Cache Browser" //L"Font Browser" //L"Font Generator" //L"Sprite Editor" //Environment->addGUIElement("textureCacheBrowser", this); IGUITab* EditorTab = TabControl->addTab(L"Editor"); OptionEditor = (CGUIAttributeEditor*) environment->addGUIElement("attributeEditor", EditorTab); OptionEditor->grab(); OptionEditor->setID(EGUIEDCE_OPTION_EDITOR); OptionEditor->setRelativePositionProportional(core::rect(0.0f, 0.0f, 1.0f, 1.0f)); OptionEditor->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); if (Parent && Parent->getParent() == Environment->getRootGUIElement()) { IGUITab* EnvTab = TabControl->addTab(L"Env"); EnvEditor = (CGUIAttributeEditor*) environment->addGUIElement("attributeEditor", EnvTab); EnvEditor->grab(); EnvEditor->setID(EGUIEDCE_ENV_EDITOR); EnvEditor->setRelativePositionProportional(core::rect(0.0f, 0.0f, 1.0f, 1.0f)); EnvEditor->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); } IGUITab* ElementTab = TabControl->addTab(L"Element"); AttribEditor = (CGUIAttributeEditor*) environment->addGUIElement("attributeEditor", ElementTab); AttribEditor->grab(); AttribEditor->setID(EGUIEDCE_ATTRIB_EDITOR); AttribEditor->setRelativePositionProportional(core::rect(0.0f, 0.0f, 1.0f, 1.0f)); AttribEditor->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); IGUITab* TreeTab = TabControl->addTab(L"Tree"); TreeView = environment->addTreeView(core::rect(0,0,0,0), TreeTab); TreeView->setRelativePositionProportional(core::rect(0.0f, 0.0f, 1.0f, 1.0f)); TreeView->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); IGUITreeViewNode* treenode = TreeView->getRoot(); //treenode->addChildFront(L"Elements"); ResizeButton = environment->addButton(core::rect(199-th,449-th,199,449), this); ResizeButton->setDrawBorder(false); ResizeButton->setEnabled(false); ResizeButton->setSpriteBank(skin->getSpriteBank()); ResizeButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_RESIZE), skin->getColor(EGDC_WINDOW_SYMBOL)); ResizeButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_RESIZE), skin->getColor(EGDC_WINDOW_SYMBOL)); ResizeButton->grab(); ResizeButton->setSubElement(true); ResizeButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); updateTree(); } //! destructor CGUIEditWindow::~CGUIEditWindow() { // drop everything if (AttribEditor) AttribEditor->drop(); if (EnvEditor) EnvEditor->drop(); if (OptionEditor) OptionEditor->drop(); if (ResizeButton) ResizeButton->drop(); } IGUITreeView* CGUIEditWindow::getTreeView() const { return TreeView; } CGUIAttributeEditor* CGUIEditWindow::getEnvironmentEditor() const { return EnvEditor; } CGUIAttributeEditor* CGUIEditWindow::getAttributeEditor() const { return AttribEditor; } CGUIAttributeEditor* CGUIEditWindow::getOptionEditor() const { return OptionEditor; } IGUITreeViewNode* CGUIEditWindow::getTreeNode(IGUIElement* element, IGUITreeViewNode* searchnode) { IGUITreeViewNode* child = searchnode->getFirstChild(); while (child) { if (((IGUIElement*) child->getData()) == element) return child; if (child->hasChildren()) { IGUITreeViewNode* foundnode = getTreeNode(element, child); if (foundnode) return foundnode; } child = child->getNextSibling(); } return 0; } void CGUIEditWindow::addChildrenToTree(IGUIElement* parentElement, IGUITreeViewNode* treenode) { core::stringw name = core::stringw(parentElement->getTypeName()); if (parentElement->getID() != -1) name += core::stringw(L" [") + core::stringw(parentElement->getID()) + core::stringw(L"]"); IGUITreeViewNode* newnode = treenode->addChildBack(name.c_str()); newnode->setData((void*)parentElement); core::list children = parentElement->getChildren(); for (core::list::Iterator i = children.begin(); i != children.end(); i++ ) { if(core::stringc((*i)->getTypeName()) != "GUIEditor" && !(*i)->isSubElement()) addChildrenToTree(*i, newnode); } } void CGUIEditWindow::updateTree() { TreeView->getRoot()->clearChildren(); IGUIElement* root = Environment->getRootGUIElement(); addChildrenToTree(root, TreeView->getRoot()); TreeView->getRoot()->getFirstChild()->setExpanded(true); } void CGUIEditWindow::setSelectedElement(IGUIElement *sel) { // save changes AttribEditor->updateAttribs(); IGUITreeViewNode* elementTreeNode = getTreeNode(sel, TreeView->getRoot()); if (elementTreeNode) { elementTreeNode->setSelected(true); while (elementTreeNode) { elementTreeNode->setExpanded(true); elementTreeNode = elementTreeNode->getParent(); } } io::IAttributes* Attribs = AttribEditor->getAttribs(); if (SelectedElement && sel != SelectedElement) { // deserialize attributes SelectedElement->deserializeAttributes(Attribs); } // clear the attributes list Attribs->clear(); SelectedElement = sel; // get the new attributes if (SelectedElement) SelectedElement->serializeAttributes(Attribs); AttribEditor->refreshAttribs(); } //! draws the element and its children. //! same code as for a window void CGUIEditWindow::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); core::rect rect = AbsoluteRect; // draw body fast rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER), AbsoluteRect, &AbsoluteClippingRect); if (Text.size()) { rect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X); rect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y); rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5; IGUIFont* font = skin->getFont(); if (font) font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true, &AbsoluteClippingRect); } IGUIElement::draw(); } //! called if an event happened. bool CGUIEditWindow::OnEvent(const SEvent &event) { switch(event.EventType) { case EET_GUI_EVENT: switch(event.GUIEvent.EventType) { case EGET_ELEMENT_FOCUS_LOST: if (event.GUIEvent.Caller == this || event.GUIEvent.Caller == ResizeButton) { Dragging = false; Resizing = false; } break; default: break; } break; case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: { DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; IGUIElement* clickedElement = getElementFromPoint(DragStart); if (clickedElement == this) { Dragging = IsDraggable; //Environment->setFocus(this); if (Parent) Parent->bringToFront(this); return true; } else if (clickedElement == ResizeButton) { Resizing = true; //Environment->setFocus(this); if (Parent) Parent->bringToFront(this); return true; } break; } case EMIE_LMOUSE_LEFT_UP: if (Dragging || Resizing) { Dragging = false; Resizing = false; return true; } break; case EMIE_MOUSE_MOVED: if (Dragging || Resizing) { // gui window should not be dragged outside of its parent if (Parent) if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 || event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 || event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 || event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1) return true; core::position2di diff(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y); if (Dragging) { move(diff); DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; } else if (Resizing) { core::position2di dp = RelativeRect.LowerRightCorner + diff; setRelativePosition(core::rect(RelativeRect.UpperLeftCorner, dp)); DragStart += dp - RelativeRect.LowerRightCorner + diff; } return true; } break; default: break; } default: break; } return Parent ? Parent->OnEvent(event) : false; } bool CGUIEditWindow::isDraggable() const { return IsDraggable; } void CGUIEditWindow::setDraggable(bool draggable) { IsDraggable = draggable; if (Dragging && !IsDraggable) Dragging = false; } // we're supposed to supply these if we're creating an IGUIWindow // but we don't need them so we'll just return null //! Returns the rectangle of the drawable area (without border, without titlebar and without scrollbars) core::rect CGUIEditWindow::getClientRect() const {return core::recti();} IGUIButton* CGUIEditWindow::getCloseButton() const {return 0;} IGUIButton* CGUIEditWindow::getMinimizeButton() const {return 0;} IGUIButton* CGUIEditWindow::getMaximizeButton() const {return 0;} irrlicht-1.8.3/tools/GUIEditor/CGUIEditFactory.h0000644000000000000000000000337012574354552020051 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUIEDIT_FACTORY_H_INCLUDED__ #define __C_GUIEDIT_FACTORY_H_INCLUDED__ #include "IGUIElementFactory.h" namespace irr { namespace gui { class IGUIElement; class IGUIEnvironment; //! Interface making it possible to dynamicly create gui elements class CGUIEditFactory : public IGUIElementFactory { public: CGUIEditFactory(IGUIEnvironment* env); ~CGUIEditFactory(); //! adds a GUI element to the GUI Environment based on its type name /** \param typeName: Type name of the element to add. \param parent: Parent scene node of the new element, can be null to add it to the root. \return Returns pointer to the new element or null if not successful. */ virtual IGUIElement* addGUIElement(const c8* typeName, IGUIElement* parent=0); //! returns amount of GUI element types this factory is able to create virtual s32 getCreatableGUIElementTypeCount() const; //! returns type name of a createable GUI element type by index /** \param idx: Index of the type in this factory. Must be a value between 0 and getCreatableGUIElementTypeCount() */ virtual const c8* getCreateableGUIElementTypeName(s32 idx) const; // not used: virtual const c8* getCreateableGUIElementTypeName(EGUI_ELEMENT_TYPE type) const {return 0;} ; virtual EGUI_ELEMENT_TYPE getCreateableGUIElementType(s32 idx) const { return EGUIET_ELEMENT;}; virtual IGUIElement* addGUIElement(EGUI_ELEMENT_TYPE type, IGUIElement* parent=0) {return 0;}; private: IGUIEnvironment* Environment; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/tools/GUIEditor/CGUIEditFactory.cpp0000644000000000000000000000775312574354552020415 0ustar rootroot#include "CGUIEditFactory.h" #include "IGUIEnvironment.h" #include "irrString.h" #include "EGUIEditTypes.h" #include "CGUIEditWorkspace.h" #include "CGUIEditWindow.h" #include "CGUIPanel.h" #include "CGUITextureCacheBrowser.h" #include "CGUIAttributeEditor.h" #include "CGUIStringAttribute.h" #include "CGUIBoolAttribute.h" #include "CGUIEnumAttribute.h" #include "CGUIColorAttribute.h" #include "CGUITextureAttribute.h" #include "CGUIDummyEditorStub.h" namespace irr { namespace gui { CGUIEditFactory::CGUIEditFactory(IGUIEnvironment* env) : Environment(env) { #ifdef _DEBUG setDebugName("CGUIEditFactory"); #endif // don't grab the gui environment here to prevent cyclic references } CGUIEditFactory::~CGUIEditFactory() { } //! adds an element to the environment based on its type name IGUIElement* CGUIEditFactory::addGUIElement(const c8* typeName, IGUIElement* parent) { /* here we create elements, add them to the manager, and then drop them */ core::stringc elementType(typeName); IGUIElement* ret=0; if (!parent) parent = Environment->getRootGUIElement(); // editor workspace if (elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_GUIEDIT])) ret = new CGUIEditWorkspace(Environment, -1, 0); // editor window else if (elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_GUIEDITWINDOW])) ret = new CGUIEditWindow(Environment, core::rect(0,0,100,100), 0); // Klasker's GUI Panel else if (elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_GUIPANEL])) ret = new CGUIPanel(Environment, 0); // texture cache browser else if (elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_TEXTUREBROWSER])) ret = new CGUITextureCacheBrowser(Environment, -1, 0); // block of attribute editors else if (elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_ATTRIBUTEEDITOR])) ret = new CGUIAttributeEditor(Environment, -1, 0); //! single attribute editors else if (elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_STRINGATTRIBUTE])) ret = new CGUIStringAttribute(Environment, 0, -1); else if (elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_BOOLATTRIBUTE])) ret = new CGUIBoolAttribute(Environment, 0, -1); else if (elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_ENUMATTRIBUTE])) ret = new CGUIEnumAttribute(Environment, 0, -1); else if (elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_COLORATTRIBUTE])) ret = new CGUIColorAttribute(Environment, 0, -1); else if (elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_COLORFATTRIBUTE])) ret = new CGUIColorAttribute(Environment, 0, -1); else if (elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_TEXTUREATTRIBUTE])) ret = new CGUITextureAttribute(Environment, 0, -1); // stubs and custom editors else if (elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_CONTEXTMENUEDITOR]) || elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_MENUEDITOR]) || elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_FILEDIALOGEDITOR]) || elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_COLORDIALOGEDITOR]) || elementType == core::stringc(GUIEditElementTypeNames[EGUIEDIT_MODALSCREENEDITOR]) ) ret = new CGUIDummyEditorStub(Environment, 0, typeName); // add the element to its parent if (ret) parent->addChild(ret); // the environment now has the reference, so we can drop the element if (ret) ret->drop(); return ret; } //! returns amount of element types this factory is able to create s32 CGUIEditFactory::getCreatableGUIElementTypeCount() const { return EGUIEDIT_COUNT; } //! returns type name of a createable element type const c8* CGUIEditFactory::getCreateableGUIElementTypeName(s32 idx) const { if (idx>=0 && idx(0, 0, 100, 100) ), TextBox(0), TypeName(text) { #ifdef _DEBUG setDebugName("CGUIDummyEditorStub"); #endif core::dimension2du d = Environment->getSkin()->getFont()->getDimension(L"A"); s32 h = d.Height / 2; s32 w = d.Width / 2; TextBox = environment->addStaticText(core::stringw(text).c_str(), core::rect(50-w, 50-h, 50+w, 50+h), false, false, this, -1, false); TextBox->grab(); TextBox->setSubElement(true); TextBox->setAlignment(EGUIA_CENTER, EGUIA_CENTER, EGUIA_CENTER, EGUIA_CENTER); } virtual ~CGUIDummyEditorStub() { if (TextBox) TextBox->drop(); } virtual const c8* getTypeName() const { return TypeName.c_str(); } protected: IGUIStaticText* TextBox; core::stringc TypeName; }; } // namespace gui } // namespace irr #endif irrlicht-1.8.3/tools/GUIEditor/CGUIColorAttribute.h0000644000000000000000000001320112574354552020570 0ustar rootroot#ifndef __C_GUI_COLOR_ATTRIBUTE_H_INCLUDED__ #define __C_GUI_COLOR_ATTRIBUTE_H_INCLUDED__ #include "CGUIAttribute.h" #include "IGUIStaticText.h" #include "IGUIScrollBar.h" #include "IGUITabControl.h" #include "EGUIEditTypes.h" namespace irr { namespace gui { class CGUIColorAttribute : public CGUIAttribute { public: // CGUIColorAttribute(IGUIEnvironment* environment, IGUIElement *parent, s32 myParentID) : CGUIAttribute(environment, parent, myParentID), AttribSliderA(0), AttribSliderR(0), AttribSliderG(0), AttribSliderB(0), AttribEditBox(0), AttribColor(0) { s32 fh = Environment->getSkin()->getFont()->getDimension(L"A").Height; core::rect r0(getAbsolutePosition()), r2(0, fh + 5, r0.getWidth() - 5, fh*2 + 10 ), r3(r2), r4(r2.getWidth() - 20, 3, r2.getWidth() - 3, r2.getHeight()-3); AttribColor = Environment->addTab(r4, this, 0); AttribColor->grab(); AttribColor->setDrawBackground(true); AttribColor->setSubElement(true); AttribColor->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); s32 h=2; r2 += core::position2di(0, h*4 + Environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH)*2); r3.LowerRightCorner.Y = r3.UpperLeftCorner.Y + Environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH)/2; AttribSliderA = environment->addScrollBar(true, r3, this, -1); AttribSliderA->setMax(255); AttribSliderA->grab(); AttribSliderA->setSubElement(true); AttribSliderA->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); r3 += core::position2di(0, r3.getHeight()+h); AttribSliderR = environment->addScrollBar(true, r3, this, -1); AttribSliderR->setMax(255); AttribSliderR->grab(); AttribSliderR->setSubElement(true); AttribSliderR->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); r3 += core::position2di(0, r3.getHeight()+h); AttribSliderG = environment->addScrollBar(true, r3, this, -1); AttribSliderG->setMax(255); AttribSliderG->grab(); AttribSliderG->setSubElement(true); AttribSliderG->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); r3 += core::position2di(0, r3.getHeight()+h); AttribSliderB = environment->addScrollBar(true, r3, this, -1); AttribSliderB->setMax(255); AttribSliderB->grab(); AttribSliderB->setSubElement(true); AttribSliderB->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); // add editbox AttribEditBox = environment->addEditBox( L"", r2, true, this, -1); AttribEditBox->grab(); AttribEditBox->setSubElement(true); AttribEditBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); } virtual ~CGUIColorAttribute() { if (AttribSliderA) AttribSliderA->drop(); if (AttribSliderR) AttribSliderR->drop(); if (AttribSliderG) AttribSliderG->drop(); if (AttribSliderB) AttribSliderB->drop(); if (AttribEditBox) AttribEditBox->drop(); if (AttribColor) AttribColor->drop(); } virtual void setAttrib(io::IAttributes *attribs, u32 attribIndex) { video::SColor col = attribs->getAttributeAsColor(attribIndex); AttribSliderA->setPos(col.getAlpha()); AttribSliderR->setPos(col.getRed()); AttribSliderG->setPos(col.getGreen()); AttribSliderB->setPos(col.getBlue()); AttribEditBox->setText( attribs->getAttributeAsStringW(attribIndex).c_str() ); AttribColor->setBackgroundColor(col); CGUIAttribute::setAttrib(attribs, attribIndex); } virtual bool OnEvent(const SEvent &e) { switch (e.EventType) { case EET_GUI_EVENT: switch (e.GUIEvent.EventType) { case EGET_EDITBOX_ENTER: case EGET_ELEMENT_FOCUS_LOST: if (e.GUIEvent.Caller == AttribEditBox) { // update scrollbars from textbox Attribs->setAttribute(Index, AttribEditBox->getText()); video::SColor col = Attribs->getAttributeAsColor(Index); AttribSliderA->setPos(col.getAlpha()); AttribSliderR->setPos(col.getRed()); AttribSliderG->setPos(col.getGreen()); AttribSliderB->setPos(col.getBlue()); // update colour AttribColor->setBackgroundColor(col); } break; case EGET_SCROLL_BAR_CHANGED: { // update editbox from scrollbars video::SColor col( AttribSliderA->getPos(), AttribSliderR->getPos(), AttribSliderG->getPos(), AttribSliderB->getPos()); Attribs->setAttribute(Index, col); AttribEditBox->setText( Attribs->getAttributeAsStringW(Index).c_str()); // update colour AttribColor->setBackgroundColor(col); } return updateAttrib(); default: break; } break; default: break; } return CGUIAttribute::OnEvent(e); } // save the attribute and possibly post the event to its parent virtual bool updateAttrib(bool sendEvent=true) { if (!Attribs) return true; Attribs->setAttribute(Index, AttribEditBox->getText()); AttribEditBox->setText(Attribs->getAttributeAsStringW(Index).c_str()); return CGUIAttribute::updateAttrib(sendEvent); } //! Returns the type name of the gui element. virtual const c8* getTypeName() const { return GUIEditElementTypeNames[EGUIEDIT_COLORATTRIBUTE]; } private: IGUIScrollBar* AttribSliderA; IGUIScrollBar* AttribSliderR; IGUIScrollBar* AttribSliderG; IGUIScrollBar* AttribSliderB; IGUIEditBox* AttribEditBox; IGUITab* AttribColor; }; } // namespace gui } // namespace irr #endif irrlicht-1.8.3/tools/GUIEditor/CGUIBoolAttribute.h0000644000000000000000000000337412574354552020417 0ustar rootroot#ifndef __C_GUI_BOOL_ATTRIBUTE_H_INCLUDED__ #define __C_GUI_BOOL_ATTRIBUTE_H_INCLUDED__ #include "CGUIAttribute.h" #include "IGUICheckBox.h" #include "EGUIEditTypes.h" namespace irr { namespace gui { class CGUIBoolAttribute : public CGUIAttribute { public: // CGUIBoolAttribute(IGUIEnvironment* environment, IGUIElement *parent, s32 myParentID) : CGUIAttribute(environment, parent, myParentID), AttribCheckBox(0) { core::rect r = getAbsolutePosition(); core::rect r2(0, Environment->getSkin()->getFont()->getDimension(L"A").Height + 10, r.getWidth() - 5, Environment->getSkin()->getFont()->getDimension(L"A").Height*2 + 15 ); AttribCheckBox = environment->addCheckBox(false, r2, this); AttribCheckBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); AttribCheckBox->setSubElement(true); AttribCheckBox->grab(); } virtual ~CGUIBoolAttribute() { if (AttribCheckBox) AttribCheckBox->drop(); } virtual void setAttrib(io::IAttributes *attribs, u32 attribIndex) { AttribCheckBox->setChecked(attribs->getAttributeAsBool(attribIndex)); CGUIAttribute::setAttrib(attribs, attribIndex); } // save the attribute and possibly post the event to its parent virtual bool updateAttrib(bool sendEvent=true) { if (!Attribs) return true; Attribs->setAttribute(Index, AttribCheckBox->isChecked()); return CGUIAttribute::updateAttrib(sendEvent); } //! Returns the type name of the gui element. virtual const c8* getTypeName() const { return GUIEditElementTypeNames[EGUIEDIT_BOOLATTRIBUTE]; } private: IGUICheckBox* AttribCheckBox; }; } // namespace gui } // namespace irr #endif irrlicht-1.8.3/tools/GUIEditor/CGUIAttributeEditor.h0000644000000000000000000000220612574354552020743 0ustar rootroot#ifndef __C_GUI_ATTRIBUTE_EDITOR_H_INCLUDED__ #define __C_GUI_ATTRIBUTE_EDITOR_H_INCLUDED__ #include "IGUIElement.h" #include "CGUIPanel.h" #include "irrArray.h" #include "IAttributes.h" #include "EGUIEditTypes.h" namespace irr { namespace gui { class CGUIAttribute; class CGUIAttributeEditor : public CGUIPanel { public: //! constructor CGUIAttributeEditor(IGUIEnvironment* environment, s32 id, IGUIElement *parent=0); //! destructor ~CGUIAttributeEditor(); // gets the current attributes list virtual io::IAttributes* getAttribs(); // update the attribute list after making a change void refreshAttribs(); // save the attributes void updateAttribs(); //! Returns the type name of the gui element. virtual const c8* getTypeName() const { return GUIEditElementTypeNames[EGUIEDIT_ATTRIBUTEEDITOR]; } private: core::array AttribList; // attributes editing controls io::IAttributes* Attribs; // current attributes CGUIPanel* Panel; }; } // end namespace gui } // end namespace irr #endif // __C_GUI_ATTRIBUTE_EDITOR_H_INCLUDED__ irrlicht-1.8.3/tools/GUIEditor/CGUIAttributeEditor.cpp0000644000000000000000000000550312574354552021301 0ustar rootroot #include "CGUIAttributeEditor.h" #include "IGUIEnvironment.h" #include "IFileSystem.h" #include "IVideoDriver.h" #include "IAttributes.h" #include "IGUIFont.h" #include "IGUIScrollBar.h" #include "CGUIEditWorkspace.h" #include "CGUIAttribute.h" #include "CGUIStringAttribute.h" namespace irr { namespace gui { using namespace core; using namespace io; CGUIAttributeEditor::CGUIAttributeEditor(IGUIEnvironment* environment, s32 id, IGUIElement *parent) : CGUIPanel(environment, parent, id, rect(0, 0, 100, 100)), Attribs(0), Panel(0) { #ifdef _DEBUG setDebugName("CGUIAttributeEditor"); #endif // create attributes Attribs = environment->getFileSystem()->createEmptyAttributes(Environment->getVideoDriver()); calculateClientArea(); resizeInnerPane(); // refresh attrib list refreshAttribs(); IGUIScrollBar* sb = getVScrollBar(); core::rect r = sb->getRelativePosition(); r.LowerRightCorner.Y -= 16; sb->setRelativePosition(r); } CGUIAttributeEditor::~CGUIAttributeEditor() { for (u32 i=0; iremove(); AttribList[i]->drop(); } AttribList.clear(); Attribs->drop(); } IAttributes* CGUIAttributeEditor::getAttribs() { return Attribs; } void CGUIAttributeEditor::refreshAttribs() { // clear the attribute list u32 i; for (i=0; iremove(); AttribList[i]->drop(); } AttribList.clear(); position2di top(10, 5); rect r(top.X, top.Y, getClientArea().getWidth() - 10, 5 + Environment->getSkin()->getFont()->getDimension(L"A").Height); // add attribute elements u32 c = Attribs->getAttributeCount(); for (i=0; igetAttributeTypeString(i); str += "_attribute"; CGUIAttribute* n = (CGUIAttribute*)Environment->addGUIElement(str.c_str(), 0); // if this doesn't exist, use a string editor if (!n) n = (CGUIAttribute*)Environment->addGUIElement("string_attribute", 0); if (n) { AttribList.push_back(n); n->setParentID(getID()); n->grab(); } // We can't set "this" as parent above as we need functionality // of the overloaded addChild which isn't called in the constructor. // (that's a general Irrlicht messup with too fat constructors) addChild(n); AttribList[i]->setSubElement(true); AttribList[i]->setRelativePosition(r); AttribList[i]->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); AttribList[i]->setAttrib(Attribs, i); r += position2di(0, AttribList[i]->getRelativePosition().getHeight() + 5); } } void CGUIAttributeEditor::updateAttribs() { for (u32 i=0; iupdateAttrib(false); } } // namespace gui } // namespace irr irrlicht-1.8.3/tools/GUIEditor/CGUIAttribute.h0000644000000000000000000001035112574354552017574 0ustar rootroot/* This base class is used by the Attribute editor for making your own attribute types. The attribute editor will try and create an attribute called "AttribType_attribute", and if it fails, it will create a "string_attribute". */ #ifndef __C_GUI_ATTRIBUTE_H_INCLUDED__ #define __C_GUI_ATTRIBUTE_H_INCLUDED__ #include "IGUIElement.h" #include "IGUIEnvironment.h" #include "IGUIFont.h" #include "IGUIStaticText.h" #include "IAttributes.h" #include "CGUIEditWorkspace.h" namespace irr { namespace gui { const u32 ATTRIBEDIT_ATTRIB_CHANGED=MAKE_IRR_ID('A','T','T','R'); class CGUIAttribute : public IGUIElement { public: //! constructor CGUIAttribute(IGUIEnvironment* environment, IGUIElement *parent, s32 myParentID) : IGUIElement(EGUIET_ELEMENT, environment, parent, -1, core::rect(0, 0, 100, 100) ), AttribName(0), Attribs(0), Index(0), MyParentID(myParentID) { #ifdef _DEBUG setDebugName("CGUIAttribute"); #endif AttribName = environment->addStaticText(0, core::rect(0, 0, 100, Environment->getSkin()->getFont()->getDimension(L"A").Height), false, false, this, -1, false); AttribName->grab(); AttribName->setSubElement(true); AttribName->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); } virtual ~CGUIAttribute() { if (Attribs) Attribs->drop(); if (AttribName) AttribName->drop(); } virtual bool OnEvent(const SEvent &e) { if (IsEnabled) { switch (e.EventType) { case EET_GUI_EVENT: switch (e.GUIEvent.EventType) { case EGET_ELEMENT_FOCUSED: if (Parent && isMyChild(e.GUIEvent.Caller)) Parent->bringToFront(this); break; case EGET_ELEMENT_HOVERED: case EGET_ELEMENT_LEFT: return IGUIElement::OnEvent(e); case EGET_ELEMENT_FOCUS_LOST: updateAttrib(); return IGUIElement::OnEvent(e); default: return updateAttrib(); } break; case EET_KEY_INPUT_EVENT: return true; default: break; } } return IGUIElement::OnEvent(e); } //! sets the attribute to use virtual void setAttrib(io::IAttributes *attribs, u32 attribIndex) { if (Attribs) Attribs->drop(); Attribs = attribs; if (Attribs) Attribs->grab(); Index = attribIndex; core::stringw name(attribs->getAttributeName(attribIndex)); name += L" ("; name += attribs->getAttributeTypeString(attribIndex); name += L")"; AttribName->setText(name.c_str()); core::rect r = Parent->getAbsolutePosition(); core::rect r2(0, 5, r.getWidth(), Environment->getSkin()->getFont()->getDimension(L"A").Height + 10 ); AttribName->setRelativePosition(r2); // get minimum height s32 y=0; core::list::Iterator it = Children.begin(); for (; it != Children.end(); ++it) { if (y < (*it)->getRelativePosition().LowerRightCorner.Y) y = (*it)->getRelativePosition().LowerRightCorner.Y; } setMinSize( core::dimension2du(0, y+5)); updateAttrib(false); } //! sets the parent ID, for identifying where events came from void setParentID(s32 parentID) { MyParentID = parentID; } //! save the attribute and possibly post the event to its parent virtual bool updateAttrib(bool sendEvent=true) { if (Attribs && IsEnabled && sendEvent) { // build event and pass to parent SEvent event; event.EventType = (EEVENT_TYPE)ATTRIBEDIT_ATTRIB_CHANGED; event.UserEvent.UserData1 = MyParentID; event.UserEvent.UserData2 = Index; return Parent->OnEvent(event); } return true; } virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) { IGUIElement::serializeAttributes(out, options); } virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUIElement::deserializeAttributes(in, options); if (AttribName) AttribName->setText(Text.c_str()); } protected: IGUIStaticText* AttribName; io::IAttributes* Attribs; u32 Index; s32 MyParentID; }; } // namespace gui } // namespace irr #endif irrlicht-1.8.3/tools/FileToHeader/0000755000000000000000000000000012574354552015510 5ustar rootrootirrlicht-1.8.3/tools/FileToHeader/Makefile0000644000000000000000000000153612574354552017155 0ustar rootroot# Makefile for FileToHeader Target = FileToHeader Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include CXXFLAGS = -O3 -ffast-math -Wall #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/tools/FileToHeader/main.cpp0000644000000000000000000001352212574354552017143 0ustar rootroot// Copyright (C) 2012 Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h /*** This tool creates a .h file from a given input file by encoding it into a C string, allowing you to build your resources directly into your binaries, just like Irrlicht's built-in font. To distribute your app as a single executable file of minimal size: 1. Put all your resources into a single directory and add it to Irrlicht's filesystem as a folder through IFileSystem::addArchive. Develop and test your app as usual. 2. Open IrrCompileConfig.h and comment out all the options that your app does not use. This will reduce the size of the Irrlicht library considerably. * You should remove the D3D video drivers, because they rely on external DLLs. * You should keep either the TAR or ZIP archive loader, used in step 6. * If you remove the JPEG loader, you don't have to say you use JPEG code in your documentation. 3. Recompile Irrlicht as a static library, editing the IRR_STATIC_LIB line in IrrCompileConfig.h. The next time you compile your application it will take a while longer, but Irrlicht will be built into your binary. 4. TAR or ZIP your resource directory using your favourite archiving tool (ie 7zip). * If you chose ZIP but compiled without zlib, don't compress this archive or it won't open. 5. Run this tool to convert your resource file into a .h file, like so: FileToHeader res.zip > EmbeddedResources.h 6. Add the .h file to your project, create the embedded read file then mount as a ZIP or TAR archive instead of the folder, like so: io::IReadFile *f = io::createEmbeddedFile(device->getFileSystem(), "res.zip"); device->getFileSystem()->addFileArchive(f); archive->drop(); 7. Recompile your app. * If you use Microsoft's compiler, make sure your CRT (common run-time) is the static library version, otherwise you'll have a dependency on the CRT DLLs. Your binary should now be completely portable; you can distribute just the exe file. 8. Optional: Use UPX (upx.sf.net) to compress your binary. */ #include #include #include using namespace std; int main(int argc, char* argv[]) { if (argc < 2) { // print usage cerr << "You must to specify at least one input file" << endl; cerr << "usage: " << argv[0] << " [file2...]" << endl; cerr << "outputs a header file to stdout, so for example use"; return 1; } int i = 1; // write file header cout << "// File made by FileToHeader, part of the Irrlicht Engine" << endl << endl << "#ifndef _EMBEDDED_FILES_H_INCLUDED_" << endl << "#define _EMBEDDED_FILES_H_INCLUDED_" << endl << endl << "#include \"irrTypes.h\"" << endl << "#include \"IReadFile.h\"" << endl << "#include \"IFileSystem.h\"" << endl << endl << "namespace irr" << endl << "{" << endl << "namespace io" << endl << "{" << endl << endl << " const c8* EmbeddedFileData[] = " << endl << " {" << endl; // store sizes and file names stringstream sizes; stringstream names; sizes << "const u32 EmbeddedFileSizes[] = {"; names << "const c8* EmbeddedFileNames[] = {"; int fileCount = 0; // char to hex digit table, probably doesn't help for speed due to fstream. better than using sprintf though char hextable[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; while (i < argc) { // open and seek to end of file ifstream input; input.open(argv[i], ios::in | ios::binary | ios::ate); if (input.is_open()) { int size = input.tellg(); input.seekg(0, ios::beg); // read the file into RAM char *entireFile = new char[size]; input.read(entireFile, size); if (fileCount) { sizes << ", "; names << ", "; cout << "," << endl; } // save file size and name sizes << size; names << '"' << argv[i] << '"'; // write the file data cout << " \""; for (int count=0; count < size; ++count) { if (count && (count % 16) == 0) cout << "\"" << endl << " \""; cout << "\\x" << hextable[(entireFile[count] >> 4) & 0xF] << hextable[entireFile[count] & 0x0F]; } cout << "\""; delete [] entireFile; // input.close(); fileCount++; } else { cerr << "Failed to open file: " << argv[i] << endl; } ++i; } // close binary file list and write file metadata cout << endl << " , 0};" << endl << endl << " const u32 EmbeddedFileCount = " << fileCount << ";" << endl << " " << sizes.str() << "};" << endl << " " << names.str() << "};" << endl << endl; // write functions to create embedded IReadFiles cout << " IReadFile* createEmbeddedFile(IFileSystem *fs, u32 index)" << endl << " {" << endl << " if (EmbeddedFileCount < index)" << endl << " return 0;" << endl << endl << " return fs->createMemoryReadFile((void*)EmbeddedFileData[index], " << endl << " EmbeddedFileSizes[index], EmbeddedFileNames[index]);" << endl << " }" << endl << endl << " IReadFile* createEmbeddedFile(IFileSystem *fs, path filename)" << endl << " {" << endl << " for (u32 i=0; i < EmbeddedFileCount; ++i)" << endl << " if (filename == EmbeddedFileNames[i])" << endl << " return createEmbeddedFile(fs, i);" << endl << endl << " return 0;" << endl << " }" << endl << endl; // write footer cout << "} // namespace io" << endl << "} // namespace irr" << endl << endl << "#endif // _EMBEDDED_FILES_H_INCLUDED_" << endl; return 0; } irrlicht-1.8.3/tools/FileToHeader/FileToHeader.cbp0000644000000000000000000000235612574354552020477 0ustar rootroot irrlicht-1.8.3/source/0000755000000000000000000000000012574354552013355 5ustar rootrootirrlicht-1.8.3/source/source.txt0000644000000000000000000000504212574354552015417 0ustar rootrootSource code of the Irrlicht Engine The complete source of the Irrlicht Engine can be found in this directory. Please note that YOU DO NOT NEED THIS SOURCE to develop 3d applications with the Irrlicht Engine. Instead, please use the .dll in the \bin directory, the .lib in the \lib directory and the header files in the \include directory. You will find a good tutorial how to set up your development environment and to use the engine in the \examples directory. (Try 01.helloworld) The source of the engine is included because for the following reasons: - To let developers be able to debug the engine. - To let developers be able to make changes to the engine. - To let developers be able to compile their own versions of the engine. HOW TO COMPILE THE ENGINE WITH LINUX If you wish to compile the engine for Linux yourself, run a 'make' in the folder 'source/Irrlicht'. After this, you should be able to make all example applications in examples. Then just run them from the directory where they are built. For the necessary compiler and linker flags please check the provided Makefiles in the examples directories. Only the Software Drivers and the Null Driver will work on all Linux machines, while OpenGL support requires either GLX support of the X11 server (try glxinfo) or a software OpenGL solution such as Mesa. If you get a compiling/linking problem like undefined reference to `glXGetProcAddress' This is a problem introduced by the NVidia drivers. There are several solutions: A) Update your drivers. All versions with GLX 1.4 support (i.e. beginning with 12/2005) will work. B) Define the symbol _IRR_GETPROCADDRESS_WORKAROUND_ during compilation of COpenGLDriver.cpp, either by adding it to the compiler command line or by uncommenting the line defining this symbol inside the OpenGL driver source. This will force the use of glXGetProcAddressARB which has better chances to work on older systems. If you get compiling or runtime problems regarding XF86VidMode, Xxf86vm.so, or the XFree86 VidMode extension you have also several solutions: A) Install the extension for your X server or the developer package in case of compiler/linker problems. B) Disable the VidMode usage by disabling the define _IRR_LINUX_X11_VIDMODE_ in include/IrrCompileConfig.h In this case you might give the RandR extension a try (by enabling the next define in that file) which also provides fullscreen support under Linux. If both extensions fail you won't have fullscreen support for Irrlicht. irrlicht-1.8.3/source/Irrlicht/0000755000000000000000000000000012574354552015135 5ustar rootrootirrlicht-1.8.3/source/Irrlicht/source.txt0000644000000000000000000000320712574354552017200 0ustar rootrootSource code of the Irrlicht Engine The complete source of the Irrlicht Engine can be found when decompressing the .zip file included in this directory. Please note that YOU DO NOT NEED THIS SOURCE to develop 3d applications with the Irrlicht Engine. Instead, please use the .dll in the \bin directory, the .lib in the \lib directory and the header files in the \include directory. You will find a good tutorial how to set up your development environment and to use the engine in the \examples directory. (Try 1.helloworld) The source of the engine is only included because of the following reasons: - To let developers be able to debug the engine. - To let developers be able to make changes to the engine. - To let developers be able to compile their own versions of the engine. HOW TO COMPILE THE ENGINE WITH LINUX If you wish to compile the engine in linux yourself, unzip the source source.zip file in the \source directory. Run a 'make' in the now existing new subfolder 'Irrlicht'. After this, you should be able to make all example applications in \examples. Then just start an X Server and run them, from the directory where they are. If you get a compiling/linking problem like undefined reference to `glXGetProcAddress' Then there are several solutions: A) This disables the use of OpenGL extensions: Open the file IrrCompileConfig.h, comment out _IRR_OPENGL_USE_EXTPOINTER_, and recompile Irrlicht using make clean make B) Replace all occurrences of 'glXGetProcAddress' with 'glXGetProcAddressARB' and run a make This will solve the issue but keep the OpenGL extension enabled. irrlicht-1.8.3/source/Irrlicht/SoftwareDriver2_helper.h0000644000000000000000000006261412574354552021706 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h /* History: - changed behavior for log2 textures ( replaced multiplies by shift ) */ #ifndef __S_VIDEO_2_SOFTWARE_HELPER_H_INCLUDED__ #define __S_VIDEO_2_SOFTWARE_HELPER_H_INCLUDED__ #include "SoftwareDriver2_compile_config.h" #include "irrMath.h" #include "CSoftwareTexture2.h" #include "SMaterial.h" namespace irr { // supporting different packed pixel needs many defines... #ifdef SOFTWARE_DRIVER_2_32BIT typedef u32 tVideoSample; #define MASK_A 0xFF000000 #define MASK_R 0x00FF0000 #define MASK_G 0x0000FF00 #define MASK_B 0x000000FF #define SHIFT_A 24 #define SHIFT_R 16 #define SHIFT_G 8 #define SHIFT_B 0 #define COLOR_MAX 0xFF #define COLOR_MAX_LOG2 8 #define COLOR_BRIGHT_WHITE 0xFFFFFFFF #define VIDEO_SAMPLE_GRANULARITY 2 #else typedef u16 tVideoSample; #define MASK_A 0x8000 #define MASK_R 0x7C00 #define MASK_G 0x03E0 #define MASK_B 0x001F #define SHIFT_A 15 #define SHIFT_R 10 #define SHIFT_G 5 #define SHIFT_B 0 #define COLOR_MAX 0x1F #define COLOR_MAX_LOG2 5 #define COLOR_BRIGHT_WHITE 0xFFFF #define VIDEO_SAMPLE_GRANULARITY 1 #endif // ----------------------- Generic ---------------------------------- //! a more useful memset for pixel // (standard memset only works with 8-bit values) inline void memset32(void * dest, const u32 value, u32 bytesize) { u32 * d = (u32*) dest; u32 i; // loops unrolled to reduce the number of increments by factor ~8. i = bytesize >> (2 + 3); while (i) { d[0] = value; d[1] = value; d[2] = value; d[3] = value; d[4] = value; d[5] = value; d[6] = value; d[7] = value; d += 8; i -= 1; } i = (bytesize >> 2 ) & 7; while (i) { d[0] = value; d += 1; i -= 1; } } //! a more useful memset for pixel // (standard memset only works with 8-bit values) inline void memset16(void * dest, const u16 value, u32 bytesize) { u16 * d = (u16*) dest; u32 i; // loops unrolled to reduce the number of increments by factor ~8. i = bytesize >> (1 + 3); while (i) { d[0] = value; d[1] = value; d[2] = value; d[3] = value; d[4] = value; d[5] = value; d[6] = value; d[7] = value; d += 8; --i; } i = (bytesize >> 1 ) & 7; while (i) { d[0] = value; ++d; --i; } } /* use biased loop counter --> 0 byte copy is forbidden */ REALINLINE void memcpy32_small ( void * dest, const void *source, u32 bytesize ) { u32 c = bytesize >> 2; do { ((u32*) dest ) [ c-1 ] = ((u32*) source) [ c-1 ]; } while ( --c ); } // integer log2 of a float ieee 754. TODO: non ieee floating point static inline s32 s32_log2_f32( f32 f) { u32 x = IR ( f ); return ((x & 0x7F800000) >> 23) - 127; } static inline s32 s32_log2_s32(u32 x) { return s32_log2_f32( (f32) x); } static inline s32 s32_abs(s32 x) { s32 b = x >> 31; return (x ^ b ) - b; } //! conditional set based on mask and arithmetic shift REALINLINE u32 if_mask_a_else_b ( const u32 mask, const u32 a, const u32 b ) { return ( mask & ( a ^ b ) ) ^ b; } // ------------------ Video--------------------------------------- /*! Pixel = dest * ( 1 - alpha ) + source * alpha alpha [0;256] */ REALINLINE u32 PixelBlend32 ( const u32 c2, const u32 c1, u32 alpha ) { u32 srcRB = c1 & 0x00FF00FF; u32 srcXG = c1 & 0x0000FF00; u32 dstRB = c2 & 0x00FF00FF; u32 dstXG = c2 & 0x0000FF00; u32 rb = srcRB - dstRB; u32 xg = srcXG - dstXG; rb *= alpha; xg *= alpha; rb >>= 8; xg >>= 8; rb += dstRB; xg += dstXG; rb &= 0x00FF00FF; xg &= 0x0000FF00; return rb | xg; } /*! Pixel = dest * ( 1 - alpha ) + source * alpha alpha [0;32] */ inline u16 PixelBlend16 ( const u16 c2, const u32 c1, const u16 alpha ) { const u16 srcRB = c1 & 0x7C1F; const u16 srcXG = c1 & 0x03E0; const u16 dstRB = c2 & 0x7C1F; const u16 dstXG = c2 & 0x03E0; u32 rb = srcRB - dstRB; u32 xg = srcXG - dstXG; rb *= alpha; xg *= alpha; rb >>= 5; xg >>= 5; rb += dstRB; xg += dstXG; rb &= 0x7C1F; xg &= 0x03E0; return (u16)(rb | xg); } /* Pixel = c0 * (c1/31). c0 Alpha retain */ inline u16 PixelMul16 ( const u16 c0, const u16 c1) { return (u16)((( ( (c0 & 0x7C00) * (c1 & 0x7C00) ) & 0x3E000000 ) >> 15 ) | (( ( (c0 & 0x03E0) * (c1 & 0x03E0) ) & 0x000F8000 ) >> 10 ) | (( ( (c0 & 0x001F) * (c1 & 0x001F) ) & 0x000003E0 ) >> 5 ) | (c0 & 0x8000)); } /* Pixel = c0 * (c1/31). */ inline u16 PixelMul16_2 ( u16 c0, u16 c1) { return (u16)(( ( (c0 & 0x7C00) * (c1 & 0x7C00) ) & 0x3E000000 ) >> 15 | ( ( (c0 & 0x03E0) * (c1 & 0x03E0) ) & 0x000F8000 ) >> 10 | ( ( (c0 & 0x001F) * (c1 & 0x001F) ) & 0x000003E0 ) >> 5 | ( c0 & c1 & 0x8000)); } /* Pixel = c0 * (c1/255). c0 Alpha Retain */ REALINLINE u32 PixelMul32 ( const u32 c0, const u32 c1) { return (c0 & 0xFF000000) | (( ( (c0 & 0x00FF0000) >> 12 ) * ( (c1 & 0x00FF0000) >> 12 ) ) & 0x00FF0000 ) | (( ( (c0 & 0x0000FF00) * (c1 & 0x0000FF00) ) >> 16 ) & 0x0000FF00 ) | (( ( (c0 & 0x000000FF) * (c1 & 0x000000FF) ) >> 8 ) & 0x000000FF); } /* Pixel = c0 * (c1/255). */ REALINLINE u32 PixelMul32_2 ( const u32 c0, const u32 c1) { return (( ( (c0 & 0xFF000000) >> 16 ) * ( (c1 & 0xFF000000) >> 16 ) ) & 0xFF000000 ) | (( ( (c0 & 0x00FF0000) >> 12 ) * ( (c1 & 0x00FF0000) >> 12 ) ) & 0x00FF0000 ) | (( ( (c0 & 0x0000FF00) * (c1 & 0x0000FF00) ) >> 16 ) & 0x0000FF00 ) | (( ( (c0 & 0x000000FF) * (c1 & 0x000000FF) ) >> 8 ) & 0x000000FF); } /* Pixel = clamp ( c0 + c1, 0, 255 ) */ REALINLINE u32 PixelAdd32 ( const u32 c2, const u32 c1) { u32 sum = ( c2 & 0x00FFFFFF ) + ( c1 & 0x00FFFFFF ); u32 low_bits = ( c2 ^ c1 ) & 0x00010101; s32 carries = ( sum - low_bits ) & 0x01010100; u32 modulo = sum - carries; u32 clamp = carries - ( carries >> 8 ); return modulo | clamp; } #if 0 // 1 - Bit Alpha Blending inline u16 PixelBlend16 ( const u16 destination, const u16 source ) { if((source & 0x8000) == 0x8000) return source; // The source is visible, so use it. else return destination; // The source is transparent, so use the destination. } // 1 - Bit Alpha Blending 16Bit SIMD inline u32 PixelBlend16_simd ( const u32 destination, const u32 source ) { switch(source & 0x80008000) { case 0x80008000: // Both source pixels are visible return source; case 0x80000000: // Only the first source pixel is visible return (source & 0xFFFF0000) | (destination & 0x0000FFFF); case 0x00008000: // Only the second source pixel is visible. return (destination & 0xFFFF0000) | (source & 0x0000FFFF); default: // Neither source pixel is visible. return destination; } } #else // 1 - Bit Alpha Blending inline u16 PixelBlend16 ( const u16 c2, const u16 c1 ) { u16 mask = ((c1 & 0x8000) >> 15 ) + 0x7fff; return (c2 & mask ) | ( c1 & ~mask ); } // 1 - Bit Alpha Blending 16Bit SIMD inline u32 PixelBlend16_simd ( const u32 c2, const u32 c1 ) { u32 mask = ((c1 & 0x80008000) >> 15 ) + 0x7fff7fff; return (c2 & mask ) | ( c1 & ~mask ); } #endif /*! Pixel = dest * ( 1 - SourceAlpha ) + source * SourceAlpha */ inline u32 PixelBlend32 ( const u32 c2, const u32 c1 ) { // alpha test u32 alpha = c1 & 0xFF000000; if ( 0 == alpha ) return c2; if ( 0xFF000000 == alpha ) { return c1; } alpha >>= 24; // add highbit alpha, if ( alpha > 127 ) alpha += 1; alpha += ( alpha >> 7); u32 srcRB = c1 & 0x00FF00FF; u32 srcXG = c1 & 0x0000FF00; u32 dstRB = c2 & 0x00FF00FF; u32 dstXG = c2 & 0x0000FF00; u32 rb = srcRB - dstRB; u32 xg = srcXG - dstXG; rb *= alpha; xg *= alpha; rb >>= 8; xg >>= 8; rb += dstRB; xg += dstXG; rb &= 0x00FF00FF; xg &= 0x0000FF00; return (c1 & 0xFF000000) | rb | xg; } // ------------------ Fix Point ---------------------------------- typedef s32 tFixPoint; typedef u32 tFixPointu; // Fix Point 12 #if 0 #define FIX_POINT_PRE 12 #define FIX_POINT_FRACT_MASK 0xFFF #define FIX_POINT_SIGNED_MASK 0xFFFFF000 #define FIX_POINT_UNSIGNED_MASK 0x7FFFF000 #define FIX_POINT_ONE 0x1000 #define FIX_POINT_ZERO_DOT_FIVE 0x0800 #define FIX_POINT_F32_MUL 4096.f #endif // Fix Point 10 #if 1 #define FIX_POINT_PRE 10 #define FIX_POINT_FRACT_MASK 0x3FF #define FIX_POINT_SIGNED_MASK 0xFFFFFC00 #define FIX_POINT_UNSIGNED_MASK 0x7FFFFE00 #define FIX_POINT_ONE 0x400 #define FIX_POINT_ZERO_DOT_FIVE 0x200 #define FIX_POINT_F32_MUL 1024.f #endif // Fix Point 9 #if 0 #define FIX_POINT_PRE 9 #define FIX_POINT_FRACT_MASK 0x1FF #define FIX_POINT_SIGNED_MASK 0xFFFFFE00 #define FIX_POINT_UNSIGNED_MASK 0x7FFFFE00 #define FIX_POINT_ONE 0x200 #define FIX_POINT_ZERO_DOT_FIVE 0x100 #define FIX_POINT_F32_MUL 512.f #endif // Fix Point 7 #if 0 #define FIX_POINT_PRE 7 #define FIX_POINT_FRACT_MASK 0x7F #define FIX_POINT_SIGNED_MASK 0xFFFFFF80 #define FIX_POINT_UNSIGNED_MASK 0x7FFFFF80 #define FIX_POINT_ONE 0x80 #define FIX_POINT_ZERO_DOT_FIVE 0x40 #define FIX_POINT_F32_MUL 128.f #endif #define FIXPOINT_COLOR_MAX ( COLOR_MAX << FIX_POINT_PRE ) #define FIX_POINT_HALF_COLOR ( (tFixPoint) ( ((f32) COLOR_MAX / 2.f * FIX_POINT_F32_MUL ) ) ) /* convert signed integer to fixpoint */ inline tFixPoint s32_to_fixPoint (const s32 x) { return x << FIX_POINT_PRE; } inline tFixPointu u32_to_fixPoint (const u32 x) { return x << FIX_POINT_PRE; } inline u32 fixPointu_to_u32 (const tFixPointu x) { return x >> FIX_POINT_PRE; } // 1/x * FIX_POINT REALINLINE f32 fix_inverse32 ( const f32 x ) { return FIX_POINT_F32_MUL / x; } /* convert float to fixpoint fast convert (fistp on x86) HAS to be used.. hints: compileflag /QIfist for msvc7. msvc 8.0 has smth different others should use their favourite assembler.. */ static inline int f_round2(f32 f) { f += (3<<22); return IR(f) - 0x4b400000; } /* convert f32 to Fix Point. multiply is needed anyway, so scale mulby */ REALINLINE tFixPoint tofix (const f32 x, const f32 mulby = FIX_POINT_F32_MUL ) { return (tFixPoint) (x * mulby); } /* Fix Point , Fix Point Multiply */ REALINLINE tFixPointu imulFixu(const tFixPointu x, const tFixPointu y) { return (x * y) >> (tFixPointu) FIX_POINT_PRE; } /* Fix Point , Fix Point Multiply */ REALINLINE tFixPoint imulFix(const tFixPoint x, const tFixPoint y) { return ( x * y) >> ( FIX_POINT_PRE ); } /* Fix Point , Fix Point Multiply x * y * 2 */ REALINLINE tFixPoint imulFix2(const tFixPoint x, const tFixPoint y) { return ( x * y) >> ( FIX_POINT_PRE -1 ); } /* Multiply x * y * 1 */ REALINLINE tFixPoint imulFix_tex1(const tFixPoint x, const tFixPoint y) { return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 4 ); } /* Multiply x * y * 2 */ REALINLINE tFixPoint imulFix_tex2(const tFixPoint x, const tFixPoint y) { return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 3 ); } /* Multiply x * y * 4 */ REALINLINE tFixPoint imulFix_tex4(const tFixPoint x, const tFixPoint y) { #ifdef SOFTWARE_DRIVER_2_32BIT return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 2 ); #else return ( x * y) >> ( FIX_POINT_PRE + ( VIDEO_SAMPLE_GRANULARITY * 3 ) ); #endif } /*! clamp FixPoint to maxcolor in FixPoint, min(a,31) */ REALINLINE tFixPoint clampfix_maxcolor ( const tFixPoint a) { tFixPoint c = (a - FIXPOINT_COLOR_MAX) >> 31; return (a & c) | ( FIXPOINT_COLOR_MAX & ~c); } /*! clamp FixPoint to 0 in FixPoint, max(a,0) */ REALINLINE tFixPoint clampfix_mincolor ( const tFixPoint a) { return a - ( a & ( a >> 31 ) ); } REALINLINE tFixPoint saturateFix ( const tFixPoint a) { return clampfix_mincolor ( clampfix_maxcolor ( a ) ); } // rount fixpoint to int inline s32 roundFix ( const tFixPoint x ) { return ( x + FIX_POINT_ZERO_DOT_FIVE ) >> FIX_POINT_PRE; } // x in [0;1[ inline s32 f32_to_23Bits(const f32 x) { f32 y = x + 1.f; return IR(y) & 0x7FFFFF; // last 23 bits } /*! return VideoSample from fixpoint */ REALINLINE tVideoSample fix_to_color ( const tFixPoint r, const tFixPoint g, const tFixPoint b ) { #ifdef __BIG_ENDIAN__ return FIXPOINT_COLOR_MAX | ( r & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - 8) | ( g & FIXPOINT_COLOR_MAX) << ( 16 - FIX_POINT_PRE ) | ( b & FIXPOINT_COLOR_MAX) << ( 24 - FIX_POINT_PRE ); #else return ( FIXPOINT_COLOR_MAX & FIXPOINT_COLOR_MAX) << ( SHIFT_A - FIX_POINT_PRE ) | ( r & FIXPOINT_COLOR_MAX) << ( SHIFT_R - FIX_POINT_PRE ) | ( g & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_G ) | ( b & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_B ); #endif } /*! return VideoSample from fixpoint */ REALINLINE tVideoSample fix4_to_color ( const tFixPoint a, const tFixPoint r, const tFixPoint g, const tFixPoint b ) { #ifdef __BIG_ENDIAN__ return ( a & (FIX_POINT_FRACT_MASK - 1 )) >> ( FIX_POINT_PRE ) | ( r & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - 8) | ( g & FIXPOINT_COLOR_MAX) << ( 16 - FIX_POINT_PRE ) | ( b & FIXPOINT_COLOR_MAX) << ( 24 - FIX_POINT_PRE ); #else return ( a & (FIX_POINT_FRACT_MASK - 1 )) << ( SHIFT_A - 1 ) | ( r & FIXPOINT_COLOR_MAX) << ( SHIFT_R - FIX_POINT_PRE ) | ( g & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_G ) | ( b & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_B ); #endif } /*! return fixpoint from VideoSample granularity COLOR_MAX */ inline void color_to_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 ) { (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE ); (tFixPointu&) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G ); (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B ); } /*! return fixpoint from VideoSample granularity COLOR_MAX */ inline void color_to_fix ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 ) { (tFixPointu&) a = (t00 & MASK_A) >> ( SHIFT_A - FIX_POINT_PRE ); (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE ); (tFixPointu&) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G ); (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B ); } /*! return fixpoint from VideoSample granularity 0..FIX_POINT_ONE */ inline void color_to_fix1 ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 ) { (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R + COLOR_MAX_LOG2 - FIX_POINT_PRE ); (tFixPointu&) g = (t00 & MASK_G) >> ( SHIFT_G + COLOR_MAX_LOG2 - FIX_POINT_PRE ); (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - COLOR_MAX_LOG2 ); } /*! return fixpoint from VideoSample granularity 0..FIX_POINT_ONE */ inline void color_to_fix1 ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 ) { (tFixPointu&) a = (t00 & MASK_A) >> ( SHIFT_A + COLOR_MAX_LOG2 - FIX_POINT_PRE ); (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R + COLOR_MAX_LOG2 - FIX_POINT_PRE ); (tFixPointu&) g = (t00 & MASK_G) >> ( SHIFT_G + COLOR_MAX_LOG2 - FIX_POINT_PRE ); (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - COLOR_MAX_LOG2 ); } // ----- FP24 ---- floating point z-buffer #if 1 typedef f32 fp24; #else struct fp24 { u32 v; fp24() {} fp24 ( const f32 f ) { f32 y = f + 1.f; v = ((u32&)y) & 0x7FFFFF; // last 23 bits } void operator=(const f32 f ) { f32 y = f + 1.f; v = ((u32&)y) & 0x7FFFFF; // last 23 bits } void operator+=(const fp24 &other ) { v += other.v; } operator f32 () const { f32 r = FR ( v ); return r + 1.f; } }; #endif // ------------------------ Internal Texture ----------------------------- struct sInternalTexture { u32 textureXMask; u32 textureYMask; u32 pitchlog2; void *data; video::CSoftwareTexture2 *Texture; s32 lodLevel; }; // get video sample plain inline tVideoSample getTexel_plain ( const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty ) { u32 ofs; ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); // texel return *((tVideoSample*)( (u8*) t->data + ofs )); } // get video sample to fix inline void getTexel_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty ) { u32 ofs; ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); // texel tVideoSample t00; t00 = *((tVideoSample*)( (u8*) t->data + ofs )); r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE); g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G ); b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B ); } // get video sample to fixpoint REALINLINE void getTexel_fix ( tFixPoint &a, const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty ) { u32 ofs; ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); // texel tVideoSample t00; t00 = *((tVideoSample*)( (u8*) t->data + ofs )); a = (t00 & MASK_A) >> ( SHIFT_A - FIX_POINT_PRE); } inline void getSample_texture_dither ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty, const u32 x, const u32 y ) { static const tFixPointu dithermask[] = { 0x00,0x80,0x20,0xa0, 0xc0,0x40,0xe0,0x60, 0x30,0xb0,0x10,0x90, 0xf0,0x70,0xd0,0x50 }; const u32 index = (y & 3 ) << 2 | (x & 3); const tFixPointu _ntx = (tx + dithermask [ index ] ) & t->textureXMask; const tFixPointu _nty = (ty + dithermask [ index ] ) & t->textureYMask; u32 ofs; ofs = ( ( _nty ) >> FIX_POINT_PRE ) << t->pitchlog2; ofs |= ( _ntx ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); // texel const tVideoSample t00 = *((tVideoSample*)( (u8*) t->data + ofs )); (tFixPointu &) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE); (tFixPointu &) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G ); (tFixPointu &) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B ); } /* load a sample from internal texture at position tx,ty to fixpoint */ #ifndef SOFTWARE_DRIVER_2_BILINEAR // get Sample linear == getSample_fixpoint inline void getSample_texture ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty ) { u32 ofs; ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); // texel const tVideoSample t00 = *((tVideoSample*)( (u8*) t->data + ofs )); (tFixPointu &) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE); (tFixPointu &) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G ); (tFixPointu &) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B ); } inline void getSample_texture ( tFixPointu &a, tFixPointu &r, tFixPointu &g, tFixPointu &b, const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty ) { u32 ofs; ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); // texel const tVideoSample t00 = *((tVideoSample*)( (u8*) t->data + ofs )); (tFixPointu &)a = (t00 & MASK_A) >> ( SHIFT_A - FIX_POINT_PRE); (tFixPointu &)r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE); (tFixPointu &)g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G ); (tFixPointu &)b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B ); } #else // get sample linear REALINLINE void getSample_linear ( tFixPointu &r, tFixPointu &g, tFixPointu &b, const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty ) { u32 ofs; ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); // texel tVideoSample t00; t00 = *((tVideoSample*)( (u8*) t->data + ofs )); r = (t00 & MASK_R) >> SHIFT_R; g = (t00 & MASK_G) >> SHIFT_G; b = (t00 & MASK_B); } // get Sample bilinear REALINLINE void getSample_texture ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty ) { tFixPointu r00,g00,b00; tFixPointu r01,g01,b01; tFixPointu r10,g10,b10; tFixPointu r11,g11,b11; #if 0 getSample_linear ( r00, g00, b00, t, tx,ty ); getSample_linear ( r10, g10, b10, t, tx + FIX_POINT_ONE,ty ); getSample_linear ( r01, g01, b01, t, tx,ty + FIX_POINT_ONE ); getSample_linear ( r11, g11, b11, t, tx + FIX_POINT_ONE,ty + FIX_POINT_ONE ); #else u32 o0, o1,o2,o3; tVideoSample t00; o0 = ( ( (ty) & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; o1 = ( ( (ty+FIX_POINT_ONE) & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; o2 = ( (tx) & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); o3 = ( (tx+FIX_POINT_ONE) & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); t00 = *((tVideoSample*)( (u8*) t->data + (o0 | o2 ) )); r00 = (t00 & MASK_R) >> SHIFT_R; g00 = (t00 & MASK_G) >> SHIFT_G; b00 = (t00 & MASK_B); t00 = *((tVideoSample*)( (u8*) t->data + (o0 | o3 ) )); r10 = (t00 & MASK_R) >> SHIFT_R; g10 = (t00 & MASK_G) >> SHIFT_G; b10 = (t00 & MASK_B); t00 = *((tVideoSample*)( (u8*) t->data + (o1 | o2 ) )); r01 = (t00 & MASK_R) >> SHIFT_R; g01 = (t00 & MASK_G) >> SHIFT_G; b01 = (t00 & MASK_B); t00 = *((tVideoSample*)( (u8*) t->data + (o1 | o3 ) )); r11 = (t00 & MASK_R) >> SHIFT_R; g11 = (t00 & MASK_G) >> SHIFT_G; b11 = (t00 & MASK_B); #endif const tFixPointu txFract = tx & FIX_POINT_FRACT_MASK; const tFixPointu txFractInv = FIX_POINT_ONE - txFract; const tFixPointu tyFract = ty & FIX_POINT_FRACT_MASK; const tFixPointu tyFractInv = FIX_POINT_ONE - tyFract; const tFixPointu w00 = imulFixu ( txFractInv, tyFractInv ); const tFixPointu w10 = imulFixu ( txFract , tyFractInv ); const tFixPointu w01 = imulFixu ( txFractInv, tyFract ); const tFixPointu w11 = imulFixu ( txFract , tyFract ); r = (r00 * w00 ) + (r01 * w01 ) + (r10 * w10 ) + (r11 * w11 ); g = (g00 * w00 ) + (g01 * w01 ) + (g10 * w10 ) + (g11 * w11 ); b = (b00 * w00 ) + (b01 * w01 ) + (b10 * w10 ) + (b11 * w11 ); } // get sample linear REALINLINE void getSample_linear ( tFixPointu &a, tFixPointu &r, tFixPointu &g, tFixPointu &b, const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty ) { u32 ofs; ofs = ( ( ty & t->textureYMask ) >> FIX_POINT_PRE ) << t->pitchlog2; ofs |= ( tx & t->textureXMask ) >> ( FIX_POINT_PRE - VIDEO_SAMPLE_GRANULARITY ); // texel tVideoSample t00; t00 = *((tVideoSample*)( (u8*) t->data + ofs )); a = (t00 & MASK_A) >> SHIFT_A; r = (t00 & MASK_R) >> SHIFT_R; g = (t00 & MASK_G) >> SHIFT_G; b = (t00 & MASK_B); } // get Sample bilinear REALINLINE void getSample_texture ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const sInternalTexture * t, const tFixPointu tx, const tFixPointu ty ) { tFixPointu a00, r00,g00,b00; tFixPointu a01, r01,g01,b01; tFixPointu a10, r10,g10,b10; tFixPointu a11, r11,g11,b11; getSample_linear ( a00, r00, g00, b00, t, tx,ty ); getSample_linear ( a10, r10, g10, b10, t, tx + FIX_POINT_ONE,ty ); getSample_linear ( a01, r01, g01, b01, t, tx,ty + FIX_POINT_ONE ); getSample_linear ( a11, r11, g11, b11, t, tx + FIX_POINT_ONE,ty + FIX_POINT_ONE ); const tFixPointu txFract = tx & FIX_POINT_FRACT_MASK; const tFixPointu txFractInv = FIX_POINT_ONE - txFract; const tFixPointu tyFract = ty & FIX_POINT_FRACT_MASK; const tFixPointu tyFractInv = FIX_POINT_ONE - tyFract; const tFixPointu w00 = imulFixu ( txFractInv, tyFractInv ); const tFixPointu w10 = imulFixu ( txFract , tyFractInv ); const tFixPointu w01 = imulFixu ( txFractInv, tyFract ); const tFixPointu w11 = imulFixu ( txFract , tyFract ); a = (a00 * w00 ) + (a01 * w01 ) + (a10 * w10 ) + (a11 * w11 ); r = (r00 * w00 ) + (r01 * w01 ) + (r10 * w10 ) + (r11 * w11 ); g = (g00 * w00 ) + (g01 * w01 ) + (g10 * w10 ) + (g11 * w11 ); b = (b00 * w00 ) + (b01 * w01 ) + (b10 * w10 ) + (b11 * w11 ); } #endif // some 2D Defines struct AbsRectangle { s32 x0; s32 y0; s32 x1; s32 y1; }; //! 2D Intersection test inline bool intersect ( AbsRectangle &dest, const AbsRectangle& a, const AbsRectangle& b) { dest.x0 = core::s32_max( a.x0, b.x0 ); dest.y0 = core::s32_max( a.y0, b.y0 ); dest.x1 = core::s32_min( a.x1, b.x1 ); dest.y1 = core::s32_min( a.y1, b.y1 ); return dest.x0 < dest.x1 && dest.y0 < dest.y1; } // some 1D defines struct sIntervall { s32 start; s32 end; }; // returning intersection width inline s32 intervall_intersect_test( const sIntervall& a, const sIntervall& b) { return core::s32_min( a.end, b.end ) - core::s32_max( a.start, b.start ); } } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/SoftwareDriver2_compile_config.h0000644000000000000000000000630612574354552023400 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_VIDEO_2_SOFTWARE_COMPILE_CONFIG_H_INCLUDED__ #define __S_VIDEO_2_SOFTWARE_COMPILE_CONFIG_H_INCLUDED__ #include "IrrCompileConfig.h" // Generic Render Flags for burning's video rasterizer // defined now in irrlicht compile config #ifdef BURNINGVIDEO_RENDERER_BEAUTIFUL #define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #define SOFTWARE_DRIVER_2_SUBTEXEL #define SOFTWARE_DRIVER_2_BILINEAR #define SOFTWARE_DRIVER_2_LIGHTING #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #define SOFTWARE_DRIVER_2_32BIT #define SOFTWARE_DRIVER_2_MIPMAPPING #define SOFTWARE_DRIVER_2_USE_WBUFFER #define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 0 #endif //! Set Flags for Windows Mobile #ifdef BURNINGVIDEO_RENDERER_CE #define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #define SOFTWARE_DRIVER_2_SUBTEXEL //#define SOFTWARE_DRIVER_2_BILINEAR //#define SOFTWARE_DRIVER_2_LIGHTING #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #define SOFTWARE_DRIVER_2_16BIT #define SOFTWARE_DRIVER_2_MIPMAPPING #define SOFTWARE_DRIVER_2_USE_WBUFFER //#define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 128 #endif #ifdef BURNINGVIDEO_RENDERER_FAST #define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #define SOFTWARE_DRIVER_2_SUBTEXEL //#define SOFTWARE_DRIVER_2_BILINEAR //#define SOFTWARE_DRIVER_2_LIGHTING //#define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #define SOFTWARE_DRIVER_2_32BIT #define SOFTWARE_DRIVER_2_MIPMAPPING #define SOFTWARE_DRIVER_2_USE_WBUFFER #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 0 #endif #ifdef BURNINGVIDEO_RENDERER_ULTRA_FAST #define BURNINGVIDEO_RENDERER_FAST //#define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #define SOFTWARE_DRIVER_2_SUBTEXEL //#define SOFTWARE_DRIVER_2_BILINEAR //#define SOFTWARE_DRIVER_2_LIGHTING //#define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR //#define SOFTWARE_DRIVER_2_32BIT #define SOFTWARE_DRIVER_2_MIPMAPPING #define SOFTWARE_DRIVER_2_USE_WBUFFER #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 0 #endif // Derivate flags // texture format #ifdef SOFTWARE_DRIVER_2_32BIT #define BURNINGSHADER_COLOR_FORMAT ECF_A8R8G8B8 #else #define BURNINGSHADER_COLOR_FORMAT ECF_A1R5G5B5 #endif // mip mapping #if defined ( SOFTWARE_DRIVER_2_MIPMAPPING ) #if defined( BURNINGVIDEO_RENDERER_BEAUTIFUL ) #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 8 #define SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS 0 #elif defined ( BURNINGVIDEO_RENDERER_CE ) #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 4 #define SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS 0 #else #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 8 #define SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS 0 #endif #else #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 1 #define SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS 0 #endif #define SOFTWARE_DRIVER_2_MIPMAPPING_SCALE (8/SOFTWARE_DRIVER_2_MIPMAPPING_MAX) #ifndef REALINLINE #ifdef _MSC_VER #define REALINLINE __forceinline #else #define REALINLINE inline #endif #endif #endif irrlicht-1.8.3/source/Irrlicht/SConstruct0000644000000000000000000002043412574354552017172 0ustar rootrootimport os import sys USE_GCC = 1; NDEBUG = 1; PROFILE = 0; APPLICATION_NAME = 'Irrlicht'; LIBRARIES = ['gdi32', 'opengl32', 'd3dx9d', 'winmm']; if USE_GCC==1 and PROFILE==1: LIBRARIES += ['gmon']; CXXINCS = ['../../include/', 'zlib/', 'jpeglib/', 'libpng/']; if USE_GCC==0: env = Environment(ENV = { 'PATH': os.environ['PATH'] }, CPPPATH=CXXINCS); else: env = Environment(ENV = { 'PATH': os.environ['PATH'] }, tools = ['mingw'], CPPPATH=CXXINCS); IRRMESHLOADER = ['CBSPMeshFileLoader.cpp', 'CMD2MeshFileLoader.cpp', 'CMD3MeshFileLoader.cpp', 'CMS3DMeshFileLoader.cpp', 'CB3DMeshFileLoader.cpp', 'C3DSMeshFileLoader.cpp', 'COgreMeshFileLoader.cpp', 'COBJMeshFileLoader.cpp', 'CColladaFileLoader.cpp', 'CCSMLoader.cpp', 'CDMFLoader.cpp', 'CLMTSMeshFileLoader.cpp', 'CMY3DMeshFileLoader.cpp', 'COCTLoader.cpp', 'CXMeshFileLoader.cpp', 'CIrrMeshFileLoader.cpp', 'CSTLMeshFileLoader.cpp', 'CLWOMeshFileLoader.cpp']; IRRMESHWRITER = ['CColladaMeshWriter.cpp', 'CIrrMeshWriter.cpp', 'COBJMeshWriter.cpp', 'CSTLMeshWriter.cpp']; IRRMESHOBJ = IRRMESHLOADER + IRRMESHWRITER + ['CSkinnedMesh.cpp', 'CBoneSceneNode.cpp', 'CMeshSceneNode.cpp', 'CAnimatedMeshSceneNode.cpp', 'CAnimatedMeshMD2.cpp', 'CAnimatedMeshMD3.cpp', 'CQ3LevelMesh.cpp', 'CQuake3ShaderSceneNode.cpp']; IRROBJ = ['CBillboardSceneNode.cpp', 'CCameraSceneNode.cpp', 'CDummyTransformationSceneNode.cpp', 'CEmptySceneNode.cpp', 'CGeometryCreator.cpp', 'CLightSceneNode.cpp', 'CMeshManipulator.cpp', 'CMetaTriangleSelector.cpp', 'COctreeSceneNode.cpp', 'COctreeTriangleSelector.cpp', 'CSceneCollisionManager.cpp', 'CSceneManager.cpp', 'CShadowVolumeSceneNode.cpp', 'CSkyBoxSceneNode.cpp', 'CSkyDomeSceneNode.cpp', 'CTerrainSceneNode.cpp', 'CTerrainTriangleSelector.cpp', 'CVolumeLightSceneNode.cpp', 'CCubeSceneNode.cpp', 'CSphereSceneNode.cpp', 'CTextSceneNode.cpp', 'CTriangleBBSelector.cpp', 'CTriangleSelector.cpp', 'CWaterSurfaceSceneNode.cpp', 'CMeshCache.cpp', 'CDefaultSceneNodeAnimatorFactory.cpp', 'CDefaultSceneNodeFactory.cpp']; IRRPARTICLEOBJ = ['CParticleAnimatedMeshSceneNodeEmitter.cpp', 'CParticleBoxEmitter.cpp', 'CParticleCylinderEmitter.cpp', 'CParticleMeshEmitter.cpp', 'CParticlePointEmitter.cpp', 'CParticleRingEmitter.cpp', 'CParticleSphereEmitter.cpp', 'CParticleAttractionAffector.cpp', 'CParticleFadeOutAffector.cpp', 'CParticleGravityAffector.cpp', 'CParticleRotationAffector.cpp', 'CParticleSystemSceneNode.cpp', 'CParticleScaleAffector.cpp']; IRRANIMOBJ = ['CSceneNodeAnimatorCameraFPS.cpp', 'CSceneNodeAnimatorCameraMaya.cpp', 'CSceneNodeAnimatorCollisionResponse.cpp', 'CSceneNodeAnimatorDelete.cpp', 'CSceneNodeAnimatorFlyCircle.cpp', 'CSceneNodeAnimatorFlyStraight.cpp', 'CSceneNodeAnimatorFollowSpline.cpp', 'CSceneNodeAnimatorRotation.cpp', 'CSceneNodeAnimatorTexture.cpp']; IRRDRVROBJ = ['CNullDriver.cpp', 'COpenGLDriver.cpp', 'COpenGLNormalMapRenderer.cpp', 'COpenGLParallaxMapRenderer.cpp', 'COpenGLShaderMaterialRenderer.cpp', 'COpenGLTexture.cpp', 'COpenGLSLMaterialRenderer.cpp', 'COpenGLExtensionHandler.cpp', 'CD3D8Driver.cpp', 'CD3D8NormalMapRenderer.cpp', 'CD3D8ParallaxMapRenderer.cpp', 'CD3D8ShaderMaterialRenderer.cpp', 'CD3D8Texture.cpp', 'CD3D9Driver.cpp', 'CD3D9HLSLMaterialRenderer.cpp', 'CD3D9NormalMapRenderer.cpp', 'CD3D9ParallaxMapRenderer.cpp', 'CD3D9ShaderMaterialRenderer.cpp', 'CD3D9Texture.cpp']; IRRIMAGEOBJ = ['CColorConverter.cpp', 'CImage.cpp', 'CImageLoaderBMP.cpp', 'CImageLoaderJPG.cpp', 'CImageLoaderPCX.cpp', 'CImageLoaderPNG.cpp', 'CImageLoaderPSD.cpp', 'CImageLoaderTGA.cpp', 'CImageLoaderPPM.cpp', 'CImageLoaderWAL.cpp', 'CImageWriterBMP.cpp', 'CImageWriterJPG.cpp', 'CImageWriterPCX.cpp', 'CImageWriterPNG.cpp', 'CImageWriterPPM.cpp', 'CImageWriterPSD.cpp', 'CImageWriterTGA.cpp']; IRRVIDEOOBJ = ['CVideoModeList.cpp', 'CFPSCounter.cpp'] + IRRDRVROBJ + IRRIMAGEOBJ; IRRSWRENDEROBJ = ['CSoftwareDriver.cpp', 'CSoftwareTexture.cpp', 'CTRFlat.cpp', 'CTRFlatWire.cpp', 'CTRGouraud.cpp', 'CTRGouraudWire.cpp', 'CTRTextureFlat.cpp', 'CTRTextureFlatWire.cpp', 'CTRTextureGouraud.cpp', 'CTRTextureGouraudAdd.cpp', 'CTRTextureGouraudNoZ.cpp', 'CTRTextureGouraudWire.cpp', 'CZBuffer.cpp', 'CTRTextureGouraudVertexAlpha2.cpp', 'CTRTextureGouraudNoZ2.cpp', 'CTRTextureLightMap2_M2.cpp', 'CTRTextureLightMap2_M4.cpp', 'CTRTextureLightMap2_M1.cpp', 'CSoftwareDriver2.cpp', 'CSoftwareTexture2.cpp', 'CTRTextureGouraud2.cpp', 'CTRGouraud2.cpp', 'CTRGouraudAlpha2.cpp', 'CTRGouraudAlphaNoZ2.cpp', 'CTRTextureDetailMap2.cpp', 'CTRTextureGouraudAdd2.cpp', 'CTRTextureGouraudAddNoZ2.cpp', 'CTRTextureWire2.cpp', 'CTRTextureLightMap2_Add.cpp', 'CTRTextureLightMapGouraud2_M4.cpp', 'IBurningShader.cpp', 'CTRTextureBlend.cpp', 'CTRTextureGouraudAlpha.cpp', 'CTRTextureGouraudAlphaNoZ.cpp', 'CDepthBuffer.cpp', 'CBurningShader_Raster_Reference.cpp']; IRRIOOBJ = ['CFileList.cpp', 'CFileSystem.cpp', 'CLimitReadFile.cpp', 'CMemoryReadFile.cpp', 'CReadFile.cpp', 'CWriteFile.cpp', 'CXMLReader.cpp', 'CXMLWriter.cpp', 'CZipReader.cpp', 'CPakReader.cpp', 'CNPKReader.cpp', 'irrXML.cpp', 'CAttributes.cpp', 'lzma/LzmaDec.c']; IRROTHEROBJ = ['CIrrDeviceSDL.cpp', 'CIrrDeviceLinux.cpp', 'CIrrDeviceStub.cpp', 'CIrrDeviceWin32.cpp', 'CLogger.cpp', 'COSOperator.cpp', 'Irrlicht.cpp', 'os.cpp']; IRRGUIOBJ = ['CGUIButton.cpp', 'CGUICheckBox.cpp', 'CGUIComboBox.cpp', 'CGUIContextMenu.cpp', 'CGUIEditBox.cpp', 'CGUIEnvironment.cpp', 'CGUIFileOpenDialog.cpp', 'CGUIFont.cpp', 'CGUIImage.cpp', 'CGUIInOutFader.cpp', 'CGUIListBox.cpp', 'CGUIMenu.cpp', 'CGUIMeshViewer.cpp', 'CGUIMessageBox.cpp', 'CGUIModalScreen.cpp', 'CGUIScrollBar.cpp', 'CGUISpinBox.cpp', 'CGUISkin.cpp', 'CGUIStaticText.cpp', 'CGUITabControl.cpp', 'CGUITable.cpp', 'CGUIToolBar.cpp', 'CGUIWindow.cpp', 'CGUIColorSelectDialog.cpp', 'CDefaultGUIElementFactory.cpp', 'CGUISpriteBank.cpp']; ZLIB_PREFIX = 'zlib/'; ZLIBNAMES = ['adler32.c', 'compress.c', 'crc32.c', 'deflate.c', 'inffast.c', 'inflate.c', 'inftrees.c', 'trees.c', 'uncompr.c', 'zutil.c']; ZLIBOBJ = []; for fileName in ZLIBNAMES: ZLIBOBJ += [ZLIB_PREFIX + fileName]; JPEGLIB_PREFIX = 'jpeglib/'; JPEGLIBNAMES = ['jaricom.c', 'jcapimin.c', 'jcapistd.c', 'jcarith.c', 'jccoefct.c', 'jccolor.c', 'jcdctmgr.c', 'jchuff.c', 'jcinit.c', 'jcmainct.c', 'jcmarker.c', 'jcmaster.c', 'jcomapi.c', 'jcparam.c', 'jcprepct.c', 'jcsample.c', 'jctrans.c', 'jdapimin.c', 'jdapistd.c', 'jdarith.c', 'jdatadst.c', 'jdatasrc.c', 'jdcoefct.c', 'jdcolor.c', 'jddctmgr.c', 'jdhuff.c', 'jdinput.c', 'jdmainct.c', 'jdmarker.c', 'jdmaster.c', 'jdmerge.c', 'jdpostct.c', 'jdsample.c', 'jdtrans.c', 'jerror.c', 'jfdctflt.c', 'jfdctfst.c', 'jfdctint.c', 'jidctflt.c', 'jidctfst.c', 'jidctint.c', 'jmemmgr.c', 'jmemnobs.c', 'jquant1.c', 'jquant2.c', 'jutils.c']; JPEGLIBOBJ = []; for fileName in JPEGLIBNAMES: JPEGLIBOBJ += [JPEGLIB_PREFIX + fileName]; LIBPNG_PREFIX = 'libpng/'; LIBPNGNAMES = ['png.c', 'pngerror.c', 'pngget.c', 'pngmem.c', 'pngpread.c', 'pngread.c', 'pngrio.c', 'pngrtran.c', 'pngrutil.c', 'pngset.c', 'pngtrans.c', 'pngwio.c', 'pngwrite.c', 'pngwtran.c', 'pngwutil.c']; LIBPNGOBJ = []; for fileName in LIBPNGNAMES: LIBPNGOBJ += [LIBPNG_PREFIX + fileName]; AESGLADMAN_PREFIX = 'aesGladman/'; AESGLADMANNAMES = ['aescrypt.cpp', 'aeskey.cpp', 'aestab.cpp', 'fileenc.cpp', 'hmac.cpp', 'prng.cpp', 'pwd2key.cpp', 'sha1.cpp', 'sha2.cpp']; AESGLADMANOBJ = []; for fileName in AESGLADMANNAMES: AESGLADMANOBJ += [AESGLADMAN_PREFIX + fileName]; BZIP2_PREFIX = 'bzip2/'; BZIP2NAMES = ['blocksort.c', 'bzcompress.c', 'bzlib.c', 'crctable.c', 'decompress.c', 'huffman.c', 'randtable.c']; BZIP2OBJ = []; for fileName in BZIP2NAMES: BZIP2OBJ += [BZIP2_PREFIX + fileName]; # Next variable is for additional scene nodes etc. of customized Irrlicht versions EXTRAOBJ = []; LINKOBJ = IRRMESHOBJ + IRROBJ + IRRPARTICLEOBJ + IRRANIMOBJ + IRRVIDEOOBJ + IRRSWRENDEROBJ + IRRIOOBJ + IRROTHEROBJ + IRRGUIOBJ + ZLIBOBJ + JPEGLIBOBJ + LIBPNGOBJ + AESGLADMANOBJ + EXTRAOBJ; env.Append(LIBS = LIBRARIES, LIBPATH = CXXINCS); CXXFLAGS = ['-Wall']; if NDEBUG: CXXFLAGS += ['-fexpensive-optimizations', '-O3']; else: CXXFLAGS += ['-g', '-D_DEBUG']; if PROFILE: CXXFLAGS += ['-pg']; CXXFLAGS += ['-DPNG_NO_MMX_CODE', '-DPNG_NO_MNG_FEATURES', '-DIRRLICHT_EXPORTS=1', '-D_IRR_STATIC_LIB_']; if USE_GCC: CXXFLAGS += ['-D__GNUWIN32__=1']; env.Append(CCFLAGS = CXXFLAGS); IrrlichtLibrary = env.SharedLibrary("Irrlicht.dll", LINKOBJ); irrlicht-1.8.3/source/Irrlicht/S4DVertex.h0000644000000000000000000003244012574354552017101 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_4D_VERTEX_H_INCLUDED__ #define __S_4D_VERTEX_H_INCLUDED__ #include "SoftwareDriver2_compile_config.h" #include "SoftwareDriver2_helper.h" #include "irrAllocator.h" namespace irr { namespace video { struct sVec2 { f32 x; f32 y; sVec2 () {} sVec2 ( f32 s) : x ( s ), y ( s ) {} sVec2 ( f32 _x, f32 _y ) : x ( _x ), y ( _y ) {} void set ( f32 _x, f32 _y ) { x = _x; y = _y; } // f = a * t + b * ( 1 - t ) void interpolate(const sVec2& a, const sVec2& b, const f32 t) { x = b.x + ( ( a.x - b.x ) * t ); y = b.y + ( ( a.y - b.y ) * t ); } sVec2 operator-(const sVec2& other) const { return sVec2(x - other.x, y - other.y); } sVec2 operator+(const sVec2& other) const { return sVec2(x + other.x, y + other.y); } void operator+=(const sVec2& other) { x += other.x; y += other.y; } sVec2 operator*(const f32 s) const { return sVec2(x * s , y * s); } void operator*=( const f32 s) { x *= s; y *= s; } void operator=(const sVec2& other) { x = other.x; y = other.y; } }; // A8R8G8B8 struct sVec4; struct sCompressedVec4 { u32 argb; void setA8R8G8B8 ( u32 value ) { argb = value; } void setColorf ( const video::SColorf & color ) { argb = core::floor32 ( color.a * 255.f ) << 24 | core::floor32 ( color.r * 255.f ) << 16 | core::floor32 ( color.g * 255.f ) << 8 | core::floor32 ( color.b * 255.f ); } void setVec4 ( const sVec4 & v ); // f = a * t + b * ( 1 - t ) void interpolate(const sCompressedVec4& a, const sCompressedVec4& b, const f32 t) { argb = PixelBlend32 ( b.argb, a.argb, core::floor32 ( t * 256.f ) ); } }; struct sVec4 { union { struct { f32 x, y, z, w; }; struct { f32 a, r, g, b; }; // struct { sVec2 xy, zw; }; // sorry, this does not compile with gcc }; sVec4 () {} sVec4 ( f32 s) : x ( s ), y ( s ), z ( s ), w ( s ) {} sVec4 ( f32 _x, f32 _y, f32 _z, f32 _w ) : x ( _x ), y ( _y ), z( _z ), w ( _w ){} void set ( f32 _x, f32 _y, f32 _z, f32 _w ) { x = _x; y = _y; z = _z; w = _w; } void setA8R8G8B8 ( u32 argb ) { x = ( ( argb & 0xFF000000 ) >> 24 ) * ( 1.f / 255.f ); y = ( ( argb & 0x00FF0000 ) >> 16 ) * ( 1.f / 255.f ); z = ( ( argb & 0x0000FF00 ) >> 8 ) * ( 1.f / 255.f ); w = ( ( argb & 0x000000FF ) ) * ( 1.f / 255.f ); } void setColorf ( const video::SColorf & color ) { x = color.a; y = color.r; z = color.g; w = color.b; } // f = a * t + b * ( 1 - t ) void interpolate(const sVec4& a, const sVec4& b, const f32 t) { x = b.x + ( ( a.x - b.x ) * t ); y = b.y + ( ( a.y - b.y ) * t ); z = b.z + ( ( a.z - b.z ) * t ); w = b.w + ( ( a.w - b.w ) * t ); } f32 dotProduct(const sVec4& other) const { return x*other.x + y*other.y + z*other.z + w*other.w; } f32 dot_xyz( const sVec4& other) const { return x*other.x + y*other.y + z*other.z; } f32 get_length_xyz_square () const { return x * x + y * y + z * z; } f32 get_length_xyz () const { return core::squareroot ( x * x + y * y + z * z ); } void normalize_xyz () { const f32 l = core::reciprocal_squareroot ( x * x + y * y + z * z ); x *= l; y *= l; z *= l; } void project_xyz () { w = core::reciprocal ( w ); x *= w; y *= w; z *= w; } sVec4 operator-(const sVec4& other) const { return sVec4(x - other.x, y - other.y, z - other.z,w - other.w); } sVec4 operator+(const sVec4& other) const { return sVec4(x + other.x, y + other.y, z + other.z,w + other.w); } void operator+=(const sVec4& other) { x += other.x; y += other.y; z += other.z; w += other.w; } sVec4 operator*(const f32 s) const { return sVec4(x * s , y * s, z * s,w * s); } sVec4 operator*(const sVec4 &other) const { return sVec4(x * other.x , y * other.y, z * other.z,w * other.w); } void mulReciprocal ( f32 s ) { const f32 i = core::reciprocal ( s ); x = (f32) ( x * i ); y = (f32) ( y * i ); z = (f32) ( z * i ); w = (f32) ( w * i ); } void mul ( const f32 s ) { x *= s; y *= s; z *= s; w *= s; } /* void operator*=(f32 s) { x *= s; y *= s; z *= s; w *= s; } */ void operator*=(const sVec4 &other) { x *= other.x; y *= other.y; z *= other.z; w *= other.w; } void operator=(const sVec4& other) { x = other.x; y = other.y; z = other.z; w = other.w; } }; struct sVec3 { union { struct { f32 r, g, b; }; struct { f32 x, y, z; }; }; sVec3 () {} sVec3 ( f32 _x, f32 _y, f32 _z ) : r ( _x ), g ( _y ), b( _z ) {} sVec3 ( const sVec4 &v ) : r ( v.x ), g ( v.y ), b( v.z ) {} void set ( f32 _r, f32 _g, f32 _b ) { r = _r; g = _g; b = _b; } void setR8G8B8 ( u32 argb ) { r = ( ( argb & 0x00FF0000 ) >> 16 ) * ( 1.f / 255.f ); g = ( ( argb & 0x0000FF00 ) >> 8 ) * ( 1.f / 255.f ); b = ( ( argb & 0x000000FF ) ) * ( 1.f / 255.f ); } void setColorf ( const video::SColorf & color ) { r = color.r; g = color.g; b = color.b; } void add (const sVec3& other) { r += other.r; g += other.g; b += other.b; } void mulAdd(const sVec3& other, const f32 v) { r += other.r * v; g += other.g * v; b += other.b * v; } void mulAdd(const sVec3& v0, const sVec3& v1) { r += v0.r * v1.r; g += v0.g * v1.g; b += v0.b * v1.b; } void saturate ( sVec4 &dest, u32 argb ) { dest.x = ( ( argb & 0xFF000000 ) >> 24 ) * ( 1.f / 255.f ); dest.y = core::min_ ( r, 1.f ); dest.z = core::min_ ( g, 1.f ); dest.w = core::min_ ( b, 1.f ); } // f = a * t + b * ( 1 - t ) void interpolate(const sVec3& v0, const sVec3& v1, const f32 t) { r = v1.r + ( ( v0.r - v1.r ) * t ); g = v1.g + ( ( v0.g - v1.g ) * t ); b = v1.b + ( ( v0.b - v1.b ) * t ); } sVec3 operator-(const sVec3& other) const { return sVec3(r - other.r, b - other.b, g - other.g); } sVec3 operator+(const sVec3& other) const { return sVec3(r + other.r, g + other.g, b + other.b); } sVec3 operator*(const f32 s) const { return sVec3(r * s , g * s, b * s); } sVec3 operator/(const f32 s) const { f32 inv = 1.f / s; return sVec3(r * inv , g * inv, b * inv); } sVec3 operator*(const sVec3 &other) const { return sVec3(r * other.r , b * other.b, g * other.g); } void operator+=(const sVec3& other) { r += other.r; g += other.g; b += other.b; } void setLength ( f32 len ) { const f32 l = len * core::reciprocal_squareroot ( r * r + g * g + b * b ); r *= l; g *= l; b *= l; } }; inline void sCompressedVec4::setVec4 ( const sVec4 & v ) { argb = core::floor32 ( v.x * 255.f ) << 24 | core::floor32 ( v.y * 255.f ) << 16 | core::floor32 ( v.z * 255.f ) << 8 | core::floor32 ( v.w * 255.f ); } enum e4DVertexFlag { VERTEX4D_INSIDE = 0x0000003F, VERTEX4D_CLIPMASK = 0x0000003F, VERTEX4D_PROJECTED = 0x00000100, VERTEX4D_FORMAT_MASK = 0xFFFF0000, VERTEX4D_FORMAT_MASK_TEXTURE = 0x000F0000, VERTEX4D_FORMAT_TEXTURE_1 = 0x00010000, VERTEX4D_FORMAT_TEXTURE_2 = 0x00020000, VERTEX4D_FORMAT_TEXTURE_3 = 0x00030000, VERTEX4D_FORMAT_TEXTURE_4 = 0x00040000, VERTEX4D_FORMAT_MASK_COLOR = 0x00F00000, VERTEX4D_FORMAT_COLOR_1 = 0x00100000, VERTEX4D_FORMAT_COLOR_2 = 0x00200000, VERTEX4D_FORMAT_MASK_BUMP = 0x0F000000, VERTEX4D_FORMAT_BUMP_DOT3 = 0x01000000, }; const u32 MATERIAL_MAX_COLORS = 1; const u32 BURNING_MATERIAL_MAX_TEXTURES = 2; const u32 BURNING_MATERIAL_MAX_TANGENT = 1; // dummy Vertex. used for calculation vertex memory size struct s4DVertex_proxy { u32 flag; sVec4 Pos; sVec2 Tex[BURNING_MATERIAL_MAX_TEXTURES]; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR sVec4 Color[MATERIAL_MAX_COLORS]; #endif sVec3 LightTangent[BURNING_MATERIAL_MAX_TANGENT]; }; #define SIZEOF_SVERTEX 64 #define SIZEOF_SVERTEX_LOG2 6 /*! Internal BurningVideo Vertex */ struct s4DVertex { u32 flag; sVec4 Pos; sVec2 Tex[ BURNING_MATERIAL_MAX_TEXTURES ]; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR sVec4 Color[ MATERIAL_MAX_COLORS ]; #endif sVec3 LightTangent[BURNING_MATERIAL_MAX_TANGENT]; //u8 fill [ SIZEOF_SVERTEX - sizeof (s4DVertex_proxy) ]; // f = a * t + b * ( 1 - t ) void interpolate(const s4DVertex& b, const s4DVertex& a, const f32 t) { u32 i; u32 size; Pos.interpolate ( a.Pos, b.Pos, t ); #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR size = (flag & VERTEX4D_FORMAT_MASK_COLOR) >> 20; for ( i = 0; i!= size; ++i ) { Color[i].interpolate ( a.Color[i], b.Color[i], t ); } #endif size = (flag & VERTEX4D_FORMAT_MASK_TEXTURE) >> 16; for ( i = 0; i!= size; ++i ) { Tex[i].interpolate ( a.Tex[i], b.Tex[i], t ); } size = (flag & VERTEX4D_FORMAT_MASK_BUMP) >> 24; for ( i = 0; i!= size; ++i ) { LightTangent[i].interpolate ( a.LightTangent[i], b.LightTangent[i], t ); } } }; // ----------------- Vertex Cache --------------------------- struct SAlignedVertex { SAlignedVertex ( u32 element, u32 aligned ) : ElementSize ( element ) { u32 byteSize = (ElementSize << SIZEOF_SVERTEX_LOG2 ) + aligned; mem = new u8 [ byteSize ]; data = (s4DVertex*) mem; } virtual ~SAlignedVertex () { delete [] mem; } s4DVertex *data; u8 *mem; u32 ElementSize; }; // hold info for different Vertex Types struct SVSize { u32 Format; u32 Pitch; u32 TexSize; }; // a cache info struct SCacheInfo { u32 index; u32 hit; }; #define VERTEXCACHE_ELEMENT 16 #define VERTEXCACHE_MISS 0xFFFFFFFF struct SVertexCache { SVertexCache (): mem ( VERTEXCACHE_ELEMENT * 2, 128 ) {} SCacheInfo info[VERTEXCACHE_ELEMENT]; // Transformed and lite, clipping state // + Clipped, Projected SAlignedVertex mem; // source const void* vertices; u32 vertexCount; const void* indices; u32 indexCount; u32 indicesIndex; u32 indicesRun; // primitives consist of x vertices u32 primitivePitch; u32 vType; //E_VERTEX_TYPE u32 pType; //scene::E_PRIMITIVE_TYPE u32 iType; //E_INDEX_TYPE iType }; // swap 2 pointer REALINLINE void swapVertexPointer(const s4DVertex** v1, const s4DVertex** v2) { const s4DVertex* b = *v1; *v1 = *v2; *v2 = b; } // ------------------------ Internal Scanline Rasterizer ----------------------------- // internal scan convert struct sScanConvertData { u8 left; // major edge left/right u8 right; // !left f32 invDeltaY[3]; // inverse edge delta y f32 x[2]; // x coordinate f32 slopeX[2]; // x slope along edges #if defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) || defined ( SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT ) f32 w[2]; // w coordinate fp24 slopeW[2]; // w slope along edges #else f32 z[2]; // z coordinate f32 slopeZ[2]; // z slope along edges #endif sVec4 c[MATERIAL_MAX_COLORS][2]; // color sVec4 slopeC[MATERIAL_MAX_COLORS][2]; // color slope along edges sVec2 t[BURNING_MATERIAL_MAX_TEXTURES][2]; // texture sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES][2]; // texture slope along edges sVec3 l[BURNING_MATERIAL_MAX_TANGENT][2]; // Light Tangent sVec3 slopeL[BURNING_MATERIAL_MAX_TEXTURES][2]; // tanget slope along edges }; // passed to scan Line struct sScanLineData { s32 y; // y position of scanline f32 x[2]; // x start, x end of scanline #if defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) || defined ( SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT ) f32 w[2]; // w start, w end of scanline #else f32 z[2]; // z start, z end of scanline #endif #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR sVec4 c[MATERIAL_MAX_COLORS][2]; // color start, color end of scanline #endif sVec2 t[BURNING_MATERIAL_MAX_TEXTURES][2]; // texture start, texture end of scanline sVec3 l[BURNING_MATERIAL_MAX_TANGENT][2]; // Light Tangent start, end }; // passed to pixel Shader struct sPixelShaderData { tVideoSample *dst; fp24 *z; s32 xStart; s32 xEnd; s32 dx; s32 i; }; /* load a color value */ inline void getTexel_plain2 ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const sVec4 &v ) { r = tofix ( v.y ); g = tofix ( v.z ); b = tofix ( v.w ); } /* load a color value */ inline void getSample_color ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const sVec4 &v ) { a = tofix ( v.x ); r = tofix ( v.y, COLOR_MAX * FIX_POINT_F32_MUL); g = tofix ( v.z, COLOR_MAX * FIX_POINT_F32_MUL); b = tofix ( v.w, COLOR_MAX * FIX_POINT_F32_MUL); } /* load a color value */ inline void getSample_color ( tFixPoint &r, tFixPoint &g, tFixPoint &b,const sVec4 &v ) { r = tofix ( v.y, COLOR_MAX * FIX_POINT_F32_MUL); g = tofix ( v.z, COLOR_MAX * FIX_POINT_F32_MUL); b = tofix ( v.w, COLOR_MAX * FIX_POINT_F32_MUL); } /* load a color value */ inline void getSample_color ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const sVec4 &v, const f32 mulby ) { r = tofix ( v.y, mulby); g = tofix ( v.z, mulby); b = tofix ( v.w, mulby); } } } #endif irrlicht-1.8.3/source/Irrlicht/S2DVertex.h0000644000000000000000000000112212574354552017070 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_K_2D_VERTEX_H_INCLUDED__ #define __S_K_2D_VERTEX_H_INCLUDED__ #include "vector2d.h" typedef signed short TZBufferType; namespace irr { namespace video { struct S2DVertex { core::vector2d Pos; // position core::vector2d TCoords; // texture coordinates TZBufferType ZValue; // zvalue u16 Color; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/resource.h0000644000000000000000000000062512574354552017140 0ustar rootroot//{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by Irrlicht.rc // Nächste Standardwerte für neue Objekte // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 101 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif irrlicht-1.8.3/source/Irrlicht/os.h0000644000000000000000000000630012574354552015726 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_OS_H_INCLUDED__ #define __IRR_OS_H_INCLUDED__ #include "IrrCompileConfig.h" // for endian check #include "irrTypes.h" #include "irrString.h" #include "path.h" #include "ILogger.h" #include "ITimer.h" namespace irr { namespace os { class Byteswap { public: static u16 byteswap(u16 num); static s16 byteswap(s16 num); static u32 byteswap(u32 num); static s32 byteswap(s32 num); static f32 byteswap(f32 num); // prevent accidental swapping of chars static u8 byteswap(u8 num); static c8 byteswap(c8 num); }; class Printer { public: // prints out a string to the console out stdout or debug log or whatever static void print(const c8* message); static void log(const c8* message, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const wchar_t* message, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const c8* message, const c8* hint, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const c8* message, const io::path& hint, ELOG_LEVEL ll = ELL_INFORMATION); static ILogger* Logger; }; // mixed linear congruential generator (MLCG) // numbers chosen according to L'Ecuyer, Commun. ACM 31 (1988) 742 // period is somewhere around m-1 class Randomizer { public: //! resets the randomizer static void reset(s32 value=0x0f0f0f0f); //! generates a pseudo random number in the range 0..randMax() static s32 rand(); //! generates a pseudo random number in the range 0..1 static f32 frand(); //! get maxmimum number generated by rand() static s32 randMax(); private: static s32 seed; static const s32 m = 2147483399; // a non-Mersenne prime static const s32 a = 40692; // another spectral success story static const s32 q = m/a; static const s32 r = m%a; // again less than q static const s32 rMax = m-1; }; class Timer { public: //! returns the current time in milliseconds static u32 getTime(); //! get current time and date in calendar form static ITimer::RealTimeDate getRealTimeAndDate(); //! initializes the real timer static void initTimer(bool usePerformanceTimer=true); //! sets the current virtual (game) time static void setTime(u32 time); //! stops the virtual (game) timer static void stopTimer(); //! starts the game timer static void startTimer(); //! sets the speed of the virtual timer static void setSpeed(f32 speed); //! gets the speed of the virtual timer static f32 getSpeed(); //! returns if the timer currently is stopped static bool isStopped(); //! makes the virtual timer update the time value based on the real time static void tick(); //! returns the current real time in milliseconds static u32 getRealTime(); private: static void initVirtualTimer(); static f32 VirtualTimerSpeed; static s32 VirtualTimerStopCounter; static u32 StartRealTime; static u32 LastVirtualTime; static u32 StaticTime; }; } // end namespace os } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/os.cpp0000644000000000000000000002026112574354552016263 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "os.h" #include "irrString.h" #include "IrrCompileConfig.h" #include "irrMath.h" #if defined(_IRR_COMPILE_WITH_SDL_DEVICE_) #include #define bswap_16(X) SDL_Swap16(X) #define bswap_32(X) SDL_Swap32(X) #elif defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && (_MSC_VER > 1298) #include #define bswap_16(X) _byteswap_ushort(X) #define bswap_32(X) _byteswap_ulong(X) #if (_MSC_VER >= 1400) #define localtime _localtime_s #endif #elif defined(_IRR_OSX_PLATFORM_) #include #define bswap_16(X) OSReadSwapInt16(&X,0) #define bswap_32(X) OSReadSwapInt32(&X,0) #elif defined(__FreeBSD__) || defined(__OpenBSD__) #include #define bswap_16(X) bswap16(X) #define bswap_32(X) bswap32(X) #elif !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__PPC__) && !defined(_IRR_WINDOWS_API_) #include #else #define bswap_16(X) ((((X)&0xFF) << 8) | (((X)&0xFF00) >> 8)) #define bswap_32(X) ( (((X)&0x000000FF)<<24) | (((X)&0xFF000000) >> 24) | (((X)&0x0000FF00) << 8) | (((X) &0x00FF0000) >> 8)) #endif namespace irr { namespace os { u16 Byteswap::byteswap(u16 num) {return bswap_16(num);} s16 Byteswap::byteswap(s16 num) {return bswap_16(num);} u32 Byteswap::byteswap(u32 num) {return bswap_32(num);} s32 Byteswap::byteswap(s32 num) {return bswap_32(num);} f32 Byteswap::byteswap(f32 num) {u32 tmp=IR(num); tmp=bswap_32(tmp); return (FR(tmp));} // prevent accidental byte swapping of chars u8 Byteswap::byteswap(u8 num) {return num;} c8 Byteswap::byteswap(c8 num) {return num;} } } #if defined(_IRR_WINDOWS_API_) // ---------------------------------------------------------------- // Windows specific functions // ---------------------------------------------------------------- #ifdef _IRR_XBOX_PLATFORM_ #include #else #define WIN32_LEAN_AND_MEAN #include #include #endif namespace irr { namespace os { //! prints a debuginfo string void Printer::print(const c8* message) { #if defined (_WIN32_WCE ) core::stringw tmp(message); tmp += L"\n"; OutputDebugStringW(tmp.c_str()); #else core::stringc tmp(message); tmp += "\n"; OutputDebugStringA(tmp.c_str()); printf("%s", tmp.c_str()); #endif } static LARGE_INTEGER HighPerformanceFreq; static BOOL HighPerformanceTimerSupport = FALSE; static BOOL MultiCore = FALSE; void Timer::initTimer(bool usePerformanceTimer) { #if !defined(_WIN32_WCE) && !defined (_IRR_XBOX_PLATFORM_) // workaround for hires timer on multiple core systems, bios bugs result in bad hires timers. SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); MultiCore = (sysinfo.dwNumberOfProcessors > 1); #endif if (usePerformanceTimer) HighPerformanceTimerSupport = QueryPerformanceFrequency(&HighPerformanceFreq); else HighPerformanceTimerSupport = FALSE; initVirtualTimer(); } u32 Timer::getRealTime() { if (HighPerformanceTimerSupport) { #if !defined(_WIN32_WCE) && !defined (_IRR_XBOX_PLATFORM_) // Avoid potential timing inaccuracies across multiple cores by // temporarily setting the affinity of this process to one core. DWORD_PTR affinityMask=0; if(MultiCore) affinityMask = SetThreadAffinityMask(GetCurrentThread(), 1); #endif LARGE_INTEGER nTime; BOOL queriedOK = QueryPerformanceCounter(&nTime); #if !defined(_WIN32_WCE) && !defined (_IRR_XBOX_PLATFORM_) // Restore the true affinity. if(MultiCore) (void)SetThreadAffinityMask(GetCurrentThread(), affinityMask); #endif if(queriedOK) return u32((nTime.QuadPart) * 1000 / HighPerformanceFreq.QuadPart); } return GetTickCount(); } } // end namespace os #else // ---------------------------------------------------------------- // linux/ansi version // ---------------------------------------------------------------- #include #include #include namespace irr { namespace os { //! prints a debuginfo string void Printer::print(const c8* message) { printf("%s\n", message); } void Timer::initTimer(bool usePerformanceTimer) { initVirtualTimer(); } u32 Timer::getRealTime() { timeval tv; gettimeofday(&tv, 0); return (u32)(tv.tv_sec * 1000) + (tv.tv_usec / 1000); } } // end namespace os #endif // end linux / windows namespace os { // The platform independent implementation of the printer ILogger* Printer::Logger = 0; void Printer::log(const c8* message, ELOG_LEVEL ll) { if (Logger) Logger->log(message, ll); } void Printer::log(const wchar_t* message, ELOG_LEVEL ll) { if (Logger) Logger->log(message, ll); } void Printer::log(const c8* message, const c8* hint, ELOG_LEVEL ll) { if (Logger) Logger->log(message, hint, ll); } void Printer::log(const c8* message, const io::path& hint, ELOG_LEVEL ll) { if (Logger) Logger->log(message, hint.c_str(), ll); } // our Randomizer is not really os specific, so we // code one for all, which should work on every platform the same, // which is desireable. s32 Randomizer::seed = 0x0f0f0f0f; //! generates a pseudo random number s32 Randomizer::rand() { // (a*seed)%m with Schrage's method seed = a * (seed%q) - r* (seed/q); if (seed<0) seed += m; return seed; } //! generates a pseudo random number f32 Randomizer::frand() { return rand()*(1.f/rMax); } s32 Randomizer::randMax() { return rMax; } //! resets the randomizer void Randomizer::reset(s32 value) { seed = value; } // ------------------------------------------------------ // virtual timer implementation f32 Timer::VirtualTimerSpeed = 1.0f; s32 Timer::VirtualTimerStopCounter = 0; u32 Timer::LastVirtualTime = 0; u32 Timer::StartRealTime = 0; u32 Timer::StaticTime = 0; //! Get real time and date in calendar form ITimer::RealTimeDate Timer::getRealTimeAndDate() { time_t rawtime; time(&rawtime); struct tm * timeinfo; timeinfo = localtime(&rawtime); // init with all 0 to indicate error ITimer::RealTimeDate date={0}; // at least Windows returns NULL on some illegal dates if (timeinfo) { // set useful values if succeeded date.Hour=(u32)timeinfo->tm_hour; date.Minute=(u32)timeinfo->tm_min; date.Second=(u32)timeinfo->tm_sec; date.Day=(u32)timeinfo->tm_mday; date.Month=(u32)timeinfo->tm_mon+1; date.Year=(u32)timeinfo->tm_year+1900; date.Weekday=(ITimer::EWeekday)timeinfo->tm_wday; date.Yearday=(u32)timeinfo->tm_yday+1; date.IsDST=timeinfo->tm_isdst != 0; } return date; } //! returns current virtual time u32 Timer::getTime() { if (isStopped()) return LastVirtualTime; return LastVirtualTime + (u32)((StaticTime - StartRealTime) * VirtualTimerSpeed); } //! ticks, advances the virtual timer void Timer::tick() { StaticTime = getRealTime(); } //! sets the current virtual time void Timer::setTime(u32 time) { StaticTime = getRealTime(); LastVirtualTime = time; StartRealTime = StaticTime; } //! stops the virtual timer void Timer::stopTimer() { if (!isStopped()) { // stop the virtual timer LastVirtualTime = getTime(); } --VirtualTimerStopCounter; } //! starts the virtual timer void Timer::startTimer() { ++VirtualTimerStopCounter; if (!isStopped()) { // restart virtual timer setTime(LastVirtualTime); } } //! sets the speed of the virtual timer void Timer::setSpeed(f32 speed) { setTime(getTime()); VirtualTimerSpeed = speed; if (VirtualTimerSpeed < 0.0f) VirtualTimerSpeed = 0.0f; } //! gets the speed of the virtual timer f32 Timer::getSpeed() { return VirtualTimerSpeed; } //! returns if the timer currently is stopped bool Timer::isStopped() { return VirtualTimerStopCounter < 0; } void Timer::initVirtualTimer() { StaticTime = getRealTime(); StartRealTime = StaticTime; } } // end namespace os } // end namespace irr irrlicht-1.8.3/source/Irrlicht/Octree.h0000644000000000000000000002236512574354552016537 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_OCTREE_H_INCLUDED__ #define __C_OCTREE_H_INCLUDED__ #include "SViewFrustum.h" #include "S3DVertex.h" #include "aabbox3d.h" #include "irrArray.h" #include "CMeshBuffer.h" /** Flags for Octree */ //! use meshbuffer for drawing, enables VBO usage #define OCTREE_USE_HARDWARE false //! use visibility information together with VBOs #define OCTREE_USE_VISIBILITY true //! use bounding box or frustum for calculate polys #define OCTREE_BOX_BASED true //! bypass full invisible/visible test #define OCTREE_PARENTTEST namespace irr { //! template octree. /** T must be a vertex type which has a member called .Pos, which is a core::vertex3df position. */ template class Octree { public: struct SMeshChunk : public scene::CMeshBuffer { SMeshChunk () : scene::CMeshBuffer(), MaterialId(0) { scene::CMeshBuffer::grab(); } virtual ~SMeshChunk () { //removeAllHardwareBuffers } s32 MaterialId; }; struct SIndexChunk { core::array Indices; s32 MaterialId; }; struct SIndexData { u16* Indices; s32 CurrentSize; s32 MaxSize; }; //! Constructor Octree(const core::array& meshes, s32 minimalPolysPerNode=128) : IndexData(0), IndexDataCount(meshes.size()), NodeCount(0) { IndexData = new SIndexData[IndexDataCount]; // construct array of all indices core::array* indexChunks = new core::array; indexChunks->reallocate(meshes.size()); for (u32 i=0; i!=meshes.size(); ++i) { IndexData[i].CurrentSize = 0; IndexData[i].MaxSize = meshes[i].Indices.size(); IndexData[i].Indices = new u16[IndexData[i].MaxSize]; indexChunks->push_back(SIndexChunk()); SIndexChunk& tic = indexChunks->getLast(); tic.MaterialId = meshes[i].MaterialId; tic.Indices = meshes[i].Indices; } // create tree Root = new OctreeNode(NodeCount, 0, meshes, indexChunks, minimalPolysPerNode); } //! returns all ids of polygons partially or fully enclosed //! by this bounding box. void calculatePolys(const core::aabbox3d& box) { for (u32 i=0; i!=IndexDataCount; ++i) IndexData[i].CurrentSize = 0; Root->getPolys(box, IndexData, 0); } //! returns all ids of polygons partially or fully enclosed //! by a view frustum. void calculatePolys(const scene::SViewFrustum& frustum) { for (u32 i=0; i!=IndexDataCount; ++i) IndexData[i].CurrentSize = 0; Root->getPolys(frustum, IndexData, 0); } const SIndexData* getIndexData() const { return IndexData; } u32 getIndexDataCount() const { return IndexDataCount; } u32 getNodeCount() const { return NodeCount; } //! for debug purposes only, collects the bounding boxes of the tree void getBoundingBoxes(const core::aabbox3d& box, core::array< const core::aabbox3d* >&outBoxes) const { Root->getBoundingBoxes(box, outBoxes); } //! destructor ~Octree() { for (u32 i=0; i& allmeshdata, core::array* indices, s32 minimalPolysPerNode) : IndexData(0), Depth(currentdepth+1) { ++nodeCount; u32 i; // new ISO for scoping problem with different compilers for (i=0; i!=8; ++i) Children[i] = 0; if (indices->empty()) { delete indices; return; } bool found = false; // find first point for bounding box for (i=0; isize(); ++i) { if (!(*indices)[i].Indices.empty()) { Box.reset(allmeshdata[i].Vertices[(*indices)[i].Indices[0]].Pos); found = true; break; } } if (!found) { delete indices; return; } s32 totalPrimitives = 0; // now lets calculate our bounding box for (i=0; isize(); ++i) { totalPrimitives += (*indices)[i].Indices.size(); for (u32 j=0; j<(*indices)[i].Indices.size(); ++j) Box.addInternalPoint(allmeshdata[i].Vertices[(*indices)[i].Indices[j]].Pos); } core::vector3df middle = Box.getCenter(); core::vector3df edges[8]; Box.getEdges(edges); // calculate all children core::aabbox3d box; core::array keepIndices; if (totalPrimitives > minimalPolysPerNode && !Box.isEmpty()) for (u32 ch=0; ch!=8; ++ch) { box.reset(middle); box.addInternalPoint(edges[ch]); // create indices for child bool added = false; core::array* cindexChunks = new core::array; cindexChunks->reallocate(allmeshdata.size()); for (i=0; ipush_back(SIndexChunk()); SIndexChunk& tic = cindexChunks->getLast(); tic.MaterialId = allmeshdata[i].MaterialId; for (u32 t=0; t<(*indices)[i].Indices.size(); t+=3) { if (box.isPointInside(allmeshdata[i].Vertices[(*indices)[i].Indices[t]].Pos) && box.isPointInside(allmeshdata[i].Vertices[(*indices)[i].Indices[t+1]].Pos) && box.isPointInside(allmeshdata[i].Vertices[(*indices)[i].Indices[t+2]].Pos)) { tic.Indices.push_back((*indices)[i].Indices[t]); tic.Indices.push_back((*indices)[i].Indices[t+1]); tic.Indices.push_back((*indices)[i].Indices[t+2]); added = true; } else { keepIndices.push_back((*indices)[i].Indices[t]); keepIndices.push_back((*indices)[i].Indices[t+1]); keepIndices.push_back((*indices)[i].Indices[t+2]); } } (*indices)[i].Indices.set_used(keepIndices.size()); memcpy( (*indices)[i].Indices.pointer(), keepIndices.pointer(), keepIndices.size()*sizeof(u16)); keepIndices.set_used(0); } if (added) Children[ch] = new OctreeNode(nodeCount, Depth, allmeshdata, cindexChunks, minimalPolysPerNode); else delete cindexChunks; } // end for all possible children IndexData = indices; } // destructor ~OctreeNode() { delete IndexData; for (u32 i=0; i<8; ++i) delete Children[i]; } // returns all ids of polygons partially or full enclosed // by this bounding box. void getPolys(const core::aabbox3d& box, SIndexData* idxdata, u32 parentTest ) const { #if defined (OCTREE_PARENTTEST ) // if not full inside if ( parentTest != 2 ) { // partially inside ? if (!Box.intersectsWithBox(box)) return; // fully inside ? parentTest = Box.isFullInside(box)?2:1; } #else if (Box.intersectsWithBox(box)) #endif { const u32 cnt = IndexData->size(); u32 i; // new ISO for scoping problem in some compilers for (i=0; igetPolys(box, idxdata,parentTest); } } // returns all ids of polygons partially or full enclosed // by the view frustum. void getPolys(const scene::SViewFrustum& frustum, SIndexData* idxdata,u32 parentTest) const { u32 i; // new ISO for scoping problem in some compilers // if parent is fully inside, no further check for the children is needed #if defined (OCTREE_PARENTTEST ) if ( parentTest != 2 ) #endif { #if defined (OCTREE_PARENTTEST ) parentTest = 2; #endif for (i=0; i!=scene::SViewFrustum::VF_PLANE_COUNT; ++i) { core::EIntersectionRelation3D r = Box.classifyPlaneRelation(frustum.planes[i]); if ( r == core::ISREL3D_FRONT ) return; #if defined (OCTREE_PARENTTEST ) if ( r == core::ISREL3D_CLIPPED ) parentTest = 1; // must still check children #endif } } const u32 cnt = IndexData->size(); for (i=0; i!=cnt; ++i) { s32 idxcnt = (*IndexData)[i].Indices.size(); if (idxcnt) { memcpy(&idxdata[i].Indices[idxdata[i].CurrentSize], &(*IndexData)[i].Indices[0], idxcnt * sizeof(s16)); idxdata[i].CurrentSize += idxcnt; } } for (i=0; i!=8; ++i) if (Children[i]) Children[i]->getPolys(frustum, idxdata,parentTest); } //! for debug purposes only, collects the bounding boxes of the node void getBoundingBoxes(const core::aabbox3d& box, core::array< const core::aabbox3d* >&outBoxes) const { if (Box.intersectsWithBox(box)) { outBoxes.push_back(&Box); for (u32 i=0; i!=8; ++i) if (Children[i]) Children[i]->getBoundingBoxes(box, outBoxes); } } private: core::aabbox3df Box; core::array* IndexData; OctreeNode* Children[8]; u32 Depth; }; OctreeNode* Root; SIndexData* IndexData; u32 IndexDataCount; u32 NodeCount; }; } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/Makefile0000644000000000000000000003031312574354552016575 0ustar rootrootVERSION_MAJOR = 1 VERSION_MINOR = 8 VERSION_RELEASE = 3 # Irrlicht Engine 1.8.3 # Makefile for Linux # # To use, just run: # # make # # This will compile Irrlicht, create a static lib (libIrrlicht.a), and copy it # into the subdirectory lib/Linux. That's all. # # If you want Irrlicht to be compiled as shared lib (libIrrlicht.so.versionnumber), then run: # # make sharedlib # make install # # If you want to compile in release mode run: # # make NDEBUG=1 # # For cross-compilation for Win32 under Linux, just use the win32 targets. You have to set # at least CXX, CC, and AR to the proper binaries. # # For compiling on MinGW you can run it with: # # make win32 # #List of object files, separated based on engine architecture IRRMESHLOADER = CBSPMeshFileLoader.o CMD2MeshFileLoader.o CMD3MeshFileLoader.o CMS3DMeshFileLoader.o CB3DMeshFileLoader.o C3DSMeshFileLoader.o COgreMeshFileLoader.o COBJMeshFileLoader.o CColladaFileLoader.o CCSMLoader.o CDMFLoader.o CLMTSMeshFileLoader.o CMY3DMeshFileLoader.o COCTLoader.o CXMeshFileLoader.o CIrrMeshFileLoader.o CSTLMeshFileLoader.o CLWOMeshFileLoader.o CPLYMeshFileLoader.o CSMFMeshFileLoader.o IRRMESHWRITER = CColladaMeshWriter.o CIrrMeshWriter.o CSTLMeshWriter.o COBJMeshWriter.o CPLYMeshWriter.o IRRMESHOBJ = $(IRRMESHLOADER) $(IRRMESHWRITER) \ CSkinnedMesh.o CBoneSceneNode.o CMeshSceneNode.o \ CAnimatedMeshSceneNode.o CAnimatedMeshMD2.o CAnimatedMeshMD3.o \ CQ3LevelMesh.o CQuake3ShaderSceneNode.o CAnimatedMeshHalfLife.o IRROBJ = CBillboardSceneNode.o CCameraSceneNode.o CDummyTransformationSceneNode.o CEmptySceneNode.o CGeometryCreator.o CLightSceneNode.o CMeshManipulator.o CMetaTriangleSelector.o COctreeSceneNode.o COctreeTriangleSelector.o CSceneCollisionManager.o CSceneManager.o CShadowVolumeSceneNode.o CSkyBoxSceneNode.o CSkyDomeSceneNode.o CTerrainSceneNode.o CTerrainTriangleSelector.o CVolumeLightSceneNode.o CCubeSceneNode.o CSphereSceneNode.o CTextSceneNode.o CTriangleBBSelector.o CTriangleSelector.o CWaterSurfaceSceneNode.o CMeshCache.o CDefaultSceneNodeAnimatorFactory.o CDefaultSceneNodeFactory.o CSceneLoaderIrr.o IRRPARTICLEOBJ = CParticleAnimatedMeshSceneNodeEmitter.o CParticleBoxEmitter.o CParticleCylinderEmitter.o CParticleMeshEmitter.o CParticlePointEmitter.o CParticleRingEmitter.o CParticleSphereEmitter.o CParticleAttractionAffector.o CParticleFadeOutAffector.o CParticleGravityAffector.o CParticleRotationAffector.o CParticleSystemSceneNode.o CParticleScaleAffector.o IRRANIMOBJ = CSceneNodeAnimatorCameraFPS.o CSceneNodeAnimatorCameraMaya.o CSceneNodeAnimatorCollisionResponse.o CSceneNodeAnimatorDelete.o CSceneNodeAnimatorFlyCircle.o CSceneNodeAnimatorFlyStraight.o CSceneNodeAnimatorFollowSpline.o CSceneNodeAnimatorRotation.o CSceneNodeAnimatorTexture.o IRRDRVROBJ = CNullDriver.o COpenGLDriver.o COpenGLNormalMapRenderer.o COpenGLParallaxMapRenderer.o COpenGLShaderMaterialRenderer.o COpenGLTexture.o COpenGLSLMaterialRenderer.o COpenGLExtensionHandler.o CD3D8Driver.o CD3D8NormalMapRenderer.o CD3D8ParallaxMapRenderer.o CD3D8ShaderMaterialRenderer.o CD3D8Texture.o CD3D9Driver.o CD3D9HLSLMaterialRenderer.o CD3D9NormalMapRenderer.o CD3D9ParallaxMapRenderer.o CD3D9ShaderMaterialRenderer.o CD3D9Texture.o IRRIMAGEOBJ = CColorConverter.o CImage.o CImageLoaderBMP.o CImageLoaderDDS.o CImageLoaderJPG.o CImageLoaderPCX.o CImageLoaderPNG.o CImageLoaderPSD.o CImageLoaderTGA.o CImageLoaderPPM.o CImageLoaderWAL.o CImageLoaderRGB.o \ CImageWriterBMP.o CImageWriterJPG.o CImageWriterPCX.o CImageWriterPNG.o CImageWriterPPM.o CImageWriterPSD.o CImageWriterTGA.o IRRVIDEOOBJ = CVideoModeList.o CFPSCounter.o $(IRRDRVROBJ) $(IRRIMAGEOBJ) IRRSWRENDEROBJ = CSoftwareDriver.o CSoftwareTexture.o CTRFlat.o CTRFlatWire.o CTRGouraud.o CTRGouraudWire.o CTRNormalMap.o CTRStencilShadow.o CTRTextureFlat.o CTRTextureFlatWire.o CTRTextureGouraud.o CTRTextureGouraudAdd.o CTRTextureGouraudNoZ.o CTRTextureGouraudWire.o CZBuffer.o CTRTextureGouraudVertexAlpha2.o CTRTextureGouraudNoZ2.o CTRTextureLightMap2_M2.o CTRTextureLightMap2_M4.o CTRTextureLightMap2_M1.o CSoftwareDriver2.o CSoftwareTexture2.o CTRTextureGouraud2.o CTRGouraud2.o CTRGouraudAlpha2.o CTRGouraudAlphaNoZ2.o CTRTextureDetailMap2.o CTRTextureGouraudAdd2.o CTRTextureGouraudAddNoZ2.o CTRTextureWire2.o CTRTextureLightMap2_Add.o CTRTextureLightMapGouraud2_M4.o IBurningShader.o CTRTextureBlend.o CTRTextureGouraudAlpha.o CTRTextureGouraudAlphaNoZ.o CDepthBuffer.o CBurningShader_Raster_Reference.o IRRIOOBJ = CFileList.o CFileSystem.o CLimitReadFile.o CMemoryFile.o CReadFile.o CWriteFile.o CXMLReader.o CXMLWriter.o CWADReader.o CZipReader.o CPakReader.o CNPKReader.o CTarReader.o CMountPointReader.o irrXML.o CAttributes.o lzma/LzmaDec.o IRROTHEROBJ = CIrrDeviceSDL.o CIrrDeviceLinux.o CIrrDeviceConsole.o CIrrDeviceStub.o CIrrDeviceWin32.o CIrrDeviceFB.o CLogger.o COSOperator.o Irrlicht.o os.o IRRGUIOBJ = CGUIButton.o CGUICheckBox.o CGUIComboBox.o CGUIContextMenu.o CGUIEditBox.o CGUIEnvironment.o CGUIFileOpenDialog.o CGUIFont.o CGUIImage.o CGUIInOutFader.o CGUIListBox.o CGUIMenu.o CGUIMeshViewer.o CGUIMessageBox.o CGUIModalScreen.o CGUIScrollBar.o CGUISpinBox.o CGUISkin.o CGUIStaticText.o CGUITabControl.o CGUITable.o CGUIToolBar.o CGUIWindow.o CGUIColorSelectDialog.o CDefaultGUIElementFactory.o CGUISpriteBank.o CGUIImageList.o CGUITreeView.o ZLIBOBJ = zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o zlib/uncompr.o zlib/zutil.o JPEGLIBOBJ = jpeglib/jcapimin.o jpeglib/jcapistd.o jpeglib/jccoefct.o jpeglib/jccolor.o jpeglib/jcdctmgr.o jpeglib/jchuff.o jpeglib/jcinit.o jpeglib/jcmainct.o jpeglib/jcmarker.o jpeglib/jcmaster.o jpeglib/jcomapi.o jpeglib/jcparam.o jpeglib/jcprepct.o jpeglib/jcsample.o jpeglib/jctrans.o jpeglib/jdapimin.o jpeglib/jdapistd.o jpeglib/jdatadst.o jpeglib/jdatasrc.o jpeglib/jdcoefct.o jpeglib/jdcolor.o jpeglib/jddctmgr.o jpeglib/jdhuff.o jpeglib/jdinput.o jpeglib/jdmainct.o jpeglib/jdmarker.o jpeglib/jdmaster.o jpeglib/jdmerge.o jpeglib/jdpostct.o jpeglib/jdsample.o jpeglib/jdtrans.o jpeglib/jerror.o jpeglib/jfdctflt.o jpeglib/jfdctfst.o jpeglib/jfdctint.o jpeglib/jidctflt.o jpeglib/jidctfst.o jpeglib/jidctint.o jpeglib/jmemmgr.o jpeglib/jmemnobs.o jpeglib/jquant1.o jpeglib/jquant2.o jpeglib/jutils.o jpeglib/jcarith.o jpeglib/jdarith.o jpeglib/jaricom.o LIBPNGOBJ = libpng/png.o libpng/pngerror.o libpng/pngget.o libpng/pngmem.o libpng/pngpread.o libpng/pngread.o libpng/pngrio.o libpng/pngrtran.o libpng/pngrutil.o libpng/pngset.o libpng/pngtrans.o libpng/pngwio.o libpng/pngwrite.o libpng/pngwtran.o libpng/pngwutil.o LIBAESGM = aesGladman/aescrypt.o aesGladman/aeskey.o aesGladman/aestab.o aesGladman/fileenc.o aesGladman/hmac.o aesGladman/prng.o aesGladman/pwd2key.o aesGladman/sha1.o aesGladman/sha2.o BZIP2OBJ = bzip2/blocksort.o bzip2/huffman.o bzip2/crctable.o bzip2/randtable.o bzip2/bzcompress.o bzip2/decompress.o bzip2/bzlib.o # Next variable is for additional scene nodes etc. of customized Irrlicht versions EXTRAOBJ = LINKOBJ = $(IRRMESHOBJ) $(IRROBJ) $(IRRPARTICLEOBJ) $(IRRANIMOBJ) \ $(IRRVIDEOOBJ) $(IRRSWRENDEROBJ) $(IRRIOOBJ) $(IRROTHEROBJ) \ $(IRRGUIOBJ) $(ZLIBOBJ) $(JPEGLIBOBJ) $(LIBPNGOBJ) $(LIBAESGM) \ $(BZIP2OBJ) $(EXTRAOBJ) ############### #Compiler flags CXXINCS = -I../../include -Izlib -Ijpeglib -Ilibpng CPPFLAGS += $(CXXINCS) -DIRRLICHT_EXPORTS=1 CXXFLAGS += -Wall -pipe -fno-exceptions -fno-rtti -fstrict-aliasing ifndef NDEBUG CXXFLAGS += -g -D_DEBUG else CXXFLAGS += -fexpensive-optimizations -O3 endif ifdef PROFILE CXXFLAGS += -pg endif CFLAGS := -O3 -fexpensive-optimizations -DPNG_THREAD_UNSAFE_OK -DPNG_NO_MMX_CODE -DPNG_NO_MNG_FEATURES sharedlib sharedlib_osx: CXXFLAGS += -fPIC sharedlib sharedlib_osx: CFLAGS += -fPIC #multilib handling ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif #Linux specific options staticlib sharedlib install: SYSTEM = Linux STATIC_LIB = libIrrlicht.a LIB_PATH = ../../lib/$(SYSTEM) INSTALL_DIR = /usr/local/lib sharedlib install: SHARED_LIB = libIrrlicht.so sharedlib: LDFLAGS += -L/usr/X11R6/lib$(LIBSELECT) -lGL -lXxf86vm staticlib sharedlib: CXXINCS += -I/usr/X11R6/include #OSX specific options staticlib_osx sharedlib_osx install_osx: SYSTEM = MacOSX staticlib_osx sharedlib_osx: IRROTHEROBJ += MacOSX/CIrrDeviceMacOSX.o MacOSX/OSXClipboard.o MacOSX/AppDelegate.o staticlib_osx sharedlib_osx: CXXINCS += -IMacOSX -I/usr/X11R6/include sharedlib_osx install_osx: SHARED_LIB = libIrrlicht.dylib staticlib_osx sharedlib_osx: LDFLAGS += --no-export-all-symbols --add-stdcall-alias sharedlib_osx: LDFLAGS += -L/usr/X11R6/lib$(LIBSELECT) -lGL -lXxf86vm # for non-X11 app #sharedlib_osx: LDFLAGS += -framework cocoa -framework carbon -framework opengl -framework IOKit #Windows specific options IRRLICHT_DLL := ../../bin/Win32-gcc/Irrlicht.dll sharedlib_win32 staticlib_win32: SYSTEM = Win32-gcc sharedlib_win32: LDFLAGS += -lgdi32 -lopengl32 -ld3dx9d -lwinmm -Wl,--add-stdcall-alias #choose either -DIRR_COMPILE_WITH_DX9_DEV_PACK or -DNO_IRR_COMPILE_WITH_DIRECT3D_9_ depending if you need dx9 #sharedlib_win32 staticlib_win32: CPPFLAGS += -DIRR_COMPILE_WITH_DX9_DEV_PACK sharedlib_win32 staticlib_win32: CPPFLAGS += -DNO_IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ -DNO_IRR_COMPILE_WITH_DIRECT3D_9_ sharedlib_win32 staticlib_win32: CPPFLAGS += -DIRR_COMPILE_WITH_DX9_DEV_PACK -D__GNUWIN32__ -D_WIN32 -DWIN32 -D_WINDOWS -D_MBCS -D_USRDLL staticlib_win32: CPPFLAGS += -D_IRR_STATIC_LIB_ VERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE) SHARED_FULLNAME = $(SHARED_LIB).$(VERSION) SONAME = $(SHARED_LIB).$(VERSION_MAJOR).$(VERSION_MINOR) #################### # All target, builds Irrlicht as static lib (libIrrlicht.a) and copies it into lib/Linux all linux: staticlib # Builds Irrlicht as shared lib (libIrrlicht.so.versionNumber) and copies it into lib/Linux sharedlib: $(LINKOBJ) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -shared -Wl,-soname,$(SONAME) -o $(SHARED_FULLNAME) $^ $(LDFLAGS) mkdir -p $(LIB_PATH) cp $(SHARED_FULLNAME) $(LIB_PATH) # Builds Irrlicht as static lib (libIrrlicht.a) $(STATIC_LIB): $(LINKOBJ) $(AR) rs $@ $^ # Copies static lib into lib/Linux staticlib staticlib_osx: $(STATIC_LIB) mkdir -p $(LIB_PATH) cp $^ $(LIB_PATH) # Builds Irrlicht as dll (Irrlicht.dll) into ../../bin/Win32-gcc all_win32 win32: sharedlib_win32 sharedlib_win32: $(IRRLICHT_DLL) ../../bin/Win32-gcc/Irrlicht.dll: $(LINKOBJ) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -shared -o $@ $^ $(LDFLAGS) -Wl,--out-implib,../../lib/Win32-gcc/$(STATIC_LIB) # Copies static lib into /lib/Win32-gcc staticlib_win32: $(STATIC_LIB) cp $^ $(LIB_PATH) # Builds Irrlicht as shared lib (libIrrlicht.so.versionNumber) and copies it into /lib/MacOSX sharedlib_osx: $(LINKOBJ) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -dynamiclib -Wl,-install_name,$(SONAME) -o $(SHARED_FULLNAME) $^ $(LDFLAGS) cp $(SHARED_FULLNAME) $(LIB_PATH) # Installs Irrlicht if it was created as shared lib install install_osx: $(RM) -r $(INSTALL_DIR)/../include/irrlicht mkdir -p $(INSTALL_DIR)/../include/irrlicht cp ../../include/*.h $(INSTALL_DIR)/../include/irrlicht/ cp $(LIB_PATH)/$(SHARED_FULLNAME) $(INSTALL_DIR) cd $(INSTALL_DIR) && ln -s -f $(SHARED_FULLNAME) $(SONAME) cd $(INSTALL_DIR) && ln -s -f $(SONAME) $(SHARED_LIB) # ldconfig -n $(INSTALL_DIR) TAGS: ctags *.cpp ../../include/*.h *.h # Create dependency files for automatic recompilation %.d:%.cpp $(CXX) $(CPPFLAGS) -MM -MF $@ $< # Create dependency files for automatic recompilation %.d:%.c $(CC) $(CPPFLAGS) -MM -MF $@ $< # Create object files from objective-c code %.o:%.mm $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< ifneq ($(MAKECMDGOALS),clean) -include $(LINKOBJ:.o=.d) endif help: @echo "Available targets for Irrlicht" @echo " sharedlib: Build shared library Irrlicht.so for Linux" @echo " staticlib: Build static library Irrlicht.a for Linux" @echo " install: Copy shared library to /usr/local/lib" @echo "" @echo " sharedlib_win32: Build shared library Irrlicht.dll for Windows" @echo " staticlib_win32: Build static library Irrlicht.a for Windows" @echo "" @echo " clean: Clean up directory" # Cleans all temporary files and compilation results. clean: $(RM) $(LINKOBJ) $(SHARED_FULLNAME) $(STATIC_LIB) $(LINKOBJ:.o=.d) .PHONY: all sharedlib staticlib sharedlib_win32 staticlib_win32 help install clean irrlicht-1.8.3/source/Irrlicht/IZBuffer.h0000644000000000000000000000201012574354552016753 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_Z_BUFFER_H_INCLUDED__ #define __I_Z_BUFFER_H_INCLUDED__ #include "IReferenceCounted.h" #include "dimension2d.h" #include "S2DVertex.h" namespace irr { namespace video { class IZBuffer : public virtual IReferenceCounted { public: //! destructor virtual ~IZBuffer() {}; //! clears the zbuffer virtual void clear() = 0; //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size) = 0; //! returns the size of the zbuffer virtual const core::dimension2d& getSize() const = 0; //! locks the zbuffer virtual TZBufferType* lock() = 0; //! unlocks the zbuffer virtual void unlock() = 0; }; //! creates a ZBuffer IZBuffer* createZBuffer(const core::dimension2d& size); } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/ITriangleRenderer.h0000644000000000000000000000402612574354552020655 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_TRIANGLE_RENDERER_H_INCLUDED__ #define __I_TRIANGLE_RENDERER_H_INCLUDED__ #include "IReferenceCounted.h" #include "S2DVertex.h" #include "rect.h" #include "IZBuffer.h" namespace irr { namespace video { class IImage; enum ETriangleRenderer { ETR_FLAT = 0, ETR_FLAT_WIRE, ETR_GOURAUD, ETR_GOURAUD_WIRE, ETR_TEXTURE_FLAT, ETR_TEXTURE_FLAT_WIRE, ETR_TEXTURE_GOURAUD, ETR_TEXTURE_GOURAUD_WIRE, ETR_TEXTURE_GOURAUD_NOZ, ETR_TEXTURE_GOURAUD_ADD, ETR_COUNT }; class ITriangleRenderer : public virtual IReferenceCounted { public: //! sets a render target virtual void setRenderTarget(video::IImage* surface, const core::rect& viewPort) = 0; //! en or disables the backface culling virtual void setBackfaceCulling(bool enabled = true) = 0; //! sets the Texture virtual void setTexture(video::IImage* texture) = 0; //! draws an indexed triangle list virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) = 0; }; ITriangleRenderer* createTriangleRendererTextureGouraud(IZBuffer* zbuffer); ITriangleRenderer* createTriangleRendererTextureGouraudWire(IZBuffer* zbuffer); ITriangleRenderer* createTriangleRendererGouraud(IZBuffer* zbuffer); ITriangleRenderer* createTriangleRendererGouraudWire(IZBuffer* zbuffer); ITriangleRenderer* createTriangleRendererTextureFlat(IZBuffer* zbuffer); ITriangleRenderer* createTriangleRendererTextureFlatWire(IZBuffer* zbuffer); ITriangleRenderer* createTriangleRendererFlat(IZBuffer* zbuffer); ITriangleRenderer* createTriangleRendererFlatWire(IZBuffer* zbuffer); ITriangleRenderer* createTriangleRendererTextureGouraudNoZ(); ITriangleRenderer* createTriangleRendererTextureGouraudAdd(IZBuffer* zbuffer); } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/ISceneNodeAnimatorFinishing.h0000644000000000000000000000147512574354552022623 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_NODE_ANIMATOR_FINISHING_H_INCLUDED__ #define __I_SCENE_NODE_ANIMATOR_FINISHING_H_INCLUDED__ #include "ISceneNode.h" namespace irr { namespace scene { //! This is an abstract base class for animators that have a discrete end time. class ISceneNodeAnimatorFinishing : public ISceneNodeAnimator { public: //! constructor ISceneNodeAnimatorFinishing(u32 finishTime) : FinishTime(finishTime), HasFinished(false) { } virtual bool hasFinished(void) const { return HasFinished; } protected: u32 FinishTime; bool HasFinished; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/irrXML.cpp0000644000000000000000000001001512574354552017013 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h #include "irrXML.h" #include "irrString.h" #include "irrArray.h" #include "fast_atof.h" #include "CXMLReaderImpl.h" namespace irr { namespace io { //! Implementation of the file read callback for ordinary files class CFileReadCallBack : public IFileReadCallBack { public: //! construct from filename CFileReadCallBack(const char* filename) : File(0), Size(-1), Close(true) { // open file File = fopen(filename, "rb"); if (File) getFileSize(); } //! construct from FILE pointer CFileReadCallBack(FILE* file) : File(file), Size(-1), Close(false) { if (File) getFileSize(); } //! destructor virtual ~CFileReadCallBack() { if (Close && File) fclose(File); } //! Reads an amount of bytes from the file. virtual int read(void* buffer, int sizeToRead) { if (!File) return 0; return (int)fread(buffer, 1, sizeToRead, File); } //! Returns size of file in bytes virtual long getSize() const { return Size; } private: //! retrieves the file size of the open file void getFileSize() { fseek(File, 0, SEEK_END); Size = ftell(File); fseek(File, 0, SEEK_SET); } FILE* File; long Size; bool Close; }; // end class CFileReadCallBack // FACTORY FUNCTIONS: //! Creates an instance of an UFT-8 or ASCII character xml parser. IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(const char* filename) { return createIrrXMLReader(new CFileReadCallBack(filename), true); } //! Creates an instance of an UFT-8 or ASCII character xml parser. IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(FILE* file) { return createIrrXMLReader(new CFileReadCallBack(file), true); } //! Creates an instance of an UFT-8 or ASCII character xml parser. IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(IFileReadCallBack* callback, bool deleteCallback) { if (callback && (callback->getSize() >= 0)) { return new CXMLReaderImpl(callback, deleteCallback); } else { if(callback && deleteCallback) delete callback; return 0; } } //! Creates an instance of an UTF-16 xml parser. IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(const char* filename) { return createIrrXMLReaderUTF16(new CFileReadCallBack(filename), true); } //! Creates an instance of an UTF-16 xml parser. IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(FILE* file) { return createIrrXMLReaderUTF16(new CFileReadCallBack(file), true); } //! Creates an instance of an UTF-16 xml parser. IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(IFileReadCallBack* callback, bool deleteCallback) { if (callback && (callback->getSize() >= 0)) { return new CXMLReaderImpl(callback, deleteCallback); } else { if(callback && deleteCallback) delete callback; return 0; } } //! Creates an instance of an UTF-32 xml parser. IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(const char* filename) { return createIrrXMLReaderUTF32(new CFileReadCallBack(filename), true); } //! Creates an instance of an UTF-32 xml parser. IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(FILE* file) { return createIrrXMLReaderUTF32(new CFileReadCallBack(file), true); } //! Creates an instance of an UTF-32 xml parser. IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32( IFileReadCallBack* callback, bool deleteCallback) { if (callback && (callback->getSize() >= 0)) { return new CXMLReaderImpl(callback, deleteCallback); } else { if(callback && deleteCallback) delete callback; return 0; } } } // end namespace io } // end namespace irr irrlicht-1.8.3/source/Irrlicht/Irrlicht_xbox.vcproj0000644000000000000000000013162112574354552021206 0ustar rootroot irrlicht-1.8.3/source/Irrlicht/Irrlicht_xbox.sln0000644000000000000000000000273012574354552020475 0ustar rootrootMicrosoft Visual Studio Solution File, Format Version 8.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht_xbox", "Irrlicht_xbox.vcproj", "{2440E601-7438-4C6B-B4AF-BBFE9735875E}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug Profile = Profile Profile_FastCap = Profile_FastCap Release = Release Release_LTCG = Release_LTCG EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {2440E601-7438-4C6B-B4AF-BBFE9735875E}.Debug.ActiveCfg = Debug|Xbox {2440E601-7438-4C6B-B4AF-BBFE9735875E}.Debug.Build.0 = Debug|Xbox {2440E601-7438-4C6B-B4AF-BBFE9735875E}.Profile.ActiveCfg = Profile|Xbox {2440E601-7438-4C6B-B4AF-BBFE9735875E}.Profile.Build.0 = Profile|Xbox {2440E601-7438-4C6B-B4AF-BBFE9735875E}.Profile_FastCap.ActiveCfg = Profile_FastCap|Xbox {2440E601-7438-4C6B-B4AF-BBFE9735875E}.Profile_FastCap.Build.0 = Profile_FastCap|Xbox {2440E601-7438-4C6B-B4AF-BBFE9735875E}.Release.ActiveCfg = Release|Xbox {2440E601-7438-4C6B-B4AF-BBFE9735875E}.Release.Build.0 = Release|Xbox {2440E601-7438-4C6B-B4AF-BBFE9735875E}.Release_LTCG.ActiveCfg = Release_LTCG|Xbox {2440E601-7438-4C6B-B4AF-BBFE9735875E}.Release_LTCG.Build.0 = Release_LTCG|Xbox EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection GlobalSection(ExtensibilityAddIns) = postSolution EndGlobalSection EndGlobal irrlicht-1.8.3/source/Irrlicht/Irrlicht_mobile6.vcproj0000644000000000000000000016507012574354552021570 0ustar rootroot irrlicht-1.8.3/source/Irrlicht/Irrlicht_mobile6.sln0000644000000000000000000000314612574354552021054 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "Irrlicht_mobile6.vcproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Windows Mobile 6 Professional SDK (ARMV4I) = Debug|Windows Mobile 6 Professional SDK (ARMV4I) Release|Windows Mobile 6 Professional SDK (ARMV4I) = Release|Windows Mobile 6 Professional SDK (ARMV4I) EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 6 Professional SDK (ARMV4I) {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).Build.0 = Debug|Windows Mobile 6 Professional SDK (ARMV4I) {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 6 Professional SDK (ARMV4I) {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Windows Mobile 6 Professional SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 6 Professional SDK (ARMV4I) {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Windows Mobile 6 Professional SDK (ARMV4I).Build.0 = Release|Windows Mobile 6 Professional SDK (ARMV4I) {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Windows Mobile 6 Professional SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 6 Professional SDK (ARMV4I) EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/source/Irrlicht/Irrlicht9.0.vcproj0000644000000000000000000022400412574354552020373 0ustar rootroot irrlicht-1.8.3/source/Irrlicht/Irrlicht9.0.sln0000644000000000000000000000374712574354552017675 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 10.00 # Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "Irrlicht9.0.vcproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release - Fast FPU|Win32 = Release - Fast FPU|Win32 Release|Win32 = Release|Win32 Static lib - Debug|Win32 = Static lib - Debug|Win32 Static lib - Release - Fast FPU|Win32 = Static lib - Release - Fast FPU|Win32 Static lib - Release|Win32 = Static lib - Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|Win32.ActiveCfg = Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|Win32.Build.0 = Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|Win32.ActiveCfg = Static lib - Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|Win32.Build.0 = Static lib - Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|Win32.ActiveCfg = Static lib - Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|Win32.Build.0 = Static lib - Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|Win32.ActiveCfg = Static lib - Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|Win32.Build.0 = Static lib - Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/source/Irrlicht/Irrlicht8.0.vcproj0000644000000000000000000021223212574354552020372 0ustar rootroot irrlicht-1.8.3/source/Irrlicht/Irrlicht8.0.sln0000644000000000000000000000333412574354552017664 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "Irrlicht8.0.vcproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 Static lib - Debug|Win32 = Static lib - Debug|Win32 Static lib - Release - Fast FPU|Win32 = Static lib - Release - Fast FPU|Win32 Static lib - Release|Win32 = Static lib - Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|Win32.ActiveCfg = Static lib - Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|Win32.Build.0 = Static lib - Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|Win32.ActiveCfg = Static lib - Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|Win32.Build.0 = Static lib - Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|Win32.ActiveCfg = Static lib - Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|Win32.Build.0 = Static lib - Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/source/Irrlicht/Irrlicht12.0.vcxproj.filters0000644000000000000000000024561712574354552022321 0ustar rootroot {b5bde5d3-f9e4-4036-8c28-2f4e8cd03846} {0b0937fb-2270-4e3e-a94f-f92bc0fa74ae} {67300400-93d5-4a7e-8b59-7c0d7b1f6d75} {feb206b9-81b6-45c0-b4e5-9e637fe060e7} {af459bf5-2849-4a0e-9a21-91acbbf1c6b5} {aa649d49-922d-4118-8574-f05c13d67706} {a72cb2e5-a5c3-41bc-9c86-fdbdae8f7866} {72c30315-bbc0-4109-9ccd-fb7107ba316a} {1fcdc900-911d-4b7a-9328-afce5bbe44fa} {41e16cbf-c3cb-4d74-8aef-c0416b6b9d7f} {b84f01e5-ae3c-457b-8d96-b3e271800162} {eca36d94-d8fb-477d-a0dc-b5498c9686d7} {67826246-df05-4523-9191-5286f9157963} {659a61d5-7ab3-4aa3-95ca-879780810b4e} {f65e8d89-c715-4794-8c2d-22f2b57cffb0} {3cb7865d-a5e9-4b22-8f54-dde759b88c51} {919fcfa4-4277-4c88-8bfc-4bfcfcbb1b65} {834213c7-9515-49de-aa27-8d3ed9c0c87a} {19838bc4-396f-4d23-ad1b-3bb652e33e6d} {a9ca9d4d-7678-4687-b78b-15236c0dcf53} {d694e7b0-0fb0-4685-ace7-56d9ec65a3d0} {e2571a61-945c-4509-b47c-daea464916ab} {1354e9fa-cea6-461e-af7f-9940bb5f0a2f} {ac7af7ba-0e6b-4da4-a695-a0070a4da974} {1173499e-79e8-4c34-8046-abc325e2f2a9} {ca095ff3-25e4-4852-ab55-af28c602cd8a} {1c8bd90a-8361-4478-8942-a062450ef209} {128cac28-b6f8-49e7-87f5-ee15951d0396} {6f10ce97-ed8b-47bc-a189-f2262eb467e4} {5d58bc55-284e-4880-9226-85083e65d660} {064ee182-9f07-4026-ac22-c141ae2c7281} {6e842906-e193-451d-8716-12eaafabd0d8} {799f220e-3a58-4788-876b-88c175b69871} {da421793-4674-481c-be46-f7a44e78aee5} include include include include include include include include include include include include include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\io include\io include\io include\io include\io include\io include\io include\io include\io include\io include\io include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\video Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\irr Irrlicht\irr Irrlicht\irr Irrlicht\irr Irrlicht\irr\extern Irrlicht\irr\extern Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui include\scene Irrlicht\scene\loaders include\scene Irrlicht\scene\loaders include\video include include\video Irrlicht\video\Direct3D9 Irrlicht\video\OpenGL Irrlicht\video doc doc Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\video Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\irr Irrlicht\irr Irrlicht\irr Irrlicht\irr Irrlicht\irr\extern Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\video\Direct3D9 Irrlicht\video\OpenGL Irrlicht\video irrlicht-1.8.3/source/Irrlicht/Irrlicht12.0.vcxproj0000644000000000000000000026301312574354552020640 0ustar rootroot Debug Win32 Debug x64 Release - Fast FPU Win32 Release - Fast FPU x64 Release Win32 Release x64 SDL-Debug Win32 SDL-Debug x64 Static lib - Debug Win32 Static lib - Debug x64 Static lib - Release - Fast FPU Win32 Static lib - Release - Fast FPU x64 Static lib - Release Win32 Static lib - Release x64 Irrlicht {E08E042A-6C45-411B-92BE-3CC31331019F} Irrlicht DynamicLibrary NotSet Windows7.1SDK DynamicLibrary NotSet Windows7.1SDK StaticLibrary MultiByte true Windows7.1SDK StaticLibrary MultiByte true Windows7.1SDK StaticLibrary MultiByte true Windows7.1SDK StaticLibrary MultiByte true Windows7.1SDK StaticLibrary NotSet Windows7.1SDK StaticLibrary NotSet Windows7.1SDK DynamicLibrary MultiByte true Windows7.1SDK DynamicLibrary MultiByte true Windows7.1SDK DynamicLibrary MultiByte true Windows7.1SDK DynamicLibrary MultiByte true Windows7.1SDK DynamicLibrary NotSet Windows7.1SDK DynamicLibrary NotSet Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ false false ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ false false ..\..\lib\Win32-VisualStudio\ ..\..\lib\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ ..\..\lib\Win32-VisualStudio\ ..\..\lib\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ ..\..\lib\Win32-VisualStudio\ ..\..\lib\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ true true AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset $(DXSDK_DIR)include;$(CG_INC_PATH);$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) obj\$(Configuration)\ obj\$(Configuration)64\ true true $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)Lib\x86;$(CG_LIB_PATH);$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 _DEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Debug/Irrlicht.tlb ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions); _ITERATOR_DEBUG_LEVEL=0 EnableFastChecks MultiThreadedDebug false false Level3 Disabled _DEBUG;%(PreprocessorDefinitions) 0x0c07 true /MACHINE:I386 %(AdditionalOptions) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-visualstudio\Irrlicht.dll %(AdditionalLibraryDirectories) libci.lib;%(IgnoreSpecificDefaultLibraries) true ..\..\lib\Win32-visualstudio\Irrlicht.lib 1.8 _DEBUG;%(PreprocessorDefinitions) true true .\..\Debug/Irrlicht.tlb ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions); _ITERATOR_DEBUG_LEVEL=0 EnableFastChecks MultiThreadedDebug false false Level3 Disabled _DEBUG;%(PreprocessorDefinitions) 0x0c07 true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies) ..\..\bin\Win64-visualstudio\Irrlicht.dll %(AdditionalLibraryDirectories) libci.lib;%(IgnoreSpecificDefaultLibraries) true ..\..\lib\Win64-visualstudio\Irrlicht.lib NDEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Release/Irrlicht.tlb MaxSpeed OnlyExplicitInline ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Level3 Default NDEBUG;%(PreprocessorDefinitions) 0x0c07 /MACHINE:I386 %(AdditionalOptions) kernel32.lib;user32.lib;gdi32.lib;opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-visualstudio\Irrlicht.dll libci.lib;%(IgnoreSpecificDefaultLibraries) false ..\..\lib\Win32-visualstudio\Irrlicht.lib 1.8 NDEBUG;%(PreprocessorDefinitions) true true .\..\Release/Irrlicht.tlb MaxSpeed OnlyExplicitInline ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Level3 Default NDEBUG;%(PreprocessorDefinitions) 0x0c07 kernel32.lib;user32.lib;gdi32.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies) ..\..\bin\Win64-visualstudio\Irrlicht.dll libci.lib;%(IgnoreSpecificDefaultLibraries) false ..\..\lib\Win64-visualstudio\Irrlicht.lib NDEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Release/Irrlicht.tlb Full AnySuitable true Speed true ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true false MultiThreaded Default false false StreamingSIMDExtensions2 Fast false Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 /MACHINE:I386 %(AdditionalOptions) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-visualstudio\Irrlicht.dll libci.lib;%(IgnoreSpecificDefaultLibraries) false true ..\..\lib\Win32-visualstudio\Irrlicht.lib Windows 1.8 NDEBUG;%(PreprocessorDefinitions) true true .\..\Release/Irrlicht.tlb Full AnySuitable true Speed true ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true false MultiThreaded Default false false StreamingSIMDExtensions2 Fast false Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies) ..\..\bin\Win64-visualstudio\Irrlicht.dll libci.lib;%(IgnoreSpecificDefaultLibraries) false true ..\..\lib\Win64-visualstudio\Irrlicht.lib Windows _DEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Debug/Irrlicht.tlb Disabled ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions); _ITERATOR_DEBUG_LEVEL=0 EnableFastChecks MultiThreadedDebug false false Level3 _DEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win32-visualstudio\Irrlicht.lib _DEBUG;%(PreprocessorDefinitions) true true .\..\Debug/Irrlicht.tlb Disabled ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions); _ITERATOR_DEBUG_LEVEL=0 EnableFastChecks MultiThreadedDebug false false Level3 _DEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win64-visualstudio\Irrlicht.lib MachineX64 NDEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Release/Irrlicht.tlb MaxSpeed OnlyExplicitInline false false ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win32-visualstudio\Irrlicht.lib NDEBUG;%(PreprocessorDefinitions) true true .\..\Release/Irrlicht.tlb MaxSpeed OnlyExplicitInline false false ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win64-visualstudio\Irrlicht.lib MachineX64 NDEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Release/Irrlicht.tlb Full AnySuitable true Speed true ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Fast false Level3 FastCall NDEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win32-visualstudio\Irrlicht.lib MachineX86 NDEBUG;%(PreprocessorDefinitions) true true .\..\Release/Irrlicht.tlb Full AnySuitable true Speed true ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Fast false Level3 FastCall NDEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win64-visualstudio\Irrlicht.lib MachineX64 _DEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Debug/Irrlicht.tlb Disabled ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_IRR_USE_SDL_DEVICE_=1;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug false false Level3 _DEBUG;%(PreprocessorDefinitions) 0x0c07 true /MACHINE:I386 %(AdditionalOptions) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-visualstudio\Irrlicht.dll %(AdditionalLibraryDirectories) libci.lib;%(IgnoreSpecificDefaultLibraries) true ..\..\lib\Win32-visualstudio\Irrlicht.lib 1.8 _DEBUG;%(PreprocessorDefinitions) true true .\..\Debug/Irrlicht.tlb Disabled ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_IRR_USE_SDL_DEVICE_=1;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug false false Level3 _DEBUG;%(PreprocessorDefinitions) 0x0c07 true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies) ..\..\bin\Win64-visualstudio\Irrlicht.dll %(AdditionalLibraryDirectories) libci.lib;%(IgnoreSpecificDefaultLibraries) true ..\..\lib\Win64-visualstudio\Irrlicht.lib irrlicht-1.8.3/source/Irrlicht/Irrlicht11.0.vcxproj.filters0000644000000000000000000024561712574354552022320 0ustar rootroot {b5bde5d3-f9e4-4036-8c28-2f4e8cd03846} {0b0937fb-2270-4e3e-a94f-f92bc0fa74ae} {67300400-93d5-4a7e-8b59-7c0d7b1f6d75} {feb206b9-81b6-45c0-b4e5-9e637fe060e7} {af459bf5-2849-4a0e-9a21-91acbbf1c6b5} {aa649d49-922d-4118-8574-f05c13d67706} {a72cb2e5-a5c3-41bc-9c86-fdbdae8f7866} {72c30315-bbc0-4109-9ccd-fb7107ba316a} {1fcdc900-911d-4b7a-9328-afce5bbe44fa} {41e16cbf-c3cb-4d74-8aef-c0416b6b9d7f} {b84f01e5-ae3c-457b-8d96-b3e271800162} {eca36d94-d8fb-477d-a0dc-b5498c9686d7} {67826246-df05-4523-9191-5286f9157963} {659a61d5-7ab3-4aa3-95ca-879780810b4e} {f65e8d89-c715-4794-8c2d-22f2b57cffb0} {3cb7865d-a5e9-4b22-8f54-dde759b88c51} {919fcfa4-4277-4c88-8bfc-4bfcfcbb1b65} {834213c7-9515-49de-aa27-8d3ed9c0c87a} {19838bc4-396f-4d23-ad1b-3bb652e33e6d} {a9ca9d4d-7678-4687-b78b-15236c0dcf53} {d694e7b0-0fb0-4685-ace7-56d9ec65a3d0} {e2571a61-945c-4509-b47c-daea464916ab} {1354e9fa-cea6-461e-af7f-9940bb5f0a2f} {ac7af7ba-0e6b-4da4-a695-a0070a4da974} {1173499e-79e8-4c34-8046-abc325e2f2a9} {ca095ff3-25e4-4852-ab55-af28c602cd8a} {1c8bd90a-8361-4478-8942-a062450ef209} {128cac28-b6f8-49e7-87f5-ee15951d0396} {6f10ce97-ed8b-47bc-a189-f2262eb467e4} {5d58bc55-284e-4880-9226-85083e65d660} {064ee182-9f07-4026-ac22-c141ae2c7281} {6e842906-e193-451d-8716-12eaafabd0d8} {799f220e-3a58-4788-876b-88c175b69871} {da421793-4674-481c-be46-f7a44e78aee5} include include include include include include include include include include include include include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\io include\io include\io include\io include\io include\io include\io include\io include\io include\io include\io include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\video Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\irr Irrlicht\irr Irrlicht\irr Irrlicht\irr Irrlicht\irr\extern Irrlicht\irr\extern Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui include\scene Irrlicht\scene\loaders include\scene Irrlicht\scene\loaders include\video include include\video Irrlicht\video\Direct3D9 Irrlicht\video\OpenGL Irrlicht\video doc doc Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\video Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\irr Irrlicht\irr Irrlicht\irr Irrlicht\irr Irrlicht\irr\extern Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\video\Direct3D9 Irrlicht\video\OpenGL Irrlicht\video irrlicht-1.8.3/source/Irrlicht/Irrlicht11.0.vcxproj0000644000000000000000000026313112574354552020640 0ustar rootroot Debug Win32 Debug x64 Release - Fast FPU Win32 Release - Fast FPU x64 Release Win32 Release x64 SDL-Debug Win32 SDL-Debug x64 Static lib - Debug Win32 Static lib - Debug x64 Static lib - Release - Fast FPU Win32 Static lib - Release - Fast FPU x64 Static lib - Release Win32 Static lib - Release x64 Irrlicht {E08E042A-6C45-411B-92BE-3CC31331019F} Irrlicht DynamicLibrary NotSet Windows7.1SDK DynamicLibrary NotSet Windows7.1SDK StaticLibrary MultiByte true Windows7.1SDK StaticLibrary MultiByte true Windows7.1SDK StaticLibrary MultiByte true Windows7.1SDK StaticLibrary MultiByte true Windows7.1SDK StaticLibrary NotSet Windows7.1SDK StaticLibrary NotSet Windows7.1SDK DynamicLibrary MultiByte true Windows7.1SDK DynamicLibrary MultiByte true Windows7.1SDK DynamicLibrary MultiByte true Windows7.1SDK DynamicLibrary MultiByte true Windows7.1SDK DynamicLibrary NotSet Windows7.1SDK DynamicLibrary NotSet Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ false false ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ false false ..\..\lib\Win32-VisualStudio\ ..\..\lib\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ ..\..\lib\Win32-VisualStudio\ ..\..\lib\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ ..\..\lib\Win32-VisualStudio\ ..\..\lib\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ true true AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset $(IncludePath);$(DXSDK_DIR)include;$(CG_INC_PATH) $(DXSDK_DIR)include;$(IncludePath) obj\$(Configuration)\ obj\$(Configuration)64\ true true $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(LibraryPath);$(DXSDK_DIR)Lib\x86;$(CG_LIB_PATH) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 _DEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Debug/Irrlicht.tlb ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions); _ITERATOR_DEBUG_LEVEL=0 EnableFastChecks MultiThreadedDebug false false Level3 Disabled _DEBUG;%(PreprocessorDefinitions) 0x0c07 true /MACHINE:I386 %(AdditionalOptions) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-visualstudio\Irrlicht.dll %(AdditionalLibraryDirectories) libci.lib;%(IgnoreSpecificDefaultLibraries) true ..\..\lib\Win32-visualstudio\Irrlicht.lib 1.8 _DEBUG;%(PreprocessorDefinitions) true true .\..\Debug/Irrlicht.tlb ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions); _ITERATOR_DEBUG_LEVEL=0 EnableFastChecks MultiThreadedDebug false false Level3 Disabled _DEBUG;%(PreprocessorDefinitions) 0x0c07 true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies) ..\..\bin\Win64-visualstudio\Irrlicht.dll %(AdditionalLibraryDirectories) libci.lib;%(IgnoreSpecificDefaultLibraries) true ..\..\lib\Win64-visualstudio\Irrlicht.lib NDEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Release/Irrlicht.tlb MaxSpeed OnlyExplicitInline ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Level3 Default NDEBUG;%(PreprocessorDefinitions) 0x0c07 /MACHINE:I386 %(AdditionalOptions) kernel32.lib;user32.lib;gdi32.lib;opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-visualstudio\Irrlicht.dll libci.lib;%(IgnoreSpecificDefaultLibraries) false ..\..\lib\Win32-visualstudio\Irrlicht.lib 1.8 NDEBUG;%(PreprocessorDefinitions) true true .\..\Release/Irrlicht.tlb MaxSpeed OnlyExplicitInline ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Level3 Default NDEBUG;%(PreprocessorDefinitions) 0x0c07 kernel32.lib;user32.lib;gdi32.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies) ..\..\bin\Win64-visualstudio\Irrlicht.dll libci.lib;%(IgnoreSpecificDefaultLibraries) false ..\..\lib\Win64-visualstudio\Irrlicht.lib NDEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Release/Irrlicht.tlb Full AnySuitable true Speed true ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true false MultiThreaded Default false false StreamingSIMDExtensions2 Fast false Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 /MACHINE:I386 %(AdditionalOptions) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-visualstudio\Irrlicht.dll libci.lib;%(IgnoreSpecificDefaultLibraries) false true ..\..\lib\Win32-visualstudio\Irrlicht.lib Windows 1.8 NDEBUG;%(PreprocessorDefinitions) true true .\..\Release/Irrlicht.tlb Full AnySuitable true Speed true ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true false MultiThreaded Default false false StreamingSIMDExtensions2 Fast false Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies) ..\..\bin\Win64-visualstudio\Irrlicht.dll libci.lib;%(IgnoreSpecificDefaultLibraries) false true ..\..\lib\Win64-visualstudio\Irrlicht.lib Windows _DEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Debug/Irrlicht.tlb Disabled ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions); _ITERATOR_DEBUG_LEVEL=0 EnableFastChecks MultiThreadedDebug false false Level3 _DEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win32-visualstudio\Irrlicht.lib _DEBUG;%(PreprocessorDefinitions) true true .\..\Debug/Irrlicht.tlb Disabled ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions); _ITERATOR_DEBUG_LEVEL=0 EnableFastChecks MultiThreadedDebug false false Level3 _DEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win64-visualstudio\Irrlicht.lib MachineX64 NDEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Release/Irrlicht.tlb MaxSpeed OnlyExplicitInline false false ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win32-visualstudio\Irrlicht.lib NDEBUG;%(PreprocessorDefinitions) true true .\..\Release/Irrlicht.tlb MaxSpeed OnlyExplicitInline false false ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win64-visualstudio\Irrlicht.lib MachineX64 NDEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Release/Irrlicht.tlb Full AnySuitable true Speed true ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Fast false Level3 FastCall NDEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win32-visualstudio\Irrlicht.lib MachineX86 NDEBUG;%(PreprocessorDefinitions) true true .\..\Release/Irrlicht.tlb Full AnySuitable true Speed true ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Fast false Level3 FastCall NDEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win64-visualstudio\Irrlicht.lib MachineX64 _DEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Debug/Irrlicht.tlb Disabled ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_IRR_USE_SDL_DEVICE_=1;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug false false Level3 _DEBUG;%(PreprocessorDefinitions) 0x0c07 true /MACHINE:I386 %(AdditionalOptions) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-visualstudio\Irrlicht.dll %(AdditionalLibraryDirectories) libci.lib;%(IgnoreSpecificDefaultLibraries) true ..\..\lib\Win32-visualstudio\Irrlicht.lib 1.8 _DEBUG;%(PreprocessorDefinitions) true true .\..\Debug/Irrlicht.tlb Disabled ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_IRR_USE_SDL_DEVICE_=1;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug false false Level3 _DEBUG;%(PreprocessorDefinitions) 0x0c07 true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies) ..\..\bin\Win64-visualstudio\Irrlicht.dll %(AdditionalLibraryDirectories) libci.lib;%(IgnoreSpecificDefaultLibraries) true ..\..\lib\Win64-visualstudio\Irrlicht.lib irrlicht-1.8.3/source/Irrlicht/Irrlicht11.0.sln0000644000000000000000000000660412574354552017741 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2012 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "Irrlicht11.0.vcxproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release - Fast FPU|Win32 = Release - Fast FPU|Win32 Release - Fast FPU|x64 = Release - Fast FPU|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 Static lib - Debug|Win32 = Static lib - Debug|Win32 Static lib - Debug|x64 = Static lib - Debug|x64 Static lib - Release - Fast FPU|Win32 = Static lib - Release - Fast FPU|Win32 Static lib - Release - Fast FPU|x64 = Static lib - Release - Fast FPU|x64 Static lib - Release|Win32 = Static lib - Release|Win32 Static lib - Release|x64 = Static lib - Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.ActiveCfg = Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.Build.0 = Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|Win32.ActiveCfg = Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|Win32.Build.0 = Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|x64.ActiveCfg = Release - Fast FPU|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|x64.Build.0 = Release - Fast FPU|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|x64.ActiveCfg = Release|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|x64.Build.0 = Release|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|Win32.ActiveCfg = Static lib - Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|Win32.Build.0 = Static lib - Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|x64.ActiveCfg = Static lib - Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|x64.Build.0 = Static lib - Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|Win32.ActiveCfg = Static lib - Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|Win32.Build.0 = Static lib - Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|x64.ActiveCfg = Static lib - Release - Fast FPU|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|x64.Build.0 = Static lib - Release - Fast FPU|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|Win32.ActiveCfg = Static lib - Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|Win32.Build.0 = Static lib - Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|x64.ActiveCfg = Static lib - Release|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|x64.Build.0 = Static lib - Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/source/Irrlicht/Irrlicht10.0.vcxproj.filters0000644000000000000000000024561712574354552022317 0ustar rootroot {b5bde5d3-f9e4-4036-8c28-2f4e8cd03846} {0b0937fb-2270-4e3e-a94f-f92bc0fa74ae} {67300400-93d5-4a7e-8b59-7c0d7b1f6d75} {feb206b9-81b6-45c0-b4e5-9e637fe060e7} {af459bf5-2849-4a0e-9a21-91acbbf1c6b5} {aa649d49-922d-4118-8574-f05c13d67706} {a72cb2e5-a5c3-41bc-9c86-fdbdae8f7866} {72c30315-bbc0-4109-9ccd-fb7107ba316a} {1fcdc900-911d-4b7a-9328-afce5bbe44fa} {41e16cbf-c3cb-4d74-8aef-c0416b6b9d7f} {b84f01e5-ae3c-457b-8d96-b3e271800162} {eca36d94-d8fb-477d-a0dc-b5498c9686d7} {67826246-df05-4523-9191-5286f9157963} {659a61d5-7ab3-4aa3-95ca-879780810b4e} {f65e8d89-c715-4794-8c2d-22f2b57cffb0} {3cb7865d-a5e9-4b22-8f54-dde759b88c51} {919fcfa4-4277-4c88-8bfc-4bfcfcbb1b65} {834213c7-9515-49de-aa27-8d3ed9c0c87a} {19838bc4-396f-4d23-ad1b-3bb652e33e6d} {a9ca9d4d-7678-4687-b78b-15236c0dcf53} {d694e7b0-0fb0-4685-ace7-56d9ec65a3d0} {e2571a61-945c-4509-b47c-daea464916ab} {1354e9fa-cea6-461e-af7f-9940bb5f0a2f} {ac7af7ba-0e6b-4da4-a695-a0070a4da974} {1173499e-79e8-4c34-8046-abc325e2f2a9} {ca095ff3-25e4-4852-ab55-af28c602cd8a} {1c8bd90a-8361-4478-8942-a062450ef209} {128cac28-b6f8-49e7-87f5-ee15951d0396} {6f10ce97-ed8b-47bc-a189-f2262eb467e4} {5d58bc55-284e-4880-9226-85083e65d660} {064ee182-9f07-4026-ac22-c141ae2c7281} {6e842906-e193-451d-8716-12eaafabd0d8} {799f220e-3a58-4788-876b-88c175b69871} {da421793-4674-481c-be46-f7a44e78aee5} include include include include include include include include include include include include include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\video include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\core include\io include\io include\io include\io include\io include\io include\io include\io include\io include\io include\io include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\scene include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui include\gui Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\video Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\irr Irrlicht\irr Irrlicht\irr Irrlicht\irr Irrlicht\irr\extern Irrlicht\irr\extern Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui include\scene Irrlicht\scene\loaders include\scene Irrlicht\scene\loaders include\video include include\video Irrlicht\video\Direct3D9 Irrlicht\video\OpenGL Irrlicht\video doc doc Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\sceneNodes Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\particleSystem Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\collision Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\animators Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\scene\writers Irrlicht\video Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\Software Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\OpenGL Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Direct3D8 Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Writer Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Null\Loader Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Direct3D9 Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\video\Burning Video Irrlicht\irr Irrlicht\irr Irrlicht\irr Irrlicht\irr Irrlicht\irr\extern Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\zlib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\jpeglib Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\libpng Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\aesGladman Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\extern\bzip2 Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\irr\device Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\io Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\gui Irrlicht\scene\loaders Irrlicht\scene\loaders Irrlicht\video\Direct3D9 Irrlicht\video\OpenGL Irrlicht\video irrlicht-1.8.3/source/Irrlicht/Irrlicht10.0.vcxproj0000644000000000000000000026301212574354552020635 0ustar rootroot Debug Win32 Debug x64 Release - Fast FPU Win32 Release - Fast FPU x64 Release Win32 Release x64 SDL-Debug Win32 SDL-Debug x64 Static lib - Debug Win32 Static lib - Debug x64 Static lib - Release - Fast FPU Win32 Static lib - Release - Fast FPU x64 Static lib - Release Win32 Static lib - Release x64 Irrlicht {E08E042A-6C45-411B-92BE-3CC31331019F} Irrlicht DynamicLibrary NotSet Windows7.1SDK DynamicLibrary NotSet Windows7.1SDK StaticLibrary MultiByte true Windows7.1SDK StaticLibrary MultiByte true Windows7.1SDK StaticLibrary MultiByte true Windows7.1SDK StaticLibrary MultiByte true Windows7.1SDK StaticLibrary NotSet Windows7.1SDK StaticLibrary NotSet Windows7.1SDK DynamicLibrary MultiByte true Windows7.1SDK DynamicLibrary MultiByte true Windows7.1SDK DynamicLibrary MultiByte true Windows7.1SDK DynamicLibrary MultiByte true Windows7.1SDK DynamicLibrary NotSet Windows7.1SDK DynamicLibrary NotSet Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ false false ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ false false ..\..\lib\Win32-VisualStudio\ ..\..\lib\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ ..\..\lib\Win32-VisualStudio\ ..\..\lib\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ ..\..\lib\Win32-VisualStudio\ ..\..\lib\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ obj\$(Configuration)\ obj\$(Configuration)64\ true true AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset $(DXSDK_DIR)include;$(CG_INC_PATH);$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) obj\$(Configuration)\ obj\$(Configuration)64\ true true $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)include;$(IncludePath) $(DXSDK_DIR)Lib\x86;$(CG_LIB_PATH);$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x86;$(LibraryPath) $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 $(DXSDK_DIR)Lib\x64;$(LibraryPath);$(VSInstallDir);$(VSInstallDir)lib\amd64 _DEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Debug/Irrlicht.tlb ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions); _ITERATOR_DEBUG_LEVEL=0 EnableFastChecks MultiThreadedDebug false false Level3 Disabled _DEBUG;%(PreprocessorDefinitions) 0x0c07 true /MACHINE:I386 %(AdditionalOptions) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-visualstudio\Irrlicht.dll %(AdditionalLibraryDirectories) libci.lib;%(IgnoreSpecificDefaultLibraries) true ..\..\lib\Win32-visualstudio\Irrlicht.lib 1.8 _DEBUG;%(PreprocessorDefinitions) true true .\..\Debug/Irrlicht.tlb ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions); _ITERATOR_DEBUG_LEVEL=0 EnableFastChecks MultiThreadedDebug false false Level3 Disabled _DEBUG;%(PreprocessorDefinitions) 0x0c07 true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies) ..\..\bin\Win64-visualstudio\Irrlicht.dll %(AdditionalLibraryDirectories) libci.lib;%(IgnoreSpecificDefaultLibraries) true ..\..\lib\Win64-visualstudio\Irrlicht.lib NDEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Release/Irrlicht.tlb MaxSpeed OnlyExplicitInline ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Level3 Default NDEBUG;%(PreprocessorDefinitions) 0x0c07 /MACHINE:I386 %(AdditionalOptions) kernel32.lib;user32.lib;gdi32.lib;opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-visualstudio\Irrlicht.dll libci.lib;%(IgnoreSpecificDefaultLibraries) false ..\..\lib\Win32-visualstudio\Irrlicht.lib 1.8 NDEBUG;%(PreprocessorDefinitions) true true .\..\Release/Irrlicht.tlb MaxSpeed OnlyExplicitInline ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Level3 Default NDEBUG;%(PreprocessorDefinitions) 0x0c07 kernel32.lib;user32.lib;gdi32.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies) ..\..\bin\Win64-visualstudio\Irrlicht.dll libci.lib;%(IgnoreSpecificDefaultLibraries) false ..\..\lib\Win64-visualstudio\Irrlicht.lib NDEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Release/Irrlicht.tlb Full AnySuitable true Speed true ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true false MultiThreaded Default false false StreamingSIMDExtensions2 Fast false Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 /MACHINE:I386 %(AdditionalOptions) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-visualstudio\Irrlicht.dll libci.lib;%(IgnoreSpecificDefaultLibraries) false true ..\..\lib\Win32-visualstudio\Irrlicht.lib Windows 1.8 NDEBUG;%(PreprocessorDefinitions) true true .\..\Release/Irrlicht.tlb Full AnySuitable true Speed true ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true false MultiThreaded Default false false StreamingSIMDExtensions2 Fast false Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies) ..\..\bin\Win64-visualstudio\Irrlicht.dll libci.lib;%(IgnoreSpecificDefaultLibraries) false true ..\..\lib\Win64-visualstudio\Irrlicht.lib Windows _DEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Debug/Irrlicht.tlb Disabled ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions); _ITERATOR_DEBUG_LEVEL=0 EnableFastChecks MultiThreadedDebug false false Level3 _DEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win32-visualstudio\Irrlicht.lib _DEBUG;%(PreprocessorDefinitions) true true .\..\Debug/Irrlicht.tlb Disabled ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions); _ITERATOR_DEBUG_LEVEL=0 EnableFastChecks MultiThreadedDebug false false Level3 _DEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win64-visualstudio\Irrlicht.lib MachineX64 NDEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Release/Irrlicht.tlb MaxSpeed OnlyExplicitInline false false ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win32-visualstudio\Irrlicht.lib NDEBUG;%(PreprocessorDefinitions) true true .\..\Release/Irrlicht.tlb MaxSpeed OnlyExplicitInline false false ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win64-visualstudio\Irrlicht.lib MachineX64 NDEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Release/Irrlicht.tlb Full AnySuitable true Speed true ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Fast false Level3 FastCall NDEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win32-visualstudio\Irrlicht.lib MachineX86 NDEBUG;%(PreprocessorDefinitions) true true .\..\Release/Irrlicht.tlb Full AnySuitable true Speed true ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;_USRDLL;_IRR_STATIC_LIB_;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true MultiThreaded false true Fast false Level3 FastCall NDEBUG;%(PreprocessorDefinitions) 0x0c07 winmm.lib;%(AdditionalDependencies) ..\..\lib\Win64-visualstudio\Irrlicht.lib MachineX64 _DEBUG;%(PreprocessorDefinitions) true true Win32 .\..\Debug/Irrlicht.tlb Disabled ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_IRR_USE_SDL_DEVICE_=1;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug false false Level3 _DEBUG;%(PreprocessorDefinitions) 0x0c07 true /MACHINE:I386 %(AdditionalOptions) kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-visualstudio\Irrlicht.dll %(AdditionalLibraryDirectories) libci.lib;%(IgnoreSpecificDefaultLibraries) true ..\..\lib\Win32-visualstudio\Irrlicht.lib 1.8 _DEBUG;%(PreprocessorDefinitions) true true .\..\Debug/Irrlicht.tlb Disabled ..\..\include;zlib;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;_USRDLL;IRRLICHT_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_IRR_USE_SDL_DEVICE_=1;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug false false Level3 _DEBUG;%(PreprocessorDefinitions) 0x0c07 true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies) ..\..\bin\Win64-visualstudio\Irrlicht.dll %(AdditionalLibraryDirectories) libci.lib;%(IgnoreSpecificDefaultLibraries) true ..\..\lib\Win64-visualstudio\Irrlicht.lib irrlicht-1.8.3/source/Irrlicht/Irrlicht10.0.sln0000644000000000000000000000660412574354552017740 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "Irrlicht10.0.vcxproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release - Fast FPU|Win32 = Release - Fast FPU|Win32 Release - Fast FPU|x64 = Release - Fast FPU|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 Static lib - Debug|Win32 = Static lib - Debug|Win32 Static lib - Debug|x64 = Static lib - Debug|x64 Static lib - Release - Fast FPU|Win32 = Static lib - Release - Fast FPU|Win32 Static lib - Release - Fast FPU|x64 = Static lib - Release - Fast FPU|x64 Static lib - Release|Win32 = Static lib - Release|Win32 Static lib - Release|x64 = Static lib - Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.ActiveCfg = Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.Build.0 = Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|Win32.ActiveCfg = Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|Win32.Build.0 = Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|x64.ActiveCfg = Release - Fast FPU|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release - Fast FPU|x64.Build.0 = Release - Fast FPU|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|x64.ActiveCfg = Release|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|x64.Build.0 = Release|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|Win32.ActiveCfg = Static lib - Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|Win32.Build.0 = Static lib - Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|x64.ActiveCfg = Static lib - Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Debug|x64.Build.0 = Static lib - Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|Win32.ActiveCfg = Static lib - Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|Win32.Build.0 = Static lib - Release - Fast FPU|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|x64.ActiveCfg = Static lib - Release - Fast FPU|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release - Fast FPU|x64.Build.0 = Static lib - Release - Fast FPU|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|Win32.ActiveCfg = Static lib - Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|Win32.Build.0 = Static lib - Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|x64.ActiveCfg = Static lib - Release|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Static lib - Release|x64.Build.0 = Static lib - Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/source/Irrlicht/Irrlicht.rc0000644000000000000000000001076612574354552017255 0ustar rootrootÿþ// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include <windows.h> ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // Deutsch (Deutschland) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) LANGUAGE LANG_GERMAN, SUBLANG_GERMAN #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""windows.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 1,8,0,0 PRODUCTVERSION 1,8,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040704b0" BEGIN VALUE "CompanyName", "Irrlicht Team" VALUE "FileDescription", "Irrlicht 3d engine" VALUE "FileVersion", "r3526" VALUE "InternalName", "Irrlicht.dll" VALUE "LegalCopyright", "Copyright (C) 2003-2011" VALUE "OriginalFilename", "Irrlicht.dll" VALUE "ProductName", "Irrlicht 3d engine" VALUE "ProductVersion", "1.8.0.alpha" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x407, 1200 END END #endif // Deutsch (Deutschland) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED irrlicht-1.8.3/source/Irrlicht/Irrlicht.dev0000644000000000000000000030776112574354552017433 0ustar rootroot[Project] FileName=Irrlicht.dev Name=Irrlicht Ver=1 IsCpp=1 Type=3 Compiler=-D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -D_USRDLL -DIRRLICHT_EXPORTS_@@_ CppCompiler=-D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -D_USRDLL -DIRRLICHT_EXPORTS_@@_ Includes=..\..\include;zlib Linker=-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lwinmm -lopengl32_@@_ Libs= UnitCount=658 Folders=doc,include,include/core,include/gui,include/io,include/scene,include/video,Irrlicht,Irrlicht/extern,Irrlicht/extern/jpeglib,Irrlicht/extern/libpng,Irrlicht/extern/zlib,Irrlicht/extern/aesGladman,Irrlicht/gui,Irrlicht/io,Irrlicht/io/archive,Irrlicht/io/attributes,Irrlicht/io/file,Irrlicht/io/xml,Irrlicht/irr,Irrlicht/irr/IrrlichtDevice,Irrlicht/scene,Irrlicht/scene/animators,Irrlicht/scene/collision,Irrlicht/scene/mesh,Irrlicht/scene/mesh/loaders,Irrlicht/scene/mesh/writers,Irrlicht/scene/nodes,Irrlicht/scene/nodes/particles,Irrlicht/video,"Irrlicht/video/Burning Video",Irrlicht/video/DirectX8,Irrlicht/video/DirectX9,Irrlicht/video/Null,Irrlicht/video/Null/Loader,Irrlicht/video/Null/Writer,Irrlicht/video/OpenGL,Irrlicht/video/Software ObjFiles= PrivateResource= ResourceIncludes= MakeIncludes= Icon= ExeOutput=..\..\bin\Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=Irrlicht.dll HostApplication= CommandLine= UseCustomMakefile=0 CustomMakefile= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000001001000000100 [Unit1] FileName=..\..\include\EDriverTypes.h Folder=include/video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit2] FileName=..\..\include\ITexture.h Folder=include/video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=..\..\include\IVideoDriver.h Folder=include/video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=..\..\include\S3DVertex.h Folder=include/video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=..\..\include\SColor.h Folder=include/video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit6] FileName=..\..\include\SLight.h Folder=include/video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit7] FileName=..\..\include\SMaterial.h Folder=include/video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit8] FileName=..\..\include\aabbox3d.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit9] FileName=..\..\include\dimension2d.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit10] FileName=..\..\include\heapsort.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit11] FileName=..\..\include\irrArray.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit12] FileName=..\..\include\irrList.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit13] FileName=..\..\include\irrMath.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit14] FileName=..\..\include\irrString.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit15] FileName=..\..\include\line2d.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit16] FileName=..\..\include\line3d.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit17] FileName=..\..\include\matrix4.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit18] FileName=..\..\include\plane3d.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit19] FileName=..\..\include\position2d.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit20] FileName=..\..\include\rect.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit21] FileName=..\..\include\vector2d.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit22] FileName=..\..\include\vector3d.h Folder=include/core Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit23] FileName=..\..\include\IFileList.h Folder=include/io Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit24] FileName=..\..\include\IFileSystem.h Folder=include/io Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit25] FileName=..\..\include\IReadFile.H Folder=include/io Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit26] FileName=..\..\include\IAnimatedMesh.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit27] FileName=..\..\include\IAnimatedMeshSceneNode.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit28] FileName=..\..\include\IBillboardSceneNode.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit29] FileName=..\..\include\ICameraSceneNode.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit30] FileName=..\..\include\ILightSceneNode.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit31] FileName=..\..\include\IMesh.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit32] FileName=..\..\include\IMeshBuffer.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit33] FileName=..\..\include\IQ3LevelMesh.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit34] FileName=..\..\include\ISceneManager.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit35] FileName=..\..\include\ISceneNode.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit36] FileName=..\..\include\ISceneNodeAnimator.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit37] FileName=..\..\include\SMesh.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit38] FileName=..\..\include\SMeshBuffer.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit39] FileName=..\..\include\SMeshBufferLightMap.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit40] FileName=..\..\include\ICursorControl.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit41] FileName=..\..\include\IGUIButton.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit42] FileName=..\..\include\IGUICheckbox.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit43] FileName=..\..\include\IGUIElement.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit44] FileName=..\..\include\IGUIEnvironment.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit45] FileName=..\..\include\IGUIFileOpenDialog.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit46] FileName=..\..\include\IGUIFont.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit47] FileName=..\..\include\IGUIImage.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit48] FileName=..\..\include\IGUIListBox.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit49] FileName=..\..\include\IGUIMeshViewer.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit50] FileName=..\..\include\IGUIScrollBar.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit51] FileName=..\..\include\IGUISkin.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit52] FileName=..\..\include\IGUIWindow.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit53] FileName=..\..\include\IEventReceiver.h Folder=include Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit54] FileName=..\..\include\Irrlicht.h Folder=include Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit55] FileName=..\..\include\IrrlichtDevice.h Folder=include Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit56] FileName=..\..\include\irrTypes.h Folder=include Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit57] FileName=..\..\include\Keycodes.h Folder=include Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit58] FileName=..\..\include\SIrrCreationParameters.h Folder=include Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit59] FileName=BuiltInFont.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit60] FileName=CGUIButton.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit61] FileName=CGUIButton.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit62] FileName=CGUICheckbox.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit63] FileName=CGUICheckbox.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit64] FileName=CGUIComboBox.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit65] FileName=CGUIComboBox.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit66] FileName=CGUIContextMenu.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit67] FileName=CGUIContextMenu.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit68] FileName=CGUIEditBox.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit69] FileName=CGUIEditBox.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit70] FileName=CGUIEnvironment.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit71] FileName=CGUIEnvironment.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit72] FileName=CGUIFileOpenDialog.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit73] FileName=CGUIFileOpenDialog.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit74] FileName=CGUIFont.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit75] FileName=CGUIFont.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit76] FileName=CGUIImage.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit77] FileName=CGUIImage.H Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit78] FileName=CGUIInOutFader.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit79] FileName=CGUIInOutFader.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit80] FileName=CGUIListBox.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit81] FileName=CGUIListBox.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit82] FileName=CGUIMenu.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit83] FileName=CGUIMenu.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit84] FileName=CGUIMeshViewer.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit85] FileName=CGUIMeshViewer.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit86] FileName=CGUIMessageBox.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit87] FileName=CGUIMessageBox.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit88] FileName=CGUIModalScreen.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit89] FileName=CGUIModalScreen.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit90] FileName=CGUIScrollBar.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit91] FileName=CGUIScrollBar.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit92] FileName=CGUISkin.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit93] FileName=CGUISkin.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit94] FileName=CGUIStaticText.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit95] FileName=CGUIStaticText.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit96] FileName=CGUITabControl.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit97] FileName=CGUITabControl.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit98] FileName=CGUIToolBar.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit99] FileName=CGUIToolBar.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit100] FileName=CGUIWindow.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit101] FileName=CGUIWindow.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit102] FileName=CSoftwareDriver.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit103] FileName=CSoftwareDriver.h Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit104] FileName=CSoftwareTexture.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit105] FileName=CSoftwareTexture.h Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit106] FileName=CTRFlat.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit107] FileName=CTRFlatWire.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit108] FileName=CTRGouraud.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit109] FileName=CTRGouraudWire.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit110] FileName=CTRTextureFlat.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit111] FileName=CTRTextureFlatWire.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit112] FileName=CTRTextureGouraud.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit113] FileName=CTRTextureGouraud.h Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit114] FileName=CTRTextureGouraudAdd.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit115] FileName=CTRTextureGouraudNoZ.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit116] FileName=CTRTextureGouraudWire.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit117] FileName=CZBuffer.cpp Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit118] FileName=CZBuffer.h Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit119] FileName=IZBuffer.h Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit120] FileName=S2DVertex.h Folder=Irrlicht/video/Software Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit121] FileName=COpenGLDriver.cpp Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit122] FileName=COpenGLDriver.h Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit123] FileName=COpenGLMaterialRenderer.h Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit124] FileName=COpenGLNormalMapRenderer.cpp Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit125] FileName=COpenGLNormalMapRenderer.h Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit126] FileName=COpenGLParallaxMapRenderer.cpp Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit127] FileName=COpenGLParallaxMapRenderer.h Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit128] FileName=COpenGLShaderMaterialRenderer.cpp Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit129] FileName=COpenGLShaderMaterialRenderer.h Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit130] FileName=COpenGLTexture.cpp Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit131] FileName=COpenGLTexture.h Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit132] FileName=glext.h Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit133] FileName=CD3D8Driver.cpp Folder=Irrlicht/video/DirectX8 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit134] FileName=CD3D8Driver.h Folder=Irrlicht/video/DirectX8 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit135] FileName=CD3D8MaterialRenderer.h Folder=Irrlicht/video/DirectX8 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit136] FileName=CD3D8NormalMapRenderer.cpp Folder=Irrlicht/video/DirectX8 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit137] FileName=CD3D8NormalMapRenderer.h Folder=Irrlicht/video/DirectX8 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit138] FileName=CD3D8ParallaxMapRenderer.cpp Folder=Irrlicht/video/DirectX8 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit139] FileName=CD3D8ParallaxMapRenderer.h Folder=Irrlicht/video/DirectX8 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit140] FileName=CD3D8ShaderMaterialRenderer.cpp Folder=Irrlicht/video/DirectX8 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit141] FileName=CD3D8ShaderMaterialRenderer.h Folder=Irrlicht/video/DirectX8 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit142] FileName=CD3D8Texture.cpp Folder=Irrlicht/video/DirectX8 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit143] FileName=CD3D8Texture.h Folder=Irrlicht/video/DirectX8 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit144] FileName=CColorConverter.cpp Folder=Irrlicht/video/Null Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit145] FileName=CColorConverter.h Folder=Irrlicht/video/Null Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit146] FileName=CFPSCounter.cpp Folder=Irrlicht/video/Null Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit147] FileName=CFPSCounter.h Folder=Irrlicht/video/Null Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit148] FileName=CImage.cpp Folder=Irrlicht/video/Null Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit149] FileName=CImage.h Folder=Irrlicht/video/Null Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit150] FileName=CImageLoaderBMP.cpp Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit151] FileName=CImageLoaderBMP.h Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit152] FileName=CImageLoaderJPG.cpp Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit153] FileName=CImageLoaderJPG.h Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit154] FileName=CImageLoaderPCX.cpp Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit155] FileName=CImageLoaderPCX.h Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit156] FileName=CImageLoaderPNG.cpp Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit157] FileName=CImageLoaderPNG.h Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit158] FileName=CImageLoaderPSD.cpp Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit159] FileName=CImageLoaderPSD.h Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit160] FileName=CImageLoaderTGA.cpp Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit161] FileName=CImageLoaderTGA.h Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit162] FileName=CNullDriver.cpp Folder=Irrlicht/video/Null Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit163] FileName=CNullDriver.h Folder=Irrlicht/video/Null Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit164] FileName=CD3D9Driver.cpp Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit165] FileName=CD3D9Driver.h Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit166] FileName=CD3D9HLSLMaterialRenderer.cpp Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit167] FileName=CD3D9HLSLMaterialRenderer.h Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit168] FileName=CD3D9MaterialRenderer.h Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit169] FileName=CD3D9NormalMapRenderer.cpp Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit170] FileName=CD3D9NormalMapRenderer.h Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit171] FileName=CD3D9ParallaxMapRenderer.cpp Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit172] FileName=CD3D9ParallaxMapRenderer.h Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit173] FileName=CD3D9ShaderMaterialRenderer.cpp Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit174] FileName=CD3D9ShaderMaterialRenderer.h Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit175] FileName=CD3D9Texture.cpp Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit176] FileName=CD3D9Texture.h Folder=Irrlicht/video/DirectX9 Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit177] FileName=CVideoModeList.cpp Folder=Irrlicht/video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit178] FileName=CVideoModeList.h Folder=Irrlicht/video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit179] FileName=C3DSMeshFileLoader.cpp Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit180] FileName=C3DSMeshFileLoader.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit181] FileName=CAnimatedMeshMD2.cpp Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit182] FileName=CAnimatedMeshMD2.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit183] FileName=CAnimatedMeshSceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit184] FileName=CAnimatedMeshSceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit185] FileName=CBillboardSceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit186] FileName=CBillboardSceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit187] FileName=CCameraSceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit188] FileName=CCameraSceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit189] FileName=CColladaFileLoader.cpp Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit190] FileName=CColladaFileLoader.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit191] FileName=CCSMLoader.cpp Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit192] FileName=CCSMLoader.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit193] FileName=CDMFLoader.cpp Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit194] FileName=CDMFLoader.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit195] FileName=CDummyTransformationSceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit196] FileName=CDummyTransformationSceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit197] FileName=CEmptySceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit198] FileName=CEmptySceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit199] FileName=CGeometryCreator.cpp Folder=Irrlicht/scene/mesh Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit200] FileName=CGeometryCreator.h Folder=Irrlicht/scene/mesh Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit201] FileName=CLightSceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit202] FileName=CLightSceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit203] FileName=CLMTSMeshFileLoader.cpp Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit204] FileName=CLMTSMeshFileLoader.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit205] FileName=CMeshManipulator.cpp Folder=Irrlicht/scene/mesh Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit206] FileName=CMeshManipulator.h Folder=Irrlicht/scene/mesh Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit207] FileName=CMeshSceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit208] FileName=CMeshSceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit209] FileName=CMetaTriangleSelector.cpp Folder=Irrlicht/scene/collision Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit210] FileName=CMetaTriangleSelector.h Folder=Irrlicht/scene/collision Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit211] FileName=CMY3DHelper.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit212] FileName=CMY3DMeshFileLoader.cpp Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit213] FileName=CMY3DMeshFileLoader.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit214] FileName=..\..\include\EGUIAlignment.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit215] FileName=COCTLoader.cpp Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit216] FileName=COCTLoader.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit217] FileName=COctreeSceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit218] FileName=COctreeSceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit219] FileName=COctreeTriangleSelector.cpp Folder=Irrlicht/scene/collision Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit220] FileName=COctreeTriangleSelector.h Folder=Irrlicht/scene/collision Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit221] FileName=CParticleBoxEmitter.cpp Folder=Irrlicht/scene/nodes/particles Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit222] FileName=CParticleBoxEmitter.h Folder=Irrlicht/scene/nodes/particles Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit223] FileName=CParticleFadeOutAffector.cpp Folder=Irrlicht/scene/nodes/particles Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit224] FileName=CParticleFadeOutAffector.h Folder=Irrlicht/scene/nodes/particles Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit225] FileName=CParticleGravityAffector.cpp Folder=Irrlicht/scene/nodes/particles Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit226] FileName=CParticleGravityAffector.h Folder=Irrlicht/scene/nodes/particles Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit227] FileName=CParticlePointEmitter.cpp Folder=Irrlicht/scene/nodes/particles Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit228] FileName=CParticlePointEmitter.h Folder=Irrlicht/scene/nodes/particles Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit229] FileName=CParticleSystemSceneNode.cpp Folder=Irrlicht/scene/nodes/particles Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit230] FileName=CParticleSystemSceneNode.h Folder=Irrlicht/scene/nodes/particles Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit231] FileName=CQ3LevelMesh.cpp Folder=Irrlicht/scene/mesh Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit232] FileName=CQ3LevelMesh.h Folder=Irrlicht/scene/mesh Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit233] FileName=CSceneCollisionManager.cpp Folder=Irrlicht/scene/collision Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit234] FileName=CSceneCollisionManager.h Folder=Irrlicht/scene/collision Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit235] FileName=CSceneManager.cpp Folder=Irrlicht/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit236] FileName=CSceneManager.h Folder=Irrlicht/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit237] FileName=CSceneNodeAnimatorCollisionResponse.cpp Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit238] FileName=CSceneNodeAnimatorCollisionResponse.h Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit239] FileName=CSceneNodeAnimatorDelete.cpp Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit240] FileName=CSceneNodeAnimatorDelete.h Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit241] FileName=CSceneNodeAnimatorFlyCircle.cpp Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit242] FileName=CSceneNodeAnimatorFlyCircle.h Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit243] FileName=CSceneNodeAnimatorFlyStraight.cpp Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit244] FileName=CSceneNodeAnimatorFlyStraight.h Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit245] FileName=CSceneNodeAnimatorFollowSpline.cpp Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit246] FileName=CSceneNodeAnimatorFollowSpline.h Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit247] FileName=CSceneNodeAnimatorRotation.cpp Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit248] FileName=CSceneNodeAnimatorRotation.h Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit249] FileName=CSceneNodeAnimatorTexture.cpp Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit250] FileName=CSceneNodeAnimatorTexture.h Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit251] FileName=CShadowVolumeSceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit252] FileName=CShadowVolumeSceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit253] FileName=CSkyBoxSceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit254] FileName=CSkyBoxSceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit255] FileName=COBJMeshFileLoader.cpp Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit256] FileName=COBJMeshFileLoader.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit257] FileName=CTerrainSceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit258] FileName=CTerrainSceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit259] FileName=CTerrainTriangleSelector.cpp Folder=Irrlicht/scene/collision Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit260] FileName=CTerrainTriangleSelector.h Folder=Irrlicht/scene/collision Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit261] FileName=CTextSceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit262] FileName=CTextSceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit263] FileName=CTriangleBBSelector.cpp Folder=Irrlicht/scene/collision Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit264] FileName=CTriangleBBSelector.h Folder=Irrlicht/scene/collision Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit265] FileName=CTriangleSelector.cpp Folder=Irrlicht/scene/collision Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit266] FileName=CTriangleSelector.h Folder=Irrlicht/scene/collision Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit267] FileName=CWaterSurfaceSceneNode.cpp Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit268] FileName=CWaterSurfaceSceneNode.h Folder=Irrlicht/scene/nodes Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit269] FileName=..\..\include\SExposedVideoData.h Folder=include/video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit270] FileName=..\..\include\SKeyMap.h Folder=include Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit271] FileName=..\..\include\SMeshBufferTangents.h Folder=include/video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit272] FileName=..\..\include\SParticle.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit273] FileName=CXMeshFileLoader.cpp Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit274] FileName=CXMeshFileLoader.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit275] FileName=Octree.h Folder=Irrlicht/scene/mesh Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit276] FileName=CFileList.cpp Folder=Irrlicht/io Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit277] FileName=CFileList.h Folder=Irrlicht/io Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit278] FileName=CFileSystem.cpp CompileCpp=1 Folder=Irrlicht/io Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit279] FileName=CFileSystem.h CompileCpp=1 Folder=Irrlicht/io Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit280] FileName=CLimitReadFile.cpp CompileCpp=1 Folder=Irrlicht/io/file Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit281] FileName=CLimitReadFile.h CompileCpp=1 Folder=Irrlicht/io/file Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit282] FileName=CMemoryFile.cpp Folder=Irrlicht/io/file Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit283] FileName=CMemoryFile.h Folder=Irrlicht/io/file Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit284] FileName=CReadFile.cpp Folder=Irrlicht/io/file Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit285] FileName=CReadFile.h Folder=Irrlicht/io/file Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit286] FileName=CWriteFile.cpp Folder=Irrlicht/io/file Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit287] FileName=CWriteFile.h Folder=Irrlicht/io/file Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit288] FileName=CXMLReader.cpp Folder=Irrlicht/io/xml Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit289] FileName=CXMLReader.h Folder=Irrlicht/io/xml Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit290] FileName=CXMLWriter.cpp Folder=Irrlicht/io/xml Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit291] FileName=CXMLWriter.h Folder=Irrlicht/io/xml Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit292] FileName=CZipReader.cpp Folder=Irrlicht/io/archive Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit293] FileName=CZipReader.h Folder=Irrlicht/io/archive Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit294] FileName=irrXML.cpp Folder=Irrlicht/io/xml Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit295] FileName=zlib\adler32.c Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit296] FileName=zlib\compress.c Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit297] FileName=zlib\crc32.c Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit298] FileName=zlib\crc32.h Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit299] FileName=zlib\deflate.c Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit300] FileName=zlib\deflate.h Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit301] FileName=zlib\inffast.c Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit302] FileName=zlib\inffast.h Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit303] FileName=zlib\inflate.c Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit304] FileName=zlib\inftrees.c Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit305] FileName=zlib\inftrees.h Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit306] FileName=zlib\trees.c Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit307] FileName=zlib\trees.h Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit308] FileName=zlib\uncompr.c Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit309] FileName=zlib\zconf.h Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit310] FileName=zlib\zlib.h Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit311] FileName=zlib\zutil.c Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit312] FileName=zlib\zutil.h Folder=Irrlicht/extern/zlib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit313] FileName=jpeglib\cderror.h Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit314] FileName=CSceneNodeAnimatorCameraFPS.h CompileCpp=1 Folder=Irrlicht/scene/animators Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit315] FileName=CSceneNodeAnimatorCameraMaya.cpp CompileCpp=1 Folder=Irrlicht/scene/animators Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit316] FileName=jpeglib\jcapimin.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit317] FileName=jpeglib\jcapistd.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit318] FileName=jpeglib\jccoefct.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit319] FileName=jpeglib\jccolor.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit320] FileName=jpeglib\jcdctmgr.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit321] FileName=jpeglib\jchuff.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit322] FileName=jpeglib\jchuff.h Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit323] FileName=jpeglib\jcinit.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit324] FileName=jpeglib\jcmainct.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit325] FileName=jpeglib\jcmarker.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit326] FileName=jpeglib\jcmaster.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit327] FileName=jpeglib\jcomapi.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit328] FileName=jpeglib\jconfig.h Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit329] FileName=jpeglib\jcparam.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit330] FileName=jpeglib\jcarith.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit331] FileName=jpeglib\jcprepct.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit332] FileName=jpeglib\jcsample.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit333] FileName=jpeglib\jctrans.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit334] FileName=jpeglib\jdapimin.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit335] FileName=jpeglib\jdapistd.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit336] FileName=jpeglib\jdatadst.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit337] FileName=jpeglib\jdatasrc.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit338] FileName=jpeglib\jdcoefct.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit339] FileName=jpeglib\jdcolor.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit340] FileName=jpeglib\jdct.h Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit341] FileName=jpeglib\jddctmgr.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit342] FileName=jpeglib\jdhuff.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit343] FileName=jpeglib\jdhuff.h Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit344] FileName=jpeglib\jdinput.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit345] FileName=jpeglib\jdmainct.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit346] FileName=jpeglib\jdmarker.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit347] FileName=jpeglib\jdmaster.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit348] FileName=jpeglib\jdmerge.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit349] FileName=jpeglib\jdarith.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit350] FileName=jpeglib\jdpostct.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit351] FileName=jpeglib\jdsample.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit352] FileName=jpeglib\jdtrans.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit353] FileName=jpeglib\jerror.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit354] FileName=jpeglib\jerror.h Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit355] FileName=jpeglib\jfdctflt.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit356] FileName=jpeglib\jfdctfst.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit357] FileName=jpeglib\jfdctint.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit358] FileName=jpeglib\jidctflt.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit359] FileName=jpeglib\jidctfst.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit360] FileName=jpeglib\jidctint.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit361] FileName=jpeglib\jaricom.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit362] FileName=jpeglib\jinclude.h Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit363] FileName=jpeglib\jmemmgr.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit364] FileName=jpeglib\jmemnobs.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit365] FileName=jpeglib\jmemsys.h Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit366] FileName=jpeglib\jmorecfg.h Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit367] FileName=jpeglib\jpegint.h Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit368] FileName=jpeglib\jpeglib.h Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit369] FileName=jpeglib\jquant1.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit370] FileName=jpeglib\jquant2.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit371] FileName=jpeglib\jutils.c Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit372] FileName=jpeglib\jversion.h Folder=Irrlicht/extern/jpeglib Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit373] FileName=CMD3MeshFileLoader.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit374] FileName=CMD3MeshFileLoader.cpp Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit375] FileName=CAnimatedMeshMD3.h Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit376] FileName=CAnimatedMeshMD3.cpp Folder=Irrlicht/scene/mesh/loaders Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit377] FileName=CGUISpriteBank.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit378] FileName=CGUISpriteBank.cpp Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit379] FileName=..\..\include\IGUIFontBitmap.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit380] FileName=..\..\include\IGUISpriteBank.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit381] FileName=COpenGLExtensionHandler.cpp Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit382] FileName=CGUISpinBox.h CompileCpp=1 Folder=Irrlicht/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit383] FileName=CGUISpinBox.cpp CompileCpp=1 Folder=Irrlicht/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit384] FileName=..\..\include\IGUISpinBox.h CompileCpp=1 Folder=include/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit385] FileName=..\..\include\SViewFrustum.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit386] FileName=..\..\include\triangle3d.h CompileCpp=1 Folder=include/core Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit387] FileName=libpng\png.c CompileCpp=0 Folder=Irrlicht/extern/libpng Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit388] FileName=libpng\png.h CompileCpp=1 Folder=Irrlicht/extern/libpng Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit389] FileName=libpng\pngconf.h CompileCpp=1 Folder=Irrlicht/extern/libpng Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit390] FileName=libpng\pngerror.c Folder=Irrlicht/extern/libpng Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit391] FileName=libpng\pngget.c CompileCpp=0 Folder=Irrlicht/extern/libpng Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit392] FileName=libpng\pngmem.c CompileCpp=0 Folder=Irrlicht/extern/libpng Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit393] FileName=libpng\pngpread.c CompileCpp=0 Folder=Irrlicht/extern/libpng Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit394] FileName=libpng\pngread.c CompileCpp=0 Folder=Irrlicht/extern/libpng Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit395] FileName=libpng\pngrio.c CompileCpp=0 Folder=Irrlicht/extern/libpng Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit396] FileName=libpng\pngrtran.c Folder=Irrlicht/extern/libpng Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit397] FileName=libpng\pngrutil.c Folder=Irrlicht/extern/libpng Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit398] FileName=libpng\pngset.c Folder=Irrlicht/extern/libpng Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit399] FileName=libpng\pngtrans.c Folder=Irrlicht/extern/libpng Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit400] FileName=libpng\pngwio.c Folder=Irrlicht/extern/libpng Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit401] FileName=libpng\pngwrite.c Folder=Irrlicht/extern/libpng Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit402] FileName=libpng\pngwtran.c Folder=Irrlicht/extern/libpng Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit403] FileName=libpng\pngwutil.c Folder=Irrlicht/extern/libpng Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit404] FileName=CIrrDeviceLinux.cpp Folder=Irrlicht/irr/IrrlichtDevice Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit405] FileName=CIrrDeviceLinux.h Folder=Irrlicht/irr/IrrlichtDevice Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit406] FileName=CIrrDeviceStub.cpp Folder=Irrlicht/irr/IrrlichtDevice Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit407] FileName=CIrrDeviceStub.h Folder=Irrlicht/irr/IrrlichtDevice Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit408] FileName=CIrrDeviceWin32.cpp Folder=Irrlicht/irr/IrrlichtDevice Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit409] FileName=CIrrDeviceWin32.h Folder=Irrlicht/irr/IrrlichtDevice Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit410] FileName=CLogger.cpp Folder=Irrlicht/irr Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit411] FileName=CLogger.h Folder=Irrlicht/irr Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit412] FileName=COSOperator.cpp Folder=Irrlicht/irr Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit413] FileName=COSOperator.h Folder=Irrlicht/irr Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit414] FileName=CTimer.h Folder=Irrlicht/irr Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit415] FileName=IImagePresenter.h Folder=Irrlicht/irr Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit416] FileName=Irrlicht.cpp Folder=Irrlicht/irr Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit417] FileName=os.cpp Folder=Irrlicht/irr Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit418] FileName=os.h Folder=Irrlicht/irr Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit419] FileName=..\..\include\IrrCompileConfig.h Folder=include Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit420] FileName=CMeshCache.h Folder=Irrlicht/scene/mesh Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit421] FileName=CMeshCache.cpp Folder=Irrlicht/scene/mesh Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit422] FileName=COpenGLSLMaterialRenderer.h Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit423] FileName=COpenGLSLMaterialRenderer.cpp Folder=Irrlicht/video/OpenGL Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit424] FileName=CSoftwareTexture2.h Folder=Irrlicht/video/Burning Video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit425] FileName=S4DVertex.h Folder=Irrlicht/video/Burning Video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit426] FileName=SoftwareDriver2_compile_config.h Folder=Irrlicht/video/Burning Video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit427] FileName=CSoftwareDriver2.h Folder=Irrlicht/video/Burning Video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit428] FileName=CTRTextureGouraudNoZ2.cpp Folder=Irrlicht/video/Burning Video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit429] FileName=CTRTextureLightMap2_M2.cpp Folder=Irrlicht/video/Burning Video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit430] FileName=CTRTextureLightMap2_M4.cpp Folder=Irrlicht/video/Burning Video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit431] FileName=CTRTextureLightMap2_M1.cpp Folder=Irrlicht/video/Burning Video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit432] FileName=SoftwareDriver2_helper.h Folder=Irrlicht/video/Burning Video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit433] FileName=CSoftwareDriver2.cpp Folder=Irrlicht/video/Burning Video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit434] FileName=CSoftwareTexture2.cpp Folder=Irrlicht/video/Burning Video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit435] FileName=CTRTextureGouraud2.cpp Folder=Irrlicht/video/Burning Video Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion=0.1 FileDescription=Developed using the Dev-C++ IDE InternalName= LegalCopyright= LegalTrademarks= OriginalFilename=Irrlicht.dll ProductName=Irrlicht ProductVersion=0.1 AutoIncBuildNr=0 [Unit436] FileName=COgreMeshFileLoader.h CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit437] FileName=COgreMeshFileLoader.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit438] FileName=CDefaultSceneNodeFactory.h CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit439] FileName=CDefaultSceneNodeAnimatorFactory.cpp CompileCpp=1 Folder=Irrlicht/scene/animators Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit440] FileName=CDefaultSceneNodeAnimatorFactory.h CompileCpp=1 Folder=Irrlicht/scene/animators Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit441] FileName=CDefaultSceneNodeFactory.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit442] FileName=CAttributes.h CompileCpp=1 Folder=Irrlicht/io/attributes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit443] FileName=CAttributeImpl.h CompileCpp=1 Folder=Irrlicht/io/attributes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit444] FileName=CAttributes.cpp CompileCpp=1 Folder=Irrlicht/io/attributes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit445] FileName=CCubeSceneNode.h CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit446] FileName=CCubeSceneNode.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit447] FileName=CTRTextureGouraudAddNoZ2.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit448] FileName=CTRTextureGouraudAdd2.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit449] FileName=CTRGouraud2.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit450] FileName=CTRGouraudAlpha2.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit451] FileName=CTRGouraudAlphaNoZ2.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit452] FileName=CTRTextureDetailMap2.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit453] FileName=CTRTextureLightMap2_Add.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit454] FileName=CTRTextureWire2.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit455] FileName=CTRTextureGouraudVertexAlpha2.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit456] FileName=..\..\changes.txt CompileCpp=1 Folder=doc Compile=0 Link=0 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit457] FileName=..\..\readme.txt CompileCpp=1 Folder=doc Compile=0 Link=0 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit458] FileName=CSphereSceneNode.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit459] FileName=CSphereSceneNode.h CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit460] FileName=CPakReader.h CompileCpp=1 Folder=Irrlicht/io/archive Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit461] FileName=CPakReader.cpp CompileCpp=1 Folder=Irrlicht/io/archive Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit462] FileName=CSkyDomeSceneNode.h CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit463] FileName=CSkyDomeSceneNode.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit464] FileName=CImageWriterTGA.h CompileCpp=1 Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit465] FileName=CImageWriterBMP.cpp CompileCpp=1 Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit466] FileName=CImageWriterBMP.h CompileCpp=1 Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit467] FileName=CImageWriterJPG.cpp CompileCpp=1 Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit468] FileName=CImageWriterJPG.h CompileCpp=1 Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit469] FileName=CImageWriterPCX.cpp CompileCpp=1 Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit470] FileName=CImageWriterPCX.h CompileCpp=1 Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit471] FileName=CImageWriterPNG.cpp Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= CompileCpp=1 [Unit472] FileName=CImageWriterPNG.h Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= CompileCpp=1 [Unit473] FileName=CImageWriterPPM.cpp CompileCpp=1 Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit474] FileName=CImageWriterPPM.h CompileCpp=1 Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit475] FileName=CImageWriterPSD.cpp CompileCpp=1 Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit476] FileName=CImageWriterPSD.h CompileCpp=1 Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit477] FileName=CImageWriterTGA.cpp CompileCpp=1 Folder=Irrlicht/video/Null/Writer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit478] FileName=CTRTextureLightMapGouraud2_M4.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit479] FileName=CGUIColorSelectDialog.cpp CompileCpp=1 Folder=Irrlicht/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit480] FileName=IBurningShader.h CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit481] FileName=IBurningShader.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit482] FileName=IDepthBuffer.h CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit483] FileName=CDepthBuffer.h CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit484] FileName=CDepthBuffer.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit485] FileName=CQuake3ShaderSceneNode.h CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit486] FileName=CQuake3ShaderSceneNode.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit487] FileName=..\..\include\fast_atof.h CompileCpp=1 Folder=include Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit488] FileName=CTRTextureBlend.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit489] FileName=CTRTextureGouraudAlpha.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit490] FileName=CTRTextureGouraudAlphaNoZ.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit491] FileName=CDefaultGUIElementFactory.cpp CompileCpp=1 Folder=Irrlicht/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit492] FileName=CDefaultGUIElementFactory.h CompileCpp=1 Folder=Irrlicht/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit493] FileName=CGUIColorSelectDialog.h CompileCpp=1 Folder=Irrlicht/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit494] FileName=CSoftware2MaterialRenderer.h CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit495] FileName=CXMLReaderImpl.h CompileCpp=1 Folder=Irrlicht/io/xml Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit496] FileName=ITriangleRenderer.h CompileCpp=1 Folder=Irrlicht/video/Software Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit497] FileName=..\..\include\EGUIElementTypes.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit498] FileName=..\..\include\ESceneNodeAnimatorTypes.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit499] FileName=..\..\include\ESceneNodeTypes.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit500] FileName=..\..\include\ETerrainElements.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit501] FileName=..\..\include\IAnimatedMeshMD2.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit502] FileName=..\..\include\IAttributeExchangingObject.h CompileCpp=1 Folder=include/io Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit503] FileName=..\..\include\IAttributes.h CompileCpp=1 Folder=include/io Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit504] FileName=..\..\include\IDummyTransformationSceneNode.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit505] FileName=..\..\include\IGPUProgrammingServices.h CompileCpp=1 Folder=include/video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit506] FileName=..\..\include\IGUIColorSelectDialog.h CompileCpp=1 Folder=include/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit507] FileName=..\..\include\IGUIComboBox.h CompileCpp=1 Folder=include/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit508] FileName=..\..\include\IGUIContextMenu.h CompileCpp=1 Folder=include/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit509] FileName=..\..\include\IGUIEditBox.h CompileCpp=1 Folder=include/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit510] FileName=..\..\include\IGUIElementFactory.h CompileCpp=1 Folder=include/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit511] FileName=..\..\include\IGUIInOutFader.h CompileCpp=1 Folder=include/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit512] FileName=..\..\include\IGUIStaticText.h CompileCpp=1 Folder=include/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit513] FileName=..\..\include\IGUITabControl.h CompileCpp=1 Folder=include/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit514] FileName=..\..\include\IGUIToolbar.h CompileCpp=1 Folder=include/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit515] FileName=..\..\include\IImage.h CompileCpp=1 Folder=include/video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit516] FileName=..\..\include\IImageLoader.h CompileCpp=1 Folder=include/video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit517] FileName=..\..\include\IImageWriter.h CompileCpp=1 Folder=include/video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit518] FileName=..\..\include\ILogger.h CompileCpp=1 Folder=include/io Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit519] FileName=..\..\include\IMaterialRenderer.h CompileCpp=1 Folder=include/video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit520] FileName=..\..\include\IMaterialRendererServices.h CompileCpp=1 Folder=include/video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit521] FileName=..\..\include\IMeshCache.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit522] FileName=..\..\include\IMeshLoader.h CompileCpp=1 Folder=include/io Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit523] FileName=..\..\include\IMeshManipulator.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit524] FileName=..\..\include\IMeshSceneNode.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit525] FileName=..\..\include\IMetaTriangleSelector.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit526] FileName=..\..\include\IOSOperator.h CompileCpp=1 Folder=include/io Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit527] FileName=..\..\include\IParticleAffector.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit528] FileName=..\..\include\IParticleEmitter.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit529] FileName=..\..\include\IParticleSystemSceneNode.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit530] FileName=..\..\include\IQ3Shader.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit531] FileName=..\..\include\irrAllocator.h CompileCpp=1 Folder=include/core Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit532] FileName=..\..\include\irrMap.h CompileCpp=1 Folder=include/core Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit533] FileName=..\..\include\irrXML.h CompileCpp=1 Folder=include/io Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit534] FileName=..\..\include\ISceneCollisionManager.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit535] FileName=..\..\include\ISceneNodeAnimatorCollisionResponse.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit536] FileName=..\..\include\ISceneNodeAnimatorFactory.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit537] FileName=..\..\include\ISceneNodeFactory.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit538] FileName=..\..\include\ISceneUserDataSerializer.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit539] FileName=..\..\include\IShaderConstantSetCallBack.h CompileCpp=1 Folder=include/video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit540] FileName=..\..\include\IShadowVolumeSceneNode.h CompileCpp=1 Folder=include/video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit541] FileName=..\..\include\ITerrainSceneNode.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit542] FileName=..\..\include\ITextSceneNode.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit543] FileName=..\..\include\ITimer.h CompileCpp=1 Folder=include Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit544] FileName=..\..\include\ITriangleSelector.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit545] FileName=..\..\include\IVideoModeList.h CompileCpp=1 Folder=include/video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit546] FileName=..\..\include\IWriteFile.h CompileCpp=1 Folder=include/io Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit547] FileName=..\..\include\IXMLReader.h CompileCpp=1 Folder=include/io Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit548] FileName=..\..\include\IXMLWriter.h CompileCpp=1 Folder=include/io Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit549] FileName=..\..\include\quaternion.h CompileCpp=1 Folder=include/core Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit550] FileName=..\..\include\SAnimatedMesh.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit551] FileName=..\..\include\SceneParameters.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit552] FileName=..\..\include\IReferenceCounted.h CompileCpp=1 Folder=include Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit553] FileName=CParticleAnimatedMeshSceneNodeEmitter.h CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit554] FileName=CParticleAnimatedMeshSceneNodeEmitter.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit555] FileName=CParticleSphereEmitter.h CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit556] FileName=CParticleAttractionAffector.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit557] FileName=CParticleAttractionAffector.h CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit558] FileName=CParticleCylinderEmitter.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit559] FileName=CParticleCylinderEmitter.h CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit560] FileName=CParticleMeshEmitter.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit561] FileName=CParticleMeshEmitter.h CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit562] FileName=CParticleRingEmitter.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit563] FileName=CParticleRingEmitter.h CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit564] FileName=CParticleRotationAffector.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit565] FileName=CParticleRotationAffector.h CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit566] FileName=CParticleSphereEmitter.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes/particles Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit567] FileName=CIrrMeshWriter.h CompileCpp=1 Folder=Irrlicht/scene/mesh/writers Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit568] FileName=CIrrMeshWriter.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/writers Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit569] FileName=CColladaMeshWriter.h CompileCpp=1 Folder=Irrlicht/scene/mesh/writers Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit570] FileName=CColladaMeshWriter.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/writers Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit571] FileName=CIrrMeshFileLoader.h CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit572] FileName=CIrrMeshFileLoader.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit573] FileName=CBSPMeshFileLoader.h CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit574] FileName=CBSPMeshFileLoader.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit575] FileName=CMD2MeshFileLoader.h CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit576] FileName=CMD2MeshFileLoader.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit577] FileName=CMS3DMeshFileLoader.h CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit578] FileName=CMS3DMeshFileLoader.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit579] FileName=CB3DMeshFileLoader.h CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit580] FileName=CB3DMeshFileLoader.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit581] FileName=CSkinnedMesh.h CompileCpp=1 Folder=Irrlicht/scene/mesh Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit582] FileName=CSkinnedMesh.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit583] FileName=CBoneSceneNode.h CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit584] FileName=CBoneSceneNode.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit585] FileName=CSTLMeshWriter.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/writers Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit586] FileName=CSTLMeshFileLoader.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit587] FileName=CImageLoaderPPM.cpp CompileCpp=1 Folder=Irrlicht/video/Null/Loader Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit588] FileName=CImageLoaderPPM.h CompileCpp=1 Folder=Irrlicht/video/Null/Loader Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit589] FileName=CBurningShader_Raster_Reference.cpp CompileCpp=1 Folder=Irrlicht/video/Burning Video Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit590] FileName=CImageLoaderWAL.cpp CompileCpp=1 Folder=Irrlicht/video/Null/Loader Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit591] FileName=CImageLoaderWAL.h Folder=Irrlicht/video/Null/Loader Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit592] FileName=CGUITable.h Folder=Irrlicht/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit593] FileName=CGUITable.cpp CompileCpp=1 Folder=Irrlicht/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit594] FileName=..\..\include\IGUITable.h Folder=include/gui Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit595] FileName=CVolumeLightSceneNode.h CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit596] FileName=CVolumeLightSceneNode.cpp CompileCpp=1 Folder=Irrlicht/scene/nodes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit597] FileName=..\..\include\IVolumeLightSceneNode.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit598] FileName=CLWOMeshFileLoader.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit599] FileName=CLWOMeshFileLoader.h CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit600] FileName=..\..\include\ISceneNodeAnimatorCameraMaya.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit601] FileName=..\..\include\ISceneNodeAnimatorCameraFPS.h CompileCpp=1 Folder=include/scene Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit602] FileName=CSceneNodeAnimatorCameraMaya.h Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit603] FileName=CSceneNodeAnimatorCameraFPS.cpp Folder=Irrlicht/scene/animators Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit604] FileName=COBJMeshWriter.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/writers Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit605] FileName=..\..\include\SSkinMeshBuffer.h Folder=include/scene Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit606] FileName=CParticleScaleAffector.cpp Folder=Irrlicht/scene/nodes/particles Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit607] FileName=CParticleScaleAffector.h Folder=Irrlicht/scene/nodes/particles Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit608] FileName=CGUIImageList.cpp CompileCpp=1 Folder=Irrlicht/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit609] FileName=CGUIImageList.h CompileCpp=1 Folder=Irrlicht/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit610] FileName=CGUITreeView.cpp CompileCpp=1 Folder=Irrlicht/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit611] FileName=CGUITreeView.h CompileCpp=1 Folder=Irrlicht/gui Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit612] FileName=CIrrDeviceConsole.cpp CompileCpp=1 Folder=Irrlicht/irr/IrrlichtDevice Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit613] FileName=CIrrDeviceConsole.h CompileCpp=1 Folder=Irrlicht/irr/IrrlichtDevice Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit614] FileName=CPLYMeshWriter.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/writers Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit615] FileName=CPLYMeshWriter.h CompileCpp=1 Folder=Irrlicht/scene/mesh/writers Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit616] FileName=CPLYMeshFileLoader.cpp CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit617] FileName=CPLYMeshFileLoader.h CompileCpp=1 Folder=Irrlicht/scene/mesh/loaders Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit618] FileName=CIrrDeviceSDL.cpp CompileCpp=1 Folder=Irrlicht/irr/IrrlichtDevice Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit619] FileName=CIrrDeviceSDL.h CompileCpp=1 Folder=Irrlicht/irr/IrrlichtDevice Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit620] FileName=CImageLoaderRGB.cpp CompileCpp=1 Folder=Irrlicht/video/Null/Loader Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit621] FileName=CImageLoaderRGB.h CompileCpp=1 Folder=Irrlicht/video/Null/Loader Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit622] FileName=CTarReader.cpp Folder=Irrlicht/io/archive Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit623] FileName=CTarReader.h Folder=Irrlicht/io/archive Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit624] FileName=CMountPointReader.cpp Folder=Irrlicht/io/archive Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit625] FileName=CMountPointReader.h Folder=Irrlicht/io/archive Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit626] FileName=CNPKReader.h CompileCpp=1 Folder=Irrlicht/io/archive Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit627] FileName=CNPKReader.cpp CompileCpp=1 Folder=Irrlicht/io/archive Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit628] FileName=..\..\include\EAttributes.h CompileCpp=1 Folder=include/io Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit629] FileName=IAttribute.h CompileCpp=1 Folder=Irrlicht/io/attributes Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit630] FileName=aesGladman\aes.h Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit631] FileName=aesGladman\aescrypt.cpp Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit632] FileName=aesGladman\aeskey.cpp Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit633] FileName=aesGladman\aesopt.h Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit634] FileName=aesGladman\aestab.cpp Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit635] FileName=aesGladman\sha2.h Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit636] FileName=aesGladman\fileenc.cpp Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit637] FileName=aesGladman\fileenc.h Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit638] FileName=aesGladman\hmac.cpp Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit639] FileName=aesGladman\hmac.h Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit640] FileName=aesGladman\prng.cpp Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit641] FileName=aesGladman\prng.h Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit642] FileName=aesGladman\pwd2key.cpp Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit643] FileName=aesGladman\pwd2key.h Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit644] FileName=aesGladman\sha1.cpp Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit645] FileName=aesGladman\sha1.h Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit646] FileName=aesGladman\sha2.cpp Folder=Irrlicht/extern/aesGladman Compile=1 CompileCpp=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit647] FileName=bzip2\blocksort.c Folder=Irrlicht/extern/bzip2 Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit648] FileName=bzip2\bzcompress.c Folder=Irrlicht/extern/bzip2 Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit649] FileName=bzip2\bzlib.c Folder=Irrlicht/extern/bzip2 Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit650] FileName=bzip2\bzlib.h Folder=Irrlicht/extern/bzip2 Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit651] FileName=bzip2\bzlib_private.h Folder=Irrlicht/extern/bzip2 Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit652] FileName=bzip2\crctable.c Folder=Irrlicht/extern/bzip2 Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit653] FileName=bzip2\decompress.c Folder=Irrlicht/extern/bzip2 Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit654] FileName=bzip2\huffman.c Folder=Irrlicht/extern/bzip2 Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit655] FileName=bzip2\randtable.c Folder=Irrlicht/extern/bzip2 Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit656] FileName=lzma\LzmaDec.c Folder=Irrlicht/extern Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit657] FileName=lzma\LzmaDec.h Folder=Irrlicht/extern Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit658] FileName=lzma\Types.h Folder=Irrlicht/extern Compile=1 CompileCpp=0 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= irrlicht-1.8.3/source/Irrlicht/Irrlicht.cpp0000644000000000000000000000772312574354552017432 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" static const char* const copyright = "Irrlicht Engine (c) 2002-2012 Nikolaus Gebhardt"; #ifdef _IRR_WINDOWS_ #include #if defined(_DEBUG) && !defined(__GNUWIN32__) && !defined(_WIN32_WCE) #include #endif // _DEBUG #endif #include "irrlicht.h" #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ #include "CIrrDeviceWin32.h" #endif #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ #include "MacOSX/CIrrDeviceMacOSX.h" #endif #ifdef _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ #include "CIrrDeviceWinCE.h" #endif #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ #include "CIrrDeviceLinux.h" #endif #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ #include "CIrrDeviceSDL.h" #endif #ifdef _IRR_COMPILE_WITH_FB_DEVICE_ #include "CIrrDeviceFB.h" #endif #ifdef _IRR_COMPILE_WITH_CONSOLE_DEVICE_ #include "CIrrDeviceConsole.h" #endif namespace irr { //! stub for calling createDeviceEx IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDevice(video::E_DRIVER_TYPE driverType, const core::dimension2d& windowSize, u32 bits, bool fullscreen, bool stencilbuffer, bool vsync, IEventReceiver* res) { SIrrlichtCreationParameters p; p.DriverType = driverType; p.WindowSize = windowSize; p.Bits = (u8)bits; p.Fullscreen = fullscreen; p.Stencilbuffer = stencilbuffer; p.Vsync = vsync; p.EventReceiver = res; return createDeviceEx(p); } extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx(const SIrrlichtCreationParameters& params) { IrrlichtDevice* dev = 0; #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ if (params.DeviceType == EIDT_WIN32 || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceWin32(params); #endif #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ if (params.DeviceType == EIDT_OSX || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceMacOSX(params); #endif #ifdef _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ if (params.DeviceType == EIDT_WINCE || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceWinCE(params); #endif #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ if (params.DeviceType == EIDT_X11 || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceLinux(params); #endif #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ if (params.DeviceType == EIDT_SDL || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceSDL(params); #endif #ifdef _IRR_COMPILE_WITH_FB_DEVICE_ if (params.DeviceType == EIDT_FRAMEBUFFER || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceFB(params); #endif #ifdef _IRR_COMPILE_WITH_CONSOLE_DEVICE_ if (params.DeviceType == EIDT_CONSOLE || (!dev && params.DeviceType == EIDT_BEST)) dev = new CIrrDeviceConsole(params); #endif if (dev && !dev->getVideoDriver() && params.DriverType != video::EDT_NULL) { dev->closeDevice(); // destroy window dev->run(); // consume quit message dev->drop(); dev = 0; } return dev; } namespace core { const matrix4 IdentityMatrix(matrix4::EM4CONST_IDENTITY); irr::core::stringc LOCALE_DECIMAL_POINTS("."); } namespace video { SMaterial IdentityMaterial; } } // end namespace irr #if defined(_IRR_WINDOWS_API_) BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { // _crtBreakAlloc = 139; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: #if defined(_DEBUG) && !defined(__GNUWIN32__) && !defined(__BORLANDC__) && !defined (_WIN32_WCE) && !defined (_IRR_XBOX_PLATFORM_) _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF); #endif break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } #endif // defined(_IRR_WINDOWS_) irrlicht-1.8.3/source/Irrlicht/Irrlicht.aps0000644000000000000000000017024412574354552017432 0ustar rootroot ÿÿÿÿL$HWBÿÿ4ïE:\official_irrlicht_windows\irrlicht\trunk\source\Irrlicht\Irrlicht.rc 4TEXTINCLUDEÿÿ0resource.h4TEXTINCLUDEÿÿ0#include "windows.h" 4TEXTINCLUDEÿÿ0 ì ÿÿÿÿ0ì4VS_VERSION_INFO½ïþ?LStringFileInfo(040704b0<CompanyNameIrrlicht TeamNFileDescriptionIrrlicht 3d engine,FileVersionr3526: InternalNameIrrlicht.dllTLegalCopyrightCopyright (C) 2003-2011B OriginalFilenameIrrlicht.dllFProductNameIrrlicht 3d engine< ProductVersion1.8.0.alphaDVarFileInfo$Translation°Ôà$HWBÿÿÈ0!!resource.h_APS_NEXT_RESOURCE_VALUE101 _APS_NEXT_COMMAND_VALUE40001 _APS_NEXT_CONTROL_VALUE1001 _APS_NEXT_SYMED_VALUE101 !!windows.h!sdkddkver.h_WIN32_WINNT_NT40x0400_WIN32_WINNT_WIN2K0x0500_WIN32_WINNT_WINXP0x0501 _WIN32_WINNT_WS030x0502!_WIN32_WINNT_WIN60x0600"_WIN32_WINNT_VISTA0x0600#_WIN32_WINNT_WS080x0600$_WIN32_WINNT_LONGHORN0x0600%_WIN32_WINNT_WIN70x0601&_WIN32_IE_IE200x0200+_WIN32_IE_IE300x0300,_WIN32_IE_IE3020x0302-_WIN32_IE_IE400x0400._WIN32_IE_IE4010x0401/_WIN32_IE_IE500x05000_WIN32_IE_IE5010x05011_WIN32_IE_IE550x05502_WIN32_IE_IE600x06003_WIN32_IE_IE60SP10x06014_WIN32_IE_IE60SP20x06035_WIN32_IE_IE700x07006_WIN32_IE_IE800x08007_WIN32_IE_NT4_WIN32_IE_IE20=_WIN32_IE_NT4SP1_WIN32_IE_IE20>_WIN32_IE_NT4SP2_WIN32_IE_IE20?_WIN32_IE_NT4SP3_WIN32_IE_IE302@_WIN32_IE_NT4SP4_WIN32_IE_IE401A_WIN32_IE_NT4SP5_WIN32_IE_IE401B_WIN32_IE_NT4SP6_WIN32_IE_IE50C_WIN32_IE_WIN98_WIN32_IE_IE401E_WIN32_IE_WIN98SE_WIN32_IE_IE50G_WIN32_IE_WINME_WIN32_IE_IE55I_WIN32_IE_WIN2K_WIN32_IE_IE501K_WIN32_IE_WIN2KSP1_WIN32_IE_IE501L_WIN32_IE_WIN2KSP2_WIN32_IE_IE501M_WIN32_IE_WIN2KSP3_WIN32_IE_IE501N_WIN32_IE_WIN2KSP4_WIN32_IE_IE501O_WIN32_IE_XP_WIN32_IE_IE60P_WIN32_IE_XPSP1_WIN32_IE_IE60SP1Q_WIN32_IE_XPSP2_WIN32_IE_IE60SP2R_WIN32_IE_WS030x0602S_WIN32_IE_WS03SP1_WIN32_IE_IE60SP2T_WIN32_IE_WIN6_WIN32_IE_IE70U_WIN32_IE_LONGHORN_WIN32_IE_IE70V_WIN32_IE_WIN7_WIN32_IE_IE80WNTDDI_WIN2K0x05000000]NTDDI_WIN2KSP10x05000100^NTDDI_WIN2KSP20x05000200_NTDDI_WIN2KSP30x05000300`NTDDI_WIN2KSP40x05000400aNTDDI_WINXP0x05010000cNTDDI_WINXPSP10x05010100dNTDDI_WINXPSP20x05010200eNTDDI_WINXPSP30x05010300fNTDDI_WINXPSP40x05010400gNTDDI_WS030x05020000iNTDDI_WS03SP10x05020100jNTDDI_WS03SP20x05020200kNTDDI_WS03SP30x05020300lNTDDI_WS03SP40x05020400mNTDDI_WIN60x06000000oNTDDI_WIN6SP10x06000100pNTDDI_WIN6SP20x06000200qNTDDI_WIN6SP30x06000300rNTDDI_WIN6SP40x06000400sNTDDI_VISTANTDDI_WIN6uNTDDI_VISTASP1NTDDI_WIN6SP1vNTDDI_VISTASP2NTDDI_WIN6SP2wNTDDI_VISTASP3NTDDI_WIN6SP3xNTDDI_VISTASP4NTDDI_WIN6SP4yNTDDI_LONGHORNNTDDI_VISTA{NTDDI_WS08NTDDI_WIN6SP1}NTDDI_WS08SP2NTDDI_WIN6SP2~NTDDI_WS08SP3NTDDI_WIN6SP3NTDDI_WS08SP4NTDDI_WIN6SP4€NTDDI_WIN70x06010000‚OSVERSION_MASK0xFFFF0000‡SPVERSION_MASK0x0000FF00ˆSUBVERSION_MASK0x000000FF‰PSAPI_VERSION1À_WIN32_WINNT0x0601ÅNTDDI_VERSIONNTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT)ËWINVER_WIN32_WINNTÔ_WIN32_IE0x0800æ!!winresrc.h_WIN32_WINDOWS0x0410!winuser.rhRT_MANIFEST24CREATEPROCESS_MANIFEST_RESOURCE_ID1ISOLATIONAWARE_MANIFEST_RESOURCE_ID2ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID3MINIMUM_RESERVED_MANIFEST_RESOURCE_ID1MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID16SW_HIDE0SW_SHOWNORMAL1SW_NORMAL1SW_SHOWMINIMIZED2 SW_SHOWMAXIMIZED3!SW_MAXIMIZE3"SW_SHOWNOACTIVATE4#SW_SHOW5$SW_MINIMIZE6%SW_SHOWMINNOACTIVE7&SW_SHOWNA8'SW_RESTORE9(SW_SHOWDEFAULT10)SW_FORCEMINIMIZE11*SW_MAX11+HIDE_WINDOW01SHOW_OPENWINDOW12SHOW_ICONWINDOW23SHOW_FULLSCREEN34SHOW_OPENNOACTIVATE45SW_PARENTCLOSING1:SW_OTHERZOOM2;SW_PARENTOPENING3<SW_OTHERUNZOOM4=VK_LBUTTON0x01CVK_RBUTTON0x02DVK_CANCEL0x03EVK_MBUTTON0x04FVK_XBUTTON10x05IVK_XBUTTON20x06JVK_BACK0x08QVK_TAB0x09RVK_CLEAR0x0CXVK_RETURN0x0DYVK_SHIFT0x10[VK_CONTROL0x11\VK_MENU0x12]VK_PAUSE0x13^VK_CAPITAL0x14_VK_KANA0x15aVK_HANGEUL0x15bVK_HANGUL0x15cVK_JUNJA0x17dVK_FINAL0x18eVK_HANJA0x19fVK_KANJI0x19gVK_ESCAPE0x1BiVK_CONVERT0x1CkVK_NONCONVERT0x1DlVK_ACCEPT0x1EmVK_MODECHANGE0x1FnVK_SPACE0x20pVK_PRIOR0x21qVK_NEXT0x22rVK_END0x23sVK_HOME0x24tVK_LEFT0x25uVK_UP0x26vVK_RIGHT0x27wVK_DOWN0x28xVK_SELECT0x29yVK_PRINT0x2AzVK_EXECUTE0x2B{VK_SNAPSHOT0x2C|VK_INSERT0x2D}VK_DELETE0x2E~VK_HELP0x2FVK_LWIN0x5B‡VK_RWIN0x5CˆVK_APPS0x5D‰VK_SLEEP0x5FVK_NUMPAD00x60‘VK_NUMPAD10x61’VK_NUMPAD20x62“VK_NUMPAD30x63”VK_NUMPAD40x64•VK_NUMPAD50x65–VK_NUMPAD60x66—VK_NUMPAD70x67˜VK_NUMPAD80x68™VK_NUMPAD90x69šVK_MULTIPLY0x6A›VK_ADD0x6BœVK_SEPARATOR0x6CVK_SUBTRACT0x6DžVK_DECIMAL0x6EŸVK_DIVIDE0x6F VK_F10x70¡VK_F20x71¢VK_F30x72£VK_F40x73¤VK_F50x74¥VK_F60x75¦VK_F70x76§VK_F80x77¨VK_F90x78©VK_F100x79ªVK_F110x7A«VK_F120x7B¬VK_F130x7C­VK_F140x7D®VK_F150x7E¯VK_F160x7F°VK_F170x80±VK_F180x81²VK_F190x82³VK_F200x83´VK_F210x84µVK_F220x85¶VK_F230x86·VK_F240x87¸VK_NUMLOCK0x90¾VK_SCROLL0x91¿VK_OEM_NEC_EQUAL0x92ÄVK_OEM_FJ_JISHO0x92ÉVK_OEM_FJ_MASSHOU0x93ÊVK_OEM_FJ_TOUROKU0x94ËVK_OEM_FJ_LOYA0x95ÌVK_OEM_FJ_ROYA0x96ÍVK_LSHIFT0xA0ØVK_RSHIFT0xA1ÙVK_LCONTROL0xA2ÚVK_RCONTROL0xA3ÛVK_LMENU0xA4ÜVK_RMENU0xA5ÝVK_BROWSER_BACK0xA6àVK_BROWSER_FORWARD0xA7áVK_BROWSER_REFRESH0xA8âVK_BROWSER_STOP0xA9ãVK_BROWSER_SEARCH0xAAäVK_BROWSER_FAVORITES0xABåVK_BROWSER_HOME0xACæVK_VOLUME_MUTE0xADèVK_VOLUME_DOWN0xAEéVK_VOLUME_UP0xAFêVK_MEDIA_NEXT_TRACK0xB0ëVK_MEDIA_PREV_TRACK0xB1ìVK_MEDIA_STOP0xB2íVK_MEDIA_PLAY_PAUSE0xB3îVK_LAUNCH_MAIL0xB4ïVK_LAUNCH_MEDIA_SELECT0xB5ðVK_LAUNCH_APP10xB6ñVK_LAUNCH_APP20xB7òVK_OEM_10xBAúVK_OEM_PLUS0xBBûVK_OEM_COMMA0xBCüVK_OEM_MINUS0xBDýVK_OEM_PERIOD0xBEþVK_OEM_20xBFÿVK_OEM_30xC0VK_OEM_40xDB VK_OEM_50xDC VK_OEM_60xDD VK_OEM_70xDE VK_OEM_80xDFVK_OEM_AX0xE1VK_OEM_1020xE2VK_ICO_HELP0xE3VK_ICO_000xE4VK_PROCESSKEY0xE5VK_ICO_CLEAR0xE6 VK_PACKET0xE7$VK_OEM_RESET0xE9.VK_OEM_JUMP0xEA/VK_OEM_PA10xEB0VK_OEM_PA20xEC1VK_OEM_PA30xED2VK_OEM_WSCTRL0xEE3VK_OEM_CUSEL0xEF4VK_OEM_ATTN0xF05VK_OEM_FINISH0xF16VK_OEM_COPY0xF27VK_OEM_AUTO0xF38VK_OEM_ENLW0xF49VK_OEM_BACKTAB0xF5:VK_ATTN0xF6<VK_CRSEL0xF7=VK_EXSEL0xF8>VK_EREOF0xF9?VK_PLAY0xFA@VK_ZOOM0xFBAVK_NONAME0xFCBVK_PA10xFDCVK_OEM_CLEAR0xFEDWM_NULL0x0000OWM_CREATE0x0001PWM_DESTROY0x0002QWM_MOVE0x0003RWM_SIZE0x0005SWM_ACTIVATE0x0006UWA_INACTIVE0YWA_ACTIVE1ZWA_CLICKACTIVE2[WM_SETFOCUS0x0007]WM_KILLFOCUS0x0008^WM_ENABLE0x000A_WM_SETREDRAW0x000B`WM_SETTEXT0x000CaWM_GETTEXT0x000DbWM_GETTEXTLENGTH0x000EcWM_PAINT0x000FdWM_CLOSE0x0010eWM_QUERYENDSESSION0x0011gWM_QUERYOPEN0x0013hWM_ENDSESSION0x0016iWM_QUIT0x0012kWM_ERASEBKGND0x0014lWM_SYSCOLORCHANGE0x0015mWM_SHOWWINDOW0x0018nWM_WININICHANGE0x001AoWM_SETTINGCHANGEWM_WININICHANGEqWM_DEVMODECHANGE0x001BuWM_ACTIVATEAPP0x001CvWM_FONTCHANGE0x001DwWM_TIMECHANGE0x001ExWM_CANCELMODE0x001FyWM_SETCURSOR0x0020zWM_MOUSEACTIVATE0x0021{WM_CHILDACTIVATE0x0022|WM_QUEUESYNC0x0023}WM_GETMINMAXINFO0x0024WM_PAINTICON0x0026€WM_ICONERASEBKGND0x0027WM_NEXTDLGCTL0x0028‚WM_SPOOLERSTATUS0x002AƒWM_DRAWITEM0x002B„WM_MEASUREITEM0x002C…WM_DELETEITEM0x002D†WM_VKEYTOITEM0x002E‡WM_CHARTOITEM0x002FˆWM_SETFONT0x0030‰WM_GETFONT0x0031ŠWM_SETHOTKEY0x0032‹WM_GETHOTKEY0x0033ŒWM_QUERYDRAGICON0x0037WM_COMPAREITEM0x0039ŽWM_GETOBJECT0x003D‘WM_COMPACTING0x0041”WM_COMMNOTIFY0x0044•WM_WINDOWPOSCHANGING0x0046–WM_WINDOWPOSCHANGED0x0047—WM_POWER0x0048™PWR_OK1PWR_FAIL(-1)žPWR_SUSPENDREQUEST1ŸPWR_SUSPENDRESUME2 PWR_CRITICALRESUME3¡WM_COPYDATA0x004A£WM_CANCELJOURNAL0x004B¤WM_NOTIFY0x004E¨WM_INPUTLANGCHANGEREQUEST0x0050©WM_INPUTLANGCHANGE0x0051ªWM_TCARD0x0052«WM_HELP0x0053¬WM_USERCHANGED0x0054­WM_NOTIFYFORMAT0x0055®NFR_ANSI1°NFR_UNICODE2±NF_QUERY3²NF_REQUERY4³WM_CONTEXTMENU0x007BµWM_STYLECHANGING0x007C¶WM_STYLECHANGED0x007D·WM_DISPLAYCHANGE0x007E¸WM_GETICON0x007F¹WM_SETICON0x0080ºWM_NCCREATE0x0081½WM_NCDESTROY0x0082¾WM_NCCALCSIZE0x0083¿WM_NCHITTEST0x0084ÀWM_NCPAINT0x0085ÁWM_NCACTIVATE0x0086ÂWM_GETDLGCODE0x0087ÃWM_SYNCPAINT0x0088ÅWM_NCMOUSEMOVE0x00A0ÇWM_NCLBUTTONDOWN0x00A1ÈWM_NCLBUTTONUP0x00A2ÉWM_NCLBUTTONDBLCLK0x00A3ÊWM_NCRBUTTONDOWN0x00A4ËWM_NCRBUTTONUP0x00A5ÌWM_NCRBUTTONDBLCLK0x00A6ÍWM_NCMBUTTONDOWN0x00A7ÎWM_NCMBUTTONUP0x00A8ÏWM_NCMBUTTONDBLCLK0x00A9ÐWM_NCXBUTTONDOWN0x00ABÕWM_NCXBUTTONUP0x00ACÖWM_NCXBUTTONDBLCLK0x00AD×WM_INPUT_DEVICE_CHANGE0x00FEÜWM_INPUT0x00FFàWM_KEYFIRST0x0100ãWM_KEYDOWN0x0100äWM_KEYUP0x0101åWM_CHAR0x0102æWM_DEADCHAR0x0103çWM_SYSKEYDOWN0x0104èWM_SYSKEYUP0x0105éWM_SYSCHAR0x0106êWM_SYSDEADCHAR0x0107ëWM_UNICHAR0x0109íWM_KEYLAST0x0109îUNICODE_NOCHAR0xFFFFïWM_IME_STARTCOMPOSITION0x010DõWM_IME_ENDCOMPOSITION0x010EöWM_IME_COMPOSITION0x010F÷WM_IME_KEYLAST0x010FøWM_INITDIALOG0x0110ûWM_COMMAND0x0111üWM_SYSCOMMAND0x0112ýWM_TIMER0x0113þWM_HSCROLL0x0114ÿWM_VSCROLL0x0115WM_INITMENU0x0116WM_INITMENUPOPUP0x0117WM_GESTURE0x0119WM_GESTURENOTIFY0x011AWM_MENUSELECT0x011FWM_MENUCHAR0x0120WM_ENTERIDLE0x0121 WM_MENURBUTTONUP0x0122 WM_MENUDRAG0x0123 WM_MENUGETOBJECT0x0124WM_UNINITMENUPOPUP0x0125WM_MENUCOMMAND0x0126WM_CHANGEUISTATE0x0127WM_UPDATEUISTATE0x0128WM_QUERYUISTATE0x0129UIS_SET1UIS_CLEAR2UIS_INITIALIZE3UISF_HIDEFOCUS0x1"UISF_HIDEACCEL0x2#UISF_ACTIVE0x4%WM_CTLCOLORMSGBOX0x0132-WM_CTLCOLOREDIT0x0133.WM_CTLCOLORLISTBOX0x0134/WM_CTLCOLORBTN0x01350WM_CTLCOLORDLG0x01361WM_CTLCOLORSCROLLBAR0x01372WM_CTLCOLORSTATIC0x01383MN_GETHMENU0x01E14WM_MOUSEFIRST0x02006WM_MOUSEMOVE0x02007WM_LBUTTONDOWN0x02018WM_LBUTTONUP0x02029WM_LBUTTONDBLCLK0x0203:WM_RBUTTONDOWN0x0204;WM_RBUTTONUP0x0205<WM_RBUTTONDBLCLK0x0206=WM_MBUTTONDOWN0x0207>WM_MBUTTONUP0x0208?WM_MBUTTONDBLCLK0x0209@WM_MOUSEWHEEL0x020ABWM_XBUTTONDOWN0x020BEWM_XBUTTONUP0x020CFWM_XBUTTONDBLCLK0x020DGWM_MOUSEHWHEEL0x020EJWM_MOUSELAST0x020ENWHEEL_DELTA120ZWHEEL_PAGESCROLL(UINT_MAX)^XBUTTON10x0001gXBUTTON20x0002hWM_PARENTNOTIFY0x0210lWM_ENTERMENULOOP0x0211mWM_EXITMENULOOP0x0212nWM_NEXTMENU0x0213qWM_SIZING0x0214rWM_CAPTURECHANGED0x0215sWM_MOVING0x0216tWM_POWERBROADCAST0x0218uWM_DEVICECHANGE0x0219xWM_MDICREATE0x0220{WM_MDIDESTROY0x0221|WM_MDIACTIVATE0x0222}WM_MDIRESTORE0x0223~WM_MDINEXT0x0224WM_MDIMAXIMIZE0x0225€WM_MDITILE0x0226WM_MDICASCADE0x0227‚WM_MDIICONARRANGE0x0228ƒWM_MDIGETACTIVE0x0229„WM_MDISETMENU0x0230‡WM_ENTERSIZEMOVE0x0231ˆWM_EXITSIZEMOVE0x0232‰WM_DROPFILES0x0233ŠWM_MDIREFRESHMENU0x0234‹WM_TOUCH0x0240ŽWM_IME_SETCONTEXT0x0281“WM_IME_NOTIFY0x0282”WM_IME_CONTROL0x0283•WM_IME_COMPOSITIONFULL0x0284–WM_IME_SELECT0x0285—WM_IME_CHAR0x0286˜WM_IME_REQUEST0x0288›WM_IME_KEYDOWN0x0290žWM_IME_KEYUP0x0291ŸWM_MOUSEHOVER0x02A1£WM_MOUSELEAVE0x02A3¤WM_NCMOUSEHOVER0x02A0§WM_NCMOUSELEAVE0x02A2¨WM_WTSSESSION_CHANGE0x02B1¬WM_TABLET_FIRST0x02c0®WM_TABLET_LAST0x02df¯WM_CUT0x0300²WM_COPY0x0301³WM_PASTE0x0302´WM_CLEAR0x0303µWM_UNDO0x0304¶WM_RENDERFORMAT0x0305·WM_RENDERALLFORMATS0x0306¸WM_DESTROYCLIPBOARD0x0307¹WM_DRAWCLIPBOARD0x0308ºWM_PAINTCLIPBOARD0x0309»WM_VSCROLLCLIPBOARD0x030A¼WM_SIZECLIPBOARD0x030B½WM_ASKCBFORMATNAME0x030C¾WM_CHANGECBCHAIN0x030D¿WM_HSCROLLCLIPBOARD0x030EÀWM_QUERYNEWPALETTE0x030FÁWM_PALETTEISCHANGING0x0310ÂWM_PALETTECHANGED0x0311ÃWM_HOTKEY0x0312ÄWM_PRINT0x0317ÇWM_PRINTCLIENT0x0318ÈWM_APPCOMMAND0x0319ÌWM_THEMECHANGED0x031AÐWM_CLIPBOARDUPDATE0x031DÕWM_DWMCOMPOSITIONCHANGED0x031EÙWM_DWMNCRENDERINGCHANGED0x031FÚWM_DWMCOLORIZATIONCOLORCHANGED0x0320ÛWM_DWMWINDOWMAXIMIZEDCHANGE0x0321ÜWM_DWMSENDICONICTHUMBNAIL0x0323àWM_DWMSENDICONICLIVEPREVIEWBITMAP0x0326áWM_GETTITLEBARINFOEX0x033FæWM_HANDHELDFIRST0x0358ëWM_HANDHELDLAST0x035FìWM_AFXFIRST0x0360îWM_AFXLAST0x037FïWM_PENWINFIRST0x0380òWM_PENWINLAST0x038FóWM_APP0x8000÷WM_USER0x0400WMSZ_LEFT1WMSZ_RIGHT2WMSZ_TOP3WMSZ_TOPLEFT4WMSZ_TOPRIGHT5 WMSZ_BOTTOM6 WMSZ_BOTTOMLEFT7 WMSZ_BOTTOMRIGHT8 HTERROR(-2)HTTRANSPARENT(-1)HTNOWHERE0HTCLIENT1HTCAPTION2HTSYSMENU3HTGROWBOX4HTSIZEHTGROWBOXHTMENU5HTHSCROLL6HTVSCROLL7HTMINBUTTON8HTMAXBUTTON9 HTLEFT10!HTRIGHT11"HTTOP12#HTTOPLEFT13$HTTOPRIGHT14%HTBOTTOM15&HTBOTTOMLEFT16'HTBOTTOMRIGHT17(HTBORDER18)HTREDUCEHTMINBUTTON*HTZOOMHTMAXBUTTON+HTSIZEFIRSTHTLEFT,HTSIZELASTHTBOTTOMRIGHT-HTOBJECT19/HTCLOSE200HTHELP211SMTO_NORMAL0x00008SMTO_BLOCK0x00019SMTO_ABORTIFHUNG0x0002:SMTO_NOTIMEOUTIFNOTHUNG0x0008<SMTO_ERRORONEXIT0x0020?MA_ACTIVATE1GMA_ACTIVATEANDEAT2HMA_NOACTIVATE3IMA_NOACTIVATEANDEAT4JICON_SMALL0OICON_BIG1PICON_SMALL22RSIZE_RESTORED0YSIZE_MINIMIZED1ZSIZE_MAXIMIZED2[SIZE_MAXSHOW3\SIZE_MAXHIDE4]SIZENORMALSIZE_RESTOREDbSIZEICONICSIZE_MINIMIZEDcSIZEFULLSCREENSIZE_MAXIMIZEDdSIZEZOOMSHOWSIZE_MAXSHOWeSIZEZOOMHIDESIZE_MAXHIDEfWVR_ALIGNTOP0x0010kWVR_ALIGNLEFT0x0020lWVR_ALIGNBOTTOM0x0040mWVR_ALIGNRIGHT0x0080nWVR_HREDRAW0x0100oWVR_VREDRAW0x0200pWVR_REDRAW(WVR_HREDRAW | WVR_VREDRAW)rWVR_VALIDRECTS0x0400sMK_LBUTTON0x0001{MK_RBUTTON0x0002|MK_SHIFT0x0004}MK_CONTROL0x0008~MK_MBUTTON0x0010MK_XBUTTON10x0020MK_XBUTTON20x0040‚TME_HOVER0x00000001‹TME_LEAVE0x00000002ŒTME_NONCLIENT0x00000010ŽTME_QUERY0x40000000TME_CANCEL0x80000000‘HOVER_DEFAULT0xFFFFFFFF”WS_OVERLAPPED0x00000000LŸWS_POPUP0x80000000L WS_CHILD0x40000000L¡WS_MINIMIZE0x20000000L¢WS_VISIBLE0x10000000L£WS_DISABLED0x08000000L¤WS_CLIPSIBLINGS0x04000000L¥WS_CLIPCHILDREN0x02000000L¦WS_MAXIMIZE0x01000000L§WS_CAPTION0x00C00000L¨WS_BORDER0x00800000L©WS_DLGFRAME0x00400000LªWS_VSCROLL0x00200000L«WS_HSCROLL0x00100000L¬WS_SYSMENU0x00080000L­WS_THICKFRAME0x00040000L®WS_GROUP0x00020000L¯WS_TABSTOP0x00010000L°WS_MINIMIZEBOX0x00020000L²WS_MAXIMIZEBOX0x00010000L³WS_TILEDWS_OVERLAPPED¶WS_ICONICWS_MINIMIZE·WS_SIZEBOXWS_THICKFRAME¸WS_TILEDWINDOWWS_OVERLAPPEDWINDOW¹WS_OVERLAPPEDWINDOW(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)ÃWS_POPUPWINDOW(WS_POPUP | WS_BORDER | WS_SYSMENU)ÇWS_CHILDWINDOW(WS_CHILD)ÉWS_EX_DLGMODALFRAME0x00000001LÎWS_EX_NOPARENTNOTIFY0x00000004LÏWS_EX_TOPMOST0x00000008LÐWS_EX_ACCEPTFILES0x00000010LÑWS_EX_TRANSPARENT0x00000020LÒWS_EX_MDICHILD0x00000040LÔWS_EX_TOOLWINDOW0x00000080LÕWS_EX_WINDOWEDGE0x00000100LÖWS_EX_CLIENTEDGE0x00000200L×WS_EX_CONTEXTHELP0x00000400LØWS_EX_RIGHT0x00001000LÝWS_EX_LEFT0x00000000LÞWS_EX_RTLREADING0x00002000LßWS_EX_LTRREADING0x00000000LàWS_EX_LEFTSCROLLBAR0x00004000LáWS_EX_RIGHTSCROLLBAR0x00000000LâWS_EX_CONTROLPARENT0x00010000LäWS_EX_STATICEDGE0x00020000LåWS_EX_APPWINDOW0x00040000LæWS_EX_OVERLAPPEDWINDOW(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE)éWS_EX_PALETTEWINDOW(WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST)êWS_EX_LAYERED0x00080000ïWS_EX_NOINHERITLAYOUT0x00100000LõWS_EX_LAYOUTRTL0x00400000LöWS_EX_COMPOSITED0x02000000LúWS_EX_NOACTIVATE0x08000000LýCS_VREDRAW0x0001CS_HREDRAW0x0002CS_DBLCLKS0x0008CS_OWNDC0x0020CS_CLASSDC0x0040CS_PARENTDC0x0080 CS_NOCLOSE0x0200 CS_SAVEBITS0x0800 CS_BYTEALIGNCLIENT0x1000 CS_BYTEALIGNWINDOW0x2000 CS_GLOBALCLASS0x4000CS_IME0x00010000CS_DROPSHADOW0x00020000CF_TEXT1CF_BITMAP2CF_METAFILEPICT3CF_SYLK4CF_DIF5CF_TIFF6CF_OEMTEXT7 CF_DIB8!CF_PALETTE9"CF_PENDATA10#CF_RIFF11$CF_WAVE12%CF_UNICODETEXT13&CF_ENHMETAFILE14'CF_HDROP15)CF_LOCALE16*CF_DIBV517-CF_MAX181CF_OWNERDISPLAY0x00808CF_DSPTEXT0x00819CF_DSPBITMAP0x0082:CF_DSPMETAFILEPICT0x0083;CF_DSPENHMETAFILE0x008E<CF_PRIVATEFIRST0x0200ACF_PRIVATELAST0x02FFBCF_GDIOBJFIRST0x0300GCF_GDIOBJLAST0x03FFHMF_INSERT0x00000000LOMF_CHANGE0x00000080LPMF_APPEND0x00000100LQMF_DELETE0x00000200LRMF_REMOVE0x00001000LSMF_BYCOMMAND0x00000000LUMF_BYPOSITION0x00000400LVMF_SEPARATOR0x00000800LXMF_ENABLED0x00000000LZMF_GRAYED0x00000001L[MF_DISABLED0x00000002L\MF_UNCHECKED0x00000000L^MF_CHECKED0x00000008L_MF_USECHECKBITMAPS0x00000200L`MF_STRING0x00000000LbMF_BITMAP0x00000004LcMF_OWNERDRAW0x00000100LdMF_POPUP0x00000010LfMF_MENUBARBREAK0x00000020LgMF_MENUBREAK0x00000040LhMF_UNHILITE0x00000000LjMF_HILITE0x00000080LkMF_DEFAULT0x00001000LnMF_SYSMENU0x00002000LpMF_HELP0x00004000LqMF_RIGHTJUSTIFY0x00004000LsMF_MOUSESELECT0x00008000LvMF_END0x00000080LxMFT_STRINGMF_STRING}MFT_BITMAPMF_BITMAP~MFT_MENUBARBREAKMF_MENUBARBREAKMFT_MENUBREAKMF_MENUBREAK€MFT_OWNERDRAWMF_OWNERDRAWMFT_RADIOCHECK0x00000200L‚MFT_SEPARATORMF_SEPARATORƒMFT_RIGHTORDER0x00002000L„MFT_RIGHTJUSTIFYMF_RIGHTJUSTIFY…MFS_GRAYED0x00000003LˆMFS_DISABLEDMFS_GRAYED‰MFS_CHECKEDMF_CHECKEDŠMFS_HILITEMF_HILITE‹MFS_ENABLEDMF_ENABLEDŒMFS_UNCHECKEDMF_UNCHECKEDMFS_UNHILITEMF_UNHILITEŽMFS_DEFAULTMF_DEFAULTSC_SIZE0xF000–SC_MOVE0xF010—SC_MINIMIZE0xF020˜SC_MAXIMIZE0xF030™SC_NEXTWINDOW0xF040šSC_PREVWINDOW0xF050›SC_CLOSE0xF060œSC_VSCROLL0xF070SC_HSCROLL0xF080žSC_MOUSEMENU0xF090ŸSC_KEYMENU0xF100 SC_ARRANGE0xF110¡SC_RESTORE0xF120¢SC_TASKLIST0xF130£SC_SCREENSAVE0xF140¤SC_HOTKEY0xF150¥SC_DEFAULT0xF160§SC_MONITORPOWER0xF170¨SC_CONTEXTHELP0xF180©SC_SEPARATOR0xF00FªSCF_ISSECURE0x00000001®SC_ICONSC_MINIMIZE¶SC_ZOOMSC_MAXIMIZE·OBM_CLOSE32754½OBM_UPARROW32753¾OBM_DNARROW32752¿OBM_RGARROW32751ÀOBM_LFARROW32750ÁOBM_REDUCE32749ÂOBM_ZOOM32748ÃOBM_RESTORE32747ÄOBM_REDUCED32746ÅOBM_ZOOMD32745ÆOBM_RESTORED32744ÇOBM_UPARROWD32743ÈOBM_DNARROWD32742ÉOBM_RGARROWD32741ÊOBM_LFARROWD32740ËOBM_MNARROW32739ÌOBM_COMBO32738ÍOBM_UPARROWI32737ÎOBM_DNARROWI32736ÏOBM_RGARROWI32735ÐOBM_LFARROWI32734ÑOBM_OLD_CLOSE32767ÓOBM_SIZE32766ÔOBM_OLD_UPARROW32765ÕOBM_OLD_DNARROW32764ÖOBM_OLD_RGARROW32763×OBM_OLD_LFARROW32762ØOBM_BTSIZE32761ÙOBM_CHECK32760ÚOBM_CHECKBOXES32759ÛOBM_BTNCORNERS32758ÜOBM_OLD_REDUCE32757ÝOBM_OLD_ZOOM32756ÞOBM_OLD_RESTORE32755ßOCR_NORMAL32512âOCR_IBEAM32513ãOCR_WAIT32514äOCR_CROSS32515åOCR_UP32516æOCR_SIZE32640çOCR_ICON32641èOCR_SIZENWSE32642éOCR_SIZENESW32643êOCR_SIZEWE32644ëOCR_SIZENS32645ìOCR_SIZEALL32646íOCR_ICOCUR32647îOCR_NO32648ïOCR_HAND32649ñOCR_APPSTARTING32650ôOIC_SAMPLE32512øOIC_HAND32513ùOIC_QUES32514úOIC_BANG32515ûOIC_NOTE32516üOIC_WINLOGO32517þOIC_WARNINGOIC_BANGÿOIC_ERROROIC_HANDOIC_INFORMATIONOIC_NOTEOIC_SHIELD32518IDI_APPLICATION32512 IDI_HAND32513 IDI_QUESTION32514IDI_EXCLAMATION32515IDI_ASTERISK32516IDI_WINLOGO32517IDI_SHIELD32518IDI_WARNINGIDI_EXCLAMATION&IDI_ERRORIDI_HAND'IDI_INFORMATIONIDI_ASTERISK(IDOK1/IDCANCEL20IDABORT31IDRETRY42IDIGNORE53IDYES64IDNO75IDCLOSE87IDHELP98IDTRYAGAIN10<IDCONTINUE11=IDTIMEOUT32000BES_LEFT0x0000LJES_CENTER0x0001LKES_RIGHT0x0002LLES_MULTILINE0x0004LMES_UPPERCASE0x0008LNES_LOWERCASE0x0010LOES_PASSWORD0x0020LPES_AUTOVSCROLL0x0040LQES_AUTOHSCROLL0x0080LRES_NOHIDESEL0x0100LSES_OEMCONVERT0x0400LTES_READONLY0x0800LUES_WANTRETURN0x1000LVES_NUMBER0x2000LXEM_GETSEL0x00B0_EM_SETSEL0x00B1`EM_GETRECT0x00B2aEM_SETRECT0x00B3bEM_SETRECTNP0x00B4cEM_SCROLL0x00B5dEM_LINESCROLL0x00B6eEM_SCROLLCARET0x00B7fEM_GETMODIFY0x00B8gEM_SETMODIFY0x00B9hEM_GETLINECOUNT0x00BAiEM_LINEINDEX0x00BBjEM_SETHANDLE0x00BCkEM_GETHANDLE0x00BDlEM_GETTHUMB0x00BEmEM_LINELENGTH0x00C1nEM_REPLACESEL0x00C2oEM_GETLINE0x00C4pEM_LIMITTEXT0x00C5qEM_CANUNDO0x00C6rEM_UNDO0x00C7sEM_FMTLINES0x00C8tEM_LINEFROMCHAR0x00C9uEM_SETTABSTOPS0x00CBvEM_SETPASSWORDCHAR0x00CCwEM_EMPTYUNDOBUFFER0x00CDxEM_GETFIRSTVISIBLELINE0x00CEyEM_SETREADONLY0x00CFzEM_SETWORDBREAKPROC0x00D0{EM_GETWORDBREAKPROC0x00D1|EM_GETPASSWORDCHAR0x00D2}EM_SETMARGINS0x00D3EM_GETMARGINS0x00D4€EM_SETLIMITTEXTEM_LIMITTEXTEM_GETLIMITTEXT0x00D5‚EM_POSFROMCHAR0x00D6ƒEM_CHARFROMPOS0x00D7„EM_SETIMESTATUS0x00D8ˆEM_GETIMESTATUS0x00D9‰BS_PUSHBUTTON0x00000000L‘BS_DEFPUSHBUTTON0x00000001L’BS_CHECKBOX0x00000002L“BS_AUTOCHECKBOX0x00000003L”BS_RADIOBUTTON0x00000004L•BS_3STATE0x00000005L–BS_AUTO3STATE0x00000006L—BS_GROUPBOX0x00000007L˜BS_USERBUTTON0x00000008L™BS_AUTORADIOBUTTON0x00000009LšBS_PUSHBOX0x0000000AL›BS_OWNERDRAW0x0000000BLœBS_TYPEMASK0x0000000FLBS_LEFTTEXT0x00000020LžBS_TEXT0x00000000L BS_ICON0x00000040L¡BS_BITMAP0x00000080L¢BS_LEFT0x00000100L£BS_RIGHT0x00000200L¤BS_CENTER0x00000300L¥BS_TOP0x00000400L¦BS_BOTTOM0x00000800L§BS_VCENTER0x00000C00L¨BS_PUSHLIKE0x00001000L©BS_MULTILINE0x00002000LªBS_NOTIFY0x00004000L«BS_FLAT0x00008000L¬BS_RIGHTBUTTONBS_LEFTTEXT­BN_CLICKED0³BN_PAINT1´BN_HILITE2µBN_UNHILITE3¶BN_DISABLE4·BN_DOUBLECLICKED5¸BN_PUSHEDBN_HILITEºBN_UNPUSHEDBN_UNHILITE»BN_DBLCLKBN_DOUBLECLICKED¼BN_SETFOCUS6½BN_KILLFOCUS7¾BM_GETCHECK0x00F0ÄBM_SETCHECK0x00F1ÅBM_GETSTATE0x00F2ÆBM_SETSTATE0x00F3ÇBM_SETSTYLE0x00F4ÈBM_CLICK0x00F5ÊBM_GETIMAGE0x00F6ËBM_SETIMAGE0x00F7ÌBM_SETDONTCLICK0x00F8ÏBST_UNCHECKED0x0000ÓBST_CHECKED0x0001ÔBST_INDETERMINATE0x0002ÕBST_PUSHED0x0004ÖBST_FOCUS0x0008×SS_LEFT0x00000000LÝSS_CENTER0x00000001LÞSS_RIGHT0x00000002LßSS_ICON0x00000003LàSS_BLACKRECT0x00000004LáSS_GRAYRECT0x00000005LâSS_WHITERECT0x00000006LãSS_BLACKFRAME0x00000007LäSS_GRAYFRAME0x00000008LåSS_WHITEFRAME0x00000009LæSS_USERITEM0x0000000ALçSS_SIMPLE0x0000000BLèSS_LEFTNOWORDWRAP0x0000000CLéSS_OWNERDRAW0x0000000DLëSS_BITMAP0x0000000ELìSS_ENHMETAFILE0x0000000FLíSS_ETCHEDHORZ0x00000010LîSS_ETCHEDVERT0x00000011LïSS_ETCHEDFRAME0x00000012LðSS_TYPEMASK0x0000001FLñSS_REALSIZECONTROL0x00000040LôSS_NOPREFIX0x00000080LöSS_NOTIFY0x00000100LøSS_CENTERIMAGE0x00000200LùSS_RIGHTJUST0x00000400LúSS_REALSIZEIMAGE0x00000800LûSS_SUNKEN0x00001000LüSS_EDITCONTROL0x00002000LýSS_ENDELLIPSIS0x00004000LþSS_PATHELLIPSIS0x00008000LÿSS_WORDELLIPSIS0x0000C000LSS_ELLIPSISMASK0x0000C000LDS_ABSALIGN0x01L DS_SYSMODAL0x02L DS_LOCALEDIT0x20L DS_SETFONT0x40L DS_MODALFRAME0x80L DS_NOIDLEMSG0x100LDS_SETFOREGROUND0x200LDS_3DLOOK0x0004LDS_FIXEDSYS0x0008LDS_NOFAILCREATE0x0010LDS_CONTROL0x0400LDS_CENTER0x0800LDS_CENTERMOUSE0x1000LDS_CONTEXTHELP0x2000LDS_SHELLFONT(DS_SETFONT | DS_FIXEDSYS)LBS_NOTIFY0x0001L&LBS_SORT0x0002L'LBS_NOREDRAW0x0004L(LBS_MULTIPLESEL0x0008L)LBS_OWNERDRAWFIXED0x0010L*LBS_OWNERDRAWVARIABLE0x0020L+LBS_HASSTRINGS0x0040L,LBS_USETABSTOPS0x0080L-LBS_NOINTEGRALHEIGHT0x0100L.LBS_MULTICOLUMN0x0200L/LBS_WANTKEYBOARDINPUT0x0400L0LBS_EXTENDEDSEL0x0800L1LBS_DISABLENOSCROLL0x1000L2LBS_NODATA0x2000L3LBS_NOSEL0x4000L5LBS_COMBOBOX0x8000L7LBS_STANDARD(LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER)9CBS_SIMPLE0x0001L?CBS_DROPDOWN0x0002L@CBS_DROPDOWNLIST0x0003LACBS_OWNERDRAWFIXED0x0010LBCBS_OWNERDRAWVARIABLE0x0020LCCBS_AUTOHSCROLL0x0040LDCBS_OEMCONVERT0x0080LECBS_SORT0x0100LFCBS_HASSTRINGS0x0200LGCBS_NOINTEGRALHEIGHT0x0400LHCBS_DISABLENOSCROLL0x0800LICBS_UPPERCASE0x2000LKCBS_LOWERCASE0x4000LLSBS_HORZ0x0000LSSBS_VERT0x0001LTSBS_TOPALIGN0x0002LUSBS_LEFTALIGN0x0002LVSBS_BOTTOMALIGN0x0004LWSBS_RIGHTALIGN0x0004LXSBS_SIZEBOXTOPLEFTALIGN0x0002LYSBS_SIZEBOXBOTTOMRIGHTALIGN0x0004LZSBS_SIZEBOX0x0008L[SBS_SIZEGRIP0x0010L]HELP_CONTEXT0x0001LdHELP_QUIT0x0002LeHELP_INDEX0x0003LfHELP_CONTENTS0x0003LgHELP_HELPONHELP0x0004LhHELP_SETINDEX0x0005LiHELP_SETCONTENTS0x0005LjHELP_CONTEXTPOPUP0x0008LkHELP_FORCEFILE0x0009LlHELP_KEY0x0101LmHELP_COMMAND0x0102LnHELP_PARTIALKEY0x0105LoHELP_MULTIKEY0x0201LpHELP_SETWINPOS0x0203LqHELP_CONTEXTMENU0x000asHELP_FINDER0x000btHELP_WM_HELP0x000cuHELP_SETPOPUP_POS0x000dvHELP_TCARD0x8000xHELP_TCARD_DATA0x0010yHELP_TCARD_OTHER_CALLER0x0011zIDH_NO_HELP28440}IDH_MISSING_CONTEXT28441~IDH_GENERIC_HELP_BUTTON28442IDH_OK28443€IDH_CANCEL28444IDH_HELP28445‚!!commctrl.rhHDS_HORZ0x0000HDS_BUTTONS0x0002HDS_HOTTRACK0x0004HDS_HIDDEN0x0008HDS_DRAGDROP0x0040HDS_FULLDRAG0x0080HDS_FILTERBAR0x0100HDS_FLAT0x0200!HDS_CHECKBOXES0x0400%HDS_NOSIZING0x0800&HDS_OVERFLOW0x1000'TBSTYLE_BUTTON0x0000*TBSTYLE_SEP0x0001+TBSTYLE_CHECK0x0002,TBSTYLE_GROUP0x0004-TBSTYLE_CHECKGROUP(TBSTYLE_GROUP | TBSTYLE_CHECK).TBSTYLE_DROPDOWN0x00080TBSTYLE_AUTOSIZE0x00103TBSTYLE_NOPREFIX0x00204TBSTYLE_TOOLTIPS0x01007TBSTYLE_WRAPABLE0x02008TBSTYLE_ALTDRAG0x04009TBSTYLE_FLAT0x0800;TBSTYLE_LIST0x1000<TBSTYLE_CUSTOMERASE0x2000=TBSTYLE_REGISTERDROP0x4000@TBSTYLE_TRANSPARENT0x8000ABTNS_BUTTONTBSTYLE_BUTTONFBTNS_SEPTBSTYLE_SEPGBTNS_CHECKTBSTYLE_CHECKHBTNS_GROUPTBSTYLE_GROUPIBTNS_CHECKGROUPTBSTYLE_CHECKGROUPJBTNS_DROPDOWNTBSTYLE_DROPDOWNKBTNS_AUTOSIZETBSTYLE_AUTOSIZELBTNS_NOPREFIXTBSTYLE_NOPREFIXMBTNS_SHOWTEXT0x0040OBTNS_WHOLEDROPDOWN0x0080QRBS_TOOLTIPS0x00000100URBS_VARHEIGHT0x00000200VRBS_BANDBORDERS0x00000400WRBS_FIXEDORDER0x00000800XRBS_REGISTERDROP0x00001000ZRBS_AUTOSIZE0x00002000[RBS_VERTICALGRIPPER0x00004000\RBS_DBLCLKTOGGLE0x00008000]TTS_ALWAYSTIP0x01aTTS_NOPREFIX0x02bTTS_NOANIMATE0x10dTTS_NOFADE0x20eTTS_BALLOON0x40fTTS_CLOSE0x80gTTS_USEVISUALSTYLE0x100jSBARS_SIZEGRIP0x0100oSBARS_TOOLTIPS0x0800qSBT_TOOLTIPS0x0800vTBS_AUTOTICKS0x0001zTBS_VERT0x0002{TBS_HORZ0x0000|TBS_TOP0x0004}TBS_BOTTOM0x0000~TBS_LEFT0x0004TBS_RIGHT0x0000€TBS_BOTH0x0008TBS_NOTICKS0x0010‚TBS_ENABLESELRANGE0x0020ƒTBS_FIXEDLENGTH0x0040„TBS_NOTHUMB0x0080…TBS_TOOLTIPS0x0100‡TBS_REVERSED0x0200ŠTBS_DOWNISLEFT0x0400ŽTBS_NOTIFYBEFOREMOVE0x0800’TBS_TRANSPARENTBKGND0x1000–UDS_WRAP0x0001šUDS_SETBUDDYINT0x0002›UDS_ALIGNRIGHT0x0004œUDS_ALIGNLEFT0x0008UDS_AUTOBUDDY0x0010žUDS_ARROWKEYS0x0020ŸUDS_HORZ0x0040 UDS_NOTHOUSANDS0x0080¡UDS_HOTTRACK0x0100£PBS_SMOOTH0x01¨PBS_VERTICAL0x04©PBS_MARQUEE0x08®PBS_SMOOTHREVERSE0x10²CCS_TOP0x00000001L¸CCS_NOMOVEY0x00000002L¹CCS_BOTTOM0x00000003LºCCS_NORESIZE0x00000004L»CCS_NOPARENTALIGN0x00000008L¼CCS_ADJUSTABLE0x00000020L½CCS_NODIVIDER0x00000040L¾CCS_VERT0x00000080LÀCCS_LEFT(CCS_VERT | CCS_TOP)ÁCCS_RIGHT(CCS_VERT | CCS_BOTTOM)ÂCCS_NOMOVEX(CCS_VERT | CCS_NOMOVEY)ÃLWS_TRANSPARENT0x0001ÇLWS_IGNORERETURN0x0002ÈLWS_NOPREFIX0x0004ÊLWS_USEVISUALSTYLE0x0008ËLWS_USECUSTOMTEXT0x0010ÌLWS_RIGHT0x0020ÍLVS_ICON0x0000ÑLVS_REPORT0x0001ÒLVS_SMALLICON0x0002ÓLVS_LIST0x0003ÔLVS_TYPEMASK0x0003ÕLVS_SINGLESEL0x0004ÖLVS_SHOWSELALWAYS0x0008×LVS_SORTASCENDING0x0010ØLVS_SORTDESCENDING0x0020ÙLVS_SHAREIMAGELISTS0x0040ÚLVS_NOLABELWRAP0x0080ÛLVS_AUTOARRANGE0x0100ÜLVS_EDITLABELS0x0200ÝLVS_OWNERDATA0x1000ßLVS_NOSCROLL0x2000áLVS_TYPESTYLEMASK0xfc00ãLVS_ALIGNTOP0x0000åLVS_ALIGNLEFT0x0800æLVS_ALIGNMASK0x0c00çLVS_OWNERDRAWFIXED0x0400éLVS_NOCOLUMNHEADER0x4000êLVS_NOSORTHEADER0x8000ëTVS_HASBUTTONS0x0001îTVS_HASLINES0x0002ïTVS_LINESATROOT0x0004ðTVS_EDITLABELS0x0008ñTVS_DISABLEDRAGDROP0x0010òTVS_SHOWSELALWAYS0x0020óTVS_RTLREADING0x0040õTVS_NOTOOLTIPS0x0080÷TVS_CHECKBOXES0x0100øTVS_TRACKSELECT0x0200ùTVS_SINGLEEXPAND0x0400ûTVS_INFOTIP0x0800üTVS_FULLROWSELECT0x1000ýTVS_NOSCROLL0x2000þTVS_NONEVENHEIGHT0x4000ÿTVS_NOHSCROLL0x8000TVS_EX_MULTISELECT0x0002TVS_EX_DOUBLEBUFFER0x0004 TVS_EX_NOINDENTSTATE0x0008 TVS_EX_RICHTOOLTIP0x0010 TVS_EX_AUTOHSCROLL0x0020 TVS_EX_FADEINOUTEXPANDOS0x0040 TVS_EX_PARTIALCHECKBOXES0x0080TVS_EX_EXCLUSIONCHECKBOXES0x0100TVS_EX_DIMMEDCHECKBOXES0x0200TVS_EX_DRAWIMAGEASYNC0x0400TCS_SCROLLOPPOSITE0x0001TCS_BOTTOM0x0002TCS_RIGHT0x0002TCS_MULTISELECT0x0004TCS_FLATBUTTONS0x0008TCS_FORCEICONLEFT0x0010TCS_FORCELABELLEFT0x0020TCS_HOTTRACK0x0040!TCS_VERTICAL0x0080"TCS_TABS0x0000$TCS_BUTTONS0x0100%TCS_SINGLELINE0x0000&TCS_MULTILINE0x0200'TCS_RIGHTJUSTIFY0x0000(TCS_FIXEDWIDTH0x0400)TCS_RAGGEDRIGHT0x0800*TCS_FOCUSONBUTTONDOWN0x1000+TCS_OWNERDRAWFIXED0x2000,TCS_TOOLTIPS0x4000-TCS_FOCUSNEVER0x8000.ACS_CENTER0x00011ACS_TRANSPARENT0x00022ACS_AUTOPLAY0x00043ACS_TIMER0x00085MCS_DAYSTATE0x00019MCS_MULTISELECT0x0002:MCS_WEEKNUMBERS0x0004;MCS_NOTODAYCIRCLE0x0008=MCS_NOTODAY0x0010>MCS_NOTRAILINGDATES0x0040CMCS_SHORTDAYSOFWEEK0x0080DMCS_NOSELCHANGEONNAV0x0100EDTS_UPDOWN0x0001JDTS_SHOWNONE0x0002KDTS_SHORTDATEFORMAT0x0000LDTS_LONGDATEFORMAT0x0004MDTS_SHORTDATECENTURYFORMAT0x000CODTS_TIMEFORMAT0x0009QDTS_APPCANPARSE0x0010RDTS_RIGHTALIGN0x0020SPGS_VERT0x00000000VPGS_HORZ0x00000001WPGS_AUTOSCROLL0x00000002XPGS_DRAGNDROP0x00000004YNFS_EDIT0x0001]NFS_STATIC0x0002^NFS_LISTCOMBO0x0004_NFS_BUTTON0x0008`NFS_ALL0x0010aNFS_USEFONTASSOC0x0020bBS_SPLITBUTTON0x0000000CLfBS_DEFSPLITBUTTON0x0000000DLgBS_COMMANDLINK0x0000000ELhBS_DEFCOMMANDLINK0x0000000FLiBCSIF_GLYPH0x0001lBCSIF_IMAGE0x0002mBCSIF_STYLE0x0004nBCSIF_SIZE0x0008oBCSS_NOSPLIT0x0001rBCSS_STRETCH0x0002sBCSS_ALIGNLEFT0x0004tBCSS_IMAGE0x0008u!!dde.rhWM_DDE_FIRST0x03E0WM_DDE_INITIATE(WM_DDE_FIRST)WM_DDE_TERMINATE(WM_DDE_FIRST+1)WM_DDE_ADVISE(WM_DDE_FIRST+2)WM_DDE_UNADVISE(WM_DDE_FIRST+3)WM_DDE_ACK(WM_DDE_FIRST+4)WM_DDE_DATA(WM_DDE_FIRST+5)WM_DDE_REQUEST(WM_DDE_FIRST+6)WM_DDE_POKE(WM_DDE_FIRST+7)WM_DDE_EXECUTE(WM_DDE_FIRST+8)WM_DDE_LAST(WM_DDE_FIRST+8)!!winnt.rhLANG_NEUTRAL0x005LANG_INVARIANT0x7f6LANG_AFRIKAANS0x368LANG_ALBANIAN0x1c9LANG_ALSATIAN0x84:LANG_AMHARIC0x5e;LANG_ARABIC0x01<LANG_ARMENIAN0x2b=LANG_ASSAMESE0x4d>LANG_AZERI0x2c?LANG_BASHKIR0x6d@LANG_BASQUE0x2dALANG_BELARUSIAN0x23BLANG_BENGALI0x45CLANG_BRETON0x7eDLANG_BOSNIAN0x1aELANG_BOSNIAN_NEUTRAL0x781aFLANG_BULGARIAN0x02GLANG_CATALAN0x03HLANG_CHINESE0x04ILANG_CHINESE_SIMPLIFIED0x04JLANG_CHINESE_TRADITIONAL0x7c04KLANG_CORSICAN0x83LLANG_CROATIAN0x1aMLANG_CZECH0x05NLANG_DANISH0x06OLANG_DARI0x8cPLANG_DIVEHI0x65QLANG_DUTCH0x13RLANG_ENGLISH0x09SLANG_ESTONIAN0x25TLANG_FAEROESE0x38ULANG_FARSI0x29VLANG_FILIPINO0x64WLANG_FINNISH0x0bXLANG_FRENCH0x0cYLANG_FRISIAN0x62ZLANG_GALICIAN0x56[LANG_GEORGIAN0x37\LANG_GERMAN0x07]LANG_GREEK0x08^LANG_GREENLANDIC0x6f_LANG_GUJARATI0x47`LANG_HAUSA0x68aLANG_HEBREW0x0dbLANG_HINDI0x39cLANG_HUNGARIAN0x0edLANG_ICELANDIC0x0feLANG_IGBO0x70fLANG_INDONESIAN0x21gLANG_INUKTITUT0x5dhLANG_IRISH0x3ciLANG_ITALIAN0x10jLANG_JAPANESE0x11kLANG_KANNADA0x4blLANG_KASHMIRI0x60mLANG_KAZAK0x3fnLANG_KHMER0x53oLANG_KICHE0x86pLANG_KINYARWANDA0x87qLANG_KONKANI0x57rLANG_KOREAN0x12sLANG_KYRGYZ0x40tLANG_LAO0x54uLANG_LATVIAN0x26vLANG_LITHUANIAN0x27wLANG_LOWER_SORBIAN0x2exLANG_LUXEMBOURGISH0x6eyLANG_MACEDONIAN0x2fzLANG_MALAY0x3e{LANG_MALAYALAM0x4c|LANG_MALTESE0x3a}LANG_MANIPURI0x58~LANG_MAORI0x81LANG_MAPUDUNGUN0x7a€LANG_MARATHI0x4eLANG_MOHAWK0x7c‚LANG_MONGOLIAN0x50ƒLANG_NEPALI0x61„LANG_NORWEGIAN0x14…LANG_OCCITAN0x82†LANG_ORIYA0x48‡LANG_PASHTO0x63ˆLANG_PERSIAN0x29‰LANG_POLISH0x15ŠLANG_PORTUGUESE0x16‹LANG_PUNJABI0x46ŒLANG_QUECHUA0x6bLANG_ROMANIAN0x18ŽLANG_ROMANSH0x17LANG_RUSSIAN0x19LANG_SAMI0x3b‘LANG_SANSKRIT0x4f’LANG_SCOTTISH_GAELIC0x91“LANG_SERBIAN0x1a”LANG_SERBIAN_NEUTRAL0x7c1a•LANG_SINDHI0x59–LANG_SINHALESE0x5b—LANG_SLOVAK0x1b˜LANG_SLOVENIAN0x24™LANG_SOTHO0x6cšLANG_SPANISH0x0a›LANG_SWAHILI0x41œLANG_SWEDISH0x1dLANG_SYRIAC0x5ažLANG_TAJIK0x28ŸLANG_TAMAZIGHT0x5f LANG_TAMIL0x49¡LANG_TATAR0x44¢LANG_TELUGU0x4a£LANG_THAI0x1e¤LANG_TIBETAN0x51¥LANG_TIGRIGNA0x73¦LANG_TSWANA0x32§LANG_TURKISH0x1f¨LANG_TURKMEN0x42©LANG_UIGHUR0x80ªLANG_UKRAINIAN0x22«LANG_UPPER_SORBIAN0x2e¬LANG_URDU0x20­LANG_UZBEK0x43®LANG_VIETNAMESE0x2a¯LANG_WELSH0x52°LANG_WOLOF0x88±LANG_XHOSA0x34²LANG_YAKUT0x85³LANG_YI0x78´LANG_YORUBA0x6aµLANG_ZULU0x35¶SUBLANG_NEUTRAL0x00ÃSUBLANG_DEFAULT0x01ÄSUBLANG_SYS_DEFAULT0x02ÅSUBLANG_CUSTOM_DEFAULT0x03ÆSUBLANG_CUSTOM_UNSPECIFIED0x04ÇSUBLANG_UI_CUSTOM_DEFAULT0x05ÈSUBLANG_AFRIKAANS_SOUTH_AFRICA0x01ËSUBLANG_ALBANIAN_ALBANIA0x01ÌSUBLANG_ALSATIAN_FRANCE0x01ÍSUBLANG_AMHARIC_ETHIOPIA0x01ÎSUBLANG_ARABIC_SAUDI_ARABIA0x01ÏSUBLANG_ARABIC_IRAQ0x02ÐSUBLANG_ARABIC_EGYPT0x03ÑSUBLANG_ARABIC_LIBYA0x04ÒSUBLANG_ARABIC_ALGERIA0x05ÓSUBLANG_ARABIC_MOROCCO0x06ÔSUBLANG_ARABIC_TUNISIA0x07ÕSUBLANG_ARABIC_OMAN0x08ÖSUBLANG_ARABIC_YEMEN0x09×SUBLANG_ARABIC_SYRIA0x0aØSUBLANG_ARABIC_JORDAN0x0bÙSUBLANG_ARABIC_LEBANON0x0cÚSUBLANG_ARABIC_KUWAIT0x0dÛSUBLANG_ARABIC_UAE0x0eÜSUBLANG_ARABIC_BAHRAIN0x0fÝSUBLANG_ARABIC_QATAR0x10ÞSUBLANG_ARMENIAN_ARMENIA0x01ßSUBLANG_ASSAMESE_INDIA0x01àSUBLANG_AZERI_LATIN0x01áSUBLANG_AZERI_CYRILLIC0x02âSUBLANG_BASHKIR_RUSSIA0x01ãSUBLANG_BASQUE_BASQUE0x01äSUBLANG_BELARUSIAN_BELARUS0x01åSUBLANG_BENGALI_INDIA0x01æSUBLANG_BENGALI_BANGLADESH0x02çSUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN0x05èSUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC0x08éSUBLANG_BRETON_FRANCE0x01êSUBLANG_BULGARIAN_BULGARIA0x01ëSUBLANG_CATALAN_CATALAN0x01ìSUBLANG_CHINESE_TRADITIONAL0x01íSUBLANG_CHINESE_SIMPLIFIED0x02îSUBLANG_CHINESE_HONGKONG0x03ïSUBLANG_CHINESE_SINGAPORE0x04ðSUBLANG_CHINESE_MACAU0x05ñSUBLANG_CORSICAN_FRANCE0x01òSUBLANG_CZECH_CZECH_REPUBLIC0x01óSUBLANG_CROATIAN_CROATIA0x01ôSUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN0x04õSUBLANG_DANISH_DENMARK0x01öSUBLANG_DARI_AFGHANISTAN0x01÷SUBLANG_DIVEHI_MALDIVES0x01øSUBLANG_DUTCH0x01ùSUBLANG_DUTCH_BELGIAN0x02úSUBLANG_ENGLISH_US0x01ûSUBLANG_ENGLISH_UK0x02üSUBLANG_ENGLISH_AUS0x03ýSUBLANG_ENGLISH_CAN0x04þSUBLANG_ENGLISH_NZ0x05ÿSUBLANG_ENGLISH_EIRE0x06SUBLANG_ENGLISH_SOUTH_AFRICA0x07SUBLANG_ENGLISH_JAMAICA0x08SUBLANG_ENGLISH_CARIBBEAN0x09SUBLANG_ENGLISH_BELIZE0x0aSUBLANG_ENGLISH_TRINIDAD0x0bSUBLANG_ENGLISH_ZIMBABWE0x0cSUBLANG_ENGLISH_PHILIPPINES0x0dSUBLANG_ENGLISH_INDIA0x10SUBLANG_ENGLISH_MALAYSIA0x11 SUBLANG_ENGLISH_SINGAPORE0x12 SUBLANG_ESTONIAN_ESTONIA0x01 SUBLANG_FAEROESE_FAROE_ISLANDS0x01 SUBLANG_FILIPINO_PHILIPPINES0x01 SUBLANG_FINNISH_FINLAND0x01SUBLANG_FRENCH0x01SUBLANG_FRENCH_BELGIAN0x02SUBLANG_FRENCH_CANADIAN0x03SUBLANG_FRENCH_SWISS0x04SUBLANG_FRENCH_LUXEMBOURG0x05SUBLANG_FRENCH_MONACO0x06SUBLANG_FRISIAN_NETHERLANDS0x01SUBLANG_GALICIAN_GALICIAN0x01SUBLANG_GEORGIAN_GEORGIA0x01SUBLANG_GERMAN0x01SUBLANG_GERMAN_SWISS0x02SUBLANG_GERMAN_AUSTRIAN0x03SUBLANG_GERMAN_LUXEMBOURG0x04SUBLANG_GERMAN_LIECHTENSTEIN0x05SUBLANG_GREEK_GREECE0x01SUBLANG_GREENLANDIC_GREENLAND0x01SUBLANG_GUJARATI_INDIA0x01SUBLANG_HAUSA_NIGERIA_LATIN0x01 SUBLANG_HEBREW_ISRAEL0x01!SUBLANG_HINDI_INDIA0x01"SUBLANG_HUNGARIAN_HUNGARY0x01#SUBLANG_ICELANDIC_ICELAND0x01$SUBLANG_IGBO_NIGERIA0x01%SUBLANG_INDONESIAN_INDONESIA0x01&SUBLANG_INUKTITUT_CANADA0x01'SUBLANG_INUKTITUT_CANADA_LATIN0x02(SUBLANG_IRISH_IRELAND0x02)SUBLANG_ITALIAN0x01*SUBLANG_ITALIAN_SWISS0x02+SUBLANG_JAPANESE_JAPAN0x01,SUBLANG_KANNADA_INDIA0x01-SUBLANG_KASHMIRI_SASIA0x02.SUBLANG_KASHMIRI_INDIA0x02/SUBLANG_KAZAK_KAZAKHSTAN0x010SUBLANG_KHMER_CAMBODIA0x011SUBLANG_KICHE_GUATEMALA0x012SUBLANG_KINYARWANDA_RWANDA0x013SUBLANG_KONKANI_INDIA0x014SUBLANG_KOREAN0x015SUBLANG_KYRGYZ_KYRGYZSTAN0x016SUBLANG_LAO_LAO0x017SUBLANG_LATVIAN_LATVIA0x018SUBLANG_LITHUANIAN0x019SUBLANG_LOWER_SORBIAN_GERMANY0x02:SUBLANG_LUXEMBOURGISH_LUXEMBOURG0x01;SUBLANG_MACEDONIAN_MACEDONIA0x01<SUBLANG_MALAY_MALAYSIA0x01=SUBLANG_MALAY_BRUNEI_DARUSSALAM0x02>SUBLANG_MALAYALAM_INDIA0x01?SUBLANG_MALTESE_MALTA0x01@SUBLANG_MAORI_NEW_ZEALAND0x01ASUBLANG_MAPUDUNGUN_CHILE0x01BSUBLANG_MARATHI_INDIA0x01CSUBLANG_MOHAWK_MOHAWK0x01DSUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA0x01ESUBLANG_MONGOLIAN_PRC0x02FSUBLANG_NEPALI_INDIA0x02GSUBLANG_NEPALI_NEPAL0x01HSUBLANG_NORWEGIAN_BOKMAL0x01ISUBLANG_NORWEGIAN_NYNORSK0x02JSUBLANG_OCCITAN_FRANCE0x01KSUBLANG_ORIYA_INDIA0x01LSUBLANG_PASHTO_AFGHANISTAN0x01MSUBLANG_PERSIAN_IRAN0x01NSUBLANG_POLISH_POLAND0x01OSUBLANG_PORTUGUESE0x02PSUBLANG_PORTUGUESE_BRAZILIAN0x01QSUBLANG_PUNJABI_INDIA0x01RSUBLANG_QUECHUA_BOLIVIA0x01SSUBLANG_QUECHUA_ECUADOR0x02TSUBLANG_QUECHUA_PERU0x03USUBLANG_ROMANIAN_ROMANIA0x01VSUBLANG_ROMANSH_SWITZERLAND0x01WSUBLANG_RUSSIAN_RUSSIA0x01XSUBLANG_SAMI_NORTHERN_NORWAY0x01YSUBLANG_SAMI_NORTHERN_SWEDEN0x02ZSUBLANG_SAMI_NORTHERN_FINLAND0x03[SUBLANG_SAMI_LULE_NORWAY0x04\SUBLANG_SAMI_LULE_SWEDEN0x05]SUBLANG_SAMI_SOUTHERN_NORWAY0x06^SUBLANG_SAMI_SOUTHERN_SWEDEN0x07_SUBLANG_SAMI_SKOLT_FINLAND0x08`SUBLANG_SAMI_INARI_FINLAND0x09aSUBLANG_SANSKRIT_INDIA0x01bSUBLANG_SCOTTISH_GAELIC0x01cSUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_LATIN0x06dSUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC0x07eSUBLANG_SERBIAN_MONTENEGRO_LATIN0x0bfSUBLANG_SERBIAN_MONTENEGRO_CYRILLIC0x0cgSUBLANG_SERBIAN_SERBIA_LATIN0x09hSUBLANG_SERBIAN_SERBIA_CYRILLIC0x0aiSUBLANG_SERBIAN_CROATIA0x01jSUBLANG_SERBIAN_LATIN0x02kSUBLANG_SERBIAN_CYRILLIC0x03lSUBLANG_SINDHI_INDIA0x01mSUBLANG_SINDHI_PAKISTAN0x02nSUBLANG_SINDHI_AFGHANISTAN0x02oSUBLANG_SINHALESE_SRI_LANKA0x01pSUBLANG_SOTHO_NORTHERN_SOUTH_AFRICA0x01qSUBLANG_SLOVAK_SLOVAKIA0x01rSUBLANG_SLOVENIAN_SLOVENIA0x01sSUBLANG_SPANISH0x01tSUBLANG_SPANISH_MEXICAN0x02uSUBLANG_SPANISH_MODERN0x03vSUBLANG_SPANISH_GUATEMALA0x04wSUBLANG_SPANISH_COSTA_RICA0x05xSUBLANG_SPANISH_PANAMA0x06ySUBLANG_SPANISH_DOMINICAN_REPUBLIC0x07zSUBLANG_SPANISH_VENEZUELA0x08{SUBLANG_SPANISH_COLOMBIA0x09|SUBLANG_SPANISH_PERU0x0a}SUBLANG_SPANISH_ARGENTINA0x0b~SUBLANG_SPANISH_ECUADOR0x0cSUBLANG_SPANISH_CHILE0x0d€SUBLANG_SPANISH_URUGUAY0x0eSUBLANG_SPANISH_PARAGUAY0x0f‚SUBLANG_SPANISH_BOLIVIA0x10ƒSUBLANG_SPANISH_EL_SALVADOR0x11„SUBLANG_SPANISH_HONDURAS0x12…SUBLANG_SPANISH_NICARAGUA0x13†SUBLANG_SPANISH_PUERTO_RICO0x14‡SUBLANG_SPANISH_US0x15ˆSUBLANG_SWAHILI_KENYA0x01‰SUBLANG_SWEDISH0x01ŠSUBLANG_SWEDISH_FINLAND0x02‹SUBLANG_SYRIAC_SYRIA0x01ŒSUBLANG_TAJIK_TAJIKISTAN0x01SUBLANG_TAMAZIGHT_ALGERIA_LATIN0x02ŽSUBLANG_TAMIL_INDIA0x01SUBLANG_TATAR_RUSSIA0x01SUBLANG_TELUGU_INDIA0x01‘SUBLANG_THAI_THAILAND0x01’SUBLANG_TIBETAN_PRC0x01“SUBLANG_TIGRIGNA_ERITREA0x02”SUBLANG_TSWANA_SOUTH_AFRICA0x01•SUBLANG_TURKISH_TURKEY0x01–SUBLANG_TURKMEN_TURKMENISTAN0x01—SUBLANG_UIGHUR_PRC0x01˜SUBLANG_UKRAINIAN_UKRAINE0x01™SUBLANG_UPPER_SORBIAN_GERMANY0x01šSUBLANG_URDU_PAKISTAN0x01›SUBLANG_URDU_INDIA0x02œSUBLANG_UZBEK_LATIN0x01SUBLANG_UZBEK_CYRILLIC0x02žSUBLANG_VIETNAMESE_VIETNAM0x01ŸSUBLANG_WELSH_UNITED_KINGDOM0x01 SUBLANG_WOLOF_SENEGAL0x01¡SUBLANG_XHOSA_SOUTH_AFRICA0x01¢SUBLANG_YAKUT_RUSSIA0x01£SUBLANG_YI_PRC0x01¤SUBLANG_YORUBA_NIGERIA0x01¥SUBLANG_ZULU_SOUTH_AFRICA0x01¦SORT_DEFAULT0x0±SORT_INVARIANT_MATH0x1³SORT_JAPANESE_XJIS0x0µSORT_JAPANESE_UNICODE0x1¶SORT_JAPANESE_RADICALSTROKE0x4·SORT_CHINESE_BIG50x0¹SORT_CHINESE_PRCP0x0ºSORT_CHINESE_UNICODE0x1»SORT_CHINESE_PRC0x2¼SORT_CHINESE_BOPOMOFO0x3½SORT_CHINESE_RADICALSTROKE0x4¾SORT_KOREAN_KSC0x0ÀSORT_KOREAN_UNICODE0x1ÁSORT_GERMAN_PHONE_BOOK0x1ÃSORT_HUNGARIAN_DEFAULT0x0ÅSORT_HUNGARIAN_TECHNICAL0x1ÆSORT_GEORGIAN_TRADITIONAL0x0ÈSORT_GEORGIAN_MODERN0x1É!!dlgs.hctlFirst0x0400ctlLast0x04ffpsh10x0400psh20x0401 psh30x0402!psh40x0403"psh50x0404#psh60x0405$psh70x0406%psh80x0407&psh90x0408'psh100x0409(psh110x040a)psh120x040b*psh130x040c+psh140x040d,psh150x040e-pshHelppsh15.psh160x040f/chx10x04104chx20x04115chx30x04126chx40x04137chx50x04148chx60x04159chx70x0416:chx80x0417;chx90x0418<chx100x0419=chx110x041a>chx120x041b?chx130x041c@chx140x041dAchx150x041eBchx160x041fCrad10x0420Hrad20x0421Irad30x0422Jrad40x0423Krad50x0424Lrad60x0425Mrad70x0426Nrad80x0427Orad90x0428Prad100x0429Qrad110x042aRrad120x042bSrad130x042cTrad140x042dUrad150x042eVrad160x042fWgrp10x0430\grp20x0431]grp30x0432^grp40x0433_frm10x0434`frm20x0435afrm30x0436bfrm40x0437crct10x0438drct20x0439erct30x043afrct40x043bgico10x043chico20x043diico30x043ejico40x043fkstc10x0440pstc20x0441qstc30x0442rstc40x0443sstc50x0444tstc60x0445ustc70x0446vstc80x0447wstc90x0448xstc100x0449ystc110x044azstc120x044b{stc130x044c|stc140x044d}stc150x044e~stc160x044fstc170x0450€stc180x0451stc190x0452‚stc200x0453ƒstc210x0454„stc220x0455…stc230x0456†stc240x0457‡stc250x0458ˆstc260x0459‰stc270x045aŠstc280x045b‹stc290x045cŒstc300x045dstc310x045eŽstc320x045flst10x0460”lst20x0461•lst30x0462–lst40x0463—lst50x0464˜lst60x0465™lst70x0466šlst80x0467›lst90x0468œlst100x0469lst110x046ažlst120x046bŸlst130x046c lst140x046d¡lst150x046e¢lst160x046f£cmb10x0470¨cmb20x0471©cmb30x0472ªcmb40x0473«cmb50x0474¬cmb60x0475­cmb70x0476®cmb80x0477¯cmb90x0478°cmb100x0479±cmb110x047a²cmb120x047b³cmb130x047c´cmb140x047dµcmb150x047e¶cmb160x047f·edt10x0480¼edt20x0481½edt30x0482¾edt40x0483¿edt50x0484Àedt60x0485Áedt70x0486Âedt80x0487Ãedt90x0488Äedt100x0489Åedt110x048aÆedt120x048bÇedt130x048cÈedt140x048dÉedt150x048eÊedt160x048fËscr10x0490Ðscr20x0491Ñscr30x0492Òscr40x0493Óscr50x0494Ôscr60x0495Õscr70x0496Öscr80x0497×ctl10x04A0ÜFILEOPENORD1536ÞMULTIFILEOPENORD1537ßPRINTDLGORD1538àPRNSETUPDLGORD1539áFINDDLGORD1540âREPLACEDLGORD1541ãFONTDLGORD1542äFORMATDLGORD311543åFORMATDLGORD301544æRUNDLGORD1545çPAGESETUPDLGORD1546êNEWFILEOPENORD1547ëPRINTDLGEXORD1549ìPAGESETUPDLGORDMOTIF1550íCOLORMGMTDLGORD1551îNEWFILEOPENV2ORD1552ïNEWFILEOPENV3ORD1553ôNEWFORMATDLGWITHLINK1591ùIDC_MANAGE_LINK1592ú!!winver.h!SpecStrings.h!sal_supp.h!!specstrings_supp.h!!sal.h_USE_DECLSPECS_FOR_SAL0_USE_ATTRIBUTES_FOR_SAL0’_In__Pre1_impl_(_$notnull) _Deref_pre2_impl_(_$valid, _$readaccess)«_In_opt__Pre_opt_valid_ _Deref_pre_readonly_¬_In_z__Pre_z_ _Deref_pre_readonly_°_In_opt_z__Pre_opt_z_ _Deref_pre_readonly_±_Out__Pre_cap_c_(1) _Pre_invalid_á_Out_opt__Pre_opt_cap_c_(1) _Pre_invalid_â_Inout__Prepost_valid_:_Inout_opt__Prepost_opt_valid_;_Inout_z__Prepost_z_?_Inout_opt_z__Prepost_opt_z_@_Ret__Ret_valid_†_Ret_opt__Ret_opt_valid_‡_Deref_out__Out_ _Deref_pre_invalid_ _Deref_post_valid_Ž_Deref_out_opt__Out_ _Deref_pre_invalid_ _Deref_post_opt_valid__Deref_opt_out__Out_opt_ _Deref_pre_invalid_ _Deref_post_valid__Deref_opt_out_opt__Out_opt_ _Deref_pre_invalid_ _Deref_post_opt_valid_‘_Deref_out_z__Out_ _Deref_pre_invalid_ _Deref_post_z_”_Deref_out_opt_z__Out_ _Deref_pre_invalid_ _Deref_post_opt_z_•_Deref_opt_out_z__Out_opt_ _Deref_pre_invalid_ _Deref_post_z_–_Deref_opt_out_opt_z__Out_opt_ _Deref_pre_invalid_ _Deref_post_opt_z_—_Check_return__Check_return_impl_ž_Printf_format_string__Printf_format_string_impl_¡_Scanf_format_string__Scanf_format_string_impl_¢_Scanf_s_format_string__Scanf_s_format_string_impl_£_In_bound__In_bound_impl_ª_Out_bound__Out_bound_impl_«_Ret_bound__Ret_bound_impl_¬_Deref_in_bound__Deref_in_bound_impl_­_Deref_out_bound__Deref_out_bound_impl_®_Deref_inout_bound__Deref_in_bound_ _Deref_out_bound_¯_Deref_ret_bound__Deref_ret_bound_impl_°_Pre_z__Pre2_impl_(_$notnull, _$zterm) _Deref_pre1_impl_(_$valid)Å_Pre_opt_z__Pre2_impl_(_$maybenull,_$zterm) _Deref_pre1_impl_(_$valid)Æ_Pre_valid__Pre1_impl_(_$notnull) _Deref_pre1_impl_(_$valid) _Pre_opt_valid__Pre1_impl_(_$maybenull) _Deref_pre1_impl_(_$valid)!_Pre_invalid__Deref_pre1_impl_(_$notvalid)#_Pre_notnull__Pre1_impl_(_$notnull)&_Pre_maybenull__Pre1_impl_(_$maybenull)'_Pre_null__Pre1_impl_(_$null)(_Pre_readonly__Pre1_impl_(_$readaccess)+_Pre_writeonly__Pre1_impl_(_$writeaccess),_Post_z__Post1_impl_(_$zterm) _Deref_post1_impl_(_$valid)4_Post_maybez__Post1_impl_(_$maybezterm)8_Post_ptr_invalid__Post1_impl_(_$notvalid)O_Post_valid__Deref_post1_impl_(_$valid)R_Post_invalid__Deref_post1_impl_(_$notvalid)S_Post_notnull__Post1_impl_(_$notnull)V_Ret_z__Ret2_impl_(_$notnull, _$zterm) _Deref_ret1_impl_(_$valid)^_Ret_opt_z__Ret2_impl_(_$maybenull,_$zterm) _Deref_ret1_impl_(_$valid)__Ret_valid__Ret1_impl_(_$notnull) _Deref_ret1_impl_(_$valid)”_Ret_opt_valid__Ret1_impl_(_$maybenull) _Deref_ret1_impl_(_$valid)•_Ret_notnull__Ret1_impl_(_$notnull)˜_Ret_maybenull__Ret1_impl_(_$maybenull)™_Ret_null__Ret1_impl_(_$null)š_Deref_pre_z__Deref_pre2_impl_(_$notnull, _$zterm) _Deref2_pre1_impl_(_$valid)¢_Deref_pre_opt_z__Deref_pre2_impl_(_$maybenull,_$zterm) _Deref2_pre1_impl_(_$valid)£_Deref_pre_valid__Deref_pre1_impl_(_$notnull) _Deref2_pre1_impl_(_$valid)ì_Deref_pre_opt_valid__Deref_pre1_impl_(_$maybenull) _Deref2_pre1_impl_(_$valid)í_Deref_pre_invalid__Deref2_pre1_impl_(_$notvalid)î_Deref_pre_notnull__Deref_pre1_impl_(_$notnull)ð_Deref_pre_maybenull__Deref_pre1_impl_(_$maybenull)ñ_Deref_pre_null__Deref_pre1_impl_(_$null)ò_Deref_pre_readonly__Deref_pre1_impl_(_$readaccess)õ_Deref_pre_writeonly__Deref_pre1_impl_(_$writeaccess)ö_Deref_post_z__Deref_post2_impl_(_$notnull, _$zterm) _Deref2_post1_impl_(_$valid)þ_Deref_post_opt_z__Deref_post2_impl_(_$maybenull,_$zterm) _Deref2_post1_impl_(_$valid)ÿ_Deref_post_valid__Deref_post1_impl_(_$notnull) _Deref2_post1_impl_(_$valid)H_Deref_post_opt_valid__Deref_post1_impl_(_$maybenull) _Deref2_post1_impl_(_$valid)I_Deref_post_notnull__Deref_post1_impl_(_$notnull)K_Deref_post_maybenull__Deref_post1_impl_(_$maybenull)L_Deref_post_null__Deref_post1_impl_(_$null)M_Deref_ret_z__Deref_ret2_impl_(_$notnull, _$zterm)S_Deref_ret_opt_z__Deref_ret2_impl_(_$maybenull,_$zterm)T_Deref2_pre_readonly__Deref2_pre1_impl_(_$readaccess)Y_Prepost_z__Pre_z_ _Post_z_b_Prepost_opt_z__Pre_opt_z_ _Post_z_c_Prepost_valid__Pre_valid_ _Post_valid_r_Prepost_opt_valid__Pre_opt_valid_ _Post_valid_s_Deref_prepost_z__Deref_pre_z_ _Deref_post_z_{_Deref_prepost_opt_z__Deref_pre_opt_z_ _Deref_post_opt_z_|_Deref_prepost_valid__Deref_pre_valid_ _Deref_post_valid_¡_Deref_prepost_opt_valid__Deref_pre_opt_valid_ _Deref_post_opt_valid_¢_Deref_inout_z__Deref_prepost_z_­__in__pre __valid __pre __deref __readonlyè__in_z__in __pre __nullterminatedë__in_nz__inî__out__ecount(1) __post __valid __refparamñ__out_z__post __valid __refparam __post __nullterminatedø__out_z_opt__post __valid __refparam __post __nullterminated __exceptthat __maybenullù__out_nz__post __valid __refparam __post__out_nz_opt__post __valid __refparam __post __exceptthat __maybenull__inout__pre __valid __post __valid __refparam__inout_z__inout __pre __nullterminated __post __nullterminated __inout_nz__inout__in_opt__in __exceptthat __maybenull__in_z_opt__in_opt __pre __nullterminated__in_nz_opt__in_opt__out_opt__out __exceptthat __maybenull__inout_opt__inout __exceptthat __maybenull+__inout_z_opt__inout_opt __pre __nullterminated __post __nullterminated2__inout_nz_opt__inout_opt6__deref_out__deref_ecount(1) __post __deref __valid __refparam;__deref_out_z__post __deref __valid __refparam __post __deref __nullterminatedB__deref_out_nz__deref_outE__deref_inout__notnull __elem_readableTo(1) __pre __deref __valid __post __deref __valid __refparamH__deref_inout_z__deref_inout __pre __deref __nullterminated __post __deref __nullterminatedI__deref_inout_nz__deref_inoutS__deref_out_opt__deref_out __post __deref __exceptthat __maybenullX__deref_out_z_opt__post __deref __valid __refparam __execeptthat __maybenull __post __deref __nullterminated___deref_out_nz_opt__deref_out_optb__deref_inout_opt__deref_inout __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenulle__deref_inout_z_opt__deref_inout_opt __pre __deref __nullterminated __post __deref __nullterminatedl__deref_inout_nz_opt__deref_inout_opto__deref_opt_out__deref_out __exceptthat __maybenullt__deref_opt_out_z__deref_opt_out __post __deref __nullterminatedu__deref_opt_inout__deref_inout __exceptthat __maybenull|__deref_opt_inout_z__deref_opt_inout __pre __deref __nullterminated __post __deref __nullterminatedƒ__deref_opt_inout_nz__deref_opt_inout†__deref_opt_out_opt__deref_out_opt __exceptthat __maybenull‹__deref_opt_out_z_opt__post __deref __valid __refparam __exceptthat __maybenull __pre __deref __exceptthat __maybenull __post __deref __exceptthat __maybenull __post __deref __nullterminated’__deref_opt_out_nz_opt__deref_opt_out_opt•__deref_opt_inout_opt__deref_inout_opt __exceptthat __maybenull˜__deref_opt_inout_z_opt__deref_opt_inout_opt __pre __deref __nullterminated __post __deref __nullterminatedŸ__deref_opt_inout_nz_opt__deref_opt_inout_opt¢__nullterminated__readableTo(sentinel(0))±__reserved__pre __null³__checkReturn__inner_checkReturn´__override__inner_override¶__callback__inner_callback·__fallthrough__inner_fallthrough¿!__SAL_H_FULL_VER140050727__deref_in__in __pre __deref __deref __readonly=__deref_in_opt__deref_in __pre __deref __exceptthat __maybenullU__deref_in_opt_out__deref_inout __pre __deref __exceptthat __maybenull __post __deref __notnullV__deref_opt_in__deref_in __exceptthat __maybenulla__deref_opt_in_opt__deref_in_opt __exceptthat __maybenulll__field_nullterminated__nullterminatedÙ__post_invalid__post __notvalidä__allocator__inner_allocatoræ__bound__inner_boundé__in_bound__pre __inner_boundë__out_bound__post __inner_boundì__deref_out_bound__post __deref __inner_boundí__rpc_entry__inner_control_entrypoint(RPC)__kernel_entry__inner_control_entrypoint(UserToKernel)__gdi_entry__inner_control_entrypoint(GDI)__encoded_pointer__inner_encoded__encoded_array__inner_encoded__field_encoded_pointer__inner_encoded__field_encoded_array__inner_encoded__deref_volatile__deref __volatile__deref_nonvolatile__deref __nonvolatile!driverspecs.h!sdv_driverspecs.h!__$drv_unit_internal_kernel_driver__drv_declspec("SAL_internal_kernel_driver")'__$drv_unit_kernel_code__drv_declspec("SAL_kernel") __drv_declspec("SAL_nodriver")5__$drv_unit_kernel_driver__drv_declspec("SAL_kernel") __drv_declspec("SAL_driver")9__$drv_unit_user_driver__drv_declspec("SAL_nokernel") __drv_declspec("SAL_driver")=__$drv_unit_user_code__drv_declspec("SAL_nokernel") __drv_declspec("SAL_nodriver")A__drv_IoGetDmaAdapter__post __drv_declspec("SAL_IoGetDmaAdapter")__drv_constant__pre __drv_declspec("SAL_constant(__yes)")9__drv_nonConstant__pre __drv_declspec("SAL_constant(__no)")?__drv_typeConst0S__drv_typeCond1T__drv_typeBitset2U__drv_typeExpr3V__drv_notPointer__pre __drv_declspec("SAL_mayBePointer(__no)")]__drv_isObjectPointer__drv_deref(__drv_notPointer)`__drv_aliasesMem__post __drv_declspec("SAL_IsAliased")m__drv_floatSaved__post __drv_declspec("SAL_floatSaved")˜__drv_floatRestored__post __drv_declspec("SAL_floatRestored")__drv_floatUsed__post __drv_declspec("SAL_floatUsed")£__drv_interlocked__pre __drv_declspec("SAL_interlocked")®__drv_inTry__pre __drv_declspec("SAL_inTry(__yes)")²__drv_notInTry__pre __drv_declspec("SAL_inTry(__no)")µ__drv_dispatchType_other__drv_dispatchType(-1)Ê!!!verrsrc.hVS_FILE_INFORT_VERSION VS_VERSION_INFO1 VS_USER_DEFINED100VS_FFI_SIGNATURE0xFEEF04BDLVS_FFI_STRUCVERSION0x00010000LVS_FFI_FILEFLAGSMASK0x0000003FLVS_FF_DEBUG0x00000001LVS_FF_PRERELEASE0x00000002LVS_FF_PATCHED0x00000004LVS_FF_PRIVATEBUILD0x00000008LVS_FF_INFOINFERRED0x00000010LVS_FF_SPECIALBUILD0x00000020LVOS_UNKNOWN0x00000000L"VOS_DOS0x00010000L#VOS_OS2160x00020000L$VOS_OS2320x00030000L%VOS_NT0x00040000L&VOS_WINCE0x00050000L'VOS__BASE0x00000000L)VOS__WINDOWS160x00000001L*VOS__PM160x00000002L+VOS__PM320x00000003L,VOS__WINDOWS320x00000004L-VOS_DOS_WINDOWS160x00010001L/VOS_DOS_WINDOWS320x00010004L0VOS_OS216_PM160x00020002L1VOS_OS232_PM320x00030003L2VOS_NT_WINDOWS320x00040004L3VFT_UNKNOWN0x00000000L6VFT_APP0x00000001L7VFT_DLL0x00000002L8VFT_DRV0x00000003L9VFT_FONT0x00000004L:VFT_VXD0x00000005L;VFT_STATIC_LIB0x00000007L<VFT2_UNKNOWN0x00000000L?VFT2_DRV_PRINTER0x00000001L@VFT2_DRV_KEYBOARD0x00000002LAVFT2_DRV_LANGUAGE0x00000003LBVFT2_DRV_DISPLAY0x00000004LCVFT2_DRV_MOUSE0x00000005LDVFT2_DRV_NETWORK0x00000006LEVFT2_DRV_SYSTEM0x00000007LFVFT2_DRV_INSTALLABLE0x00000008LGVFT2_DRV_SOUND0x00000009LHVFT2_DRV_COMM0x0000000ALIVFT2_DRV_INPUTMETHOD0x0000000BLJVFT2_DRV_VERSIONED_PRINTER0x0000000CLKVFT2_FONT_RASTER0x00000001LNVFT2_FONT_VECTOR0x00000002LOVFT2_FONT_TRUETYPE0x00000003LPVFFF_ISSHAREDFILE0x0001SVFF_CURNEDEST0x0001UVFF_FILEINUSE0x0002VVFF_BUFFTOOSMALL0x0004WVIFF_FORCEINSTALL0x0001ZVIFF_DONTDELETEOLD0x0002[VIF_TEMPFILE0x00000001L]VIF_MISMATCH0x00000002L^VIF_SRCOLD0x00000004L_VIF_DIFFLANG0x00000008LaVIF_DIFFCODEPG0x00000010LbVIF_DIFFTYPE0x00000020LcVIF_WRITEPROT0x00000040LeVIF_FILEINUSE0x00000080LfVIF_OUTOFSPACE0x00000100LgVIF_ACCESSVIOLATION0x00000200LhVIF_SHARINGVIOLATION0x00000400LiVIF_CANNOTCREATE0x00000800LjVIF_CANNOTDELETE0x00001000LkVIF_CANNOTRENAME0x00002000LlVIF_CANNOTDELETECUR0x00004000LmVIF_OUTOFMEMORY0x00008000LnVIF_CANNOTREADSRC0x00010000LpVIF_CANNOTREADDST0x00020000LqVIF_BUFFTOOSMALL0x00040000LsVIF_CANNOTLOADLZ320x00080000LtVIF_CANNOTLOADCABINET0x00100000Lu!!!!!ãÿæ$HWBÿÿÉ0ÿÿÿÿÿÿÿÿE:\official_irrlicht_windows\irrlicht\trunk\source\Irrlicht\resource.hÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\windows.hÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\sdkddkver.hÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\winresrc.hÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\winuser.rhÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\commctrl.rhÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\dde.rhÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\winnt.rhÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\dlgs.hÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\winver.hÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\SpecStrings.hÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\sal_supp.hÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\specstrings_supp.hÿÿÿÿÿÿÿÿD:\Programme\Microsoft Visual Studio 10.0\VC\include\sal.hÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\driverspecs.hÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\sdv_driverspecs.hÿÿÿÿÿÿÿÿD:\Programme\Microsoft SDKs\Windows\v7.0A\include\verrsrc.h©$HWBÿÿÊ0TEXTINCLUDE1$ÿÿTEXTINCLUDE2$ÿÿTEXTINCLUDE3$ÿÿ161VS_VERSION_INFOE:\official_irrlicht_windows\irrlicht\trunk\source\Irrlicht\Irrlicht.rc4$ÿÿ$ÿÿL$HWBÿÿ0LDHWBÿÿ ÄTEXTINCLUDEÿÿ0TEXTINCLUDEÿÿ0PTEXTINCLUDEÿÿ0ìtÿÿÿÿ0Ôà„HWBÿÿÈ0æ|åHWBÿÿÉ0©ˆîHWBÿÿÊ0irrlicht-1.8.3/source/Irrlicht/Irrlicht-gcc.cbp0000644000000000000000000014205412574354552020143 0ustar rootroot irrlicht-1.8.3/source/Irrlicht/IImagePresenter.h0000644000000000000000000000150412574354552020331 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_IMAGE_PRESENTER_H_INCLUDED__ #define __I_IMAGE_PRESENTER_H_INCLUDED__ #include "IImage.h" namespace irr { namespace video { /*! Interface for a class which is able to present an IImage an the Screen. Usually only implemented by an IrrDevice for presenting Software Device Rendered images. This class should be used only internally. */ class IImagePresenter { public: virtual ~IImagePresenter() {}; //! presents a surface in the client area virtual bool present(video::IImage* surface, void* windowId=0, core::rect* src=0 ) = 0; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/IDepthBuffer.h0000644000000000000000000000350112574354552017614 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_Z2_BUFFER_H_INCLUDED__ #define __I_Z2_BUFFER_H_INCLUDED__ #include "IReferenceCounted.h" #include "dimension2d.h" #include "S4DVertex.h" namespace irr { namespace video { class IDepthBuffer : public virtual IReferenceCounted { public: //! destructor virtual ~IDepthBuffer() {}; //! clears the zbuffer virtual void clear() = 0; //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size) = 0; //! returns the size of the zbuffer virtual const core::dimension2d& getSize() const = 0; //! locks the zbuffer virtual void* lock() = 0; //! unlocks the zbuffer virtual void unlock() = 0; //! returns pitch of depthbuffer (in bytes) virtual u32 getPitch() const = 0; }; //! creates a ZBuffer IDepthBuffer* createDepthBuffer(const core::dimension2d& size); class IStencilBuffer : public virtual IReferenceCounted { public: //! destructor virtual ~IStencilBuffer() {}; //! clears the zbuffer virtual void clear() = 0; //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size) = 0; //! returns the size of the zbuffer virtual const core::dimension2d& getSize() const = 0; //! locks the zbuffer virtual void* lock() = 0; //! unlocks the zbuffer virtual void unlock() = 0; //! returns pitch of depthbuffer (in bytes) virtual u32 getPitch() const = 0; }; //! creates a Stencil Buffer IStencilBuffer* createStencilBuffer(const core::dimension2d& size); } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/IBurningShader.h0000644000000000000000000001305012574354552020151 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_BURNING_SHADER_H_INCLUDED__ #define __I_BURNING_SHADER_H_INCLUDED__ #include "SoftwareDriver2_compile_config.h" #include "IReferenceCounted.h" #include "irrMath.h" #include "IImage.h" #include "S2DVertex.h" #include "rect.h" #include "CDepthBuffer.h" #include "S4DVertex.h" #include "irrArray.h" #include "SLight.h" #include "SMaterial.h" #include "os.h" namespace irr { namespace video { struct SBurningShaderLight { //SLight org; bool LightIsOn; E_LIGHT_TYPE Type; f32 radius; f32 linearAttenuation; f32 constantAttenuation; f32 quadraticAttenuation; sVec4 pos; sVec3 AmbientColor; sVec3 DiffuseColor; sVec3 SpecularColor; sVec4 pos_objectspace; }; enum eLightFlags { ENABLED = 0x01, POINTLIGHT = 0x02, SPECULAR = 0x04, FOG = 0x08, NORMALIZE = 0x10, VERTEXTRANSFORM = 0x20, }; struct SBurningShaderLightSpace { void reset () { Light.set_used ( 0 ); Global_AmbientLight.set ( 0.f, 0.f, 0.f ); Flags = 0; } core::array Light; sVec3 Global_AmbientLight; sVec4 FogColor; sVec4 campos; sVec4 vertex; sVec4 normal; u32 Flags; }; struct SBurningShaderMaterial { SMaterial org; sVec3 AmbientColor; sVec3 DiffuseColor; sVec3 SpecularColor; sVec3 EmissiveColor; }; enum EBurningFFShader { ETR_FLAT = 0, ETR_FLAT_WIRE, ETR_GOURAUD, ETR_GOURAUD_WIRE, ETR_TEXTURE_FLAT, ETR_TEXTURE_FLAT_WIRE, ETR_TEXTURE_GOURAUD, ETR_TEXTURE_GOURAUD_WIRE, ETR_TEXTURE_GOURAUD_NOZ, ETR_TEXTURE_GOURAUD_ADD, ETR_TEXTURE_GOURAUD_ADD_NO_Z, ETR_TEXTURE_GOURAUD_VERTEX_ALPHA, ETR_TEXTURE_GOURAUD_LIGHTMAP_M1, ETR_TEXTURE_GOURAUD_LIGHTMAP_M2, ETR_TEXTURE_GOURAUD_LIGHTMAP_M4, ETR_TEXTURE_LIGHTMAP_M4, ETR_TEXTURE_GOURAUD_DETAIL_MAP, ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD, ETR_GOURAUD_ALPHA, ETR_GOURAUD_ALPHA_NOZ, ETR_TEXTURE_GOURAUD_ALPHA, ETR_TEXTURE_GOURAUD_ALPHA_NOZ, ETR_NORMAL_MAP_SOLID, ETR_STENCIL_SHADOW, ETR_TEXTURE_BLEND, ETR_REFERENCE, ETR_INVALID, ETR2_COUNT }; class CBurningVideoDriver; class IBurningShader : public virtual IReferenceCounted { public: IBurningShader(CBurningVideoDriver* driver); //! destructor virtual ~IBurningShader(); //! sets a render target virtual void setRenderTarget(video::IImage* surface, const core::rect& viewPort); //! sets the Texture virtual void setTextureParam( u32 stage, video::CSoftwareTexture2* texture, s32 lodLevel); virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) = 0; virtual void drawLine ( const s4DVertex *a,const s4DVertex *b) {}; virtual void setParam ( u32 index, f32 value) {}; virtual void setZCompareFunc ( u32 func) {}; virtual void setMaterial ( const SBurningShaderMaterial &material ) {}; protected: CBurningVideoDriver *Driver; video::CImage* RenderTarget; CDepthBuffer* DepthBuffer; CStencilBuffer * Stencil; tVideoSample ColorMask; sInternalTexture IT[ BURNING_MATERIAL_MAX_TEXTURES ]; static const tFixPointu dithermask[ 4 * 4]; }; IBurningShader* createTriangleRendererTextureGouraud2(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererTextureLightMap2_M1(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererTextureLightMap2_M2(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererTextureLightMap2_M4(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererGTextureLightMap2_M4(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererTextureLightMap2_Add(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererTextureDetailMap2(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererTextureVertexAlpha2(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererTextureGouraudWire2(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererGouraud2(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererGouraudAlpha2(CBurningVideoDriver* driver); IBurningShader* createTRGouraudAlphaNoZ2(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererGouraudWire2(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererTextureFlat2(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererTextureFlatWire2(CBurningVideoDriver* driver); IBurningShader* createTRFlat2(CBurningVideoDriver* driver); IBurningShader* createTRFlatWire2(CBurningVideoDriver* driver); IBurningShader* createTRTextureGouraudNoZ2(CBurningVideoDriver* driver); IBurningShader* createTRTextureGouraudAdd2(CBurningVideoDriver* driver); IBurningShader* createTRTextureGouraudAddNoZ2(CBurningVideoDriver* driver); IBurningShader* createTRTextureGouraudAlpha(CBurningVideoDriver* driver); IBurningShader* createTRTextureGouraudAlphaNoZ(CBurningVideoDriver* driver); IBurningShader* createTRTextureBlend(CBurningVideoDriver* driver); IBurningShader* createTRTextureInverseAlphaBlend(CBurningVideoDriver* driver); IBurningShader* createTRNormalMap(CBurningVideoDriver* driver); IBurningShader* createTRStencilShadow(CBurningVideoDriver* driver); IBurningShader* createTriangleRendererReference(CBurningVideoDriver* driver); } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/IBurningShader.cpp0000644000000000000000000000550112574354552020506 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ #include "SoftwareDriver2_compile_config.h" #include "IBurningShader.h" #include "CSoftwareDriver2.h" namespace irr { namespace video { const tFixPointu IBurningShader::dithermask[] = { 0x00,0x80,0x20,0xa0, 0xc0,0x40,0xe0,0x60, 0x30,0xb0,0x10,0x90, 0xf0,0x70,0xd0,0x50 }; IBurningShader::IBurningShader(CBurningVideoDriver* driver) { #ifdef _DEBUG setDebugName("IBurningShader"); #endif for ( u32 i = 0; i != BURNING_MATERIAL_MAX_TEXTURES; ++i ) { IT[i].Texture = 0; } Driver = driver; RenderTarget = 0; ColorMask = COLOR_BRIGHT_WHITE; DepthBuffer = (CDepthBuffer*) driver->getDepthBuffer (); if ( DepthBuffer ) DepthBuffer->grab(); Stencil = (CStencilBuffer*) driver->getStencilBuffer (); if ( Stencil ) Stencil->grab(); } //! destructor IBurningShader::~IBurningShader() { if (RenderTarget) RenderTarget->drop(); if (DepthBuffer) DepthBuffer->drop(); if (Stencil) Stencil->drop(); for ( u32 i = 0; i != BURNING_MATERIAL_MAX_TEXTURES; ++i ) { if ( IT[i].Texture ) IT[i].Texture->drop(); } } //! sets a render target void IBurningShader::setRenderTarget(video::IImage* surface, const core::rect& viewPort) { if (RenderTarget) RenderTarget->drop(); RenderTarget = (video::CImage* ) surface; if (RenderTarget) { RenderTarget->grab(); //(tVideoSample*)RenderTarget->lock() = (tVideoSample*)RenderTarget->lock(); //(fp24*) DepthBuffer->lock() = DepthBuffer->lock(); } } //! sets the Texture void IBurningShader::setTextureParam( u32 stage, video::CSoftwareTexture2* texture, s32 lodLevel) { sInternalTexture *it = &IT[stage]; if ( it->Texture) it->Texture->drop(); it->Texture = texture; if ( it->Texture) { it->Texture->grab(); // select mignify and magnify ( lodLevel ) //SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS it->lodLevel = lodLevel; it->data = (tVideoSample*) it->Texture->lock(ETLM_READ_ONLY, core::s32_clamp ( lodLevel + SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS, 0, SOFTWARE_DRIVER_2_MIPMAPPING_MAX - 1 )); // prepare for optimal fixpoint it->pitchlog2 = s32_log2_s32 ( it->Texture->getPitch() ); const core::dimension2d &dim = it->Texture->getSize(); it->textureXMask = s32_to_fixPoint ( dim.Width - 1 ) & FIX_POINT_UNSIGNED_MASK; it->textureYMask = s32_to_fixPoint ( dim.Height - 1 ) & FIX_POINT_UNSIGNED_MASK; } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ irrlicht-1.8.3/source/Irrlicht/IAttribute.h0000644000000000000000000001022712574354552017364 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_ATTRIBUTE_H_INCLUDED__ #define __I_ATTRIBUTE_H_INCLUDED__ #include "IReferenceCounted.h" #include "SColor.h" #include "vector3d.h" #include "vector2d.h" #include "line2d.h" #include "line3d.h" #include "triangle3d.h" #include "position2d.h" #include "rect.h" #include "dimension2d.h" #include "matrix4.h" #include "quaternion.h" #include "plane3d.h" #include "triangle3d.h" #include "line2d.h" #include "line3d.h" #include "irrString.h" #include "irrArray.h" #include "EAttributes.h" namespace irr { namespace io { class IAttribute : public virtual IReferenceCounted { public: virtual ~IAttribute() {}; virtual s32 getInt() { return 0; } virtual f32 getFloat() { return 0; } virtual video::SColorf getColorf() { return video::SColorf(1.0f,1.0f,1.0f,1.0f); } virtual video::SColor getColor() { return video::SColor(255,255,255,255); } virtual core::stringc getString() { return core::stringc(getStringW().c_str()); } virtual core::stringw getStringW() { return core::stringw(); } virtual core::array getArray() { return core::array(); }; virtual bool getBool() { return false; } virtual void getBinary(void* outdata, s32 maxLength) {}; virtual core::vector3df getVector() { return core::vector3df(); } virtual core::position2di getPosition() { return core::position2di(); } virtual core::rect getRect() { return core::rect(); } virtual core::quaternion getQuaternion(){ return core::quaternion(); } virtual core::matrix4 getMatrix() { return core::matrix4(); } virtual core::triangle3df getTriangle() { return core::triangle3df(); } virtual core::vector2df getVector2d() { return core::vector2df(); } virtual core::vector2di getVector2di() { return core::vector2di(); } virtual core::line2df getLine2d() { return core::line2df(); } virtual core::line2di getLine2di() { return core::line2di(); } virtual core::line3df getLine3d() { return core::line3df(); } virtual core::line3di getLine3di() { return core::line3di(); } virtual core::dimension2du getDimension2d() { return core::dimension2du(); } virtual core::aabbox3d getBBox() { return core::aabbox3d(); } virtual core::plane3df getPlane() { return core::plane3df(); } virtual video::ITexture* getTexture() { return 0; } virtual const char* getEnum() { return 0; } virtual void* getUserPointer() { return 0; } virtual void setInt(s32 intValue) {}; virtual void setFloat(f32 floatValue) {}; virtual void setString(const char* text) {}; virtual void setString(const wchar_t* text){ setString(core::stringc(text).c_str()); }; virtual void setArray(const core::array& arr ) {}; virtual void setColor(video::SColorf color) {}; virtual void setColor(video::SColor color) {}; virtual void setBool(bool boolValue) {}; virtual void setBinary(void* data, s32 maxLenght) {}; virtual void setVector(core::vector3df v) {}; virtual void setPosition(core::position2di v) {}; virtual void setRect(core::rect v) {}; virtual void setQuaternion(core::quaternion v) {}; virtual void setMatrix(core::matrix4 v) {}; virtual void setTriangle(core::triangle3df v) {}; virtual void setVector2d(core::vector2df v) {}; virtual void setVector2d(core::vector2di v) {}; virtual void setLine2d(core::line2df v) {}; virtual void setLine2d(core::line2di v) {}; virtual void setLine3d(core::line3df v) {}; virtual void setLine3d(core::line3di v) {}; virtual void setDimension2d(core::dimension2du v) {}; virtual void setBBox(core::aabbox3d v) {}; virtual void setPlane(core::plane3df v) {}; virtual void setUserPointer(void* v) {}; virtual void setEnum(const char* enumValue, const char* const* enumerationLiterals) {}; virtual void setTexture(video::ITexture*, const path& filename) {}; core::stringc Name; virtual E_ATTRIBUTE_TYPE getType() const = 0; virtual const wchar_t* getTypeString() const = 0; }; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/dmfsupport.h0000644000000000000000000005201012574354552017507 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // This file was originally written by Salvatore Russo. // I (Nikolaus Gebhardt) did some minor modifications changes to it and integrated // it into Irrlicht: // - removed STL dependency // - removed log file and replaced it with irrlicht logging // - adapted code formatting a bit to Irrlicht style // - removed memory leaks // Thanks a lot to Salvatore for his work on this and that he gave me // his permission to add it into Irrlicht. // This support library has been made by Salvatore Russo and is released under GNU public license for general uses. // For uses in Irrlicht core and only for Irrlicht related uses I release this library under zlib license. #ifndef __DMF_SUPPORT_H_INCLUDED__ #define __DMF_SUPPORT_H_INCLUDED__ #include "irrString.h" #include "fast_atof.h" namespace irr { namespace scene { namespace { /** A structure representing some DeleD infos. This structure contains data about DeleD level file like: version, ambient color, number of objects etc...*/ struct dmfHeader { //main file header core::stringc dmfName; //! tileNum;//! StringList; //Loads a stringlist from a file //note that each String added to StringList //is separated by a \\n character and it's present //at the end of line. /** Loads a StringList from a file. This function loads a StringList from a file where each string is divided by a \\n char.*/ void LoadFromFile(io::IReadFile* file, StringList& strlist) { const long sz = file->getSize(); char* buf = new char[sz+1]; file->read(buf, sz); buf[sz] = 0; char* p = buf; char* start = p; while(*p) { if (*p == '\n') { core::stringc str(start, (u32)(p - start - 1)); str.trim(); strlist.push_back(str); start = p+1; } ++p; } if (p - start > 1) { core::stringc str(start, (u32)(p - start - 1)); str.trim(); strlist.push_back(str); } delete [] buf; }; //This function subdivides a string in a list of strings /** This function subdivides strings divided by divider in a list of strings. \return A StringList made of all strings divided by divider.*/ StringList SubdivideString(const core::stringc& str, const core::stringc& divider) { StringList strings; //returned StringList strings.clear(); //clear returned stringlist int c=0; int l=str.size(); //process entire string while(c& materials, int num_material) { // offset for already handled lines const int offs=4; StringList temp; StringList temp1; // The number of materials is predetermined materials.reallocate(num_material); for(int i=0; i=9) { temp1=SubdivideString(temp[temp.size() - 1],","); materials[i].lightmapFlag=atoi(temp1[0].c_str()); materials[i].lightmapName=temp1[1]; materials[i].lightmapName.replace('\\','/'); materials[i].lightmapBlend = atoi(temp1[2].c_str()); } else { materials[i].lightmapFlag=1; materials[i].lightmapName=""; } } return true; } /**This function extract an array of dmfMaterial from a DMF file considering 1st an 2nd layer for water plains. You must give in input a StringList representing a DMF file loaded with LoadFromFile. \return true if function succeed or false on fail.*/ bool GetDMFWaterMaterials(const StringList& RawFile /**& materials/**= 0.91 temp=SubdivideString(RawFile[0],";");//file info if ( temp[0] != "DeleD Map File" ) return false;//not a deled file temp.clear(); temp=SubdivideString(RawFile[1]," ");//get version temp1=SubdivideString(temp[1],";"); if (atof(temp1[0].c_str()) < 0.91) return false;//not correct version //end checking temp.clear(); temp1.clear(); for(int i=0;i pos; const u32 posCount = core::strtoul10(RawFile[offs].c_str()); ++offs; pos.reallocate(posCount); for (u32 i=0; i= 0.91 temp=SubdivideString(RawFile[0],";");//file info if ( temp[0] != "DeleD Map File" ) return false;//not a deled file temp.clear(); temp=SubdivideString(RawFile[1]," ");//get version temp1=SubdivideString(temp[1],";"); if (atof(temp1[0].c_str()) < 0.91) return false;//not correct version //end checking temp.clear(); temp1.clear(); offs=offs + atoi(RawFile[offs].c_str()); offs++; s32 objs = atoi(RawFile[offs].c_str()); s32 lit=0; s32 d_lit=0; offs++; //let's get position of lights in file int i; for(i=0;i= 0.91 temp=SubdivideString(RawFile[0],";");//file info if ( temp[0] != "DeleD Map File" ) return false;//not a deled file temp.clear(); temp=SubdivideString(RawFile[1]," ");//get version temp1=SubdivideString(temp[1],";"); if (atof(temp1[0].c_str()) < 0.91) return false;//not correct version //end checking temp.clear(); temp1.clear(); offs=offs+atoi(RawFile[offs].c_str()); offs++; s32 objs=atoi(RawFile[offs].c_str()); s32 fac=0,vert=0,tmp_sz=0,vert_cnt=0,face_cnt=0,wat_id=0; core::dimension2d tilenum(40,40); f32 waveheight=3.0f; f32 wavespeed=300.0f; f32 wavelength=80.0f; offs++; for(int i=0;i FileInfo; bool IsGZip; }; } // end namespace io } // end namespace irr #endif // __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ #endif // __C_ZIP_READER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CZipReader.cpp0000644000000000000000000005762012574354552017643 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CZipReader.h" #include "os.h" // This method is used for error output from bzip2. extern "C" void bz_internal_error(int errorCode) { irr::os::Printer::log("Error in bzip2 handling", irr::core::stringc(errorCode), irr::ELL_ERROR); } #ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ #include "CFileList.h" #include "CReadFile.h" #include "coreutil.h" #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_ZLIB_ #ifndef _IRR_USE_NON_SYSTEM_ZLIB_ #include // use system lib #else #include "zlib/zlib.h" #endif #ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ #include "aesGladman/fileenc.h" #endif #ifdef _IRR_COMPILE_WITH_BZIP2_ #ifndef _IRR_USE_NON_SYSTEM_BZLIB_ #include #else #include "bzip2/bzlib.h" #endif #endif #ifdef _IRR_COMPILE_WITH_LZMA_ #include "lzma/LzmaDec.h" #endif #endif namespace irr { namespace io { // ----------------------------------------------------------------------------- // zip loader // ----------------------------------------------------------------------------- //! Constructor CArchiveLoaderZIP::CArchiveLoaderZIP(io::IFileSystem* fs) : FileSystem(fs) { #ifdef _DEBUG setDebugName("CArchiveLoaderZIP"); #endif } //! returns true if the file maybe is able to be loaded by this class bool CArchiveLoaderZIP::isALoadableFileFormat(const io::path& filename) const { return core::hasFileExtension(filename, "zip", "pk3") || core::hasFileExtension(filename, "gz", "tgz"); } //! Check to see if the loader can create archives of this type. bool CArchiveLoaderZIP::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const { return (fileType == EFAT_ZIP || fileType == EFAT_GZIP); } //! Creates an archive from the filename /** \param file File handle to check. \return Pointer to newly created archive, or 0 upon error. */ IFileArchive* CArchiveLoaderZIP::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const { IFileArchive *archive = 0; io::IReadFile* file = FileSystem->createAndOpenFile(filename); if (file) { archive = createArchive(file, ignoreCase, ignorePaths); file->drop(); } return archive; } //! creates/loads an archive from the file. //! \return Pointer to the created archive. Returns 0 if loading failed. IFileArchive* CArchiveLoaderZIP::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const { IFileArchive *archive = 0; if (file) { file->seek(0); u16 sig; file->read(&sig, 2); #ifdef __BIG_ENDIAN__ sig = os::Byteswap::byteswap(sig); #endif file->seek(0); bool isGZip = (sig == 0x8b1f); archive = new CZipReader(file, ignoreCase, ignorePaths, isGZip); } return archive; } //! Check if the file might be loaded by this class /** Check might look into the file. \param file File handle to check. \return True if file seems to be loadable. */ bool CArchiveLoaderZIP::isALoadableFileFormat(io::IReadFile* file) const { SZIPFileHeader header; file->read( &header.Sig, 4 ); #ifdef __BIG_ENDIAN__ header.Sig = os::Byteswap::byteswap(header.Sig); #endif return header.Sig == 0x04034b50 || // ZIP (header.Sig&0xffff) == 0x8b1f; // gzip } // ----------------------------------------------------------------------------- // zip archive // ----------------------------------------------------------------------------- CZipReader::CZipReader(IReadFile* file, bool ignoreCase, bool ignorePaths, bool isGZip) : CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file), IsGZip(isGZip) { #ifdef _DEBUG setDebugName("CZipReader"); #endif if (File) { File->grab(); // load file entries if (IsGZip) while (scanGZipHeader()) { } else while (scanZipHeader()) { } sort(); } } CZipReader::~CZipReader() { if (File) File->drop(); } //! get the archive type E_FILE_ARCHIVE_TYPE CZipReader::getType() const { return IsGZip ? EFAT_GZIP : EFAT_ZIP; } const IFileList* CZipReader::getFileList() const { return this; } //! scans for a local header, returns false if there is no more local file header. //! The gzip file format seems to think that there can be multiple files in a gzip file //! but none bool CZipReader::scanGZipHeader() { SZipFileEntry entry; entry.Offset = 0; memset(&entry.header, 0, sizeof(SZIPFileHeader)); // read header SGZIPMemberHeader header; if (File->read(&header, sizeof(SGZIPMemberHeader)) == sizeof(SGZIPMemberHeader)) { #ifdef __BIG_ENDIAN__ header.sig = os::Byteswap::byteswap(header.sig); header.time = os::Byteswap::byteswap(header.time); #endif // check header value if (header.sig != 0x8b1f) return false; // now get the file info if (header.flags & EGZF_EXTRA_FIELDS) { // read lenth of extra data u16 dataLen; File->read(&dataLen, 2); #ifdef __BIG_ENDIAN__ dataLen = os::Byteswap::byteswap(dataLen); #endif // skip it File->seek(dataLen, true); } io::path ZipFileName = ""; if (header.flags & EGZF_FILE_NAME) { c8 c; File->read(&c, 1); while (c) { ZipFileName.append(c); File->read(&c, 1); } } else { // no file name? ZipFileName = Path; core::deletePathFromFilename(ZipFileName); // rename tgz to tar or remove gz extension if (core::hasFileExtension(ZipFileName, "tgz")) { ZipFileName[ ZipFileName.size() - 2] = 'a'; ZipFileName[ ZipFileName.size() - 1] = 'r'; } else if (core::hasFileExtension(ZipFileName, "gz")) { ZipFileName[ ZipFileName.size() - 3] = 0; ZipFileName.validate(); } } if (header.flags & EGZF_COMMENT) { c8 c='a'; while (c) File->read(&c, 1); } if (header.flags & EGZF_CRC16) File->seek(2, true); // we are now at the start of the data blocks entry.Offset = File->getPos(); entry.header.FilenameLength = ZipFileName.size(); entry.header.CompressionMethod = header.compressionMethod; entry.header.DataDescriptor.CompressedSize = (File->getSize() - 8) - File->getPos(); // seek to file end File->seek(entry.header.DataDescriptor.CompressedSize, true); // read CRC File->read(&entry.header.DataDescriptor.CRC32, 4); // read uncompressed size File->read(&entry.header.DataDescriptor.UncompressedSize, 4); #ifdef __BIG_ENDIAN__ entry.header.DataDescriptor.CRC32 = os::Byteswap::byteswap(entry.header.DataDescriptor.CRC32); entry.header.DataDescriptor.UncompressedSize = os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize); #endif // now we've filled all the fields, this is just a standard deflate block addItem(ZipFileName, entry.Offset, entry.header.DataDescriptor.UncompressedSize, false, 0); FileInfo.push_back(entry); } // there's only one block of data in a gzip file return false; } //! scans for a local header, returns false if there is no more local file header. bool CZipReader::scanZipHeader(bool ignoreGPBits) { io::path ZipFileName = ""; SZipFileEntry entry; entry.Offset = 0; memset(&entry.header, 0, sizeof(SZIPFileHeader)); File->read(&entry.header, sizeof(SZIPFileHeader)); #ifdef __BIG_ENDIAN__ entry.header.Sig = os::Byteswap::byteswap(entry.header.Sig); entry.header.VersionToExtract = os::Byteswap::byteswap(entry.header.VersionToExtract); entry.header.GeneralBitFlag = os::Byteswap::byteswap(entry.header.GeneralBitFlag); entry.header.CompressionMethod = os::Byteswap::byteswap(entry.header.CompressionMethod); entry.header.LastModFileTime = os::Byteswap::byteswap(entry.header.LastModFileTime); entry.header.LastModFileDate = os::Byteswap::byteswap(entry.header.LastModFileDate); entry.header.DataDescriptor.CRC32 = os::Byteswap::byteswap(entry.header.DataDescriptor.CRC32); entry.header.DataDescriptor.CompressedSize = os::Byteswap::byteswap(entry.header.DataDescriptor.CompressedSize); entry.header.DataDescriptor.UncompressedSize = os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize); entry.header.FilenameLength = os::Byteswap::byteswap(entry.header.FilenameLength); entry.header.ExtraFieldLength = os::Byteswap::byteswap(entry.header.ExtraFieldLength); #endif if (entry.header.Sig != 0x04034b50) return false; // local file headers end here. // read filename { c8 *tmp = new c8 [ entry.header.FilenameLength + 2 ]; File->read(tmp, entry.header.FilenameLength); tmp[entry.header.FilenameLength] = 0; ZipFileName = tmp; delete [] tmp; } #ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ // AES encryption if ((entry.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (entry.header.CompressionMethod == 99)) { s16 restSize = entry.header.ExtraFieldLength; SZipFileExtraHeader extraHeader; while (restSize) { File->read(&extraHeader, sizeof(extraHeader)); #ifdef __BIG_ENDIAN__ extraHeader.ID = os::Byteswap::byteswap(extraHeader.ID); extraHeader.Size = os::Byteswap::byteswap(extraHeader.Size); #endif restSize -= sizeof(extraHeader); if (extraHeader.ID==(s16)0x9901) { SZipFileAESExtraData data; File->read(&data, sizeof(data)); #ifdef __BIG_ENDIAN__ data.Version = os::Byteswap::byteswap(data.Version); data.CompressionMode = os::Byteswap::byteswap(data.CompressionMode); #endif restSize -= sizeof(data); if (data.Vendor[0]=='A' && data.Vendor[1]=='E') { // encode values into Sig // AE-Version | Strength | ActualMode entry.header.Sig = ((data.Version & 0xff) << 24) | (data.EncryptionStrength << 16) | (data.CompressionMode); File->seek(restSize, true); break; } } } } // move forward length of extra field. else #endif if (entry.header.ExtraFieldLength) File->seek(entry.header.ExtraFieldLength, true); // if bit 3 was set, use CentralDirectory for setup if (!ignoreGPBits && entry.header.GeneralBitFlag & ZIP_INFO_IN_DATA_DESCRIPTOR) { SZIPFileCentralDirEnd dirEnd; FileInfo.clear(); Files.clear(); // First place where the end record could be stored File->seek(File->getSize()-22); const char endID[] = {0x50, 0x4b, 0x05, 0x06, 0x0}; char tmp[5]={'\0'}; bool found=false; // search for the end record ID while (!found && File->getPos()>0) { int seek=8; File->read(tmp, 4); switch (tmp[0]) { case 0x50: if (!strcmp(endID, tmp)) { seek=4; found=true; } break; case 0x4b: seek=5; break; case 0x05: seek=6; break; case 0x06: seek=7; break; } File->seek(-seek, true); } File->read(&dirEnd, sizeof(dirEnd)); #ifdef __BIG_ENDIAN__ dirEnd.NumberDisk = os::Byteswap::byteswap(dirEnd.NumberDisk); dirEnd.NumberStart = os::Byteswap::byteswap(dirEnd.NumberStart); dirEnd.TotalDisk = os::Byteswap::byteswap(dirEnd.TotalDisk); dirEnd.TotalEntries = os::Byteswap::byteswap(dirEnd.TotalEntries); dirEnd.Size = os::Byteswap::byteswap(dirEnd.Size); dirEnd.Offset = os::Byteswap::byteswap(dirEnd.Offset); dirEnd.CommentLength = os::Byteswap::byteswap(dirEnd.CommentLength); #endif FileInfo.reallocate(dirEnd.TotalEntries); File->seek(dirEnd.Offset); while (scanCentralDirectoryHeader()) { } return false; } // store position in file entry.Offset = File->getPos(); // move forward length of data File->seek(entry.header.DataDescriptor.CompressedSize, true); #ifdef _DEBUG //os::Debuginfo::print("added file from archive", ZipFileName.c_str()); #endif addItem(ZipFileName, entry.Offset, entry.header.DataDescriptor.UncompressedSize, ZipFileName.lastChar()=='/', FileInfo.size()); FileInfo.push_back(entry); return true; } //! scans for a local header, returns false if there is no more local file header. bool CZipReader::scanCentralDirectoryHeader() { io::path ZipFileName = ""; SZIPFileCentralDirFileHeader entry; File->read(&entry, sizeof(SZIPFileCentralDirFileHeader)); #ifdef __BIG_ENDIAN__ entry.Sig = os::Byteswap::byteswap(entry.Sig); entry.VersionMadeBy = os::Byteswap::byteswap(entry.VersionMadeBy); entry.VersionToExtract = os::Byteswap::byteswap(entry.VersionToExtract); entry.GeneralBitFlag = os::Byteswap::byteswap(entry.GeneralBitFlag); entry.CompressionMethod = os::Byteswap::byteswap(entry.CompressionMethod); entry.LastModFileTime = os::Byteswap::byteswap(entry.LastModFileTime); entry.LastModFileDate = os::Byteswap::byteswap(entry.LastModFileDate); entry.CRC32 = os::Byteswap::byteswap(entry.CRC32); entry.CompressedSize = os::Byteswap::byteswap(entry.CompressedSize); entry.UncompressedSize = os::Byteswap::byteswap(entry.UncompressedSize); entry.FilenameLength = os::Byteswap::byteswap(entry.FilenameLength); entry.ExtraFieldLength = os::Byteswap::byteswap(entry.ExtraFieldLength); entry.FileCommentLength = os::Byteswap::byteswap(entry.FileCommentLength); entry.DiskNumberStart = os::Byteswap::byteswap(entry.DiskNumberStart); entry.InternalFileAttributes = os::Byteswap::byteswap(entry.InternalFileAttributes); entry.ExternalFileAttributes = os::Byteswap::byteswap(entry.ExternalFileAttributes); entry.RelativeOffsetOfLocalHeader = os::Byteswap::byteswap(entry.RelativeOffsetOfLocalHeader); #endif if (entry.Sig != 0x02014b50) return false; // central dir headers end here. const long pos = File->getPos(); File->seek(entry.RelativeOffsetOfLocalHeader); scanZipHeader(true); File->seek(pos+entry.FilenameLength+entry.ExtraFieldLength+entry.FileCommentLength); FileInfo.getLast().header.DataDescriptor.CompressedSize=entry.CompressedSize; FileInfo.getLast().header.DataDescriptor.UncompressedSize=entry.UncompressedSize; FileInfo.getLast().header.DataDescriptor.CRC32=entry.CRC32; Files.getLast().Size=entry.UncompressedSize; return true; } //! opens a file by file name IReadFile* CZipReader::createAndOpenFile(const io::path& filename) { s32 index = findFile(filename, false); if (index != -1) return createAndOpenFile(index); return 0; } #ifdef _IRR_COMPILE_WITH_LZMA_ //! Used for LZMA decompression. The lib has no default memory management namespace { void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } void SzFree(void *p, void *address) { p = p; free(address); } ISzAlloc lzmaAlloc = { SzAlloc, SzFree }; } #endif //! opens a file by index IReadFile* CZipReader::createAndOpenFile(u32 index) { // Irrlicht supports 0, 8, 12, 14, 99 //0 - The file is stored (no compression) //1 - The file is Shrunk //2 - The file is Reduced with compression factor 1 //3 - The file is Reduced with compression factor 2 //4 - The file is Reduced with compression factor 3 //5 - The file is Reduced with compression factor 4 //6 - The file is Imploded //7 - Reserved for Tokenizing compression algorithm //8 - The file is Deflated //9 - Reserved for enhanced Deflating //10 - PKWARE Date Compression Library Imploding //12 - bzip2 - Compression Method from libbz2, WinZip 10 //14 - LZMA - Compression Method, WinZip 12 //96 - Jpeg compression - Compression Method, WinZip 12 //97 - WavPack - Compression Method, WinZip 11 //98 - PPMd - Compression Method, WinZip 10 //99 - AES encryption, WinZip 9 const SZipFileEntry &e = FileInfo[Files[index].ID]; wchar_t buf[64]; s16 actualCompressionMethod=e.header.CompressionMethod; IReadFile* decrypted=0; u8* decryptedBuf=0; u32 decryptedSize=e.header.DataDescriptor.CompressedSize; #ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ if ((e.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (e.header.CompressionMethod == 99)) { os::Printer::log("Reading encrypted file."); u8 salt[16]={0}; const u16 saltSize = (((e.header.Sig & 0x00ff0000) >>16)+1)*4; File->seek(e.Offset); File->read(salt, saltSize); char pwVerification[2]; char pwVerificationFile[2]; File->read(pwVerification, 2); fcrypt_ctx zctx; // the encryption context int rc = fcrypt_init( (e.header.Sig & 0x00ff0000) >>16, (const unsigned char*)Password.c_str(), // the password Password.size(), // number of bytes in password salt, // the salt (unsigned char*)pwVerificationFile, // on return contains password verifier &zctx); // encryption context if (strncmp(pwVerificationFile, pwVerification, 2)) { os::Printer::log("Wrong password"); return 0; } decryptedSize= e.header.DataDescriptor.CompressedSize-saltSize-12; decryptedBuf= new u8[decryptedSize]; u32 c = 0; while ((c+32768)<=decryptedSize) { File->read(decryptedBuf+c, 32768); fcrypt_decrypt( decryptedBuf+c, // pointer to the data to decrypt 32768, // how many bytes to decrypt &zctx); // decryption context c+=32768; } File->read(decryptedBuf+c, decryptedSize-c); fcrypt_decrypt( decryptedBuf+c, // pointer to the data to decrypt decryptedSize-c, // how many bytes to decrypt &zctx); // decryption context char fileMAC[10]; char resMAC[10]; rc = fcrypt_end( (unsigned char*)resMAC, // on return contains the authentication code &zctx); // encryption context if (rc != 10) { os::Printer::log("Error on encryption closing"); delete [] decryptedBuf; return 0; } File->read(fileMAC, 10); if (strncmp(fileMAC, resMAC, 10)) { os::Printer::log("Error on encryption check"); delete [] decryptedBuf; return 0; } decrypted = io::createMemoryReadFile(decryptedBuf, decryptedSize, Files[index].FullName, true); actualCompressionMethod = (e.header.Sig & 0xffff); #if 0 if ((e.header.Sig & 0xff000000)==0x01000000) { } else if ((e.header.Sig & 0xff000000)==0x02000000) { } else { os::Printer::log("Unknown encryption method"); return 0; } #endif } #endif switch(actualCompressionMethod) { case 0: // no compression { if (decrypted) return decrypted; else return createLimitReadFile(Files[index].FullName, File, e.Offset, decryptedSize); } case 8: { #ifdef _IRR_COMPILE_WITH_ZLIB_ const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; c8* pBuf = new c8[ uncompressedSize ]; if (!pBuf) { swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); os::Printer::log( buf, ELL_ERROR); if (decrypted) decrypted->drop(); return 0; } u8 *pcData = decryptedBuf; if (!pcData) { pcData = new u8[decryptedSize]; if (!pcData) { swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); os::Printer::log( buf, ELL_ERROR); delete [] pBuf; return 0; } //memset(pcData, 0, decryptedSize); File->seek(e.Offset); File->read(pcData, decryptedSize); } // Setup the inflate stream. z_stream stream; s32 err; stream.next_in = (Bytef*)pcData; stream.avail_in = (uInt)decryptedSize; stream.next_out = (Bytef*)pBuf; stream.avail_out = uncompressedSize; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; // Perform inflation. wbits < 0 indicates no zlib header inside the data. err = inflateInit2(&stream, -MAX_WBITS); if (err == Z_OK) { err = inflate(&stream, Z_FINISH); inflateEnd(&stream); if (err == Z_STREAM_END) err = Z_OK; err = Z_OK; inflateEnd(&stream); } if (decrypted) decrypted->drop(); else delete[] pcData; if (err != Z_OK) { swprintf ( buf, 64, L"Error decompressing %s", Files[index].FullName.c_str() ); os::Printer::log( buf, ELL_ERROR); delete [] pBuf; return 0; } else return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); #else return 0; // zlib not compiled, we cannot decompress the data. #endif } case 12: { #ifdef _IRR_COMPILE_WITH_BZIP2_ const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; c8* pBuf = new c8[ uncompressedSize ]; if (!pBuf) { swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); os::Printer::log( buf, ELL_ERROR); if (decrypted) decrypted->drop(); return 0; } u8 *pcData = decryptedBuf; if (!pcData) { pcData = new u8[decryptedSize]; if (!pcData) { swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); os::Printer::log( buf, ELL_ERROR); delete [] pBuf; return 0; } //memset(pcData, 0, decryptedSize); File->seek(e.Offset); File->read(pcData, decryptedSize); } bz_stream bz_ctx={0}; /* use BZIP2's default memory allocation bz_ctx->bzalloc = NULL; bz_ctx->bzfree = NULL; bz_ctx->opaque = NULL; */ int err = BZ2_bzDecompressInit(&bz_ctx, 0, 0); /* decompression */ if(err != BZ_OK) { os::Printer::log("bzip2 decompression failed. File cannot be read.", ELL_ERROR); return 0; } bz_ctx.next_in = (char*)pcData; bz_ctx.avail_in = decryptedSize; /* pass all input to decompressor */ bz_ctx.next_out = pBuf; bz_ctx.avail_out = uncompressedSize; err = BZ2_bzDecompress(&bz_ctx); err = BZ2_bzDecompressEnd(&bz_ctx); if (decrypted) decrypted->drop(); else delete[] pcData; if (err != BZ_OK) { swprintf ( buf, 64, L"Error decompressing %s", Files[index].FullName.c_str() ); os::Printer::log( buf, ELL_ERROR); delete [] pBuf; return 0; } else return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); #else os::Printer::log("bzip2 decompression not supported. File cannot be read.", ELL_ERROR); return 0; #endif } case 14: { #ifdef _IRR_COMPILE_WITH_LZMA_ u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; c8* pBuf = new c8[ uncompressedSize ]; if (!pBuf) { swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); os::Printer::log( buf, ELL_ERROR); if (decrypted) decrypted->drop(); return 0; } u8 *pcData = decryptedBuf; if (!pcData) { pcData = new u8[decryptedSize]; if (!pcData) { swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); os::Printer::log( buf, ELL_ERROR); delete [] pBuf; return 0; } //memset(pcData, 0, decryptedSize); File->seek(e.Offset); File->read(pcData, decryptedSize); } ELzmaStatus status; SizeT tmpDstSize = uncompressedSize; SizeT tmpSrcSize = decryptedSize; unsigned int propSize = (pcData[3]<<8)+pcData[2]; int err = LzmaDecode((Byte*)pBuf, &tmpDstSize, pcData+4+propSize, &tmpSrcSize, pcData+4, propSize, e.header.GeneralBitFlag&0x1?LZMA_FINISH_END:LZMA_FINISH_ANY, &status, &lzmaAlloc); uncompressedSize = tmpDstSize; // may be different to expected value if (decrypted) decrypted->drop(); else delete[] pcData; if (err != SZ_OK) { os::Printer::log( "Error decompressing", Files[index].FullName, ELL_ERROR); delete [] pBuf; return 0; } else return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); #else os::Printer::log("lzma decompression not supported. File cannot be read.", ELL_ERROR); return 0; #endif } case 99: // If we come here with an encrypted file, decryption support is missing os::Printer::log("Decryption support not enabled. File cannot be read.", ELL_ERROR); return 0; default: swprintf ( buf, 64, L"file has unsupported compression method. %s", Files[index].FullName.c_str() ); os::Printer::log( buf, ELL_ERROR); return 0; }; } } // end namespace io } // end namespace irr #endif // __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ irrlicht-1.8.3/source/Irrlicht/CZBuffer.h0000644000000000000000000000201012574354552016745 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_Z_BUFFER_H_INCLUDED__ #define __C_Z_BUFFER_H_INCLUDED__ #include "IZBuffer.h" namespace irr { namespace video { class CZBuffer : public IZBuffer { public: //! constructor CZBuffer(const core::dimension2d& size); //! destructor virtual ~CZBuffer(); //! clears the zbuffer virtual void clear(); //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size); //! returns the size of the zbuffer virtual const core::dimension2d& getSize() const; //! locks the zbuffer virtual TZBufferType* lock(); //! unlocks the zbuffer virtual void unlock(); private: TZBufferType* Buffer; TZBufferType* BufferEnd; core::dimension2d Size; s32 TotalSize; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CZBuffer.cpp0000644000000000000000000000325112574354552017310 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CZBuffer.h" #include "irrString.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! constructor CZBuffer::CZBuffer(const core::dimension2d& size) : Buffer(0), BufferEnd(0), Size(0,0), TotalSize(0) { #ifdef _DEBUG setDebugName("CZBuffer"); #endif setSize(size); } //! destructor CZBuffer::~CZBuffer() { delete [] Buffer; } //! clears the zbuffer void CZBuffer::clear() { memset(Buffer, 0, (BufferEnd-Buffer)*sizeof(TZBufferType)); } //! sets the new size of the zbuffer void CZBuffer::setSize(const core::dimension2d& size) { if (size == Size) return; Size = size; delete [] Buffer; TotalSize = size.Width * size.Height; Buffer = new TZBufferType[TotalSize]; BufferEnd = Buffer + TotalSize; } //! returns the size of the zbuffer const core::dimension2d& CZBuffer::getSize() const { return Size; } //! locks the zbuffer TZBufferType* CZBuffer::lock() { return Buffer; } //! unlocks the zbuffer void CZBuffer::unlock() { } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! creates a ZBuffer IZBuffer* createZBuffer(const core::dimension2d& size) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CZBuffer(size); #else return 0; #endif // _IRR_COMPILE_WITH_SOFTWARE_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CXMLWriter.h0000644000000000000000000000410712574354552017250 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_XML_WRITER_H_INCLUDED__ #define __C_XML_WRITER_H_INCLUDED__ #include #include "IXMLWriter.h" #include "IWriteFile.h" namespace irr { namespace io { //! Interface providing methods for making it easier to write XML files. class CXMLWriter : public IXMLWriter { public: //! Constructor CXMLWriter(IWriteFile* file); //! Destructor virtual ~CXMLWriter(); //! Writes a xml 1.0 header like virtual void writeXMLHeader(); //! Writes an xml element with maximal 5 attributes virtual void writeElement(const wchar_t* name, bool empty=false, const wchar_t* attr1Name = 0, const wchar_t* attr1Value = 0, const wchar_t* attr2Name = 0, const wchar_t* attr2Value = 0, const wchar_t* attr3Name = 0, const wchar_t* attr3Value = 0, const wchar_t* attr4Name = 0, const wchar_t* attr4Value = 0, const wchar_t* attr5Name = 0, const wchar_t* attr5Value = 0); //! Writes an xml element with any number of attributes virtual void writeElement(const wchar_t* name, bool empty, core::array &names, core::array &values); //! Writes a comment into the xml file virtual void writeComment(const wchar_t* comment); //! Writes the closing tag for an element. Like virtual void writeClosingTag(const wchar_t* name); //! Writes a text into the file. All occurrences of special characters like //! & (&), < (<), > (>), and " (") are automaticly replaced. virtual void writeText(const wchar_t* text); //! Writes a line break virtual void writeLineBreak(); struct XMLSpecialCharacters { wchar_t Character; const wchar_t* Symbol; }; private: void writeAttribute(const wchar_t* att, const wchar_t* name); IWriteFile* File; s32 Tabs; bool TextWrittenLast; }; } // end namespace irr } // end namespace io #endif irrlicht-1.8.3/source/Irrlicht/CXMLWriter.cpp0000644000000000000000000001243412574354552017605 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CXMLWriter.h" #include #include "irrString.h" #include "IrrCompileConfig.h" namespace irr { namespace io { //! Constructor CXMLWriter::CXMLWriter(IWriteFile* file) : File(file), Tabs(0), TextWrittenLast(false) { #ifdef _DEBUG setDebugName("CXMLWriter"); #endif if (File) File->grab(); } //! Destructor CXMLWriter::~CXMLWriter() { if (File) File->drop(); } //! Writes a xml 1.0 header like void CXMLWriter::writeXMLHeader() { if (!File) return; if (sizeof(wchar_t)==2) { const u16 h = 0xFEFF; File->write(&h, 2); } else { const u32 h = 0x0000FEFF; File->write(&h, sizeof(wchar_t)); } const wchar_t* const p = L""; File->write(p, wcslen(p)*sizeof(wchar_t)); writeLineBreak(); TextWrittenLast = false; } //! Writes an xml element with maximal 5 attributes void CXMLWriter::writeElement(const wchar_t* name, bool empty, const wchar_t* attr1Name, const wchar_t* attr1Value, const wchar_t* attr2Name, const wchar_t* attr2Value, const wchar_t* attr3Name, const wchar_t* attr3Value, const wchar_t* attr4Name, const wchar_t* attr4Value, const wchar_t* attr5Name, const wchar_t* attr5Value) { if (!File || !name) return; if (Tabs > 0) { for (int i=0; iwrite(L"\t", sizeof(wchar_t)); } // write name File->write(L"<", sizeof(wchar_t)); File->write(name, wcslen(name)*sizeof(wchar_t)); // write attributes writeAttribute(attr1Name, attr1Value); writeAttribute(attr2Name, attr2Value); writeAttribute(attr3Name, attr3Value); writeAttribute(attr4Name, attr4Value); writeAttribute(attr5Name, attr5Value); // write closing tag if (empty) File->write(L" />", 3*sizeof(wchar_t)); else { File->write(L">", sizeof(wchar_t)); ++Tabs; } TextWrittenLast = false; } //! Writes an xml element with any number of attributes void CXMLWriter::writeElement(const wchar_t* name, bool empty, core::array &names, core::array &values) { if (!File || !name) return; if (Tabs > 0) { for (int i=0; iwrite(L"\t", sizeof(wchar_t)); } // write name File->write(L"<", sizeof(wchar_t)); File->write(name, wcslen(name)*sizeof(wchar_t)); // write attributes u32 i=0; for (; i < names.size() && i < values.size(); ++i) writeAttribute(names[i].c_str(), values[i].c_str()); // write closing tag if (empty) File->write(L" />", 3*sizeof(wchar_t)); else { File->write(L">", sizeof(wchar_t)); ++Tabs; } TextWrittenLast = false; } void CXMLWriter::writeAttribute(const wchar_t* name, const wchar_t* value) { if (!name || !value) return; File->write(L" ", sizeof(wchar_t)); File->write(name, wcslen(name)*sizeof(wchar_t)); File->write(L"=\"", 2*sizeof(wchar_t)); writeText(value); File->write(L"\"", sizeof(wchar_t)); } //! Writes a comment into the xml file void CXMLWriter::writeComment(const wchar_t* comment) { if (!File || !comment) return; File->write(L"", 3*sizeof(wchar_t)); } //! Writes the closing tag for an element. Like void CXMLWriter::writeClosingTag(const wchar_t* name) { if (!File || !name) return; --Tabs; if (Tabs > 0 && !TextWrittenLast) { for (int i=0; iwrite(L"\t", sizeof(wchar_t)); } File->write(L"write(name, wcslen(name)*sizeof(wchar_t)); File->write(L">", sizeof(wchar_t)); TextWrittenLast = false; } const CXMLWriter::XMLSpecialCharacters XMLWSChar[] = { { L'&', L"&" }, { L'<', L"<" }, { L'>', L">" }, { L'"', L""" }, { L'\0', 0 } }; //! Writes a text into the file. All occurrences of special characters like //! & (&), < (<), > (>), and " (") are automaticly replaced. void CXMLWriter::writeText(const wchar_t* text) { if (!File || !text) return; // TODO: we have to get rid of that reserve call as well as it slows down xml-writing seriously. // Making a member-variable would work, but a lot of memory would stay around after writing. // So the correct solution is probably using fixed block here and always write when that is full. core::stringw s; s.reserve(wcslen(text)+1); const wchar_t* p = text; while(*p) { // check if it is matching bool found = false; for (s32 i=0; XMLWSChar[i].Character != '\0'; ++i) if (*p == XMLWSChar[i].Character) { s.append(XMLWSChar[i].Symbol); found = true; break; } if (!found) s.append(*p); ++p; } // write new string File->write(s.c_str(), s.size()*sizeof(wchar_t)); TextWrittenLast = true; } //! Writes a line break void CXMLWriter::writeLineBreak() { if (!File) return; #if defined(_IRR_OSX_PLATFORM_) File->write(L"\r", sizeof(wchar_t)); #elif defined(_IRR_WINDOWS_API_) File->write(L"\r\n", 2*sizeof(wchar_t)); #else File->write(L"\n", sizeof(wchar_t)); #endif } } // end namespace irr } // end namespace io irrlicht-1.8.3/source/Irrlicht/CXMLReaderImpl.h0000644000000000000000000004472512574354552020032 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h #ifndef __ICXML_READER_IMPL_H_INCLUDED__ #define __ICXML_READER_IMPL_H_INCLUDED__ #include "irrXML.h" #include "irrString.h" #include "irrArray.h" #include "fast_atof.h" #ifdef _DEBUG #define IRR_DEBUGPRINT(x) printf((x)); #else // _DEBUG #define IRR_DEBUGPRINT(x) #endif // _DEBUG namespace irr { namespace io { //! implementation of the IrrXMLReader template class CXMLReaderImpl : public IIrrXMLReader { public: //! Constructor CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) : IgnoreWhitespaceText(true), TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE), SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII), IsEmptyElement(false) { if (!callback) return; storeTargetFormat(); // read whole xml file readFile(callback); // clean up if (deleteCallBack) delete callback; // create list with special characters createSpecialCharacterList(); // set pointer to text begin P = TextBegin; } //! Destructor virtual ~CXMLReaderImpl() { delete [] TextData; } //! Reads forward to the next xml node. //! \return Returns false, if there was no further node. virtual bool read() { // if not end reached, parse the node if (P && ((unsigned int)(P - TextBegin) < TextSize - 1) && (*P != 0)) { return parseCurrentNode(); } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } //! Returns the type of the current XML node. virtual EXML_NODE getNodeType() const { return CurrentNodeType; } //! Returns attribute count of the current XML node. virtual unsigned int getAttributeCount() const { return Attributes.size(); } //! Returns name of an attribute. virtual const char_type* getAttributeName(int idx) const { if ((u32)idx >= Attributes.size()) return 0; return Attributes[idx].Name.c_str(); } //! Returns the value of an attribute. virtual const char_type* getAttributeValue(int idx) const { if ((unsigned int)idx >= Attributes.size()) return 0; return Attributes[idx].Value.c_str(); } //! Returns the value of an attribute. virtual const char_type* getAttributeValue(const char_type* name) const { const SAttribute* attr = getAttributeByName(name); if (!attr) return 0; return attr->Value.c_str(); } //! Returns the value of an attribute virtual const char_type* getAttributeValueSafe(const char_type* name) const { const SAttribute* attr = getAttributeByName(name); if (!attr) return EmptyString.c_str(); return attr->Value.c_str(); } //! Returns the value of an attribute as integer. int getAttributeValueAsInt(const char_type* name) const { const SAttribute* attr = getAttributeByName(name); if (!attr) return 0; core::stringc c(attr->Value.c_str()); return core::strtol10(c.c_str()); } //! Returns the value of an attribute as integer. int getAttributeValueAsInt(int idx) const { const char_type* attrvalue = getAttributeValue(idx); if (!attrvalue) return 0; core::stringc c(attrvalue); return core::strtol10(c.c_str()); } //! Returns the value of an attribute as float. float getAttributeValueAsFloat(const char_type* name) const { const SAttribute* attr = getAttributeByName(name); if (!attr) return 0; core::stringc c = attr->Value.c_str(); return core::fast_atof(c.c_str()); } //! Returns the value of an attribute as float. float getAttributeValueAsFloat(int idx) const { const char_type* attrvalue = getAttributeValue(idx); if (!attrvalue) return 0; core::stringc c = attrvalue; return core::fast_atof(c.c_str()); } //! Returns the name of the current node. virtual const char_type* getNodeName() const { return NodeName.c_str(); } //! Returns data of the current node. virtual const char_type* getNodeData() const { return NodeName.c_str(); } //! Returns if an element is an empty element, like virtual bool isEmptyElement() const { return IsEmptyElement; } //! Returns format of the source xml file. virtual ETEXT_FORMAT getSourceFormat() const { return SourceFormat; } //! Returns format of the strings returned by the parser. virtual ETEXT_FORMAT getParserFormat() const { return TargetFormat; } private: // Reads the current xml node // return false if no further node is found bool parseCurrentNode() { char_type* start = P; // more forward until '<' found while(*P != L'<' && *P) ++P; // not a node, so return false if (!*P) return false; if (P - start > 0) { // we found some text, store it if (setText(start, P)) return true; } ++P; // based on current token, parse and report next element switch(*P) { case L'/': parseClosingXMLElement(); break; case L'?': ignoreDefinition(); break; case L'!': if (!parseCDATA()) parseComment(); break; default: parseOpeningXMLElement(); break; } return true; } //! sets the state that text was found. Returns true if set should be set bool setText(char_type* start, char_type* end) { // By default xml preserves all whitespace. But Irrlicht dropped some whitespace by default // in the past which did lead to OS dependent behavior. We just ignore all whitespace for now // as it's the closest to fixing behavior without breaking downward compatibility too much. if ( IgnoreWhitespaceText ) { char_type* p = start; for(; p != end; ++p) if (!isWhiteSpace(*p)) break; if (p == end) return false; } // set current text to the parsed text, and replace xml special characters core::string s(start, (int)(end - start)); NodeName = replaceSpecialCharacters(s); // current XML node type is text CurrentNodeType = EXN_TEXT; return true; } //! ignores an xml definition like void ignoreDefinition() { CurrentNodeType = EXN_UNKNOWN; // move until end marked with '>' reached while(*P != L'>') ++P; ++P; } //! parses a comment void parseComment() { CurrentNodeType = EXN_COMMENT; P += 1; char_type *pCommentBegin = P; int count = 1; // move until end of comment reached while(count) { if (*P == L'>') --count; else if (*P == L'<') ++count; ++P; } P -= 3; NodeName = core::string(pCommentBegin+2, (int)(P - pCommentBegin-2)); P += 3; } //! parses an opening xml element and reads attributes void parseOpeningXMLElement() { CurrentNodeType = EXN_ELEMENT; IsEmptyElement = false; Attributes.clear(); // find name const char_type* startName = P; // find end of element while(*P != L'>' && !isWhiteSpace(*P)) ++P; const char_type* endName = P; // find Attributes while(*P != L'>') { if (isWhiteSpace(*P)) ++P; else { if (*P != L'/') { // we've got an attribute // read the attribute names const char_type* attributeNameBegin = P; while(!isWhiteSpace(*P) && *P != L'=') ++P; const char_type* attributeNameEnd = P; ++P; // read the attribute value // check for quotes and single quotes, thx to murphy while( (*P != L'\"') && (*P != L'\'') && *P) ++P; if (!*P) // malformatted xml file return; const char_type attributeQuoteChar = *P; ++P; const char_type* attributeValueBegin = P; while(*P != attributeQuoteChar && *P) ++P; if (!*P) // malformatted xml file return; const char_type* attributeValueEnd = P; ++P; SAttribute attr; attr.Name = core::string(attributeNameBegin, (int)(attributeNameEnd - attributeNameBegin)); core::string s(attributeValueBegin, (int)(attributeValueEnd - attributeValueBegin)); attr.Value = replaceSpecialCharacters(s); Attributes.push_back(attr); } else { // tag is closed directly ++P; IsEmptyElement = true; break; } } } // check if this tag is closing directly if (endName > startName && *(endName-1) == L'/') { // directly closing tag IsEmptyElement = true; endName--; } NodeName = core::string(startName, (int)(endName - startName)); ++P; } //! parses an closing xml tag void parseClosingXMLElement() { CurrentNodeType = EXN_ELEMENT_END; IsEmptyElement = false; Attributes.clear(); ++P; const char_type* pBeginClose = P; while(*P != L'>') ++P; NodeName = core::string(pBeginClose, (int)(P - pBeginClose)); ++P; } //! parses a possible CDATA section, returns false if begin was not a CDATA section bool parseCDATA() { if (*(P+1) != L'[') return false; CurrentNodeType = EXN_CDATA; // skip '' && (*(P-1) == L']') && (*(P-2) == L']')) { cDataEnd = P - 2; } ++P; } if ( cDataEnd ) NodeName = core::string(cDataBegin, (int)(cDataEnd - cDataBegin)); else NodeName = ""; return true; } // structure for storing attribute-name pairs struct SAttribute { core::string Name; core::string Value; }; // finds a current attribute by name, returns 0 if not found const SAttribute* getAttributeByName(const char_type* name) const { if (!name) return 0; core::string n = name; for (int i=0; i<(int)Attributes.size(); ++i) if (Attributes[i].Name == n) return &Attributes[i]; return 0; } // replaces xml special characters in a string and creates a new one core::string replaceSpecialCharacters( core::string& origstr) { int pos = origstr.findFirst(L'&'); int oldPos = 0; if (pos == -1) return origstr; core::string newstr; while(pos != -1 && pos < (int)origstr.size()-2) { // check if it is one of the special characters int specialChar = -1; for (int i=0; i<(int)SpecialCharacters.size(); ++i) { const char_type* p = &origstr.c_str()[pos]+1; if (equalsn(&SpecialCharacters[i][1], p, SpecialCharacters[i].size()-1)) { specialChar = i; break; } } if (specialChar != -1) { newstr.append(origstr.subString(oldPos, pos - oldPos)); newstr.append(SpecialCharacters[specialChar][0]); pos += SpecialCharacters[specialChar].size(); } else { newstr.append(origstr.subString(oldPos, pos - oldPos + 1)); pos += 1; } // find next & oldPos = pos; pos = origstr.findNext(L'&', pos); } if (oldPos < (int)origstr.size()-1) newstr.append(origstr.subString(oldPos, origstr.size()-oldPos)); return newstr; } //! reads the xml file and converts it into the wanted character format. bool readFile(IFileReadCallBack* callback) { long size = callback->getSize(); if (size<0) return false; size += 4; // We need four terminating 0's at the end. // For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4. char* data8 = new char[size]; if (!callback->read(data8, size-4)) { delete [] data8; return false; } // add zeros at end memset(data8+size-4, 0, 4); char16* data16 = reinterpret_cast(data8); char32* data32 = reinterpret_cast(data8); // now we need to convert the data to the desired target format // based on the byte order mark. const unsigned char UTF8[] = {0xEF, 0xBB, 0xBF}; // 0xEFBBBF; const u16 UTF16_BE = 0xFFFE; const u16 UTF16_LE = 0xFEFF; const u32 UTF32_BE = 0xFFFE0000; const u32 UTF32_LE = 0x0000FEFF; // check source for all utf versions and convert to target data format if (size >= 4 && data32[0] == static_cast(UTF32_BE)) { // UTF-32, big endian SourceFormat = ETF_UTF32_BE; convertTextData(data32+1, data8, (size/4)-1); // data32+1 because we need to skip the header } else if (size >= 4 && data32[0] == static_cast(UTF32_LE)) { // UTF-32, little endian SourceFormat = ETF_UTF32_LE; convertTextData(data32+1, data8, (size/4)-1); // data32+1 because we need to skip the header } else if (size >= 2 && data16[0] == UTF16_BE) { // UTF-16, big endian SourceFormat = ETF_UTF16_BE; convertTextData(data16+1, data8, (size/2)-1); // data16+1 because we need to skip the header } else if (size >= 2 && data16[0] == UTF16_LE) { // UTF-16, little endian SourceFormat = ETF_UTF16_LE; convertTextData(data16+1, data8, (size/2)-1); // data16+1 because we need to skip the header } else if (size >= 3 && memcmp(data8,UTF8,3)==0) { // UTF-8 SourceFormat = ETF_UTF8; convertTextData(data8+3, data8, size-3); // data8+3 because we need to skip the header } else { // ASCII SourceFormat = ETF_ASCII; convertTextData(data8, data8, size); } return true; } //! converts the text file into the desired format. /** \param source: begin of the text (without byte order mark) \param pointerToStore: pointer to text data block which can be stored or deleted based on the nesessary conversion. \param sizeWithoutHeader: Text size in characters without header */ template void convertTextData(src_char_type* source, char* pointerToStore, int sizeWithoutHeader) { // convert little to big endian if necessary if (sizeof(src_char_type) > 1 && isLittleEndian(TargetFormat) != isLittleEndian(SourceFormat)) convertToLittleEndian(source); // check if conversion is necessary: if (sizeof(src_char_type) == sizeof(char_type)) { // no need to convert TextBegin = (char_type*)source; TextData = (char_type*)pointerToStore; TextSize = sizeWithoutHeader; } else { // convert source into target data format. // TODO: implement a real conversion. This one just // copies bytes. This is a problem when there are // unicode symbols using more than one character. TextData = new char_type[sizeWithoutHeader]; if ( sizeof(src_char_type) == 1 ) { // we have to cast away negative numbers or results might add the sign instead of just doing a copy for (int i=0; i(static_cast(source[i])); } } else { for (int i=0; i(source[i]); } TextBegin = TextData; TextSize = sizeWithoutHeader; // delete original data because no longer needed delete [] pointerToStore; } } //! converts whole text buffer to little endian template void convertToLittleEndian(src_char_type* t) { if (sizeof(src_char_type) == 4) { // 32 bit while(*t) { *t = ((*t & 0xff000000) >> 24) | ((*t & 0x00ff0000) >> 8) | ((*t & 0x0000ff00) << 8) | ((*t & 0x000000ff) << 24); ++t; } } else { // 16 bit while(*t) { *t = (*t >> 8) | (*t << 8); ++t; } } } //! returns if a format is little endian inline bool isLittleEndian(ETEXT_FORMAT f) { return f == ETF_ASCII || f == ETF_UTF8 || f == ETF_UTF16_LE || f == ETF_UTF32_LE; } //! returns true if a character is whitespace inline bool isWhiteSpace(char_type c) { return (c==' ' || c=='\t' || c=='\n' || c=='\r'); } //! generates a list with xml special characters void createSpecialCharacterList() { // list of strings containing special symbols, // the first character is the special character, // the following is the symbol string without trailing &. SpecialCharacters.push_back("&"); SpecialCharacters.push_back("gt;"); SpecialCharacters.push_back("\"quot;"); SpecialCharacters.push_back("'apos;"); } //! compares the first n characters of the strings bool equalsn(const char_type* str1, const char_type* str2, int len) { int i; for(i=0; str1[i] && str2[i] && i < len; ++i) if (str1[i] != str2[i]) return false; // if one (or both) of the strings was smaller then they // are only equal if they have the same lenght return (i == len) || (str1[i] == 0 && str2[i] == 0); } //! stores the target text format void storeTargetFormat() { // get target format. We could have done this using template specialization, // but VisualStudio 6 don't like it and we want to support it. switch(sizeof(char_type)) { case 1: TargetFormat = ETF_UTF8; break; case 2: TargetFormat = ETF_UTF16_LE; break; case 4: TargetFormat = ETF_UTF32_LE; break; default: TargetFormat = ETF_ASCII; // should never happen. } } // instance variables: bool IgnoreWhitespaceText; // do not return EXN_TEXT nodes for pure whitespace char_type* TextData; // data block of the text file char_type* P; // current point in text to parse char_type* TextBegin; // start of text to parse unsigned int TextSize; // size of text to parse in characters, not bytes EXML_NODE CurrentNodeType; // type of the currently parsed node ETEXT_FORMAT SourceFormat; // source format of the xml file ETEXT_FORMAT TargetFormat; // output format of this parser core::string NodeName; // name of the node currently in - also used for text core::string EmptyString; // empty string to be returned by getSafe() methods bool IsEmptyElement; // is the currently parsed node empty? core::array< core::string > SpecialCharacters; // see createSpecialCharacterList() core::array Attributes; // attributes of current element }; // end CXMLReaderImpl } // end namespace } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/CXMLReader.h0000644000000000000000000000105712574354552017177 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_XML_READER_H_INCLUDED__ #define __C_XML_READER_H_INCLUDED__ #include "IXMLReader.h" namespace irr { namespace io { class IReadFile; //! creates an IXMLReader IXMLReader* createIXMLReader(IReadFile* file); //! creates an IXMLReader IXMLReaderUTF8* createIXMLReaderUTF8(IReadFile* file); } // end namespace irr } // end namespace io #endif irrlicht-1.8.3/source/Irrlicht/CXMLReader.cpp0000644000000000000000000000312212574354552017525 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CXMLReaderImpl.h" #include "CXMLReader.h" #include "IReadFile.h" namespace irr { namespace io { //! Irrlicht implementation of the file read callback for the xml parser class CIrrXMLFileReadCallBack : public IFileReadCallBack { public: //! construct from FILE pointer CIrrXMLFileReadCallBack(IReadFile* file) : ReadFile(file) { ReadFile->grab(); } //! destructor virtual ~CIrrXMLFileReadCallBack() { ReadFile->drop(); } //! Reads an amount of bytes from the file. virtual int read(void* buffer, int sizeToRead) { return ReadFile->read(buffer, sizeToRead); } //! Returns size of file in bytes virtual long getSize() const { return ReadFile->getSize(); } private: IReadFile* ReadFile; }; // end class CMyXMLFileReadCallBack // now create an implementation for IXMLReader using irrXML. //! Creates an instance of a wide character xml parser. IXMLReader* createIXMLReader(IReadFile* file) { if (!file) return 0; return new CXMLReaderImpl(new CIrrXMLFileReadCallBack(file)); } //! Creates an instance of an UFT-8 or ASCII character xml parser. IXMLReaderUTF8* createIXMLReaderUTF8(IReadFile* file) { if (!file) return 0; return new CXMLReaderImpl(new CIrrXMLFileReadCallBack(file)); } } // end namespace } // end namespace irrlicht-1.8.3/source/Irrlicht/CXMeshFileLoader.h0000644000000000000000000001243712574354552020373 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_X_MESH_FILE_LOADER_H_INCLUDED__ #define __C_X_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "irrString.h" #include "CSkinnedMesh.h" namespace irr { namespace io { class IFileSystem; class IReadFile; } // end namespace io namespace scene { class IMeshManipulator; //! Meshloader capable of loading x meshes. class CXMeshFileLoader : public IMeshLoader { public: //! Constructor CXMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); struct SXTemplateMaterial { core::stringc Name; // template name from Xfile video::SMaterial Material; // material }; struct SXMesh { SXMesh() : MaxSkinWeightsPerVertex(0), MaxSkinWeightsPerFace(0), BoneCount(0),AttachedJointID(-1),HasSkinning(false), HasVertexColors(false) {} // this mesh contains triangulated texture data. // because in an .x file, faces can be made of more than 3 // vertices, the indices data structure is triangulated during the // loading process. The IndexCountPerFace array is filled during // this triangulation process and stores how much indices belong to // every face. This data structure can be ignored, because all data // in this structure is triangulated. core::stringc Name; u32 MaxSkinWeightsPerVertex; u32 MaxSkinWeightsPerFace; u32 BoneCount; core::array IndexCountPerFace; // default 3, but could be more core::array Buffers; core::array Vertices; core::array TCoords2; core::array Indices; core::array FaceMaterialIndices; // index of material for each face core::array Materials; // material array core::array WeightJoint; core::array WeightNum; s32 AttachedJointID; bool HasSkinning; bool HasVertexColors; }; private: bool load(io::IReadFile* file); bool readFileIntoMemory(io::IReadFile* file); bool parseFile(); bool parseDataObject(); bool parseDataObjectTemplate(); bool parseDataObjectFrame(CSkinnedMesh::SJoint *parent); bool parseDataObjectTransformationMatrix(core::matrix4 &mat); bool parseDataObjectMesh(SXMesh &mesh); bool parseDataObjectSkinWeights(SXMesh &mesh); bool parseDataObjectSkinMeshHeader(SXMesh &mesh); bool parseDataObjectMeshNormals(SXMesh &mesh); bool parseDataObjectMeshTextureCoords(SXMesh &mesh); bool parseDataObjectMeshVertexColors(SXMesh &mesh); bool parseDataObjectMeshMaterialList(SXMesh &mesh); bool parseDataObjectMaterial(video::SMaterial& material); bool parseDataObjectAnimationSet(); bool parseDataObjectAnimation(); bool parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint); bool parseDataObjectTextureFilename(core::stringc& texturename); bool parseUnknownDataObject(); //! places pointer to next begin of a token, and ignores comments void findNextNoneWhiteSpace(); //! places pointer to next begin of a token, which must be a number, // and ignores comments void findNextNoneWhiteSpaceNumber(); //! returns next parseable token. Returns empty string if no token there core::stringc getNextToken(); //! reads header of dataobject including the opening brace. //! returns false if error happened, and writes name of object //! if there is one bool readHeadOfDataObject(core::stringc* outname=0); //! checks for closing curly brace, returns false if not there bool checkForClosingBrace(); //! checks for one following semicolons, returns false if not there bool checkForOneFollowingSemicolons(); //! checks for two following semicolons, returns false if they are not there bool checkForTwoFollowingSemicolons(); //! reads a x file style string bool getNextTokenAsString(core::stringc& out); void readUntilEndOfLine(); u16 readBinWord(); u32 readBinDWord(); u32 readInt(); f32 readFloat(); bool readVector2(core::vector2df& vec); bool readVector3(core::vector3df& vec); bool readMatrix(core::matrix4& mat); bool readRGB(video::SColor& color); bool readRGBA(video::SColor& color); ISceneManager* SceneManager; io::IFileSystem* FileSystem; core::array *AllJoints; CSkinnedMesh* AnimatedMesh; c8* Buffer; const c8* P; c8* End; // counter for number arrays in binary format u32 BinaryNumCount; u32 Line; io::path FilePath; CSkinnedMesh::SJoint *CurFrame; core::array Meshes; core::array TemplateMaterials; u32 MajorVersion; u32 MinorVersion; bool BinaryFormat; c8 FloatSize; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CXMeshFileLoader.cpp0000644000000000000000000016522212574354552020727 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_X_LOADER_ #include "CXMeshFileLoader.h" #include "os.h" #include "fast_atof.h" #include "coreutil.h" #include "ISceneManager.h" #include "IVideoDriver.h" #include "IFileSystem.h" #include "IReadFile.h" #ifdef _DEBUG #define _XREADER_DEBUG #endif //#define BETTER_MESHBUFFER_SPLITTING_FOR_X namespace irr { namespace scene { //! Constructor CXMeshFileLoader::CXMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) : SceneManager(smgr), FileSystem(fs), AllJoints(0), AnimatedMesh(0), Buffer(0), P(0), End(0), BinaryNumCount(0), Line(0), CurFrame(0), MajorVersion(0), MinorVersion(0), BinaryFormat(false), FloatSize(0) { #ifdef _DEBUG setDebugName("CXMeshFileLoader"); #endif } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool CXMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "x" ); } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* CXMeshFileLoader::createMesh(io::IReadFile* f) { if (!f) return 0; #ifdef _XREADER_DEBUG u32 time = os::Timer::getRealTime(); #endif AnimatedMesh = new CSkinnedMesh(); if (load(f)) { AnimatedMesh->finalize(); } else { AnimatedMesh->drop(); AnimatedMesh = 0; } #ifdef _XREADER_DEBUG time = os::Timer::getRealTime() - time; core::stringc tmpString = "Time to load "; tmpString += BinaryFormat ? "binary" : "ascii"; tmpString += " X file: "; tmpString += time; tmpString += "ms"; os::Printer::log(tmpString.c_str()); #endif //Clear up MajorVersion=0; MinorVersion=0; BinaryFormat=0; BinaryNumCount=0; FloatSize=0; P=0; End=0; CurFrame=0; TemplateMaterials.clear(); delete [] Buffer; Buffer = 0; for (u32 i=0; iMaterials.size()) { mesh->Materials.push_back(video::SMaterial()); mesh->Materials[0].DiffuseColor.set(0xff777777); mesh->Materials[0].Shininess=0.f; mesh->Materials[0].SpecularColor.set(0xff777777); mesh->Materials[0].EmissiveColor.set(0xff000000); } u32 i; mesh->Buffers.reallocate(mesh->Materials.size()); #ifndef BETTER_MESHBUFFER_SPLITTING_FOR_X const u32 bufferOffset = AnimatedMesh->getMeshBufferCount(); #endif for (i=0; iMaterials.size(); ++i) { mesh->Buffers.push_back( AnimatedMesh->addMeshBuffer() ); mesh->Buffers.getLast()->Material = mesh->Materials[i]; if (!mesh->HasSkinning) { //Set up rigid animation if (mesh->AttachedJointID!=-1) { AnimatedMesh->getAllJoints()[mesh->AttachedJointID]->AttachedMeshes.push_back( AnimatedMesh->getMeshBuffers().size()-1 ); } } } if (!mesh->FaceMaterialIndices.size()) { mesh->FaceMaterialIndices.set_used(mesh->Indices.size() / 3); for (i=0; iFaceMaterialIndices.size(); ++i) mesh->FaceMaterialIndices[i]=0; } if (!mesh->HasVertexColors) { for (u32 j=0;jFaceMaterialIndices.size();++j) { for (u32 id=j*3+0;id<=j*3+2;++id) { mesh->Vertices[ mesh->Indices[id] ].Color = mesh->Buffers[mesh->FaceMaterialIndices[j]]->Material.DiffuseColor; } } } #ifdef BETTER_MESHBUFFER_SPLITTING_FOR_X { //the same vertex can be used in many different meshbuffers, but it's slow to work out core::array< core::array< u32 > > verticesLinkIndex; verticesLinkIndex.reallocate(mesh->Vertices.size()); core::array< core::array< u16 > > verticesLinkBuffer; verticesLinkBuffer.reallocate(mesh->Vertices.size()); for (i=0;iVertices.size();++i) { verticesLinkIndex.push_back( core::array< u32 >() ); verticesLinkBuffer.push_back( core::array< u16 >() ); } for (i=0;iFaceMaterialIndices.size();++i) { for (u32 id=i*3+0;id<=i*3+2;++id) { core::array< u16 > &Array=verticesLinkBuffer[ mesh->Indices[id] ]; bool found=false; for (u32 j=0; j < Array.size(); ++j) { if (Array[j]==mesh->FaceMaterialIndices[i]) { found=true; break; } } if (!found) Array.push_back( mesh->FaceMaterialIndices[i] ); } } for (i=0;iVertices.size();++i) { core::array< u16 > &Array = verticesLinkBuffer[i]; verticesLinkIndex[i].reallocate(Array.size()); for (u32 j=0; j < Array.size(); ++j) { scene::SSkinMeshBuffer *buffer = mesh->Buffers[ Array[j] ]; verticesLinkIndex[i].push_back( buffer->Vertices_Standard.size() ); buffer->Vertices_Standard.push_back( mesh->Vertices[i] ); } } for (i=0;iFaceMaterialIndices.size();++i) { scene::SSkinMeshBuffer *buffer=mesh->Buffers[ mesh->FaceMaterialIndices[i] ]; for (u32 id=i*3+0;id<=i*3+2;++id) { core::array< u16 > &Array=verticesLinkBuffer[ mesh->Indices[id] ]; for (u32 j=0;j< Array.size() ;++j) { if ( Array[j]== mesh->FaceMaterialIndices[i] ) buffer->Indices.push_back( verticesLinkIndex[ mesh->Indices[id] ][j] ); } } } for (u32 j=0;jWeightJoint.size();++j) { ISkinnedMesh::SJoint* joint = AnimatedMesh->getAllJoints()[mesh->WeightJoint[j]]; ISkinnedMesh::SWeight& weight = joint->Weights[mesh->WeightNum[j]]; u32 id = weight.vertex_id; if (id>=verticesLinkIndex.size()) { os::Printer::log("X loader: Weight id out of range", ELL_WARNING); id=0; weight.strength=0.f; } if (verticesLinkBuffer[id].size()==1) { weight.vertex_id=verticesLinkIndex[id][0]; weight.buffer_id=verticesLinkBuffer[id][0]; } else if (verticesLinkBuffer[id].size() != 0) { for (u32 k=1; k < verticesLinkBuffer[id].size(); ++k) { ISkinnedMesh::SWeight* WeightClone = AnimatedMesh->addWeight(joint); WeightClone->strength = weight.strength; WeightClone->vertex_id = verticesLinkIndex[id][k]; WeightClone->buffer_id = verticesLinkBuffer[id][k]; } } } } #else { core::array< u32 > verticesLinkIndex; core::array< s16 > verticesLinkBuffer; verticesLinkBuffer.set_used(mesh->Vertices.size()); // init with 0 for (i=0;iVertices.size();++i) { // watch out for vertices which are not part of the mesh // they will keep the -1 and can lead to out-of-bounds access verticesLinkBuffer[i]=-1; } bool warned = false; // store meshbuffer number per vertex for (i=0;iFaceMaterialIndices.size();++i) { for (u32 id=i*3+0;id<=i*3+2;++id) { if ((verticesLinkBuffer[mesh->Indices[id]] != -1) && (verticesLinkBuffer[mesh->Indices[id]] != (s16)mesh->FaceMaterialIndices[i])) { if (!warned) { os::Printer::log("X loader", "Duplicated vertex, animation might be corrupted.", ELL_WARNING); warned=true; } const u32 tmp = mesh->Vertices.size(); mesh->Vertices.push_back(mesh->Vertices[ mesh->Indices[id] ]); mesh->Indices[id] = tmp; verticesLinkBuffer.set_used(mesh->Vertices.size()); } verticesLinkBuffer[ mesh->Indices[id] ] = mesh->FaceMaterialIndices[i]; } } if (mesh->FaceMaterialIndices.size() != 0) { // store vertices in buffers and remember relation in verticesLinkIndex u32* vCountArray = new u32[mesh->Buffers.size()]; memset(vCountArray, 0, mesh->Buffers.size()*sizeof(u32)); // count vertices in each buffer and reallocate for (i=0; iVertices.size(); ++i) { if (verticesLinkBuffer[i] != -1) ++vCountArray[verticesLinkBuffer[i]]; } if (mesh->TCoords2.size()) { for (i=0; i!=mesh->Buffers.size(); ++i) { mesh->Buffers[i]->Vertices_2TCoords.reallocate(vCountArray[i]); mesh->Buffers[i]->VertexType=video::EVT_2TCOORDS; } } else { for (i=0; i!=mesh->Buffers.size(); ++i) mesh->Buffers[i]->Vertices_Standard.reallocate(vCountArray[i]); } verticesLinkIndex.set_used(mesh->Vertices.size()); // actually store vertices for (i=0; iVertices.size(); ++i) { // if a vertex is missing for some reason, just skip it if (verticesLinkBuffer[i]==-1) continue; scene::SSkinMeshBuffer *buffer = mesh->Buffers[ verticesLinkBuffer[i] ]; if (mesh->TCoords2.size()) { verticesLinkIndex[i] = buffer->Vertices_2TCoords.size(); buffer->Vertices_2TCoords.push_back( mesh->Vertices[i] ); // We have a problem with correct tcoord2 handling here // crash fixed for now by checking the values buffer->Vertices_2TCoords.getLast().TCoords2=(iTCoords2.size())?mesh->TCoords2[i]:mesh->Vertices[i].TCoords; } else { verticesLinkIndex[i] = buffer->Vertices_Standard.size(); buffer->Vertices_Standard.push_back( mesh->Vertices[i] ); } } // count indices per buffer and reallocate memset(vCountArray, 0, mesh->Buffers.size()*sizeof(u32)); for (i=0; iFaceMaterialIndices.size(); ++i) ++vCountArray[ mesh->FaceMaterialIndices[i] ]; for (i=0; i!=mesh->Buffers.size(); ++i) mesh->Buffers[i]->Indices.reallocate(vCountArray[i]); delete [] vCountArray; // create indices per buffer for (i=0; iFaceMaterialIndices.size(); ++i) { scene::SSkinMeshBuffer *buffer = mesh->Buffers[ mesh->FaceMaterialIndices[i] ]; for (u32 id=i*3+0; id!=i*3+3; ++id) { buffer->Indices.push_back( verticesLinkIndex[ mesh->Indices[id] ] ); } } } for (u32 j=0; jWeightJoint.size(); ++j) { ISkinnedMesh::SWeight& weight = (AnimatedMesh->getAllJoints()[mesh->WeightJoint[j]]->Weights[mesh->WeightNum[j]]); u32 id = weight.vertex_id; if (id>=verticesLinkIndex.size()) { os::Printer::log("X loader: Weight id out of range", ELL_WARNING); id=0; weight.strength=0.f; } weight.vertex_id=verticesLinkIndex[id]; weight.buffer_id=verticesLinkBuffer[id] + bufferOffset; } } #endif } return true; } //! Reads file into memory bool CXMeshFileLoader::readFileIntoMemory(io::IReadFile* file) { const long size = file->getSize(); if (size < 12) { os::Printer::log("X File is too small.", ELL_WARNING); return false; } Buffer = new c8[size]; //! read all into memory if (file->read(Buffer, size) != size) { os::Printer::log("Could not read from x file.", ELL_WARNING); return false; } Line = 1; End = Buffer + size; //! check header "xof " if (strncmp(Buffer, "xof ", 4)!=0) { os::Printer::log("Not an x file, wrong header.", ELL_WARNING); return false; } //! read minor and major version, e.g. 0302 or 0303 c8 tmp[3]; tmp[0] = Buffer[4]; tmp[1] = Buffer[5]; tmp[2] = 0x0; MajorVersion = core::strtoul10(tmp); tmp[0] = Buffer[6]; tmp[1] = Buffer[7]; MinorVersion = core::strtoul10(tmp); //! read format if (strncmp(&Buffer[8], "txt ", 4) ==0) BinaryFormat = false; else if (strncmp(&Buffer[8], "bin ", 4) ==0) BinaryFormat = true; else { os::Printer::log("Only uncompressed x files currently supported.", ELL_WARNING); return false; } BinaryNumCount=0; //! read float size if (strncmp(&Buffer[12], "0032", 4) ==0) FloatSize = 4; else if (strncmp(&Buffer[12], "0064", 4) ==0) FloatSize = 8; else { os::Printer::log("Float size not supported.", ELL_WARNING); return false; } P = &Buffer[16]; readUntilEndOfLine(); FilePath = FileSystem->getFileDir(file->getFileName()) + "/"; return true; } //! Parses the file bool CXMeshFileLoader::parseFile() { while(parseDataObject()) { // loop } return true; } //! Parses the next Data object in the file bool CXMeshFileLoader::parseDataObject() { core::stringc objectName = getNextToken(); if (objectName.size() == 0) return false; // parse specific object #ifdef _XREADER_DEBUG os::Printer::log("debug DataObject:", objectName.c_str(), ELL_DEBUG); #endif if (objectName == "template") return parseDataObjectTemplate(); else if (objectName == "Frame") { return parseDataObjectFrame( 0 ); } else if (objectName == "Mesh") { // some meshes have no frames at all //CurFrame = AnimatedMesh->addJoint(0); SXMesh *mesh=new SXMesh; //mesh->Buffer=AnimatedMesh->addMeshBuffer(); Meshes.push_back(mesh); return parseDataObjectMesh(*mesh); } else if (objectName == "AnimationSet") { return parseDataObjectAnimationSet(); } else if (objectName == "Material") { // template materials now available thanks to joeWright TemplateMaterials.push_back(SXTemplateMaterial()); TemplateMaterials.getLast().Name = getNextToken(); return parseDataObjectMaterial(TemplateMaterials.getLast().Material); } else if (objectName == "}") { os::Printer::log("} found in dataObject", ELL_WARNING); return true; } os::Printer::log("Unknown data object in animation of .x file", objectName.c_str(), ELL_WARNING); return parseUnknownDataObject(); } bool CXMeshFileLoader::parseDataObjectTemplate() { #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: Reading template", ELL_DEBUG); #endif // parse a template data object. Currently not stored. core::stringc name; if (!readHeadOfDataObject(&name)) { os::Printer::log("Left delimiter in template data object missing.", name.c_str(), ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } // read GUID getNextToken(); // read and ignore data members while(true) { core::stringc s = getNextToken(); if (s == "}") break; if (s.size() == 0) return false; } return true; } bool CXMeshFileLoader::parseDataObjectFrame(CSkinnedMesh::SJoint *Parent) { #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: Reading frame", ELL_DEBUG); #endif // A coordinate frame, or "frame of reference." The Frame template // is open and can contain any object. The Direct3D extensions (D3DX) // mesh-loading functions recognize Mesh, FrameTransformMatrix, and // Frame template instances as child objects when loading a Frame // instance. u32 JointID=0; core::stringc name; if (!readHeadOfDataObject(&name)) { os::Printer::log("No opening brace in Frame found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } CSkinnedMesh::SJoint *joint=0; if (name.size()) { for (u32 n=0; n < AnimatedMesh->getAllJoints().size(); ++n) { if (AnimatedMesh->getAllJoints()[n]->Name==name) { joint=AnimatedMesh->getAllJoints()[n]; JointID=n; break; } } } if (!joint) { #ifdef _XREADER_DEBUG os::Printer::log("creating joint ", name.c_str(), ELL_DEBUG); #endif joint=AnimatedMesh->addJoint(Parent); joint->Name=name; JointID=AnimatedMesh->getAllJoints().size()-1; } else { #ifdef _XREADER_DEBUG os::Printer::log("using joint ", name.c_str(), ELL_DEBUG); #endif if (Parent) Parent->Children.push_back(joint); } // Now inside a frame. // read tokens until closing brace is reached. while(true) { core::stringc objectName = getNextToken(); #ifdef _XREADER_DEBUG os::Printer::log("debug DataObject in frame:", objectName.c_str(), ELL_DEBUG); #endif if (objectName.size() == 0) { os::Printer::log("Unexpected ending found in Frame in x file.", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } else if (objectName == "}") { break; // frame finished } else if (objectName == "Frame") { if (!parseDataObjectFrame(joint)) return false; } else if (objectName == "FrameTransformMatrix") { if (!parseDataObjectTransformationMatrix(joint->LocalMatrix)) return false; //joint->LocalAnimatedMatrix //joint->LocalAnimatedMatrix.makeInverse(); //joint->LocalMatrix=tmp*joint->LocalAnimatedMatrix; } else if (objectName == "Mesh") { /* frame.Meshes.push_back(SXMesh()); if (!parseDataObjectMesh(frame.Meshes.getLast())) return false; */ SXMesh *mesh=new SXMesh; mesh->AttachedJointID=JointID; Meshes.push_back(mesh); if (!parseDataObjectMesh(*mesh)) return false; } else { os::Printer::log("Unknown data object in frame in x file", objectName.c_str(), ELL_WARNING); if (!parseUnknownDataObject()) return false; } } return true; } bool CXMeshFileLoader::parseDataObjectTransformationMatrix(core::matrix4 &mat) { #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: Reading Transformation Matrix", ELL_DEBUG); #endif if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Transformation Matrix found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } readMatrix(mat); if (!checkForOneFollowingSemicolons()) { os::Printer::log("No finishing semicolon in Transformation Matrix found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } if (!checkForClosingBrace()) { os::Printer::log("No closing brace in Transformation Matrix found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } return true; } bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) { core::stringc name; if (!readHeadOfDataObject(&name)) { #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: Reading mesh", ELL_DEBUG); #endif os::Printer::log("No opening brace in Mesh found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: Reading mesh", name.c_str(), ELL_DEBUG); #endif // read vertex count const u32 nVertices = readInt(); // read vertices mesh.Vertices.set_used(nVertices); for (u32 n=0; n polygonfaces; u32 currentIndex = 0; for (u32 k=0; k>8)&0xf)*sizeof(core::vector2df); for (u32 j=0; jgetAllJoints().size(); ++n) { if (AnimatedMesh->getAllJoints()[n]->Name==TransformNodeName) { joint=AnimatedMesh->getAllJoints()[n]; break; } } if (!joint) { #ifdef _XREADER_DEBUG os::Printer::log("creating joint for skinning ", TransformNodeName.c_str(), ELL_DEBUG); #endif n = AnimatedMesh->getAllJoints().size(); joint=AnimatedMesh->addJoint(0); joint->Name=TransformNodeName; } // read vertex weights const u32 nWeights = readInt(); // read vertex indices u32 i; const u32 jointStart = joint->Weights.size(); joint->Weights.reallocate(jointStart+nWeights); mesh.WeightJoint.reallocate( mesh.WeightJoint.size() + nWeights ); mesh.WeightNum.reallocate( mesh.WeightNum.size() + nWeights ); for (i=0; iWeights.size()); CSkinnedMesh::SWeight *weight=AnimatedMesh->addWeight(joint); weight->buffer_id=0; weight->vertex_id=readInt(); } // read vertex weights for (i=jointStart; iWeights[i].strength = readFloat(); // read matrix offset // transforms the mesh vertices to the space of the bone // When concatenated to the bone's transform, this provides the // world space coordinates of the mesh as affected by the bone core::matrix4& MatrixOffset = joint->GlobalInversedMatrix; readMatrix(MatrixOffset); if (!checkForOneFollowingSemicolons()) { os::Printer::log("No finishing semicolon in Skin Weights found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } if (!checkForClosingBrace()) { os::Printer::log("No closing brace in Skin Weights found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } return true; } bool CXMeshFileLoader::parseDataObjectSkinMeshHeader(SXMesh& mesh) { #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: Reading skin mesh header", ELL_DEBUG); #endif if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Skin Mesh header found in .x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } mesh.MaxSkinWeightsPerVertex = readInt(); mesh.MaxSkinWeightsPerFace = readInt(); mesh.BoneCount = readInt(); if (!BinaryFormat) getNextToken(); // skip semicolon if (!checkForClosingBrace()) { os::Printer::log("No closing brace in skin mesh header in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } return true; } bool CXMeshFileLoader::parseDataObjectMeshNormals(SXMesh &mesh) { #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: reading mesh normals", ELL_DEBUG); #endif if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Mesh Normals found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } // read count const u32 nNormals = readInt(); core::array normals; normals.set_used(nNormals); // read normals for (u32 i=0; i normalIndices; normalIndices.set_used(mesh.Indices.size()); // read face normal indices const u32 nFNormals = readInt(); u32 normalidx = 0; core::array polygonfaces; for (u32 k=0; k=mesh.Vertices.size()) { os::Printer::log("index value in parseDataObjectMeshVertexColors out of bounds", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } readRGBA(mesh.Vertices[Index].Color); checkForOneFollowingSemicolons(); } if (!checkForOneFollowingSemicolons()) { os::Printer::log("No finishing semicolon in Mesh Vertex Colors Array found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } if (!checkForClosingBrace()) { os::Printer::log("No closing brace in Mesh Texture Coordinates Array found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } return true; } bool CXMeshFileLoader::parseDataObjectMeshMaterialList(SXMesh &mesh) { #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: Reading mesh material list", ELL_DEBUG); #endif if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Mesh Material List found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } // read material count mesh.Materials.reallocate(readInt()); // read non triangulated face material index count const u32 nFaceIndices = readInt(); // There seems to be a compact representation of "all faces the same material" // being represented as 1;1;0;; which means 1 material, 1 face with first material // all the other faces have to obey then, so check is disabled //if (nFaceIndices != mesh.IndexCountPerFace.size()) // os::Printer::log("Index count per face not equal to face material index count in x file.", ELL_WARNING); // read non triangulated face indices and create triangulated ones mesh.FaceMaterialIndices.set_used( mesh.Indices.size() / 3); u32 triangulatedindex = 0; u32 ind = 0; for (u32 tfi=0; tfiexistFile(TextureFileName)) material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName)); // mesh path else { TextureFileName=FilePath + FileSystem->getFileBasename(TextureFileName); if (FileSystem->existFile(TextureFileName)) material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName)); // working directory else material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(FileSystem->getFileBasename(TextureFileName))); } ++textureLayer; if (textureLayer==2) material.MaterialType=video::EMT_LIGHTMAP; } else if (objectName.equals_ignore_case("NormalmapFilename")) { // some exporters write "NormalmapFileName" instead. core::stringc TextureFileName; if (!parseDataObjectTextureFilename(TextureFileName)) return false; // original name if (FileSystem->existFile(TextureFileName)) material.setTexture(1, SceneManager->getVideoDriver()->getTexture(TextureFileName)); // mesh path else { TextureFileName=FilePath + FileSystem->getFileBasename(TextureFileName); if (FileSystem->existFile(TextureFileName)) material.setTexture(1, SceneManager->getVideoDriver()->getTexture(TextureFileName)); // working directory else material.setTexture(1, SceneManager->getVideoDriver()->getTexture(FileSystem->getFileBasename(TextureFileName))); } if (textureLayer==1) ++textureLayer; } else { os::Printer::log("Unknown data object in material in .x file", objectName.c_str(), ELL_WARNING); if (!parseUnknownDataObject()) return false; } } return true; } bool CXMeshFileLoader::parseDataObjectAnimationSet() { #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: Reading animation set", ELL_DEBUG); #endif core::stringc AnimationName; if (!readHeadOfDataObject(&AnimationName)) { os::Printer::log("No opening brace in Animation Set found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } os::Printer::log("Reading animationset ", AnimationName, ELL_DEBUG); while(true) { core::stringc objectName = getNextToken(); if (objectName.size() == 0) { os::Printer::log("Unexpected ending found in Animation set in x file.", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } else if (objectName == "}") { break; // animation set finished } else if (objectName == "Animation") { if (!parseDataObjectAnimation()) return false; } else { os::Printer::log("Unknown data object in animation set in x file", objectName.c_str(), ELL_WARNING); if (!parseUnknownDataObject()) return false; } } return true; } bool CXMeshFileLoader::parseDataObjectAnimation() { #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: reading animation", ELL_DEBUG); #endif if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Animation found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } //anim.closed = true; //anim.linearPositionQuality = true; CSkinnedMesh::SJoint animationDump; core::stringc FrameName; while(true) { core::stringc objectName = getNextToken(); if (objectName.size() == 0) { os::Printer::log("Unexpected ending found in Animation in x file.", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } else if (objectName == "}") { break; // animation finished } else if (objectName == "AnimationKey") { if (!parseDataObjectAnimationKey(&animationDump)) return false; } else if (objectName == "AnimationOptions") { //TODO: parse options. if (!parseUnknownDataObject()) return false; } else if (objectName == "{") { // read frame name FrameName = getNextToken(); if (!checkForClosingBrace()) { os::Printer::log("Unexpected ending found in Animation in x file.", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } } else { os::Printer::log("Unknown data object in animation in x file", objectName.c_str(), ELL_WARNING); if (!parseUnknownDataObject()) return false; } } if (FrameName.size() != 0) { #ifdef _XREADER_DEBUG os::Printer::log("frame name", FrameName.c_str(), ELL_DEBUG); #endif CSkinnedMesh::SJoint *joint=0; u32 n; for (n=0; n < AnimatedMesh->getAllJoints().size(); ++n) { if (AnimatedMesh->getAllJoints()[n]->Name==FrameName) { joint=AnimatedMesh->getAllJoints()[n]; break; } } if (!joint) { #ifdef _XREADER_DEBUG os::Printer::log("creating joint for animation ", FrameName.c_str(), ELL_DEBUG); #endif joint=AnimatedMesh->addJoint(0); joint->Name=FrameName; } joint->PositionKeys.reallocate(joint->PositionKeys.size()+animationDump.PositionKeys.size()); for (n=0; nPositionKeys.push_back(animationDump.PositionKeys[n]); } joint->ScaleKeys.reallocate(joint->ScaleKeys.size()+animationDump.ScaleKeys.size()); for (n=0; nScaleKeys.push_back(animationDump.ScaleKeys[n]); } joint->RotationKeys.reallocate(joint->RotationKeys.size()+animationDump.RotationKeys.size()); for (n=0; nRotationKeys.push_back(animationDump.RotationKeys[n]); } } else os::Printer::log("joint name was never given", ELL_WARNING); return true; } bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) { #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: reading animation key", ELL_DEBUG); #endif if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Animation Key found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } // read key type const u32 keyType = readInt(); if (keyType > 4) { os::Printer::log("Unknown key type found in Animation Key in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } // read number of keys const u32 numberOfKeys = readInt(); // eat the semicolon after the "0". if there are keys present, readInt() // does this for us. If there aren't, we need to do it explicitly if (numberOfKeys == 0) checkForOneFollowingSemicolons(); for (u32 i=0; iaddRotationKey(joint); key->frame=time; key->rotation.set(X,Y,Z,W); key->rotation.normalize(); } break; case 1: //scale case 2: //position { // read vectors // read count if (readInt() != 3) { os::Printer::log("Expected 3 numbers in animation key in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } core::vector3df vector; readVector3(vector); if (!checkForTwoFollowingSemicolons()) { os::Printer::log("No finishing semicolon after vector animation key in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } if (keyType==2) { ISkinnedMesh::SPositionKey *key=AnimatedMesh->addPositionKey(joint); key->frame=time; key->position=vector; } else { ISkinnedMesh::SScaleKey *key=AnimatedMesh->addScaleKey(joint); key->frame=time; key->scale=vector; } } break; case 3: case 4: { // read matrix // read count if (readInt() != 16) { os::Printer::log("Expected 16 numbers in animation key in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } // read matrix core::matrix4 mat(core::matrix4::EM4CONST_NOTHING); readMatrix(mat); //mat=joint->LocalMatrix*mat; if (!checkForOneFollowingSemicolons()) { os::Printer::log("No finishing semicolon after matrix animation key in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); } //core::vector3df rotation = mat.getRotationDegrees(); ISkinnedMesh::SRotationKey *keyR=AnimatedMesh->addRotationKey(joint); keyR->frame=time; // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched from mat to mat.getTransposed() for downward compatibility. // Not tested so far if this was correct or wrong before quaternion fix! keyR->rotation= core::quaternion(mat.getTransposed()); ISkinnedMesh::SPositionKey *keyP=AnimatedMesh->addPositionKey(joint); keyP->frame=time; keyP->position=mat.getTranslation(); /* core::vector3df scale=mat.getScale(); if (scale.X==0) scale.X=1; if (scale.Y==0) scale.Y=1; if (scale.Z==0) scale.Z=1; ISkinnedMesh::SScaleKey *keyS=AnimatedMesh->addScaleKey(joint); keyS->frame=time; keyS->scale=scale; */ } break; } // end switch } if (!checkForOneFollowingSemicolons()) --P; if (!checkForClosingBrace()) { os::Printer::log("No closing brace in animation key in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } return true; } bool CXMeshFileLoader::parseDataObjectTextureFilename(core::stringc& texturename) { #ifdef _XREADER_DEBUG os::Printer::log("CXFileReader: reading texture filename", ELL_DEBUG); #endif if (!readHeadOfDataObject()) { os::Printer::log("No opening brace in Texture filename found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } if (!getNextTokenAsString(texturename)) { os::Printer::log("Unknown syntax while reading texture filename string in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } if (!checkForClosingBrace()) { os::Printer::log("No closing brace in Texture filename found in x file", ELL_WARNING); os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); return false; } return true; } bool CXMeshFileLoader::parseUnknownDataObject() { // find opening delimiter while(true) { core::stringc t = getNextToken(); if (t.size() == 0) return false; if (t == "{") break; } u32 counter = 1; // parse until closing delimiter while(counter) { core::stringc t = getNextToken(); if (t.size() == 0) return false; if (t == "{") ++counter; else if (t == "}") --counter; } return true; } //! checks for closing curly brace, returns false if not there bool CXMeshFileLoader::checkForClosingBrace() { return (getNextToken() == "}"); } //! checks for one following semicolon, returns false if not there bool CXMeshFileLoader::checkForOneFollowingSemicolons() { if (BinaryFormat) return true; if (getNextToken() == ";") return true; else { --P; return false; } } //! checks for two following semicolons, returns false if they are not there bool CXMeshFileLoader::checkForTwoFollowingSemicolons() { if (BinaryFormat) return true; for (u32 k=0; k<2; ++k) { if (getNextToken() != ";") { --P; return false; } } return true; } //! reads header of dataobject including the opening brace. //! returns false if error happened, and writes name of object //! if there is one bool CXMeshFileLoader::readHeadOfDataObject(core::stringc* outname) { core::stringc nameOrBrace = getNextToken(); if (nameOrBrace != "{") { if (outname) (*outname) = nameOrBrace; if (getNextToken() != "{") return false; } return true; } //! returns next parseable token. Returns empty string if no token there core::stringc CXMeshFileLoader::getNextToken() { core::stringc s; // process binary-formatted file if (BinaryFormat) { // in binary mode it will only return NAME and STRING token // and (correctly) skip over other tokens. s16 tok = readBinWord(); u32 len; // standalone tokens switch (tok) { case 1: // name token len = readBinDWord(); s = core::stringc(P, len); P += len; return s; case 2: // string token len = readBinDWord(); s = core::stringc(P, len); P += (len + 2); return s; case 3: // integer token P += 4; return ""; case 5: // GUID token P += 16; return ""; case 6: len = readBinDWord(); P += (len * 4); return ""; case 7: len = readBinDWord(); P += (len * FloatSize); return ""; case 0x0a: return "{"; case 0x0b: return "}"; case 0x0c: return "("; case 0x0d: return ")"; case 0x0e: return "["; case 0x0f: return "]"; case 0x10: return "<"; case 0x11: return ">"; case 0x12: return "."; case 0x13: return ","; case 0x14: return ";"; case 0x1f: return "template"; case 0x28: return "WORD"; case 0x29: return "DWORD"; case 0x2a: return "FLOAT"; case 0x2b: return "DOUBLE"; case 0x2c: return "CHAR"; case 0x2d: return "UCHAR"; case 0x2e: return "SWORD"; case 0x2f: return "SDWORD"; case 0x30: return "void"; case 0x31: return "string"; case 0x32: return "unicode"; case 0x33: return "cstring"; case 0x34: return "array"; } } // process text-formatted file else { findNextNoneWhiteSpace(); if (P >= End) return s; while((P < End) && !core::isspace(P[0])) { // either keep token delimiters when already holding a token, or return if first valid char if (P[0]==';' || P[0]=='}' || P[0]=='{' || P[0]==',') { if (!s.size()) { s.append(P[0]); ++P; } break; // stop for delimiter } s.append(P[0]); ++P; } } return s; } //! places pointer to next begin of a token, which must be a number, // and ignores comments void CXMeshFileLoader::findNextNoneWhiteSpaceNumber() { if (BinaryFormat) return; while((P < End) && (P[0] != '-') && (P[0] != '.') && !( core::isdigit(P[0]))) { // check if this is a comment if ((P[0] == '/' && P[1] == '/') || P[0] == '#') readUntilEndOfLine(); else ++P; } } // places pointer to next begin of a token, and ignores comments void CXMeshFileLoader::findNextNoneWhiteSpace() { if (BinaryFormat) return; while(true) { while((P < End) && core::isspace(P[0])) { if (*P=='\n') ++Line; ++P; } if (P >= End) return; // check if this is a comment if ((P[0] == '/' && P[1] == '/') || P[0] == '#') readUntilEndOfLine(); else break; } } //! reads a x file style string bool CXMeshFileLoader::getNextTokenAsString(core::stringc& out) { if (BinaryFormat) { out=getNextToken(); return true; } findNextNoneWhiteSpace(); if (P >= End) return false; if (P[0] != '"') return false; ++P; while(P < End && P[0]!='"') { out.append(P[0]); ++P; } if ( P[1] != ';' || P[0] != '"') return false; P+=2; return true; } void CXMeshFileLoader::readUntilEndOfLine() { if (BinaryFormat) return; while(P < End) { if (P[0] == '\n' || P[0] == '\r') { ++P; ++Line; return; } ++P; } } u16 CXMeshFileLoader::readBinWord() { if (P>=End) return 0; #ifdef __BIG_ENDIAN__ const u16 tmp = os::Byteswap::byteswap(*(u16 *)P); #else const u16 tmp = *(u16 *)P; #endif P += 2; return tmp; } u32 CXMeshFileLoader::readBinDWord() { if (P>=End) return 0; #ifdef __BIG_ENDIAN__ const u32 tmp = os::Byteswap::byteswap(*(u32 *)P); #else const u32 tmp = *(u32 *)P; #endif P += 4; return tmp; } u32 CXMeshFileLoader::readInt() { if (BinaryFormat) { if (!BinaryNumCount) { const u16 tmp = readBinWord(); // 0x06 or 0x03 if (tmp == 0x06) BinaryNumCount = readBinDWord(); else BinaryNumCount = 1; // single int } --BinaryNumCount; return readBinDWord(); } else { findNextNoneWhiteSpaceNumber(); return core::strtoul10(P, &P); } } f32 CXMeshFileLoader::readFloat() { if (BinaryFormat) { if (!BinaryNumCount) { const u16 tmp = readBinWord(); // 0x07 or 0x42 if (tmp == 0x07) BinaryNumCount = readBinDWord(); else BinaryNumCount = 1; // single int } --BinaryNumCount; if (FloatSize == 8) { #ifdef __BIG_ENDIAN__ //TODO: Check if data is properly converted here f32 ctmp[2]; ctmp[1] = os::Byteswap::byteswap(*(f32*)P); ctmp[0] = os::Byteswap::byteswap(*(f32*)P+4); const f32 tmp = (f32)(*(f64*)(void*)ctmp); #else const f32 tmp = (f32)(*(f64 *)P); #endif P += 8; return tmp; } else { #ifdef __BIG_ENDIAN__ const f32 tmp = os::Byteswap::byteswap(*(f32 *)P); #else const f32 tmp = *(f32 *)P; #endif P += 4; return tmp; } } findNextNoneWhiteSpaceNumber(); f32 ftmp; P = core::fast_atof_move(P, ftmp); return ftmp; } // read 2-dimensional vector. Stops at semicolon after second value for text file format bool CXMeshFileLoader::readVector2(core::vector2df& vec) { vec.X = readFloat(); vec.Y = readFloat(); return true; } // read 3-dimensional vector. Stops at semicolon after third value for text file format bool CXMeshFileLoader::readVector3(core::vector3df& vec) { vec.X = readFloat(); vec.Y = readFloat(); vec.Z = readFloat(); return true; } // read color without alpha value. Stops after second semicolon after blue value bool CXMeshFileLoader::readRGB(video::SColor& color) { video::SColorf tmpColor; tmpColor.r = readFloat(); tmpColor.g = readFloat(); tmpColor.b = readFloat(); color = tmpColor.toSColor(); return checkForOneFollowingSemicolons(); } // read color with alpha value. Stops after second semicolon after blue value bool CXMeshFileLoader::readRGBA(video::SColor& color) { video::SColorf tmpColor; tmpColor.r = readFloat(); tmpColor.g = readFloat(); tmpColor.b = readFloat(); tmpColor.a = readFloat(); color = tmpColor.toSColor(); return checkForOneFollowingSemicolons(); } // read matrix from list of floats bool CXMeshFileLoader::readMatrix(core::matrix4& mat) { for (u32 i=0; i<16; ++i) mat[i] = readFloat(); return checkForOneFollowingSemicolons(); } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_X_LOADER_ irrlicht-1.8.3/source/Irrlicht/CWriteFile.h0000644000000000000000000000226012574354552017303 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_WRITE_FILE_H_INCLUDED__ #define __C_WRITE_FILE_H_INCLUDED__ #include #include "IWriteFile.h" #include "irrString.h" namespace irr { namespace io { /*! Class for writing a real file to disk. */ class CWriteFile : public IWriteFile { public: CWriteFile(const io::path& fileName, bool append); virtual ~CWriteFile(); //! Reads an amount of bytes from the file. virtual s32 write(const void* buffer, u32 sizeToWrite); //! Changes position in file, returns true if successful. virtual bool seek(long finalPos, bool relativeMovement = false); //! Returns the current position in the file. virtual long getPos() const; //! Returns name of file. virtual const io::path& getFileName() const; //! returns if file is open bool isOpen() const; private: //! opens the file void openFile(bool append); io::path Filename; FILE* File; long FileSize; }; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CWriteFile.cpp0000644000000000000000000000400412574354552017634 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CWriteFile.h" #include namespace irr { namespace io { CWriteFile::CWriteFile(const io::path& fileName, bool append) : FileSize(0) { #ifdef _DEBUG setDebugName("CWriteFile"); #endif Filename = fileName; openFile(append); } CWriteFile::~CWriteFile() { if (File) fclose(File); } //! returns if file is open inline bool CWriteFile::isOpen() const { return File != 0; } //! returns how much was read s32 CWriteFile::write(const void* buffer, u32 sizeToWrite) { if (!isOpen()) return 0; return (s32)fwrite(buffer, 1, sizeToWrite, File); } //! changes position in file, returns true if successful //! if relativeMovement==true, the pos is changed relative to current pos, //! otherwise from begin of file bool CWriteFile::seek(long finalPos, bool relativeMovement) { if (!isOpen()) return false; return fseek(File, finalPos, relativeMovement ? SEEK_CUR : SEEK_SET) == 0; } //! returns where in the file we are. long CWriteFile::getPos() const { return ftell(File); } //! opens the file void CWriteFile::openFile(bool append) { if (Filename.size() == 0) { File = 0; return; } #if defined(_IRR_WCHAR_FILESYSTEM) File = _wfopen(Filename.c_str(), append ? L"ab" : L"wb"); #else File = fopen(Filename.c_str(), append ? "ab" : "wb"); #endif if (File) { // get FileSize fseek(File, 0, SEEK_END); FileSize = ftell(File); fseek(File, 0, SEEK_SET); } } //! returns name of file const io::path& CWriteFile::getFileName() const { return Filename; } IWriteFile* createWriteFile(const io::path& fileName, bool append) { CWriteFile* file = new CWriteFile(fileName, append); if (file->isOpen()) return file; file->drop(); return 0; } } // end namespace io } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CWaterSurfaceSceneNode.h0000644000000000000000000000320712574354552021572 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_WATER_SURFACE_SCENE_NODE_H_INCLUDED__ #define __C_WATER_SURFACE_SCENE_NODE_H_INCLUDED__ #include "CMeshSceneNode.h" namespace irr { namespace scene { class CWaterSurfaceSceneNode : public CMeshSceneNode { public: //! constructor CWaterSurfaceSceneNode(f32 waveHeight, f32 waveSpeed, f32 waveLength, IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); //! destructor virtual ~CWaterSurfaceSceneNode(); //! frame registration virtual void OnRegisterSceneNode(); //! animated update virtual void OnAnimate(u32 timeMs); //! Update mesh virtual void setMesh(IMesh* mesh); //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_WATER_SURFACE; } //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: inline f32 addWave(const core::vector3df &source, f32 time) const; f32 WaveLength; f32 WaveSpeed; f32 WaveHeight; IMesh* OriginalMesh; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CWaterSurfaceSceneNode.cpp0000644000000000000000000000713312574354552022127 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CWaterSurfaceSceneNode.h" #include "ISceneManager.h" #include "IMeshManipulator.h" #include "IMeshCache.h" #include "S3DVertex.h" #include "SMesh.h" #include "os.h" namespace irr { namespace scene { //! constructor CWaterSurfaceSceneNode::CWaterSurfaceSceneNode(f32 waveHeight, f32 waveSpeed, f32 waveLength, IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) : CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale), WaveLength(waveLength), WaveSpeed(waveSpeed), WaveHeight(waveHeight), OriginalMesh(0) { #ifdef _DEBUG setDebugName("CWaterSurfaceSceneNode"); #endif setMesh(mesh); } //! destructor CWaterSurfaceSceneNode::~CWaterSurfaceSceneNode() { // Mesh is dropped in CMeshSceneNode destructor if (OriginalMesh) OriginalMesh->drop(); } //! frame void CWaterSurfaceSceneNode::OnRegisterSceneNode() { CMeshSceneNode::OnRegisterSceneNode(); } void CWaterSurfaceSceneNode::OnAnimate(u32 timeMs) { if (Mesh && IsVisible) { const u32 meshBufferCount = Mesh->getMeshBufferCount(); const f32 time = timeMs / WaveSpeed; for (u32 b=0; bgetMeshBuffer(b)->getVertexCount(); for (u32 i=0; igetMeshBuffer(b)->getPosition(i).Y = addWave( OriginalMesh->getMeshBuffer(b)->getPosition(i), time); }// end for all mesh buffers Mesh->setDirty(scene::EBT_VERTEX); SceneManager->getMeshManipulator()->recalculateNormals(Mesh); } CMeshSceneNode::OnAnimate(timeMs); } void CWaterSurfaceSceneNode::setMesh(IMesh* mesh) { CMeshSceneNode::setMesh(mesh); if (!mesh) return; if (OriginalMesh) OriginalMesh->drop(); IMesh* clone = SceneManager->getMeshManipulator()->createMeshCopy(mesh); OriginalMesh = mesh; Mesh = clone; Mesh->setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_INDEX); // Mesh->setHardwareMappingHint(scene::EHM_STREAM, scene::EBT_VERTEX); } //! Writes attributes of the scene node. void CWaterSurfaceSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addFloat("WaveLength", WaveLength); out->addFloat("WaveSpeed", WaveSpeed); out->addFloat("WaveHeight", WaveHeight); CMeshSceneNode::serializeAttributes(out, options); // serialize original mesh out->setAttribute("Mesh", SceneManager->getMeshCache()->getMeshName(OriginalMesh).getPath().c_str()); } //! Reads attributes of the scene node. void CWaterSurfaceSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { WaveLength = in->getAttributeAsFloat("WaveLength"); WaveSpeed = in->getAttributeAsFloat("WaveSpeed"); WaveHeight = in->getAttributeAsFloat("WaveHeight"); if (Mesh) { Mesh->drop(); Mesh = OriginalMesh; OriginalMesh = 0; } // deserialize original mesh CMeshSceneNode::deserializeAttributes(in, options); if (Mesh) { IMesh* clone = SceneManager->getMeshManipulator()->createMeshCopy(Mesh); OriginalMesh = Mesh; Mesh = clone; } } f32 CWaterSurfaceSceneNode::addWave(const core::vector3df &source, f32 time) const { return source.Y + (sinf(((source.X/WaveLength) + time)) * WaveHeight) + (cosf(((source.Z/WaveLength) + time)) * WaveHeight); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CWADReader.h0000644000000000000000000001045512574354552017154 0ustar rootroot// Copyright (C) 2002-2012 Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_WAD_READER_H_INCLUDED__ #define __C_WAD_READER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ #include "IReferenceCounted.h" #include "IReadFile.h" #include "irrArray.h" #include "irrString.h" #include "IFileSystem.h" #include "CFileList.h" namespace irr { namespace io { enum eWADFileTypes { WAD_FORMAT_UNKNOWN = 0, WAD_FORMAT_QUAKE2 = 1, WAD_FORMAT_HALFLIFE = 2, WAD_CMP_NONE = 0, WAD_CMP_LZSS = 1, WAD_TYP_NONE = 0, WAD_TYP_LABEL = 1, WAD_TYP_LUMPY = 64, // 64 + grab command number WAD_TYP_PALETTE = 64, WAD_TYP_QTEX = 65, WAD_TYP_QPIC = 66, WAD_TYP_SOUND = 67, WAD_TYP_MIPTEX = 68, WAD_TYP_MIPTEX_HALFLIFE = 67, WAD_TYP_FONT = 70, }; // byte-align structures #include "irrpack.h" struct SWADFileHeader { c8 tag[4]; // type of WAD format WAD2 = quake2, WAD3 = halflife u32 numlumps; u32 infotableofs; } PACK_STRUCT; struct SWADFileEntryOriginal { u32 filepos; u32 disksize; u32 size; // uncompressed u8 type; u8 compression; u8 pad[2]; u8 name[16]; // must be null terminated } PACK_STRUCT; // Default alignment #include "irrunpack.h" struct SWADFileEntry { io::path simpleFileName; bool operator < (const SWADFileEntry& other) const { return simpleFileName < other.simpleFileName; } io::path wadFileName; SWADFileEntryOriginal header; }; //! Archiveloader capable of loading WAD Archives class CArchiveLoaderWAD : public IArchiveLoader { public: //! Constructor CArchiveLoaderWAD(io::IFileSystem* fs); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".zip") virtual bool isALoadableFileFormat(const io::path& filename) const; //! Check if the file might be loaded by this class /** Check might look into the file. \param file File handle to check. \return True if file seems to be loadable. */ virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! Check to see if the loader can create archives of this type. /** Check based on the archive type. \param fileType The archive type to check. \return True if the archile loader supports this type, false if not */ virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const; //! Creates an archive from the filename /** \param file File handle to check. \return Pointer to newly created archive, or 0 upon error. */ virtual IFileArchive* createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const; //! creates/loads an archive from the file. //! \return Pointer to the created archive. Returns 0 if loading failed. virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; private: io::IFileSystem* FileSystem; }; //! reads from WAD class CWADReader : public IFileArchive, virtual CFileList { public: CWADReader(IReadFile* file, bool ignoreCase, bool ignorePaths); virtual ~CWADReader(); // file archive methods //! return the id of the file Archive virtual const io::path& getArchiveName() const; //! opens a file by file name virtual IReadFile* createAndOpenFile(const io::path& filename); //! opens a file by index virtual IReadFile* createAndOpenFile(u32 index); //! returns the list of files virtual const IFileList* getFileList() const; //! get the class Type virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_WAD; } private: io::path Type; //! scans for a local header, returns false if there is no more local file header. bool scanLocalHeader(); //! splits filename from zip file into useful filenames and paths void extractFilename(SWADFileEntry* entry); io::path Base; io::path MountPoint; IReadFile* File; eWADFileTypes WadType; SWADFileHeader Header; //core::array FileInfo; io::IFileSystem* FileSystem; }; } // end namespace io } // end namespace irr #endif #endif // #ifdef __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ irrlicht-1.8.3/source/Irrlicht/CWADReader.cpp0000644000000000000000000001377212574354552017514 0ustar rootroot// Copyright (C) 2002-2012 Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // Code contributed by skreamz #include "IrrCompileConfig.h" #ifdef __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ #include "CWADReader.h" #include "os.h" #include "coreutil.h" namespace irr { namespace io { //! Constructor CArchiveLoaderWAD::CArchiveLoaderWAD( io::IFileSystem* fs) : FileSystem(fs) { #ifdef _DEBUG setDebugName("CArchiveLoaderWAD"); #endif } //! returns true if the file maybe is able to be loaded by this class bool CArchiveLoaderWAD::isALoadableFileFormat(const io::path& filename) const { return core::hasFileExtension ( filename, "wad" ); } //! Creates an archive from the filename /** \param file File handle to check. \return Pointer to newly created archive, or 0 upon error. */ IFileArchive* CArchiveLoaderWAD::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const { IFileArchive *archive = 0; io::IReadFile* file = FileSystem->createAndOpenFile(filename); if (file) { archive = createArchive ( file, ignoreCase, ignorePaths ); file->drop (); } return archive; } //! creates/loads an archive from the file. //! \return Pointer to the created archive. Returns 0 if loading failed. IFileArchive* CArchiveLoaderWAD::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const { IFileArchive *archive = 0; if ( file ) { file->seek ( 0 ); archive = new CWADReader(file, ignoreCase, ignorePaths); } return archive; } //! Check if the file might be loaded by this class /** Check might look into the file. \param file File handle to check. \return True if file seems to be loadable. */ bool CArchiveLoaderWAD::isALoadableFileFormat(io::IReadFile* file) const { SWADFileHeader header; memset(&header, 0, sizeof(header)); file->read( &header.tag, 4 ); return !strncmp ( header.tag, "WAD2", 4 ) || !strncmp ( header.tag, "WAD3", 4 ); } //! Check to see if the loader can create archives of this type. bool CArchiveLoaderWAD::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const { return fileType == EFAT_WAD; } void createDir ( const c8 *full ); /*! WAD Reader */ CWADReader::CWADReader(IReadFile* file, bool ignoreCase, bool ignorePaths) : CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file) { #ifdef _DEBUG setDebugName("CWADReader"); #endif if (File) { File->grab(); Base = File->getFileName(); Base.replace ( '\\', '/' ); // scan local headers scanLocalHeader(); sort(); } #if 0 for ( u32 i = 0; i < FileList.size(); ++i ) { SWADFileEntry &e = FileList[i]; char buf[128]; snprintf ( buf, 128, "c:\\h2\\%s", e.wadFileName.c_str() ); createDir ( buf ); FILE * f = fopen ( buf, "wb" ); if ( 0 == f ) continue; u8 * mem = new u8 [ e.header.disksize ]; File->seek ( e.header.filepos ); File->read ( mem, e.header.disksize ); fwrite ( mem, e.header.disksize, 1, f ); delete [] mem; fclose ( f ); } #endif } CWADReader::~CWADReader() { if (File) File->drop(); } //! return the id of the file Archive const io::path& CWADReader::getArchiveName () const { return Base; } const IFileList* CWADReader::getFileList() const { return this; } //! scans for a local header, returns false if there is no more local file header. bool CWADReader::scanLocalHeader() { SWADFileEntryOriginal entry; SWADFileEntry save; memset(&Header, 0, sizeof(SWADFileHeader)); File->read(&Header, sizeof(SWADFileHeader)); if ( 0 == strncmp ( Header.tag, "WAD2", 4 ) ) WadType = WAD_FORMAT_QUAKE2; else if ( 0 == strncmp ( Header.tag, "WAD3", 4 ) ) WadType = WAD_FORMAT_HALFLIFE; else WadType = WAD_FORMAT_UNKNOWN; if ( WadType == WAD_FORMAT_UNKNOWN ) return false; #ifdef __BIG_ENDIAN__ Header.numlumps = os::Byteswap::byteswap(Header.numlumps); Header.infotableofs = os::Byteswap::byteswap(Header.infotableofs); #endif File->seek ( Header.infotableofs ); c8 buf[16]; for ( u32 i = 0; i < Header.numlumps; ++i ) { // read entry File->read(&entry, sizeof ( SWADFileEntryOriginal )); entry.name[ sizeof ( entry.name ) - 1 ] = 0; save.header = entry; save.wadFileName = "/"; save.wadFileName += entry.name; if ( WadType == WAD_FORMAT_HALFLIFE ) { // don't know about the types! i'm guessing switch ( entry.type ) { case WAD_TYP_MIPTEX_HALFLIFE: save.wadFileName += ".wal2"; break; default: snprintf ( buf, 16, ".%02d", entry.type ); save.wadFileName += buf; break; } } else if ( WadType == WAD_FORMAT_QUAKE2 ) { switch ( entry.type ) { case WAD_TYP_MIPTEX: save.wadFileName += ".miptex"; break; case WAD_TYP_SOUND: save.wadFileName += ".sound"; break; case WAD_TYP_PALETTE: save.wadFileName += ".palette"; break; case WAD_TYP_QTEX: save.wadFileName += ".qtex"; break; case WAD_TYP_QPIC: save.wadFileName += ".qpic"; break; case WAD_TYP_FONT: save.wadFileName += ".font"; break; default: snprintf ( buf, 16, ".%02d", entry.type ); save.wadFileName += buf; break; } } // add file to list addItem(save.wadFileName,save.header.filepos, save.header.disksize, false ); //FileInfo.push_back(save); } return true; } //! opens a file by file name IReadFile* CWADReader::createAndOpenFile(const io::path& filename) { s32 index = findFile(filename, false); if (index != -1) return createAndOpenFile(index); return 0; } //! opens a file by index IReadFile* CWADReader::createAndOpenFile(u32 index) { if (index >= Files.size() ) return 0; const SFileListEntry &entry = Files[index]; return createLimitReadFile( entry.FullName, File, entry.Offset, entry.Size ); } } // end namespace io } // end namespace irr #endif // __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ irrlicht-1.8.3/source/Irrlicht/CVolumeLightSceneNode.h0000644000000000000000000000632012574354552021435 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // created by Dean Wadsworth aka Varmint Dec 31 2007 #ifndef __VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ #define __VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ #include "IVolumeLightSceneNode.h" #include "IMesh.h" namespace irr { namespace scene { class CVolumeLightSceneNode : public IVolumeLightSceneNode { public: //! constructor CVolumeLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const u32 subdivU = 32, const u32 subdivV = 32, const video::SColor foot = video::SColor(51, 0, 230, 180), const video::SColor tail = video::SColor(0, 0, 0, 0), const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); virtual ~CVolumeLightSceneNode(); virtual void OnRegisterSceneNode(); //! renders the node. virtual void render(); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! returns the material based on the zero based index i. virtual video::SMaterial& getMaterial(u32 i); //! returns amount of materials used by this scene node. virtual u32 getMaterialCount() const; //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_VOLUME_LIGHT; } //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); virtual void setSubDivideU(const u32 inU); virtual void setSubDivideV(const u32 inV); virtual u32 getSubDivideU() const { return SubdivideU; } virtual u32 getSubDivideV() const { return SubdivideV; } virtual void setFootColor(const video::SColor inColor); virtual void setTailColor(const video::SColor inColor); virtual video::SColor getFootColor() const { return FootColor; } virtual video::SColor getTailColor() const { return TailColor; } private: void constructLight(); IMesh* Mesh; f32 LPDistance; // Distance to hypothetical lightsource point -- affects fov angle u32 SubdivideU; // Number of subdivisions in U and V space. u32 SubdivideV; // Controls the number of "slices" in the volume. // NOTE : Total number of polygons = 2 + ((SubdivideU + 1) + (SubdivideV + 1)) * 2 // Each slice being a quad plus the rectangular plane at the bottom. video::SColor FootColor; // Color at the source video::SColor TailColor; // Color at the end. core::vector3df LightDimensions; // LightDimensions.Y Distance of shooting -- Length of beams // LightDimensions.X and LightDimensions.Z determine the size/dimension of the plane }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CVolumeLightSceneNode.cpp0000644000000000000000000001165412574354552021776 0ustar rootroot// Copyright (C) 2007-2012 Dean Wadsworth // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CVolumeLightSceneNode.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "S3DVertex.h" #include "os.h" namespace irr { namespace scene { //! constructor CVolumeLightSceneNode::CVolumeLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const u32 subdivU, const u32 subdivV, const video::SColor foot, const video::SColor tail, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) : IVolumeLightSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), LPDistance(8.0f), SubdivideU(subdivU), SubdivideV(subdivV), FootColor(foot), TailColor(tail), LightDimensions(core::vector3df(1.0f, 1.2f, 1.0f)) { #ifdef _DEBUG setDebugName("CVolumeLightSceneNode"); #endif constructLight(); } CVolumeLightSceneNode::~CVolumeLightSceneNode() { if (Mesh) Mesh->drop(); } void CVolumeLightSceneNode::constructLight() { if (Mesh) Mesh->drop(); Mesh = SceneManager->getGeometryCreator()->createVolumeLightMesh(SubdivideU, SubdivideV, FootColor, TailColor, LPDistance, LightDimensions); } //! renders the node. void CVolumeLightSceneNode::render() { if (!Mesh) return; video::IVideoDriver* driver = SceneManager->getVideoDriver(); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial()); driver->drawMeshBuffer(Mesh->getMeshBuffer(0)); } //! returns the axis aligned bounding box of this node const core::aabbox3d& CVolumeLightSceneNode::getBoundingBox() const { return Mesh->getBoundingBox(); } void CVolumeLightSceneNode::OnRegisterSceneNode() { if (IsVisible) { SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT); } ISceneNode::OnRegisterSceneNode(); } //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. video::SMaterial& CVolumeLightSceneNode::getMaterial(u32 i) { return Mesh->getMeshBuffer(i)->getMaterial(); } //! returns amount of materials used by this scene node. u32 CVolumeLightSceneNode::getMaterialCount() const { return 1; } void CVolumeLightSceneNode::setSubDivideU (const u32 inU) { if (inU != SubdivideU) { SubdivideU = inU; constructLight(); } } void CVolumeLightSceneNode::setSubDivideV (const u32 inV) { if (inV != SubdivideV) { SubdivideV = inV; constructLight(); } } void CVolumeLightSceneNode::setFootColor(const video::SColor inColor) { if (inColor != FootColor) { FootColor = inColor; constructLight(); } } void CVolumeLightSceneNode::setTailColor(const video::SColor inColor) { if (inColor != TailColor) { TailColor = inColor; constructLight(); } } //! Writes attributes of the scene node. void CVolumeLightSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { ISceneNode::serializeAttributes(out, options); out->addFloat("lpDistance", LPDistance); out->addInt("subDivideU", SubdivideU); out->addInt("subDivideV", SubdivideV); out->addColor("footColor", FootColor); out->addColor("tailColor", TailColor); out->addVector3d("lightDimension", LightDimensions); } //! Reads attributes of the scene node. void CVolumeLightSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { LPDistance = in->getAttributeAsFloat("lpDistance"); LPDistance = core::max_(LPDistance, 8.0f); SubdivideU = in->getAttributeAsInt("subDivideU"); SubdivideU = core::max_(SubdivideU, 1u); SubdivideV = in->getAttributeAsInt("subDivideV"); SubdivideV = core::max_(SubdivideV, 1u); FootColor = in->getAttributeAsColor("footColor"); TailColor = in->getAttributeAsColor("tailColor"); LightDimensions = in->getAttributeAsVector3d("lightDimension"); constructLight(); ISceneNode::deserializeAttributes(in, options); } //! Creates a clone of this scene node and its children. ISceneNode* CVolumeLightSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CVolumeLightSceneNode* nb = new CVolumeLightSceneNode(newParent, newManager, ID, SubdivideU, SubdivideV, FootColor, TailColor, RelativeTranslation); nb->cloneMembers(this, newManager); nb->getMaterial(0) = Mesh->getMeshBuffer(0)->getMaterial(); if ( newParent ) nb->drop(); return nb; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CVideoModeList.h0000644000000000000000000000407612574354552020127 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_C_VIDEO_MODE_LIST_H_INCLUDED__ #define __IRR_C_VIDEO_MODE_LIST_H_INCLUDED__ #include "IVideoModeList.h" #include "dimension2d.h" #include "irrArray.h" namespace irr { namespace video { class CVideoModeList : public IVideoModeList { public: //! constructor CVideoModeList(); //! Gets amount of video modes in the list. virtual s32 getVideoModeCount() const; //! Returns the screen size of a video mode in pixels. virtual core::dimension2d getVideoModeResolution(s32 modeNumber) const; //! Returns the screen size of an optimal video mode in pixels. virtual core::dimension2d getVideoModeResolution(const core::dimension2d& minSize, const core::dimension2d& maxSize) const; //! Returns the pixel depth of a video mode in bits. virtual s32 getVideoModeDepth(s32 modeNumber) const; //! Returns current desktop screen resolution. virtual const core::dimension2d& getDesktopResolution() const; //! Returns the pixel depth of a video mode in bits. virtual s32 getDesktopDepth() const; //! adds a new mode to the list void addMode(const core::dimension2d& size, s32 depth); void setDesktop(s32 desktopDepth, const core::dimension2d& desktopSize); private: struct SVideoMode { core::dimension2d size; s32 depth; bool operator==(const SVideoMode& other) const { return size == other.size && depth == other.depth; } bool operator <(const SVideoMode& other) const { return (size.Width < other.size.Width || (size.Width == other.size.Width && size.Height < other.size.Height) || (size.Width == other.size.Width && size.Height == other.size.Height && depth < other.depth)); } }; core::array VideoModes; SVideoMode Desktop; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CVideoModeList.cpp0000644000000000000000000000574512574354552020466 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CVideoModeList.h" #include "irrMath.h" namespace irr { namespace video { //! constructor CVideoModeList::CVideoModeList() { #ifdef _DEBUG setDebugName("CVideoModeList"); #endif Desktop.depth = 0; Desktop.size = core::dimension2d(0,0); } void CVideoModeList::setDesktop(s32 desktopDepth, const core::dimension2d& desktopSize) { Desktop.depth = desktopDepth; Desktop.size = desktopSize; } //! Gets amount of video modes in the list. s32 CVideoModeList::getVideoModeCount() const { return (s32)VideoModes.size(); } //! Returns the screen size of a video mode in pixels. core::dimension2d CVideoModeList::getVideoModeResolution(s32 modeNumber) const { if (modeNumber < 0 || modeNumber > (s32)VideoModes.size()) return core::dimension2d(0,0); return VideoModes[modeNumber].size; } core::dimension2d CVideoModeList::getVideoModeResolution( const core::dimension2d& minSize, const core::dimension2d& maxSize) const { u32 best=VideoModes.size(); // if only one or no mode if (best<2) return getVideoModeResolution(0); u32 i; for (i=0; i=minSize.Width && VideoModes[i].size.Height>=minSize.Height && VideoModes[i].size.Width<=maxSize.Width && VideoModes[i].size.Height<=maxSize.Height) best=i; } // we take the last one found, the largest one fitting if (best (s32)VideoModes.size()) return 0; return VideoModes[modeNumber].depth; } //! Returns current desktop screen resolution. const core::dimension2d& CVideoModeList::getDesktopResolution() const { return Desktop.size; } //! Returns the pixel depth of a video mode in bits. s32 CVideoModeList::getDesktopDepth() const { return Desktop.depth; } //! adds a new mode to the list void CVideoModeList::addMode(const core::dimension2d& size, s32 depth) { SVideoMode m; m.depth = depth; m.size = size; for (u32 i=0; igetDimension().Width << VIDEO_SAMPLE_GRANULARITY; int pitch1 = RenderTarget->getDimension().Width << 2; int aposx = (int) a->Pos.x; int aposy = (int) a->Pos.y; int bposx = (int) b->Pos.x; int bposy = (int) b->Pos.y; int dx = bposx - aposx; int dy = bposy - aposy; int c; int m; int d = 0; int run; tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif int xInc0 = 1 << VIDEO_SAMPLE_GRANULARITY; int yInc0 = pitch0; int xInc1 = 4; int yInc1 = pitch1; tVideoSample color; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR tFixPoint r0, g0, b0; getSample_color ( r0, g0, b0, a->Color[0] ); color = fix_to_color ( r0, g0, b0 ); #else color = (tVideoSample) 0xFFFFFFFF; #endif if ( dx < 0 ) { xInc0 = - ( 1 << VIDEO_SAMPLE_GRANULARITY); xInc1 = -4; dx = -dx; } if ( dy > dx ) { swap_xor ( dx, dy ); swap_xor ( xInc0, yInc0 ); swap_xor ( xInc1, yInc1 ); } if ( 0 == dx ) return; dst = (tVideoSample*) ( (u8*) (tVideoSample*)RenderTarget->lock() + ( aposy * pitch0 ) + (aposx << VIDEO_SAMPLE_GRANULARITY ) ); #ifdef USE_ZBUFFER z = (fp24*) ( (u8*) (fp24*) DepthBuffer->lock() + ( aposy * pitch1 ) + (aposx << 2 ) ); #endif c = dx << 1; m = dy << 1; #ifdef IPOL_Z f32 slopeZ = (b->Pos.z - a->Pos.z) / f32(dx); f32 dataZ = a->Pos.z; #endif #ifdef IPOL_W fp24 slopeW = (b->Pos.w - a->Pos.w) / f32( dx ); fp24 dataW = a->Pos.w; #endif run = dx; while ( run ) { #ifdef CMP_Z if ( *z >= dataZ ) #endif #ifdef CMP_W if ( dataW >= *z ) #endif { #ifdef WRITE_Z *z = dataZ; #endif #ifdef WRITE_W *z = dataW; #endif *dst = color; } dst = (tVideoSample*) ( (u8*) dst + xInc0 ); // x += xInc #ifdef IPOL_Z z = (fp24*) ( (u8*) z + xInc1 ); #endif #ifdef IPOL_W z = (fp24*) ( (u8*) z + xInc1 ); #endif d += m; if ( d > dx ) { dst = (tVideoSample*) ( (u8*) dst + yInc0 ); // y += yInc #ifdef IPOL_Z z = (fp24*) ( (u8*) z + yInc1 ); #endif #ifdef IPOL_W z = (fp24*) ( (u8*) z + yInc1 ); #endif d -= c; } run -= 1; #ifdef IPOL_Z dataZ += slopeZ; #endif #ifdef IPOL_W dataW += slopeW; #endif } } void CTRTextureWire2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { sScanLineData line; // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); renderLine ( a, b ); renderLine ( b, c ); renderLine ( a, c ); } void CTRTextureWire2::drawLine ( const s4DVertex *a,const s4DVertex *b) { // query access to TexMaps // sort on height, y if ( a->Pos.y > b->Pos.y ) swapVertexPointer(&a, &b); renderLine ( a, b ); } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureGouraudWire2(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureWire2(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp0000644000000000000000000003461312574354552023260 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W #define IPOL_C0 #define IPOL_T0 #define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRGTextureLightMap2_M4 : public IBurningShader { public: //! constructor CTRGTextureLightMap2_M4(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; }; //! constructor CTRGTextureLightMap2_M4::CTRGTextureLightMap2_M4(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRGTextureLightMap2_M4"); #endif } /*! */ void CTRGTextureLightMap2_M4::scanline_bilinear () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef INVERSE_W f32 inversew; #endif tFixPoint tx0, tx1; tFixPoint ty0, ty1; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; #ifdef IPOL_C0 tFixPoint r3, g3, b3; #endif for ( s32 i = 0; i <= dx; i++ ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); tx0 = tofix ( line.t[0][0].x,inversew); ty0 = tofix ( line.t[0][0].y,inversew); tx1 = tofix ( line.t[1][0].x,inversew); ty1 = tofix ( line.t[1][0].y,inversew); #ifdef IPOL_C0 r3 = tofix ( line.c[0][0].y ,inversew ); g3 = tofix ( line.c[0][0].z ,inversew ); b3 = tofix ( line.c[0][0].w ,inversew ); #endif #else tx0 = tofix ( line.t[0][0].x ); ty0 = tofix ( line.t[0][0].y ); tx1 = tofix ( line.t[1][0].x ); ty1 = tofix ( line.t[1][0].y ); #ifdef IPOL_C0 r3 = tofix ( line.c[0][0].y ); g3 = tofix ( line.c[0][0].z ); b3 = tofix ( line.c[0][0].w ); #endif #endif getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); getSample_texture ( r1, g1, b1, &IT[1], tx1, ty1 ); #ifdef IPOL_C0 r2 = imulFix ( r0, r3 ); g2 = imulFix ( g0, g3 ); b2 = imulFix ( b0, b3 ); r2 = clampfix_maxcolor ( imulFix_tex4 ( r2, r1 ) ); g2 = clampfix_maxcolor ( imulFix_tex4 ( g2, g1 ) ); b2 = clampfix_maxcolor ( imulFix_tex4 ( b2, b1 ) ); /* r2 = r3 << 8; g2 = g3 << 8; b2 = b3 << 8; */ #else r2 = clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ); g2 = clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ); b2 = clampfix_maxcolor ( imulFix_tex4 ( b0, b1 ) ); #endif dst[i] = fix_to_color ( r2, g2, b2 ); #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRGTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle //if ( (f32) 0.0 != scan.invDeltaY[1] ) if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle //if ( (f32) 0.0 != scan.invDeltaY[2] ) if ( F32_GREATER_0 ( scan.invDeltaY[2] ) ) { // advance to middle point //if( (f32) 0.0 != scan.invDeltaY[1] ) if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTriangleRendererGTextureLightMap2_M4(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRGTextureLightMap2_M4(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureLightMap2_M4.cpp0000644000000000000000000006144712574354552021736 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W //#define IPOL_C0 #define IPOL_T0 #define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureLightMap2_M4 : public IBurningShader { public: //! constructor CTRTextureLightMap2_M4(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void drawTriangle_Min ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); void drawTriangle_Mag ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); void scanline_bilinear (); void scanline_bilinear2_mag (); void scanline_bilinear2_min (); sScanLineData line; }; //! constructor CTRTextureLightMap2_M4::CTRTextureLightMap2_M4(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureLightMap2_M4"); #endif } /*! */ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_mag () { tVideoSample *dst; fp24 *z; // apply top-left fill-convention, left const s32 xStart = irr::core::ceil32( line.x[0] ); const s32 xEnd = irr::core::ceil32( line.x[1] ) - 1; s32 dx; s32 i; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel i = ( line.y * RenderTarget->getDimension().Width ) + xStart; z = (fp24*) DepthBuffer->lock() + i; dst = (tVideoSample*)RenderTarget->lock() + i; // subTexel const f32 subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_W const fp24 b = (line.w[1] - line.w[0]) * invDeltaX; fp24 a = line.w[0] + ( b * subPixel ); i = 0; while ( a < z[i] ) { a += b; i += 1; if ( i > dx ) return; } // lazy setup rest of scanline line.w[0] = a; line.w[1] = b; #else const f32 b = (line.z[1] - line.z[0]) * invDeltaX; f32 a = line.z[0] + ( b * subPixel ); i = 0; while ( a > z[i] ) { a += b; i += 1; if ( i > dx ) return; } // lazy setup rest of scanline line.z[0] = a; line.z[1] = b; #endif a = (f32) i + subPixel; line.t[0][1] = (line.t[0][1] - line.t[0][0]) * invDeltaX; line.t[1][1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; line.t[0][0] += line.t[0][1] * a; line.t[1][0] += line.t[1][1] * a; #ifdef BURNINGVIDEO_RENDERER_FAST u32 dIndex = ( line.y & 3 ) << 2; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; #else // tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; #endif for ( ;i <= dx; i++ ) { #ifdef IPOL_W if ( line.w[0] >= z[i] ) { z[i] = line.w[0]; #else if ( line.z[0] < z[i] ) { z[i] = line.z[0]; #endif #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT f32 inversew = fix_inverse32 ( line.w[0] ); #else f32 inversew = FIX_POINT_F32_MUL; #endif #ifdef BURNINGVIDEO_RENDERER_FAST const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; getSample_texture ( r0, g0, b0, &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ); getSample_texture ( r1, g1, b1, &IT[1], d + tofix ( line.t[1][0].x,inversew), d + tofix ( line.t[1][0].y,inversew) ); #else getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); #endif dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ), clampfix_maxcolor ( imulFix_tex4 ( b0, b1 ) ) ); } #ifdef IPOL_W line.w[0] += line.w[1]; #else line.z[0] += line.z[1]; #endif line.t[0][0] += line.t[0][1]; line.t[1][0] += line.t[1][1]; } } /*! */ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_min () { tVideoSample *dst; fp24 *z; s32 xStart; s32 xEnd; s32 dx; s32 i; // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; // subTexel const f32 subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_W const f32 b = (line.w[1] - line.w[0]) * invDeltaX; f32 a = line.w[0] + ( b * subPixel ); i = 0; while ( a <= z[i] ) { a += b; i += 1; if ( i > dx ) return; } // lazy setup rest of scanline line.w[0] = a; line.w[1] = b; #else const f32 b = (line.z[1] - line.z[0]) * invDeltaX; f32 a = line.z[0] + ( b * subPixel ); i = 0; while ( a > z[i] ) { a += b; i += 1; if ( i > dx ) return; } // lazy setup rest of scanline line.z[0] = a; line.z[1] = b; #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; a = (f32) i + subPixel; line.t[0][1] = (line.t[0][1] - line.t[0][0]) * invDeltaX; line.t[1][1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; line.t[0][0] += line.t[0][1] * a; line.t[1][0] += line.t[1][1] * a; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; for ( ;i <= dx; i++ ) { #ifdef IPOL_W if ( line.w[0] >= z[i] ) { z[i] = line.w[0]; #else if ( line.z[0] < z[i] ) { z[i] = line.z[0]; #endif #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT f32 inversew = fix_inverse32 ( line.w[0] ); #else f32 inversew = FIX_POINT_F32_MUL; #endif getTexel_fix ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); getTexel_fix ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ), clampfix_maxcolor ( imulFix_tex4 ( b0, b1 ) ) ); } #ifdef IPOL_W line.w[0] += line.w[1]; #else line.z[0] += line.z[1]; #endif line.t[0][0] += line.t[0][1]; line.t[1][0] += line.t[1][1]; } } //#ifdef BURNINGVIDEO_RENDERER_FAST #if 1 void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { if ( IT[0].lodLevel <= 2 ) drawTriangle_Mag ( a, b, c ); else drawTriangle_Min ( a, b, c ); } void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { sScanConvertData scan; // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear2_min (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle //if ( (f32) 0.0 != scan.invDeltaY[2] ) if ( F32_GREATER_0 ( scan.invDeltaY[2] ) ) { // advance to middle point if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear2_min (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } void CTRTextureLightMap2_M4::drawTriangle_Mag ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) #else void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) #endif { sScanConvertData scan; // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear2_mag (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle //if ( (f32) 0.0 != scan.invDeltaY[2] ) if ( F32_GREATER_0 ( scan.invDeltaY[2] ) ) { // advance to middle point if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear2_mag (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureLightMap2_M4(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureLightMap2_M4(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureLightMap2_M2.cpp0000644000000000000000000003276012574354552021730 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W //#define IPOL_C0 #define IPOL_T0 #define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureLightMap2_M2 : public IBurningShader { public: //! constructor CTRTextureLightMap2_M2(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear2 (); sScanLineData line; }; //! constructor CTRTextureLightMap2_M2::CTRTextureLightMap2_M2(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureLightMap2_M2"); #endif } /*! */ REALINLINE void CTRTextureLightMap2_M2::scanline_bilinear2 () { tVideoSample *dst; fp24 *z; s32 xStart; s32 xEnd; s32 dx; s32 i; // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; // subTexel const f32 subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_W const f32 b = (line.w[1] - line.w[0]) * invDeltaX; f32 a = line.w[0] + ( b * subPixel ); i = 0; while ( a <= z[i] ) { a += b; i += 1; if ( i > dx ) return; } // lazy setup rest of scanline line.w[0] = a; line.w[1] = b; #else const f32 b = (line.z[1] - line.z[0]) * invDeltaX; f32 a = line.z[0] + ( b * subPixel ); i = 0; while ( a > z[i] ) { a += b; i += 1; if ( i > dx ) return; } // lazy setup rest of scanline line.z[0] = a; line.z[1] = b; #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; a = (f32) i + subPixel; line.t[0][1] = (line.t[0][1] - line.t[0][0]) * invDeltaX; line.t[1][1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; line.t[0][0] += line.t[0][1] * a; line.t[1][0] += line.t[1][1] * a; #ifdef BURNINGVIDEO_RENDERER_FAST u32 dIndex = ( line.y & 3 ) << 2; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; #else // tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; #endif for ( ;i <= dx; i++ ) { #ifdef IPOL_W if ( line.w[0] >= z[i] ) { z[i] = line.w[0]; #else if ( line.z[0] < z[i] ) { z[i] = line.z[0]; #endif #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT f32 inversew = fix_inverse32 ( line.w[0] ); #else f32 inversew = FIX_POINT_F32_MUL; #endif #ifdef BURNINGVIDEO_RENDERER_FAST const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; getSample_texture ( r0, g0, b0, &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ); getSample_texture ( r1, g1, b1, &IT[1], d + tofix ( line.t[1][0].x,inversew), d + tofix ( line.t[1][0].y,inversew) ); #else getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); #endif dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); } #ifdef IPOL_W line.w[0] += line.w[1]; #else line.z[0] += line.z[1]; #endif line.t[0][0] += line.t[0][1]; line.t[1][0] += line.t[1][1]; } } void CTRTextureLightMap2_M2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { sScanConvertData scan; // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear2 (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle //if ( (f32) 0.0 != scan.invDeltaY[2] ) if ( F32_GREATER_0 ( scan.invDeltaY[2] ) ) { // advance to middle point if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear2 (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureLightMap2_M2(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureLightMap2_M2(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureLightMap2_M1.cpp0000644000000000000000000003265612574354552021733 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W //#define IPOL_C0 #define IPOL_T0 #define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureLightMap2_M1 : public IBurningShader { public: //! constructor CTRTextureLightMap2_M1(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear2 (); sScanLineData line; }; //! constructor CTRTextureLightMap2_M1::CTRTextureLightMap2_M1(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureLightMap2_M1"); #endif } /*! */ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () { tVideoSample *dst; fp24 *z; s32 xStart; s32 xEnd; s32 dx; s32 i; // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; // subTexel const f32 subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_W const f32 b = (line.w[1] - line.w[0]) * invDeltaX; f32 a = line.w[0] + ( b * subPixel ); i = 0; while ( a <= z[i] ) { a += b; i += 1; if ( i > dx ) return; } // lazy setup rest of scanline line.w[0] = a; line.w[1] = b; #else const f32 b = (line.z[1] - line.z[0]) * invDeltaX; f32 a = line.z[0] + ( b * subPixel ); i = 0; while ( a > z[i] ) { a += b; i += 1; if ( i > dx ) return; } // lazy setup rest of scanline line.z[0] = a; line.z[1] = b; #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; a = (f32) i + subPixel; line.t[0][1] = (line.t[0][1] - line.t[0][0]) * invDeltaX; line.t[1][1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; line.t[0][0] += line.t[0][1] * a; line.t[1][0] += line.t[1][1] * a; #ifdef BURNINGVIDEO_RENDERER_FAST u32 dIndex = ( line.y & 3 ) << 2; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; #else // tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; #endif for ( ;i <= dx; i++ ) { #ifdef IPOL_W if ( line.w[0] >= z[i] ) { z[i] = line.w[0]; #else if ( line.z[0] < z[i] ) { z[i] = line.z[0]; #endif #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT f32 inversew = fix_inverse32 ( line.w[0] ); #else f32 inversew = FIX_POINT_F32_MUL; #endif #ifdef BURNINGVIDEO_RENDERER_FAST const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; getSample_texture ( r0, g0, b0, &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ); getSample_texture ( r1, g1, b1, &IT[1], d + tofix ( line.t[1][0].x,inversew), d + tofix ( line.t[1][0].y,inversew) ); #else getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); #endif dst[i] = fix_to_color ( imulFix_tex1 ( r0, r1 ), imulFix_tex1 ( g0, g1 ), imulFix_tex1 ( b0, b1 ) ); } #ifdef IPOL_W line.w[0] += line.w[1]; #else line.z[0] += line.z[1]; #endif line.t[0][0] += line.t[0][1]; line.t[1][0] += line.t[1][1]; } } void CTRTextureLightMap2_M1::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { sScanConvertData scan; // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear2 (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle //if ( (f32) 0.0 != scan.invDeltaY[2] ) if ( F32_GREATER_0 ( scan.invDeltaY[2] ) ) { // advance to middle point if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear2 (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureLightMap2_M1(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureLightMap2_M1(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureLightMap2_Add.cpp0000644000000000000000000003373412574354552022144 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W //#define IPOL_C0 #define IPOL_T0 #define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureLightMap2_Add : public IBurningShader { public: //! constructor CTRTextureLightMap2_Add(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; }; //! constructor CTRTextureLightMap2_Add::CTRTextureLightMap2_Add(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureLightMap2_Add"); #endif } /*! */ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC = (line.c[1] - line.c[0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0] += slopeC * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef BURNINGVIDEO_RENDERER_FAST u32 dIndex = ( line.y & 3 ) << 2; #else // tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; #endif for ( s32 i = 0; i <= dx; i++ ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef BURNINGVIDEO_RENDERER_FAST #ifdef INVERSE_W const f32 inversew = fix_inverse32 ( line.w[0] ); const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; dst[i] = PixelAdd32 ( getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ), getTexel_plain ( &IT[1], d + tofix ( line.t[1][0].x,inversew), d + tofix ( line.t[1][0].y,inversew) ) ); #else const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; dst[i] = PixelAdd32 ( getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x), d + tofix ( line.t[0][0].y) ), getTexel_plain ( &IT[1], d + tofix ( line.t[1][0].x), d + tofix ( line.t[1][0].y) ) ); #endif #else const f32 inversew = fix_inverse32 ( line.w[0] ); getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[0][1].x,inversew), tofix ( line.t[0][1].y,inversew) ); dst[i] = fix_to_color ( clampfix_maxcolor ( r0 + r1 ), clampfix_maxcolor ( g0 + g1 ), clampfix_maxcolor ( b0 + b1 ) ); #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0] += slopeC; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRTextureLightMap2_Add::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureLightMap2_Add(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureLightMap2_Add(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureGouraudWire.cpp0000644000000000000000000002636412574354552022043 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CTRTextureGouraud.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { class CTRTextureGouraudWire : public CTRTextureGouraud { public: CTRTextureGouraudWire(IZBuffer* zbuffer) : CTRTextureGouraud(zbuffer) { #ifdef _DEBUG setDebugName("CTRGouraudWire"); #endif } //! draws an indexed triangle list virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) { const S2DVertex *v1, *v2, *v3; u16 color; f32 tmpDiv; // temporary division factor f32 longest; // saves the longest span s32 height; // saves height of triangle u16* targetSurface; // target pointer where to plot pixels s32 spanEnd; // saves end of spans f32 leftdeltaxf; // amount of pixels to increase on left side of triangle f32 rightdeltaxf; // amount of pixels to increase on right side of triangle s32 leftx, rightx; // position where we are f32 leftxf, rightxf; // same as above, but as f32 values s32 span; // current span s32 leftR, leftG, leftB, rightR, rightG, rightB; // color values s32 leftStepR, leftStepG, leftStepB, rightStepR, rightStepG, rightStepB; // color steps s32 leftTx, rightTx, leftTy, rightTy; // texture interpolating values s32 leftTxStep, rightTxStep, leftTyStep, rightTyStep; // texture interpolating values core::rect TriangleRect; s32 leftZValue, rightZValue; s32 leftZStep, rightZStep; TZBufferType* zTarget;//, *spanZTarget; // target of ZBuffer; lockedSurface = (u16*)RenderTarget->lock(); lockedZBuffer = ZBuffer->lock(); lockedTexture = (u16*)Texture->lock(); for (s32 i=0; iPos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) - ((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X)); if (z < 0) continue; } //near plane clipping if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0) continue; // sort for width for inscreen clipping if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2); if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3); if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3); if ((v1->Pos.X - v3->Pos.X) == 0) continue; TriangleRect.UpperLeftCorner.X = v1->Pos.X; TriangleRect.LowerRightCorner.X = v3->Pos.X; // sort for height for faster drawing. if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2); if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3); if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3); TriangleRect.UpperLeftCorner.Y = v1->Pos.Y; TriangleRect.LowerRightCorner.Y = v3->Pos.Y; if (!TriangleRect.isRectCollided(ViewPortRect)) continue; // calculate height of triangle height = v3->Pos.Y - v1->Pos.Y; if (!height) continue; // calculate longest span longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X); spanEnd = v2->Pos.Y; span = v1->Pos.Y; leftxf = (f32)v1->Pos.X; rightxf = (f32)v1->Pos.X; leftZValue = v1->ZValue; rightZValue = v1->ZValue; leftR = rightR = video::getRed(v1->Color)<<8; leftG = rightG = video::getGreen(v1->Color)<<8; leftB = rightB = video::getBlue(v1->Color)<<8; leftTx = rightTx = v1->TCoords.X; leftTy = rightTy = v1->TCoords.Y; targetSurface = lockedSurface + span * SurfaceWidth; zTarget = lockedZBuffer + span * SurfaceWidth; if (longest < 0.0f) { tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); rightStepR = (s32)(((s32)(video::getRed(v2->Color)<<8) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v2->Color)<<8) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v2->Color)<<8) - rightB) * tmpDiv); rightTxStep = (s32)((v2->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v2->TCoords.Y - rightTy) * tmpDiv); tmpDiv = 1.0f / (f32)height; leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - leftB) * tmpDiv); leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv); } else { tmpDiv = 1.0f / (f32)height; rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - rightB) * tmpDiv); rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv); tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); leftStepR = (s32)(((s32)(video::getRed(v2->Color)<<8) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v2->Color)<<8) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v2->Color)<<8) - leftB) * tmpDiv); leftTxStep = (s32)((v2->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v2->TCoords.Y - leftTy) * tmpDiv); } // do it twice, once for the first half of the triangle, // end then for the second half. for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf) { if (spanEnd > ViewPortRect.LowerRightCorner.Y) spanEnd = ViewPortRect.LowerRightCorner.Y; // if the span <0, than we can skip these spans, // and proceed to the next spans which are really on the screen. if (span < ViewPortRect.UpperLeftCorner.Y) { // we'll use leftx as temp variable if (spanEnd < ViewPortRect.UpperLeftCorner.Y) { leftx = spanEnd - span; span = spanEnd; } else { leftx = ViewPortRect.UpperLeftCorner.Y - span; span = ViewPortRect.UpperLeftCorner.Y; } leftxf += leftdeltaxf*leftx; rightxf += rightdeltaxf*leftx; targetSurface += SurfaceWidth*leftx; zTarget += SurfaceWidth*leftx; leftZValue += leftZStep*leftx; rightZValue += rightZStep*leftx; leftR += leftStepR*leftx; leftG += leftStepG*leftx; leftB += leftStepB*leftx; rightR += rightStepR*leftx; rightG += rightStepG*leftx; rightB += rightStepB*leftx; leftTx += leftTxStep*leftx; leftTy += leftTyStep*leftx; rightTx += rightTxStep*leftx; rightTy += rightTyStep*leftx; } // the main loop. Go through every span and draw it. while (span < spanEnd) { leftx = (s32)(leftxf); rightx = (s32)(rightxf + 0.5f); // perform some clipping if (leftx>=ViewPortRect.UpperLeftCorner.X && leftx<=ViewPortRect.LowerRightCorner.X) { if (leftZValue > *(zTarget + leftx)) { *(zTarget + leftx) = leftZValue; color = lockedTexture[((leftTy>>8)&textureYMask) * lockedTextureWidth + ((leftTx>>8)&textureXMask)]; *(targetSurface + leftx) = video::RGB16(video::getRed(color) * (leftR>>8) >>2, video::getGreen(color) * (leftG>>8) >>2, video::getBlue(color) * (leftR>>8) >>2); } } if (rightx>=ViewPortRect.UpperLeftCorner.X && rightx<=ViewPortRect.LowerRightCorner.X) { if (rightZValue > *(zTarget + rightx)) { *(zTarget + rightx) = rightZValue; color = lockedTexture[((rightTy>>8)&textureYMask) * lockedTextureWidth + ((rightTx>>8)&textureXMask)]; *(targetSurface + rightx) = video::RGB16(video::getRed(color) * (rightR>>8) >>2, video::getGreen(color) * (rightG>>8) >>2, video::getBlue(color) * (rightR>>8) >>2); } } leftxf += leftdeltaxf; rightxf += rightdeltaxf; ++span; targetSurface += SurfaceWidth; zTarget += SurfaceWidth; leftZValue += leftZStep; rightZValue += rightZStep; leftR += leftStepR; leftG += leftStepG; leftB += leftStepB; rightR += rightStepR; rightG += rightStepG; rightB += rightStepB; leftTx += leftTxStep; leftTy += leftTyStep; rightTx += rightTxStep; rightTy += rightTyStep; } if (triangleHalf>0) // break, we've gout only two halves break; // setup variables for second half of the triangle. if (longest < 0.0f) { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; rightxf = (f32)v2->Pos.X; rightZValue = v2->ZValue; rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); rightR = video::getRed(v2->Color)<<8; rightG = video::getGreen(v2->Color)<<8; rightB = video::getBlue(v2->Color)<<8; rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - rightB) * tmpDiv); rightTx = v2->TCoords.X; rightTy = v2->TCoords.Y; rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv); } else { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; leftxf = (f32)v2->Pos.X; leftZValue = v2->ZValue; leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); leftR = video::getRed(v2->Color)<<8; leftG = video::getGreen(v2->Color)<<8; leftB = video::getBlue(v2->Color)<<8; leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - leftB) * tmpDiv); leftTx = v2->TCoords.X; leftTy = v2->TCoords.Y; leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv); } spanEnd = v3->Pos.Y; } } RenderTarget->unlock(); ZBuffer->unlock(); Texture->unlock(); } }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! creates a flat triangle renderer ITriangleRenderer* createTriangleRendererTextureGouraudWire(IZBuffer* zbuffer) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CTRTextureGouraudWire(zbuffer); #else return 0; #endif // _IRR_COMPILE_WITH_SOFTWARE_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp0000644000000000000000000003403012574354552023427 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W //#define WRITE_W #define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureVertexAlpha2 : public IBurningShader { public: //! constructor CTRTextureVertexAlpha2(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; }; //! constructor CTRTextureVertexAlpha2::CTRTextureVertexAlpha2(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureVertexAlpha2"); #endif } /*! */ void CTRTextureVertexAlpha2::scanline_bilinear ( ) { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef INVERSE_W f32 inversew; #endif //#define __TEST_THIS #ifdef __TEST_THIS #else tFixPoint tx0; tFixPoint ty0; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; #endif #ifdef IPOL_C0 tFixPoint a3; #endif for ( s32 i = 0; i <= dx; ++i ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef __TEST_THIS inversew = fix_inverse32 ( line.w[0] ); dst[i] = PixelAdd32 ( dst[i], getTexel_plain ( &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ) ); #else #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); tx0 = tofix ( line.t[0][0].x,inversew); ty0 = tofix ( line.t[0][0].y,inversew); #ifdef IPOL_C0 a3 = tofix ( line.c[0][0].y,inversew ); #endif #else tx0 = tofix ( line.t[0][0].x ); ty0 = tofix ( line.t[0][0].y ); #ifdef IPOL_C0 a3 = tofix ( line.c[0][0].y ); #endif #endif getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); color_to_fix ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 r2 = clampfix_maxcolor ( r1 + imulFix ( r0, a3 ) ); g2 = clampfix_maxcolor ( g1 + imulFix ( g0, a3 ) ); b2 = clampfix_maxcolor ( b1 + imulFix ( b0, a3 ) ); #else r2 = clampfix_maxcolor ( r1 + r0 ); g2 = clampfix_maxcolor ( g1 + g0 ); b2 = clampfix_maxcolor ( b1 + b0 ); #endif dst[i] = fix_to_color ( r2, g2, b2 ); #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureVertexAlpha2(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureVertexAlpha2(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureGouraudNoZ2.cpp0000644000000000000000000003220412574354552021713 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #ifdef BURNINGVIDEO_RENDERER_FAST #define SUBTEXEL #define INVERSE_W #else #define SUBTEXEL #define INVERSE_W #endif //#define USE_ZBUFFER #define IPOL_W //#define CMP_W //#define WRITE_W //#define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureGouraudNoZ2 : public IBurningShader { public: //! constructor CTRTextureGouraudNoZ2(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; }; //! constructor CTRTextureGouraudNoZ2::CTRTextureGouraudNoZ2(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureGouraudNoZ2"); #endif } /*! */ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC = (line.c[1] - line.c[0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0] += slopeC * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef INVERSE_W f32 inversew; #endif tFixPoint tx0; tFixPoint ty0; for ( s32 i = 0; i <= dx; ++i ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); tx0 = tofix ( line.t[0][0].x,inversew); ty0 = tofix ( line.t[0][0].y,inversew); #else tx0 = tofix ( line.t[0][0].x ); ty0 = tofix ( line.t[0][0].y ); #endif dst[i] = getTexel_plain ( &IT[0], tx0, ty0 ); /* getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); dst[i] = fix_to_color ( r0, g0, b0 ); */ #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0] += slopeC; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRTextureGouraudNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear ( ); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTRTextureGouraudNoZ2(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureGouraudNoZ2( driver ); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureGouraudNoZ.cpp0000644000000000000000000002655312574354552021643 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CTRTextureGouraud.h" #include "SColor.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { class CTRTextureGouraudNoZ : public CTRTextureGouraud { public: CTRTextureGouraudNoZ() : CTRTextureGouraud(0) { #ifdef _DEBUG setDebugName("CTRGouraudWireNoZ"); #endif } //! draws an indexed triangle list virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) { const S2DVertex *v1, *v2, *v3; u16 color; f32 tmpDiv; // temporary division factor f32 longest; // saves the longest span s32 height; // saves height of triangle u16* targetSurface; // target pointer where to plot pixels s32 spanEnd; // saves end of spans f32 leftdeltaxf; // amount of pixels to increase on left side of triangle f32 rightdeltaxf; // amount of pixels to increase on right side of triangle s32 leftx, rightx; // position where we are f32 leftxf, rightxf; // same as above, but as f32 values s32 span; // current span u16 *hSpanBegin, *hSpanEnd; // pointer used when plotting pixels s32 leftR, leftG, leftB, rightR, rightG, rightB; // color values s32 leftStepR, leftStepG, leftStepB, rightStepR, rightStepG, rightStepB; // color steps s32 spanR, spanG, spanB, spanStepR, spanStepG, spanStepB; // color interpolating values while drawing a span. s32 leftTx, rightTx, leftTy, rightTy; // texture interpolating values s32 leftTxStep, rightTxStep, leftTyStep, rightTyStep; // texture interpolating values s32 spanTx, spanTy, spanTxStep, spanTyStep; // values of Texturecoords when drawing a span core::rect TriangleRect; lockedSurface = (u16*)RenderTarget->lock(); lockedTexture = (u16*)Texture->lock(); for (s32 i=0; iPos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) - ((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X)); if (z < 0) continue; } //near plane clipping if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0) continue; // sort for width for inscreen clipping if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2); if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3); if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3); if ((v1->Pos.X - v3->Pos.X) == 0) continue; TriangleRect.UpperLeftCorner.X = v1->Pos.X; TriangleRect.LowerRightCorner.X = v3->Pos.X; // sort for height for faster drawing. if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2); if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3); if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3); TriangleRect.UpperLeftCorner.Y = v1->Pos.Y; TriangleRect.LowerRightCorner.Y = v3->Pos.Y; if (!TriangleRect.isRectCollided(ViewPortRect)) continue; // calculate height of triangle height = v3->Pos.Y - v1->Pos.Y; if (!height) continue; // calculate longest span longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X); spanEnd = v2->Pos.Y; span = v1->Pos.Y; leftxf = (f32)v1->Pos.X; rightxf = (f32)v1->Pos.X; leftR = rightR = video::getRed(v1->Color)<<8; leftG = rightG = video::getGreen(v1->Color)<<8; leftB = rightB = video::getBlue(v1->Color)<<8; leftTx = rightTx = v1->TCoords.X; leftTy = rightTy = v1->TCoords.Y; targetSurface = lockedSurface + span * SurfaceWidth; if (longest < 0.0f) { tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; rightStepR = (s32)(((s32)(video::getRed(v2->Color)<<8) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v2->Color)<<8) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v2->Color)<<8) - rightB) * tmpDiv); rightTxStep = (s32)((v2->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v2->TCoords.Y - rightTy) * tmpDiv); tmpDiv = 1.0f / (f32)height; leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - leftB) * tmpDiv); leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv); } else { tmpDiv = 1.0f / (f32)height; rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - rightB) * tmpDiv); rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv); tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; leftStepR = (s32)(((s32)(video::getRed(v2->Color)<<8) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v2->Color)<<8) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v2->Color)<<8) - leftB) * tmpDiv); leftTxStep = (s32)((v2->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v2->TCoords.Y - leftTy) * tmpDiv); } // do it twice, once for the first half of the triangle, // end then for the second half. for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf) { if (spanEnd > ViewPortRect.LowerRightCorner.Y) spanEnd = ViewPortRect.LowerRightCorner.Y; // if the span <0, than we can skip these spans, // and proceed to the next spans which are really on the screen. if (span < ViewPortRect.UpperLeftCorner.Y) { // we'll use leftx as temp variable if (spanEnd < ViewPortRect.UpperLeftCorner.Y) { leftx = spanEnd - span; span = spanEnd; } else { leftx = ViewPortRect.UpperLeftCorner.Y - span; span = ViewPortRect.UpperLeftCorner.Y; } leftxf += leftdeltaxf*leftx; rightxf += rightdeltaxf*leftx; targetSurface += SurfaceWidth*leftx; leftR += leftStepR*leftx; leftG += leftStepG*leftx; leftB += leftStepB*leftx; rightR += rightStepR*leftx; rightG += rightStepG*leftx; rightB += rightStepB*leftx; leftTx += leftTxStep*leftx; leftTy += leftTyStep*leftx; rightTx += rightTxStep*leftx; rightTy += rightTyStep*leftx; } // the main loop. Go through every span and draw it. while (span < spanEnd) { leftx = (s32)(leftxf); rightx = (s32)(rightxf + 0.5f); // perform some clipping // thanks to a correction by hybrid // calculations delayed to correctly propagate to textures etc. s32 tDiffLeft=0, tDiffRight=0; if (leftxViewPortRect.LowerRightCorner.X) tDiffLeft=ViewPortRect.LowerRightCorner.X-leftx; if (rightxViewPortRect.LowerRightCorner.X) tDiffRight=ViewPortRect.LowerRightCorner.X-rightx; // draw the span if (rightx + tDiffRight - leftx - tDiffLeft) { tmpDiv = 1.0f / (f32)(rightx - leftx); spanStepR = (s32)((rightR - leftR) * tmpDiv); spanR = leftR+tDiffLeft*spanStepR; spanStepG = (s32)((rightG - leftG) * tmpDiv); spanG = leftG+tDiffLeft*spanStepG; spanStepB = (s32)((rightB - leftB) * tmpDiv); spanB = leftB+tDiffLeft*spanStepB; spanTxStep = (s32)((rightTx - leftTx) * tmpDiv); spanTx = leftTx + tDiffLeft*spanTxStep; spanTyStep = (s32)((rightTy - leftTy) * tmpDiv); spanTy = leftTy+tDiffLeft*spanTyStep; hSpanBegin = targetSurface + leftx+tDiffLeft; hSpanEnd = targetSurface + rightx+tDiffRight; while (hSpanBegin < hSpanEnd) { color = lockedTexture[((spanTy>>8)&textureYMask) * lockedTextureWidth + ((spanTx>>8)&textureXMask)]; *hSpanBegin = video::RGB16(video::getRed(color) * (spanR>>8) >>2, video::getGreen(color) * (spanG>>8) >>2, video::getBlue(color) * (spanB>>8) >>2); spanR += spanStepR; spanG += spanStepG; spanB += spanStepB; spanTx += spanTxStep; spanTy += spanTyStep; ++hSpanBegin; } } leftxf += leftdeltaxf; rightxf += rightdeltaxf; ++span; targetSurface += SurfaceWidth; leftR += leftStepR; leftG += leftStepG; leftB += leftStepB; rightR += rightStepR; rightG += rightStepG; rightB += rightStepB; leftTx += leftTxStep; leftTy += leftTyStep; rightTx += rightTxStep; rightTy += rightTyStep; } if (triangleHalf>0) // break, we've gout only two halves break; // setup variables for second half of the triangle. if (longest < 0.0f) { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; rightxf = (f32)v2->Pos.X; rightR = video::getRed(v2->Color)<<8; rightG = video::getGreen(v2->Color)<<8; rightB = video::getBlue(v2->Color)<<8; rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - rightB) * tmpDiv); rightTx = v2->TCoords.X; rightTy = v2->TCoords.Y; rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv); } else { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; leftxf = (f32)v2->Pos.X; leftR = video::getRed(v2->Color)<<8; leftG = video::getGreen(v2->Color)<<8; leftB = video::getBlue(v2->Color)<<8; leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - leftB) * tmpDiv); leftTx = v2->TCoords.X; leftTy = v2->TCoords.Y; leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv); } spanEnd = v3->Pos.Y; } } RenderTarget->unlock(); Texture->unlock(); } }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! creates a flat triangle renderer ITriangleRenderer* createTriangleRendererTextureGouraudNoZ() { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CTRTextureGouraudNoZ(); #else return 0; #endif // _IRR_COMPILE_WITH_SOFTWARE_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp0000644000000000000000000003635012574354552022605 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W //#define WRITE_W #define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureGouraudAlphaNoZ : public IBurningShader { public: //! constructor CTRTextureGouraudAlphaNoZ(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); virtual void setParam ( u32 index, f32 value); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; u32 AlphaRef; }; //! constructor CTRTextureGouraudAlphaNoZ::CTRTextureGouraudAlphaNoZ(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureGouraudAlphaNoZ"); #endif AlphaRef = 0; } /*! */ void CTRTextureGouraudAlphaNoZ::setParam ( u32 index, f32 value) { #ifdef BURNINGVIDEO_RENDERER_FAST AlphaRef = core::floor32 ( value * 256.f ); #else AlphaRef = u32_to_fixPoint ( core::floor32 ( value * 256.f ) ); #endif } /*! */ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef INVERSE_W f32 inversew; #endif #ifdef BURNINGVIDEO_RENDERER_FAST u32 dIndex = ( line.y & 3 ) << 2; #else tFixPoint a0; tFixPoint r0, g0, b0; #endif #ifdef IPOL_C0 tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; #endif for ( s32 i = 0; i <= dx; ++i ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef BURNINGVIDEO_RENDERER_FAST const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); u32 argb = getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ); #else u32 argb = getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x), d + tofix ( line.t[0][0].y) ); #endif const u32 alpha = ( argb >> 24 ); if ( alpha > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif dst[i] = PixelBlend32 ( dst[i], argb, alpha ); } #else #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); getSample_texture ( a0, r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); #else getSample_texture ( a0, r0, g0,b0, &IT[0], tofix ( line.t[0][0].x), tofix ( line.t[0][0].y) ); #endif if ( (tFixPointu) a0 > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W getSample_color ( r2, g2, b2, line.c[0][0], inversew ); #else getSample_color ( r2, g2, b2, line.c[0][0] ); #endif r0 = imulFix ( r0, r2 ); g0 = imulFix ( g0, g2 ); b0 = imulFix ( b0, b2 ); color_to_fix ( r1, g1, b1, dst[i] ); a0 >>= 8; r2 = r1 + imulFix ( a0, r0 - r1 ); g2 = g1 + imulFix ( a0, g0 - g1 ); b2 = b1 + imulFix ( a0, b0 - b1 ); dst[i] = fix4_to_color ( a0, r2, g2, b2 ); /* dst[i] = PixelBlend32 ( dst[i], fix_to_color ( r0,g0, b0 ), fixPointu_to_u32 ( a0 ) ); */ /* getSample_color ( r2, g2, b2, line.c[0][0], inversew * COLOR_MAX ); color_to_fix ( r1, g1, b1, dst[i] ); r2 = r0 + imulFix ( a0, r1 - r0 ); g2 = g0 + imulFix ( a0, g1 - g0 ); b2 = b0 + imulFix ( a0, b1 - b0 ); dst[i] = fix_to_color ( r2, g2, b2 ); */ } #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear ( ); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear ( ); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTRTextureGouraudAlphaNoZ(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureGouraudAlphaNoZ(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureGouraudAlpha.cpp0000644000000000000000000003631212574354552022154 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W #define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureGouraudAlpha2 : public IBurningShader { public: //! constructor CTRTextureGouraudAlpha2(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); virtual void setParam ( u32 index, f32 value); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; u32 AlphaRef; }; //! constructor CTRTextureGouraudAlpha2::CTRTextureGouraudAlpha2(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureGouraudAlpha2"); #endif AlphaRef = 0; } /*! */ void CTRTextureGouraudAlpha2::setParam ( u32 index, f32 value) { #ifdef BURNINGVIDEO_RENDERER_FAST AlphaRef = core::floor32 ( value * 256.f ); #else AlphaRef = u32_to_fixPoint ( core::floor32 ( value * 256.f ) ); #endif } /*! */ void CTRTextureGouraudAlpha2::scanline_bilinear () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef INVERSE_W f32 inversew; #endif #ifdef BURNINGVIDEO_RENDERER_FAST u32 dIndex = ( line.y & 3 ) << 2; #else tFixPoint a0; tFixPoint r0, g0, b0; #endif #ifdef IPOL_C0 tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; #endif for ( s32 i = 0; i <= dx; ++i ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef BURNINGVIDEO_RENDERER_FAST const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); u32 argb = getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ); #else u32 argb = getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x), d + tofix ( line.t[0][0].y) ); #endif const u32 alpha = ( argb >> 24 ); if ( alpha > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif dst[i] = PixelBlend32 ( dst[i], argb, alpha ); } #else #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); getSample_texture ( a0,r0,g0,b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); #else getSample_texture ( a0,r0,g0,b0, &IT[0], tofix ( line.t[0][0].x), tofix ( line.t[0][0].y) ); #endif if ( (tFixPointu) a0 > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W getSample_color ( r2, g2, b2, line.c[0][0], inversew ); #else getSample_color ( r2, g2, b2, line.c[0][0] ); #endif r0 = imulFix ( r0, r2 ); g0 = imulFix ( g0, g2 ); b0 = imulFix ( b0, b2 ); color_to_fix ( r1, g1, b1, dst[i] ); a0 >>= 8; r2 = r1 + imulFix ( a0, r0 - r1 ); g2 = g1 + imulFix ( a0, g0 - g1 ); b2 = b1 + imulFix ( a0, b0 - b1 ); dst[i] = fix4_to_color ( a0, r2, g2, b2 ); /* dst[i] = PixelBlend32 ( dst[i], fix_to_color ( r0,g0, b0 ), fixPointu_to_u32 ( a0 ) ); */ /* getSample_color ( r2, g2, b2, line.c[0][0], inversew * COLOR_MAX ); color_to_fix ( r1, g1, b1, dst[i] ); r2 = r0 + imulFix ( a0, r1 - r0 ); g2 = g0 + imulFix ( a0, g1 - g0 ); b2 = b0 + imulFix ( a0, b1 - b0 ); dst[i] = fix_to_color ( r2, g2, b2 ); */ } #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear ( ); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear ( ); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTRTextureGouraudAlpha(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureGouraudAlpha2(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp0000644000000000000000000003233212574354552022326 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W //#define WRITE_W //#define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureGouraudAddNoZ2 : public IBurningShader { public: //! constructor CTRTextureGouraudAddNoZ2(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; }; //! constructor CTRTextureGouraudAddNoZ2::CTRTextureGouraudAddNoZ2(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureGouraudAddNoZ2"); #endif } /*! */ void CTRTextureGouraudAddNoZ2::scanline_bilinear () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC = (line.c[1] - line.c[0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0] += slopeC * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef IPOL_W f32 inversew; #endif tFixPoint tx0; tFixPoint ty0; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; for ( s32 i = 0; i <= dx; ++i ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef IPOL_W inversew = fix_inverse32 ( line.w[0] ); tx0 = tofix ( line.t[0][0].x,inversew); ty0 = tofix ( line.t[0][0].y,inversew); #else tx0 = tofix ( line.t[0][0].x ); ty0 = tofix ( line.t[0][0].y ); #endif getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); color_to_fix ( r1, g1, b1, dst[i] ); dst[i] = fix_to_color ( clampfix_maxcolor ( r1 + (r0 >> 1 ) ), clampfix_maxcolor ( g1 + (g0 >> 1 ) ), clampfix_maxcolor ( b1 + (b0 >> 1) ) ); #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0] += slopeC; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear ( ); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTRTextureGouraudAddNoZ2(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureGouraudAddNoZ2(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureGouraudAdd2.cpp0000644000000000000000000003337112574354552021703 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W //#define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureGouraudAdd2 : public IBurningShader { public: //! constructor CTRTextureGouraudAdd2(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear (); sScanLineData line; }; //! constructor CTRTextureGouraudAdd2::CTRTextureGouraudAdd2(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureGouraudAdd2"); #endif } /*! */ void CTRTextureGouraudAdd2::scanline_bilinear () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC = (line.c[1] - line.c[0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0] += slopeC * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef INVERSE_W f32 inversew; #endif #ifdef BURNINGVIDEO_RENDERER_FAST u32 dIndex = ( line.y & 3 ) << 2; #else tFixPoint tx0; tFixPoint ty0; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; #endif for ( s32 i = 0; i <= dx; ++i ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef BURNINGVIDEO_RENDERER_FAST const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); dst[i] = PixelAdd32 ( dst[i], getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ) ); #else dst[i] = PixelAdd32 ( dst[i], getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x), d + tofix ( line.t[0][0].y) ) ); #endif #else #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); tx0 = tofix ( line.t[0][0].x,inversew); ty0 = tofix ( line.t[0][0].y,inversew); #else tx0 = tofix ( line.t[0][0].x ); ty0 = tofix ( line.t[0][0].y ); #endif getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); color_to_fix ( r1, g1, b1, dst[i] ); dst[i] = fix_to_color ( clampfix_maxcolor ( r1 + r0 ), clampfix_maxcolor ( g1 + g0 ), clampfix_maxcolor ( b1 + b0 ) ); #endif #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0] += slopeC; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRTextureGouraudAdd2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { sScanConvertData scan; // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0] * subPixel; scan.c[1] += scan.slopeC[1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[scan.left] = scan.c[0]; line.c[scan.right] = scan.c[1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0] += scan.slopeC[0]; scan.c[1] += scan.slopeC[1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTRTextureGouraudAdd2(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureGouraudAdd2(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureGouraudAdd.cpp0000644000000000000000000003153512574354552021621 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CTRTextureGouraud.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { class CTRTextureGouraudAdd : public CTRTextureGouraud { public: //! constructor CTRTextureGouraudAdd(IZBuffer* zbuffer); //! draws an indexed triangle list virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount); protected: }; //! constructor CTRTextureGouraudAdd::CTRTextureGouraudAdd(IZBuffer* zbuffer) : CTRTextureGouraud(zbuffer) { #ifdef _DEBUG setDebugName("CTRTextureGouraudAdd"); #endif } //! draws an indexed triangle list void CTRTextureGouraudAdd::drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) { const S2DVertex *v1, *v2, *v3; u16 color; f32 tmpDiv; // temporary division factor f32 longest; // saves the longest span s32 height; // saves height of triangle u16* targetSurface; // target pointer where to plot pixels s32 spanEnd; // saves end of spans f32 leftdeltaxf; // amount of pixels to increase on left side of triangle f32 rightdeltaxf; // amount of pixels to increase on right side of triangle s32 leftx, rightx; // position where we are f32 leftxf, rightxf; // same as above, but as f32 values s32 span; // current span u16 *hSpanBegin, *hSpanEnd; // pointer used when plotting pixels s32 leftR, leftG, leftB, rightR, rightG, rightB; // color values s32 leftStepR, leftStepG, leftStepB, rightStepR, rightStepG, rightStepB; // color steps s32 spanR, spanG, spanB, spanStepR, spanStepG, spanStepB; // color interpolating values while drawing a span. s32 leftTx, rightTx, leftTy, rightTy; // texture interpolating values s32 leftTxStep, rightTxStep, leftTyStep, rightTyStep; // texture interpolating values s32 spanTx, spanTy, spanTxStep, spanTyStep; // values of Texturecoords when drawing a span core::rect TriangleRect; s32 leftZValue, rightZValue; s32 leftZStep, rightZStep; s32 spanZValue, spanZStep; // ZValues when drawing a span TZBufferType* zTarget, *spanZTarget; // target of ZBuffer; lockedSurface = (u16*)RenderTarget->lock(); lockedZBuffer = ZBuffer->lock(); lockedTexture = (u16*)Texture->lock(); for (s32 i=0; iPos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) - ((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X)); if (z < 0) continue; } //near plane clipping if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0) continue; // sort for width for inscreen clipping if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2); if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3); if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3); if ((v1->Pos.X - v3->Pos.X) == 0) continue; TriangleRect.UpperLeftCorner.X = v1->Pos.X; TriangleRect.LowerRightCorner.X = v3->Pos.X; // sort for height for faster drawing. if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2); if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3); if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3); TriangleRect.UpperLeftCorner.Y = v1->Pos.Y; TriangleRect.LowerRightCorner.Y = v3->Pos.Y; if (!TriangleRect.isRectCollided(ViewPortRect)) continue; // calculate height of triangle height = v3->Pos.Y - v1->Pos.Y; if (!height) continue; // calculate longest span longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X); spanEnd = v2->Pos.Y; span = v1->Pos.Y; leftxf = (f32)v1->Pos.X; rightxf = (f32)v1->Pos.X; leftZValue = v1->ZValue; rightZValue = v1->ZValue; leftR = rightR = video::getRed(v1->Color)<<8; leftG = rightG = video::getGreen(v1->Color)<<8; leftB = rightB = video::getBlue(v1->Color)<<8; leftTx = rightTx = v1->TCoords.X; leftTy = rightTy = v1->TCoords.Y; targetSurface = lockedSurface + span * SurfaceWidth; zTarget = lockedZBuffer + span * SurfaceWidth; if (longest < 0.0f) { tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); rightStepR = (s32)(((s32)(video::getRed(v2->Color)<<8) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v2->Color)<<8) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v2->Color)<<8) - rightB) * tmpDiv); rightTxStep = (s32)((v2->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v2->TCoords.Y - rightTy) * tmpDiv); tmpDiv = 1.0f / (f32)height; leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - leftB) * tmpDiv); leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv); } else { tmpDiv = 1.0f / (f32)height; rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - rightB) * tmpDiv); rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv); tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); leftStepR = (s32)(((s32)(video::getRed(v2->Color)<<8) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v2->Color)<<8) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v2->Color)<<8) - leftB) * tmpDiv); leftTxStep = (s32)((v2->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v2->TCoords.Y - leftTy) * tmpDiv); } // do it twice, once for the first half of the triangle, // end then for the second half. for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf) { if (spanEnd > ViewPortRect.LowerRightCorner.Y) spanEnd = ViewPortRect.LowerRightCorner.Y; // if the span <0, than we can skip these spans, // and proceed to the next spans which are really on the screen. if (span < ViewPortRect.UpperLeftCorner.Y) { // we'll use leftx as temp variable if (spanEnd < ViewPortRect.UpperLeftCorner.Y) { leftx = spanEnd - span; span = spanEnd; } else { leftx = ViewPortRect.UpperLeftCorner.Y - span; span = ViewPortRect.UpperLeftCorner.Y; } leftxf += leftdeltaxf*leftx; rightxf += rightdeltaxf*leftx; targetSurface += SurfaceWidth*leftx; zTarget += SurfaceWidth*leftx; leftZValue += leftZStep*leftx; rightZValue += rightZStep*leftx; leftR += leftStepR*leftx; leftG += leftStepG*leftx; leftB += leftStepB*leftx; rightR += rightStepR*leftx; rightG += rightStepG*leftx; rightB += rightStepB*leftx; leftTx += leftTxStep*leftx; leftTy += leftTyStep*leftx; rightTx += rightTxStep*leftx; rightTy += rightTyStep*leftx; } // the main loop. Go through every span and draw it. while (span < spanEnd) { leftx = (s32)(leftxf); rightx = (s32)(rightxf + 0.5f); // perform some clipping // thanks to a correction by hybrid // calculations delayed to correctly propagate to textures etc. s32 tDiffLeft=0, tDiffRight=0; if (leftxViewPortRect.LowerRightCorner.X) tDiffLeft=ViewPortRect.LowerRightCorner.X-leftx; if (rightxViewPortRect.LowerRightCorner.X) tDiffRight=ViewPortRect.LowerRightCorner.X-rightx; // draw the span if (rightx + tDiffRight - leftx - tDiffLeft) { tmpDiv = 1.0f / (f32)(rightx - leftx); spanZStep = (s32)((rightZValue - leftZValue) * tmpDiv); spanZValue = leftZValue+tDiffLeft*spanZStep; spanStepR = (s32)((rightR - leftR) * tmpDiv); spanR = leftR+tDiffLeft*spanStepR; spanStepG = (s32)((rightG - leftG) * tmpDiv); spanG = leftG+tDiffLeft*spanStepG; spanStepB = (s32)((rightB - leftB) * tmpDiv); spanB = leftB+tDiffLeft*spanStepB; spanTxStep = (s32)((rightTx - leftTx) * tmpDiv); spanTx = leftTx + tDiffLeft*spanTxStep; spanTyStep = (s32)((rightTy - leftTy) * tmpDiv); spanTy = leftTy+tDiffLeft*spanTyStep; hSpanBegin = targetSurface + leftx+tDiffLeft; spanZTarget = zTarget + leftx+tDiffLeft; hSpanEnd = targetSurface + rightx+tDiffRight; while (hSpanBegin < hSpanEnd) { if (spanZValue > *spanZTarget) { //*spanZTarget = spanZValue; color = lockedTexture[((spanTy>>8)&textureYMask) * lockedTextureWidth + ((spanTx>>8)&textureXMask)]; s32 basis = *hSpanBegin; s32 r = (video::getRed(basis)<<3) + (video::getRed(color)<<3); if (r > 255) r = 255; s32 g = (video::getGreen(basis)<<3) + (video::getGreen(color)<<3); if (g > 255) g = 255; s32 b = (video::getBlue(basis)<<3) + (video::getBlue(color)<<3); if (b > 255) b = 255; *hSpanBegin = video::RGB16(r, g, b); } spanR += spanStepR; spanG += spanStepG; spanB += spanStepB; spanTx += spanTxStep; spanTy += spanTyStep; spanZValue += spanZStep; ++hSpanBegin; ++spanZTarget; } } leftxf += leftdeltaxf; rightxf += rightdeltaxf; ++span; targetSurface += SurfaceWidth; zTarget += SurfaceWidth; leftZValue += leftZStep; rightZValue += rightZStep; leftR += leftStepR; leftG += leftStepG; leftB += leftStepB; rightR += rightStepR; rightG += rightStepG; rightB += rightStepB; leftTx += leftTxStep; leftTy += leftTyStep; rightTx += rightTxStep; rightTy += rightTyStep; } if (triangleHalf>0) // break, we've gout only two halves break; // setup variables for second half of the triangle. if (longest < 0.0f) { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; rightxf = (f32)v2->Pos.X; rightZValue = v2->ZValue; rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); rightR = video::getRed(v2->Color)<<8; rightG = video::getGreen(v2->Color)<<8; rightB = video::getBlue(v2->Color)<<8; rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - rightB) * tmpDiv); rightTx = v2->TCoords.X; rightTy = v2->TCoords.Y; rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv); } else { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; leftxf = (f32)v2->Pos.X; leftZValue = v2->ZValue; leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); leftR = video::getRed(v2->Color)<<8; leftG = video::getGreen(v2->Color)<<8; leftB = video::getBlue(v2->Color)<<8; leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - leftB) * tmpDiv); leftTx = v2->TCoords.X; leftTy = v2->TCoords.Y; leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv); } spanEnd = v3->Pos.Y; } } RenderTarget->unlock(); ZBuffer->unlock(); Texture->unlock(); } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { ITriangleRenderer* createTriangleRendererTextureGouraudAdd(IZBuffer* zbuffer) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CTRTextureGouraudAdd(zbuffer); #else return 0; #endif // _IRR_COMPILE_WITH_SOFTWARE_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureGouraud2.cpp0000644000000000000000000003350712574354552021273 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W #define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureGouraud2 : public IBurningShader { public: //! constructor CTRTextureGouraud2(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; }; //! constructor CTRTextureGouraud2::CTRTextureGouraud2(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureGouraud2"); #endif } /*! */ void CTRTextureGouraud2::scanline_bilinear () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef INVERSE_W f32 inversew; #endif tFixPoint tx0; tFixPoint ty0; tFixPoint r0, g0, b0; #ifdef IPOL_C0 tFixPoint r1, g1, b1; #endif #ifdef BURNINGVIDEO_RENDERER_FAST u32 dIndex = ( line.y & 3 ) << 2; #endif for ( s32 i = 0; i <= dx; ++i ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); tx0 = tofix ( line.t[0][0].x, inversew); ty0 = tofix ( line.t[0][0].y, inversew); #ifdef IPOL_C0 r1 = tofix ( line.c[0][0].y ,inversew ); g1 = tofix ( line.c[0][0].z ,inversew ); b1 = tofix ( line.c[0][0].w ,inversew ); #endif #else tx0 = tofix ( line.t[0][0].x ); ty0 = tofix ( line.t[0][0].y ); #ifdef IPOL_C0 getTexel_plain2 ( r1, g1, b1, line.c[0][0] ); #endif #endif #ifdef IPOL_C0 getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); dst[i] = fix_to_color ( imulFix ( r0, r1 ), imulFix ( g0, g1 ), imulFix ( b0, b1 ) ); #else #ifdef BURNINGVIDEO_RENDERER_FAST const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; dst[i] = getTexel_plain ( &IT[0], d + tx0, d + ty0 ); #else getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); dst[i] = fix_to_color ( r0, g0, b0 ); #endif #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear ( ); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureGouraud2(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureGouraud2(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureGouraud.h0000644000000000000000000000360512574354552020652 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_TRIANGLE_RENDERER_TEXTURE_GOURAUD_H_INCLUDED__ #define __C_TRIANGLE_RENDERER_TEXTURE_GOURAUD_H_INCLUDED__ #include "IrrCompileConfig.h" #ifndef _IRR_COMPILE_WITH_SOFTWARE_ // forward declarations for create methods namespace irr { namespace video { class ITriangleRenderer; class IZBuffer; } // end namespace video } // end namespace irr #else #include "ITriangleRenderer.h" #include "IImage.h" namespace irr { namespace video { //! CTRTextureGouraud class class CTRTextureGouraud : public ITriangleRenderer { public: //! constructor CTRTextureGouraud(IZBuffer* zbuffer); //! destructor virtual ~CTRTextureGouraud(); //! sets a render target virtual void setRenderTarget(video::IImage* surface, const core::rect& viewPort); //! draws an indexed triangle list virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount); //! en or disables the backface culling virtual void setBackfaceCulling(bool enabled = true); //! sets the Texture virtual void setTexture(video::IImage* texture); protected: //! vertauscht zwei vertizen inline void swapVertices(const S2DVertex** v1, const S2DVertex** v2) { const S2DVertex* b = *v1; *v1 = *v2; *v2 = b; } video::IImage* RenderTarget; core::rect ViewPortRect; IZBuffer* ZBuffer; s32 SurfaceWidth; s32 SurfaceHeight; bool BackFaceCullingEnabled; TZBufferType* lockedZBuffer; u16* lockedSurface; u16* lockedTexture; s32 lockedTextureWidth; s32 textureXMask, textureYMask; video::IImage* Texture; }; } // end namespace video } // end namespace irr #endif #endif irrlicht-1.8.3/source/Irrlicht/CTRTextureGouraud.cpp0000644000000000000000000003317312574354552021210 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CTRTextureGouraud.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! constructor CTRTextureGouraud::CTRTextureGouraud(IZBuffer* zbuffer) : RenderTarget(0), ZBuffer(zbuffer), SurfaceWidth(0), SurfaceHeight(0), BackFaceCullingEnabled(true), lockedZBuffer(0), lockedSurface(0), lockedTexture(0), lockedTextureWidth(0), textureXMask(0), textureYMask(0), Texture(0) { #ifdef _DEBUG setDebugName("CTRTextureGouraud"); #endif if (ZBuffer) zbuffer->grab(); } //! destructor CTRTextureGouraud::~CTRTextureGouraud() { if (RenderTarget) RenderTarget->drop(); if (ZBuffer) ZBuffer->drop(); if (Texture) Texture->drop(); } //! sets the Texture void CTRTextureGouraud::setTexture(video::IImage* texture) { if (Texture) Texture->drop(); Texture = texture; if (Texture) { Texture->grab(); lockedTextureWidth = Texture->getDimension().Width; textureXMask = lockedTextureWidth-1; textureYMask = Texture->getDimension().Height-1; } } //! en or disables the backface culling void CTRTextureGouraud::setBackfaceCulling(bool enabled) { BackFaceCullingEnabled = enabled; } //! sets a render target void CTRTextureGouraud::setRenderTarget(video::IImage* surface, const core::rect& viewPort) { if (RenderTarget) RenderTarget->drop(); RenderTarget = surface; if (RenderTarget) { SurfaceWidth = RenderTarget->getDimension().Width; SurfaceHeight = RenderTarget->getDimension().Height; RenderTarget->grab(); ViewPortRect = viewPort; } } //! draws an indexed triangle list void CTRTextureGouraud::drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) { const S2DVertex *v1, *v2, *v3; f32 tmpDiv; // temporary division factor f32 longest; // saves the longest span s32 height; // saves height of triangle u16* targetSurface; // target pointer where to plot pixels s32 spanEnd; // saves end of spans f32 leftdeltaxf; // amount of pixels to increase on left side of triangle f32 rightdeltaxf; // amount of pixels to increase on right side of triangle s32 leftx, rightx; // position where we are f32 leftxf, rightxf; // same as above, but as f32 values s32 span; // current span u16 *hSpanBegin, *hSpanEnd; // pointer used when plotting pixels s32 leftR, leftG, leftB, rightR, rightG, rightB; // color values s32 leftStepR, leftStepG, leftStepB, rightStepR, rightStepG, rightStepB; // color steps s32 spanR, spanG, spanB, spanStepR, spanStepG, spanStepB; // color interpolating values while drawing a span. s32 leftTx, rightTx, leftTy, rightTy; // texture interpolating values s32 leftTxStep, rightTxStep, leftTyStep, rightTyStep; // texture interpolating values s32 spanTx, spanTy, spanTxStep, spanTyStep; // values of Texturecoords when drawing a span core::rect TriangleRect; s32 leftZValue, rightZValue; s32 leftZStep, rightZStep; s32 spanZValue, spanZStep; // ZValues when drawing a span TZBufferType* zTarget, *spanZTarget; // target of ZBuffer; lockedSurface = (u16*)RenderTarget->lock(); lockedZBuffer = ZBuffer->lock(); lockedTexture = (u16*)Texture->lock(); for (s32 i=0; iPos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) - ((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X)); if (z < 0) continue; } //near plane clipping if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0) continue; // sort for width for inscreen clipping if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2); if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3); if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3); if ((v1->Pos.X - v3->Pos.X) == 0) continue; TriangleRect.UpperLeftCorner.X = v1->Pos.X; TriangleRect.LowerRightCorner.X = v3->Pos.X; // sort for height for faster drawing. if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2); if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3); if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3); TriangleRect.UpperLeftCorner.Y = v1->Pos.Y; TriangleRect.LowerRightCorner.Y = v3->Pos.Y; if (!TriangleRect.isRectCollided(ViewPortRect)) continue; // calculate height of triangle height = v3->Pos.Y - v1->Pos.Y; if (!height) continue; // calculate longest span longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X); spanEnd = v2->Pos.Y; span = v1->Pos.Y; leftxf = (f32)v1->Pos.X; rightxf = (f32)v1->Pos.X; leftZValue = v1->ZValue; rightZValue = v1->ZValue; leftR = rightR = video::getRed(v1->Color)<<8; leftG = rightG = video::getGreen(v1->Color)<<8; leftB = rightB = video::getBlue(v1->Color)<<8; leftTx = rightTx = v1->TCoords.X; leftTy = rightTy = v1->TCoords.Y; targetSurface = lockedSurface + span * SurfaceWidth; zTarget = lockedZBuffer + span * SurfaceWidth; if (longest < 0.0f) { tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); rightStepR = (s32)(((s32)(video::getRed(v2->Color)<<8) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v2->Color)<<8) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v2->Color)<<8) - rightB) * tmpDiv); rightTxStep = (s32)((v2->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v2->TCoords.Y - rightTy) * tmpDiv); tmpDiv = 1.0f / (f32)height; leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - leftB) * tmpDiv); leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv); } else { tmpDiv = 1.0f / (f32)height; rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - rightB) * tmpDiv); rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv); tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); leftStepR = (s32)(((s32)(video::getRed(v2->Color)<<8) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v2->Color)<<8) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v2->Color)<<8) - leftB) * tmpDiv); leftTxStep = (s32)((v2->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v2->TCoords.Y - leftTy) * tmpDiv); } // do it twice, once for the first half of the triangle, // end then for the second half. for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf) { if (spanEnd > ViewPortRect.LowerRightCorner.Y) spanEnd = ViewPortRect.LowerRightCorner.Y; // if the span <0, than we can skip these spans, // and proceed to the next spans which are really on the screen. if (span < ViewPortRect.UpperLeftCorner.Y) { // we'll use leftx as temp variable if (spanEnd < ViewPortRect.UpperLeftCorner.Y) { leftx = spanEnd - span; span = spanEnd; } else { leftx = ViewPortRect.UpperLeftCorner.Y - span; span = ViewPortRect.UpperLeftCorner.Y; } leftxf += leftdeltaxf*leftx; rightxf += rightdeltaxf*leftx; targetSurface += SurfaceWidth*leftx; zTarget += SurfaceWidth*leftx; leftZValue += leftZStep*leftx; rightZValue += rightZStep*leftx; leftR += leftStepR*leftx; leftG += leftStepG*leftx; leftB += leftStepB*leftx; rightR += rightStepR*leftx; rightG += rightStepG*leftx; rightB += rightStepB*leftx; leftTx += leftTxStep*leftx; leftTy += leftTyStep*leftx; rightTx += rightTxStep*leftx; rightTy += rightTyStep*leftx; } // the main loop. Go through every span and draw it. while (span < spanEnd) { leftx = (s32)(leftxf); rightx = (s32)(rightxf + 0.5f); // perform some clipping // thanks to a correction by hybrid // calculations delayed to correctly propagate to textures etc. s32 tDiffLeft=0, tDiffRight=0; if (leftxViewPortRect.LowerRightCorner.X) tDiffLeft=ViewPortRect.LowerRightCorner.X-leftx; if (rightxViewPortRect.LowerRightCorner.X) tDiffRight=ViewPortRect.LowerRightCorner.X-rightx; // draw the span if (rightx + tDiffRight - leftx - tDiffLeft) { tmpDiv = 1.0f / (f32)(rightx - leftx); spanZStep = (s32)((rightZValue - leftZValue) * tmpDiv); spanZValue = leftZValue+tDiffLeft*spanZStep; spanStepR = (s32)((rightR - leftR) * tmpDiv); spanR = leftR+tDiffLeft*spanStepR; spanStepG = (s32)((rightG - leftG) * tmpDiv); spanG = leftG+tDiffLeft*spanStepG; spanStepB = (s32)((rightB - leftB) * tmpDiv); spanB = leftB+tDiffLeft*spanStepB; spanTxStep = (s32)((rightTx - leftTx) * tmpDiv); spanTx = leftTx + tDiffLeft*spanTxStep; spanTyStep = (s32)((rightTy - leftTy) * tmpDiv); spanTy = leftTy+tDiffLeft*spanTyStep; hSpanBegin = targetSurface + leftx+tDiffLeft; spanZTarget = zTarget + leftx+tDiffLeft; hSpanEnd = targetSurface + rightx+tDiffRight; while (hSpanBegin < hSpanEnd) { if (spanZValue > *spanZTarget) { *spanZTarget = spanZValue; u16 color = lockedTexture[((spanTy>>8)&textureYMask) * lockedTextureWidth + ((spanTx>>8)&textureXMask)]; *hSpanBegin = video::RGB16(video::getRed(color) * (spanR>>8) >>2, video::getGreen(color) * (spanG>>8) >>2, video::getBlue(color) * (spanB>>8) >>2); } spanR += spanStepR; spanG += spanStepG; spanB += spanStepB; spanTx += spanTxStep; spanTy += spanTyStep; spanZValue += spanZStep; ++hSpanBegin; ++spanZTarget; } } leftxf += leftdeltaxf; rightxf += rightdeltaxf; ++span; targetSurface += SurfaceWidth; zTarget += SurfaceWidth; leftZValue += leftZStep; rightZValue += rightZStep; leftR += leftStepR; leftG += leftStepG; leftB += leftStepB; rightR += rightStepR; rightG += rightStepG; rightB += rightStepB; leftTx += leftTxStep; leftTy += leftTyStep; rightTx += rightTxStep; rightTy += rightTyStep; } if (triangleHalf>0) // break, we've gout only two halves break; // setup variables for second half of the triangle. if (longest < 0.0f) { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; rightxf = (f32)v2->Pos.X; rightZValue = v2->ZValue; rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); rightR = video::getRed(v2->Color)<<8; rightG = video::getGreen(v2->Color)<<8; rightB = video::getBlue(v2->Color)<<8; rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - rightB) * tmpDiv); rightTx = v2->TCoords.X; rightTy = v2->TCoords.Y; rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv); } else { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; leftxf = (f32)v2->Pos.X; leftZValue = v2->ZValue; leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); leftR = video::getRed(v2->Color)<<8; leftG = video::getGreen(v2->Color)<<8; leftB = video::getBlue(v2->Color)<<8; leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - leftB) * tmpDiv); leftTx = v2->TCoords.X; leftTy = v2->TCoords.Y; leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv); } spanEnd = v3->Pos.Y; } } RenderTarget->unlock(); ZBuffer->unlock(); Texture->unlock(); } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! creates a flat triangle renderer ITriangleRenderer* createTriangleRendererTextureGouraud(IZBuffer* zbuffer) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CTRTextureGouraud(zbuffer); #else return 0; #endif // _IRR_COMPILE_WITH_SOFTWARE_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureFlatWire.cpp0000644000000000000000000002101612574354552021310 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CTRTextureGouraud.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { class CTRTextureFlatWire : public CTRTextureGouraud { public: CTRTextureFlatWire(IZBuffer* zbuffer) : CTRTextureGouraud(zbuffer) { #ifdef _DEBUG setDebugName("CTRTextureFlatWire"); #endif } //! draws an indexed triangle list virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) { const S2DVertex *v1, *v2, *v3; f32 tmpDiv; // temporary division factor f32 longest; // saves the longest span s32 height; // saves height of triangle u16* targetSurface; // target pointer where to plot pixels s32 spanEnd; // saves end of spans f32 leftdeltaxf; // amount of pixels to increase on left side of triangle f32 rightdeltaxf; // amount of pixels to increase on right side of triangle s32 leftx, rightx; // position where we are f32 leftxf, rightxf; // same as above, but as f32 values s32 span; // current span s32 leftTx, rightTx, leftTy, rightTy; // texture interpolating values s32 leftTxStep, rightTxStep, leftTyStep, rightTyStep; // texture interpolating values core::rect TriangleRect; s32 leftZValue, rightZValue; s32 leftZStep, rightZStep; TZBufferType* zTarget; // target of ZBuffer; lockedSurface = (u16*)RenderTarget->lock(); lockedZBuffer = ZBuffer->lock(); lockedTexture = (u16*)Texture->lock(); for (s32 i=0; iPos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) - ((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X)); if (z < 0) continue; } //near plane clipping if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0) continue; // sort for width for inscreen clipping if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2); if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3); if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3); if ((v1->Pos.X - v3->Pos.X) == 0) continue; TriangleRect.UpperLeftCorner.X = v1->Pos.X; TriangleRect.LowerRightCorner.X = v3->Pos.X; // sort for height for faster drawing. if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2); if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3); if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3); TriangleRect.UpperLeftCorner.Y = v1->Pos.Y; TriangleRect.LowerRightCorner.Y = v3->Pos.Y; if (!TriangleRect.isRectCollided(ViewPortRect)) continue; // calculate height of triangle height = v3->Pos.Y - v1->Pos.Y; if (!height) continue; // calculate longest span longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X); spanEnd = v2->Pos.Y; span = v1->Pos.Y; leftxf = (f32)v1->Pos.X; rightxf = (f32)v1->Pos.X; leftZValue = v1->ZValue; rightZValue = v1->ZValue; leftTx = rightTx = v1->TCoords.X; leftTy = rightTy = v1->TCoords.Y; targetSurface = lockedSurface + span * SurfaceWidth; zTarget = lockedZBuffer + span * SurfaceWidth; if (longest < 0.0f) { tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); rightTxStep = (s32)((v2->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v2->TCoords.Y - rightTy) * tmpDiv); tmpDiv = 1.0f / (f32)height; leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv); } else { tmpDiv = 1.0f / (f32)height; rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv); tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); leftTxStep = (s32)((v2->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v2->TCoords.Y - leftTy) * tmpDiv); } // do it twice, once for the first half of the triangle, // end then for the second half. for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf) { if (spanEnd > ViewPortRect.LowerRightCorner.Y) spanEnd = ViewPortRect.LowerRightCorner.Y; // if the span <0, than we can skip these spans, // and proceed to the next spans which are really on the screen. if (span < ViewPortRect.UpperLeftCorner.Y) { // we'll use leftx as temp variable if (spanEnd < ViewPortRect.UpperLeftCorner.Y) { leftx = spanEnd - span; span = spanEnd; } else { leftx = ViewPortRect.UpperLeftCorner.Y - span; span = ViewPortRect.UpperLeftCorner.Y; } leftxf += leftdeltaxf*leftx; rightxf += rightdeltaxf*leftx; targetSurface += SurfaceWidth*leftx; zTarget += SurfaceWidth*leftx; leftZValue += leftZStep*leftx; rightZValue += rightZStep*leftx; leftTx += leftTxStep*leftx; leftTy += leftTyStep*leftx; rightTx += rightTxStep*leftx; rightTy += rightTyStep*leftx; } // the main loop. Go through every span and draw it. while (span < spanEnd) { leftx = (s32)(leftxf); rightx = (s32)(rightxf + 0.5f); // perform some clipping if (leftx>=ViewPortRect.UpperLeftCorner.X && leftx<=ViewPortRect.LowerRightCorner.X) { if (leftZValue > *(zTarget + leftx)) { *(zTarget + leftx) = leftZValue; *(targetSurface + leftx) = lockedTexture[((leftTy>>8)&textureYMask) * lockedTextureWidth + ((rightTx>>8)&textureXMask)]; } } if (rightx>=ViewPortRect.UpperLeftCorner.X && rightx<=ViewPortRect.LowerRightCorner.X) { if (rightZValue > *(zTarget + rightx)) { *(zTarget + rightx) = rightZValue; *(targetSurface + rightx) = lockedTexture[((rightTy>>8)&textureYMask) * lockedTextureWidth + ((rightTx>>8)&textureXMask)]; } } leftxf += leftdeltaxf; rightxf += rightdeltaxf; ++span; targetSurface += SurfaceWidth; zTarget += SurfaceWidth; leftZValue += leftZStep; rightZValue += rightZStep; leftTx += leftTxStep; leftTy += leftTyStep; rightTx += rightTxStep; rightTy += rightTyStep; } if (triangleHalf>0) // break, we've gout only two halves break; // setup variables for second half of the triangle. if (longest < 0.0f) { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; rightxf = (f32)v2->Pos.X; rightZValue = v2->ZValue; rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); rightTx = v2->TCoords.X; rightTy = v2->TCoords.Y; rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv); } else { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; leftxf = (f32)v2->Pos.X; leftZValue = v2->ZValue; leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); leftTx = v2->TCoords.X; leftTy = v2->TCoords.Y; leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv); } spanEnd = v3->Pos.Y; } } RenderTarget->unlock(); ZBuffer->unlock(); Texture->unlock(); } }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! creates a flat triangle renderer ITriangleRenderer* createTriangleRendererTextureFlatWire(IZBuffer* zbuffer) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CTRTextureFlatWire(zbuffer); #else return 0; #endif // _IRR_COMPILE_WITH_SOFTWARE_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureFlat.cpp0000644000000000000000000002262212574354552020465 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CTRTextureGouraud.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { class CTRTextureFlat : public CTRTextureGouraud { public: CTRTextureFlat(IZBuffer* zbuffer) : CTRTextureGouraud(zbuffer) { #ifdef _DEBUG setDebugName("CTRTextureFlat"); #endif } //! draws an indexed triangle list virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) { const S2DVertex *v1, *v2, *v3; f32 tmpDiv; // temporary division factor f32 longest; // saves the longest span s32 height; // saves height of triangle u16* targetSurface; // target pointer where to plot pixels s32 spanEnd; // saves end of spans f32 leftdeltaxf; // amount of pixels to increase on left side of triangle f32 rightdeltaxf; // amount of pixels to increase on right side of triangle s32 leftx, rightx; // position where we are f32 leftxf, rightxf; // same as above, but as f32 values s32 span; // current span u16 *hSpanBegin, *hSpanEnd; // pointer used when plotting pixels s32 leftTx, rightTx, leftTy, rightTy; // texture interpolating values s32 leftTxStep, rightTxStep, leftTyStep, rightTyStep; // texture interpolating values s32 spanTx, spanTy, spanTxStep, spanTyStep; // values of Texturecoords when drawing a span core::rect TriangleRect; s32 leftZValue, rightZValue; s32 leftZStep, rightZStep; s32 spanZValue, spanZStep; // ZValues when drawing a span TZBufferType* zTarget, *spanZTarget; // target of ZBuffer; lockedSurface = (u16*)RenderTarget->lock(); lockedZBuffer = ZBuffer->lock(); lockedTexture = (u16*)Texture->lock(); for (s32 i=0; iPos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) - ((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X)); if (z < 0) continue; } //near plane clipping if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0) continue; // sort for width for inscreen clipping if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2); if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3); if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3); if ((v1->Pos.X - v3->Pos.X) == 0) continue; TriangleRect.UpperLeftCorner.X = v1->Pos.X; TriangleRect.LowerRightCorner.X = v3->Pos.X; // sort for height for faster drawing. if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2); if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3); if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3); TriangleRect.UpperLeftCorner.Y = v1->Pos.Y; TriangleRect.LowerRightCorner.Y = v3->Pos.Y; if (!TriangleRect.isRectCollided(ViewPortRect)) continue; // calculate height of triangle height = v3->Pos.Y - v1->Pos.Y; if (!height) continue; // calculate longest span longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X); spanEnd = v2->Pos.Y; span = v1->Pos.Y; leftxf = (f32)v1->Pos.X; rightxf = (f32)v1->Pos.X; leftZValue = v1->ZValue; rightZValue = v1->ZValue; leftTx = rightTx = v1->TCoords.X; leftTy = rightTy = v1->TCoords.Y; targetSurface = lockedSurface + span * SurfaceWidth; zTarget = lockedZBuffer + span * SurfaceWidth; if (longest < 0.0f) { tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); rightTxStep = (s32)((v2->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v2->TCoords.Y - rightTy) * tmpDiv); tmpDiv = 1.0f / (f32)height; leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv); } else { tmpDiv = 1.0f / (f32)height; rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv); tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); leftTxStep = (s32)((v2->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v2->TCoords.Y - leftTy) * tmpDiv); } // do it twice, once for the first half of the triangle, // end then for the second half. for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf) { if (spanEnd > ViewPortRect.LowerRightCorner.Y) spanEnd = ViewPortRect.LowerRightCorner.Y; // if the span <0, than we can skip these spans, // and proceed to the next spans which are really on the screen. if (span < ViewPortRect.UpperLeftCorner.Y) { // we'll use leftx as temp variable if (spanEnd < ViewPortRect.UpperLeftCorner.Y) { leftx = spanEnd - span; span = spanEnd; } else { leftx = ViewPortRect.UpperLeftCorner.Y - span; span = ViewPortRect.UpperLeftCorner.Y; } leftxf += leftdeltaxf*leftx; rightxf += rightdeltaxf*leftx; targetSurface += SurfaceWidth*leftx; zTarget += SurfaceWidth*leftx; leftZValue += leftZStep*leftx; rightZValue += rightZStep*leftx; leftTx += leftTxStep*leftx; leftTy += leftTyStep*leftx; rightTx += rightTxStep*leftx; rightTy += rightTyStep*leftx; } // the main loop. Go through every span and draw it. while (span < spanEnd) { leftx = (s32)(leftxf); rightx = (s32)(rightxf + 0.5f); // perform some clipping // TODO: clipping is not correct when leftx is clipped. if (leftxViewPortRect.LowerRightCorner.X) leftx = ViewPortRect.LowerRightCorner.X; if (rightxViewPortRect.LowerRightCorner.X) rightx = ViewPortRect.LowerRightCorner.X; // draw the span if (rightx - leftx != 0) { tmpDiv = 1.0f / (rightx - leftx); spanZValue = leftZValue; spanZStep = (s32)((rightZValue - leftZValue) * tmpDiv); hSpanBegin = targetSurface + leftx; spanZTarget = zTarget + leftx; hSpanEnd = targetSurface + rightx; spanTx = leftTx; spanTy = leftTy; spanTxStep = (s32)((rightTx - leftTx) * tmpDiv); spanTyStep = (s32)((rightTy - leftTy) * tmpDiv); while (hSpanBegin < hSpanEnd) { if (spanZValue > *spanZTarget) { *spanZTarget = spanZValue; *hSpanBegin = lockedTexture[((spanTy>>8)&textureYMask) * lockedTextureWidth + ((spanTx>>8)&textureXMask)]; } spanTx += spanTxStep; spanTy += spanTyStep; spanZValue += spanZStep; ++hSpanBegin; ++spanZTarget; } } leftxf += leftdeltaxf; rightxf += rightdeltaxf; ++span; targetSurface += SurfaceWidth; zTarget += SurfaceWidth; leftZValue += leftZStep; rightZValue += rightZStep; leftTx += leftTxStep; leftTy += leftTyStep; rightTx += rightTxStep; rightTy += rightTyStep; } if (triangleHalf>0) // break, we've gout only two halves break; // setup variables for second half of the triangle. if (longest < 0.0f) { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; rightxf = (f32)v2->Pos.X; rightZValue = v2->ZValue; rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); rightTx = v2->TCoords.X; rightTy = v2->TCoords.Y; rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv); rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv); } else { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; leftxf = (f32)v2->Pos.X; leftZValue = v2->ZValue; leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); leftTx = v2->TCoords.X; leftTy = v2->TCoords.Y; leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv); leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv); } spanEnd = v3->Pos.Y; } } RenderTarget->unlock(); ZBuffer->unlock(); Texture->unlock(); } }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! creates a flat triangle renderer ITriangleRenderer* createTriangleRendererTextureFlat(IZBuffer* zbuffer) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CTRTextureFlat(zbuffer); #else return 0; #endif // _IRR_COMPILE_WITH_SOFTWARE_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureDetailMap2.cpp0000644000000000000000000003327012574354552021522 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W #define IPOL_C0 #define IPOL_T0 #define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureDetailMap2 : public IBurningShader { public: //! constructor CTRTextureDetailMap2(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; }; //! constructor CTRTextureDetailMap2::CTRTextureDetailMap2(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureDetailMap2"); #endif } /*! */ void CTRTextureDetailMap2::scanline_bilinear () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef INVERSE_W f32 inversew; #endif tFixPoint tx0, tx1; tFixPoint ty0, ty1; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; for ( s32 i = 0; i <= dx; ++i ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); tx0 = tofix ( line.t[0][0].x,inversew); ty0 = tofix ( line.t[0][0].y,inversew); tx1 = tofix ( line.t[1][0].x,inversew); ty1 = tofix ( line.t[1][0].y,inversew); #else tx0 = tofix ( line.t[0][0].x ); ty0 = tofix ( line.t[0][0].y ); tx1 = tofix ( line.t[1][0].x ); ty1 = tofix ( line.t[1][0].y ); #endif getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); getSample_texture ( r1, g1, b1, &IT[1], tx1,ty1 ); // bias half color r1 += -FIX_POINT_HALF_COLOR; g1 += -FIX_POINT_HALF_COLOR; b1 += -FIX_POINT_HALF_COLOR; r2 = clampfix_mincolor ( clampfix_maxcolor ( r0 + r1 ) ); g2 = clampfix_mincolor ( clampfix_maxcolor ( g0 + g1 ) ); b2 = clampfix_mincolor ( clampfix_maxcolor ( b0 + b1 ) ); dst[i] = fix_to_color ( r2, g2, b2 ); #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRTextureDetailMap2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureDetailMap2(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureDetailMap2(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRTextureBlend.cpp0000644000000000000000000013522512574354552020627 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W #define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRTextureBlend : public IBurningShader { public: //! constructor CTRTextureBlend(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); virtual void setZCompareFunc ( u32 func); virtual void setParam ( u32 index, f32 value); private: // fragment shader typedef void (CTRTextureBlend::*tFragmentShader) (); void fragment_dst_color_zero (); void fragment_dst_color_one (); void fragment_dst_color_src_alpha (); void fragment_dst_color_one_minus_dst_alpha (); void fragment_zero_one_minus_scr_color (); void fragment_src_color_src_alpha (); void fragment_one_one_minus_src_alpha (); void fragment_one_minus_dst_alpha_one(); void fragment_src_alpha_one(); tFragmentShader fragmentShader; sScanConvertData scan; sScanLineData line; u32 ZCompare; }; //! constructor CTRTextureBlend::CTRTextureBlend(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRTextureBlend"); #endif ZCompare = 1; } /*! */ void CTRTextureBlend::setZCompareFunc ( u32 func) { ZCompare = func; } /*! */ void CTRTextureBlend::setParam ( u32 index, f32 value) { u8 showname = 0; E_BLEND_FACTOR srcFact,dstFact; E_MODULATE_FUNC modulate; u32 alphaSrc; unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSrc, value ); fragmentShader = 0; if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ZERO ) { fragmentShader = &CTRTextureBlend::fragment_dst_color_zero; } else if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ONE ) { fragmentShader = &CTRTextureBlend::fragment_dst_color_one; } else if ( srcFact == EBF_DST_COLOR && dstFact == EBF_SRC_ALPHA) { fragmentShader = &CTRTextureBlend::fragment_dst_color_src_alpha; } else if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ONE_MINUS_DST_ALPHA) { fragmentShader = &CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha; } else if ( srcFact == EBF_ZERO && dstFact == EBF_ONE_MINUS_SRC_COLOR ) { fragmentShader = &CTRTextureBlend::fragment_zero_one_minus_scr_color; } else if ( srcFact == EBF_ONE && dstFact == EBF_ONE_MINUS_SRC_ALPHA) { fragmentShader = &CTRTextureBlend::fragment_one_one_minus_src_alpha; } else if ( srcFact == EBF_ONE_MINUS_DST_ALPHA && dstFact == EBF_ONE ) { fragmentShader = &CTRTextureBlend::fragment_one_minus_dst_alpha_one; } else if ( srcFact == EBF_SRC_ALPHA && dstFact == EBF_ONE ) { fragmentShader = &CTRTextureBlend::fragment_src_alpha_one; } else if ( srcFact == EBF_SRC_COLOR && dstFact == EBF_SRC_ALPHA ) { fragmentShader = &CTRTextureBlend::fragment_src_color_src_alpha; } else { showname = 1; fragmentShader = &CTRTextureBlend::fragment_dst_color_zero; } static const c8 *n[] = { "gl_zero", "gl_one", "gl_dst_color", "gl_one_minus_dst_color", "gl_src_color", "gl_one_minus_src_color", "gl_src_alpha", "gl_one_minus_src_alpha", "gl_dst_alpha", "gl_one_minus_dst_alpha", "gl_src_alpha_saturate" }; static E_BLEND_FACTOR lsrcFact = EBF_ZERO; static E_BLEND_FACTOR ldstFact = EBF_ZERO; if ( showname && ( lsrcFact != srcFact || ldstFact != dstFact ) ) { char buf[128]; snprintf ( buf, 128, "missing shader: %s %s",n[srcFact], n[dstFact] ); os::Printer::log( buf, ELL_INFORMATION ); lsrcFact = srcFact; ldstFact = dstFact; } } /*! */ void CTRTextureBlend::fragment_dst_color_src_alpha () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif f32 iw = FIX_POINT_F32_MUL; tFixPoint a0, r0, g0, b0; tFixPoint r1, g1, b1; s32 i; switch ( ZCompare ) { case 1: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( a0,r0,g0,b0, &IT[0], tofix ( line.t[0][0].x,iw), tofix ( line.t[0][0].y,iw) ); color_to_fix ( r1, g1, b1, dst[i] ); dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif } break; case 2: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] == z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( a0,r0,g0,b0, &IT[0], tofix ( line.t[0][0].x,iw), tofix ( line.t[0][0].y,iw) ); color_to_fix ( r1, g1, b1, dst[i] ); dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif }break; } // zcompare } /*! */ void CTRTextureBlend::fragment_src_color_src_alpha () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif f32 iw = FIX_POINT_F32_MUL; tFixPoint a0, r0, g0, b0; tFixPoint r1, g1, b1; s32 i; switch ( ZCompare ) { case 1: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( a0, r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,iw), tofix ( line.t[0][0].y,iw) ); color_to_fix ( r1, g1, b1, dst[i] ); // u32 check = imulFix_tex1( r0, r1 ); dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1( r0, r1 ) + imulFix_tex1( r1, a0 ) ), clampfix_maxcolor ( imulFix_tex1( g0, g1 ) + imulFix_tex1( g1, a0 ) ), clampfix_maxcolor ( imulFix_tex1( b0, b1 ) + imulFix_tex1( b1, a0 ) ) ); } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif } break; case 2: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] == z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( a0,r0,g0,b0, &IT[0], tofix ( line.t[0][0].x,iw), tofix ( line.t[0][0].y,iw) ); color_to_fix ( r1, g1, b1, dst[i] ); dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif }break; } // zcompare } /*! */ void CTRTextureBlend::fragment_one_one_minus_src_alpha() { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif f32 iw = FIX_POINT_F32_MUL; tFixPoint a0,r0, g0, b0; tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; s32 i; switch ( ZCompare ) { case 1: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); a0 = FIX_POINT_ONE - a0; color_to_fix1 ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); dst[i] = fix_to_color ( imulFix ( r0 + imulFix ( r1, a0 ), r2 ), imulFix ( g0 + imulFix ( g1, a0 ), g2 ), imulFix ( b0 + imulFix ( b1, a0 ), b2 ) ); #else dst[i] = fix_to_color ( r0 + imulFix ( r1, a0 ), g0 + imulFix ( g1, a0 ), b0 + imulFix ( b1, a0 ) ); #endif } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif } break; case 2: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] == z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); a0 = FIX_POINT_ONE - a0; color_to_fix1 ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); dst[i] = fix_to_color ( imulFix ( r0 + imulFix ( r1, a0 ), r2 ), imulFix ( g0 + imulFix ( g1, a0 ), g2 ), imulFix ( b0 + imulFix ( b1, a0 ), b2 ) ); #else dst[i] = fix_to_color ( r0 + imulFix ( r1, a0 ), g0 + imulFix ( g1, a0 ), b0 + imulFix ( b1, a0 ) ); #endif } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif }break; } // zcompare } /*! */ void CTRTextureBlend::fragment_one_minus_dst_alpha_one () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif f32 iw = FIX_POINT_F32_MUL; tFixPoint r0, g0, b0; tFixPoint a1, r1, g1, b1; tFixPoint r2, g2, b2; s32 i; switch ( ZCompare ) { case 1: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix1 ( a1, r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); a1 = FIX_POINT_ONE - a1; dst[i] = fix_to_color ( imulFix ( imulFix ( r0, a1 ) + r1, r2 ), imulFix ( imulFix ( g0, a1 ) + g1, g2 ), imulFix ( imulFix ( b0, a1 ) + b1, b2 ) ); #else dst[i] = fix_to_color ( imulFix ( r0, a1) + r0, imulFix ( g0, a1) + g0, imulFix ( b0, a1) + b0 ); #endif } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif } break; case 2: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] == z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix1 ( a1, r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); a1 = FIX_POINT_ONE - a1; dst[i] = fix_to_color ( imulFix ( imulFix ( r0, a1 ) + r1, r2 ), imulFix ( imulFix ( g0, a1 ) + g1, g2 ), imulFix ( imulFix ( b0, a1 ) + b1, b2 ) ); #else dst[i] = fix_to_color ( imulFix ( r0, a1) + r0, imulFix ( g0, a1) + g0, imulFix ( b0, a1) + b0 ); #endif } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif }break; } // zcompare } /*! */ void CTRTextureBlend::fragment_src_alpha_one () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif f32 iw = FIX_POINT_F32_MUL; tFixPoint a0, r0, g0, b0; tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; s32 i; switch ( ZCompare ) { case 1: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); if ( a0 > 0 ) { a0 >>= 8; color_to_fix ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); dst[i] = fix4_to_color ( a0, clampfix_maxcolor ( imulFix (r0,a0 ) + r1), clampfix_maxcolor ( imulFix (g0,a0 ) + g1), clampfix_maxcolor ( imulFix (b0,a0 ) + b1) ); /* a0 >>= 8; dst[i] = fix4_to_color ( a0, imulFix ( imulFix ( r0, a0 ) + r1, r2 ), imulFix ( imulFix ( g0, a0 ) + g1, g2 ), imulFix ( imulFix ( b0, a0 ) + b1, b2 ) ); */ #else dst[i] = fix4_to_color ( a0, clampfix_maxcolor ( imulFix (r0,a0 ) + r1 ), clampfix_maxcolor ( imulFix (g0,a0 ) + g1 ), clampfix_maxcolor ( imulFix (b0,a0 ) + b1 ) ); #endif #ifdef WRITE_W //z[i] = line.w[0]; #endif } } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif } break; case 2: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] == z[i] ) #endif { #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); if ( a0 > 0 ) { a0 >>= 8; color_to_fix ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); dst[i] = fix4_to_color ( a0, clampfix_maxcolor ( imulFix ( imulFix (r0,a0 ) + r1, r2 ) ), clampfix_maxcolor ( imulFix ( imulFix (g0,a0 ) + g1, g2 ) ), clampfix_maxcolor ( imulFix ( imulFix (b0,a0 ) + b1, b2 ) ) ); /* a0 >>= 8; dst[i] = fix4_to_color ( a0, imulFix ( imulFix ( r0, a0 ) + r1, r2 ), imulFix ( imulFix ( g0, a0 ) + g1, g2 ), imulFix ( imulFix ( b0, a0 ) + b1, b2 ) ); */ #else dst[i] = fix4_to_color ( a0, clampfix_maxcolor ( imulFix (r0,a0 ) + r1 ), clampfix_maxcolor ( imulFix (g0,a0 ) + g1 ), clampfix_maxcolor ( imulFix (b0,a0 ) + b1 ) ); #endif #ifdef WRITE_W z[i] = line.w[0]; #endif } } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif }break; } // zcompare } /*! */ void CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif f32 iw = FIX_POINT_F32_MUL; tFixPoint r0, g0, b0; tFixPoint a1, r1, g1, b1; tFixPoint r2, g2, b2; s32 i; switch ( ZCompare ) { case 1: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix1 ( a1, r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); a1 = FIX_POINT_ONE - a1; dst[i] = fix_to_color ( imulFix ( imulFix ( r1, r0 + a1 ), r2 ), imulFix ( imulFix ( g1, g0 + a1 ), g2 ), imulFix ( imulFix ( b1, b0 + a1 ), b2 ) ); #else dst[i] = fix_to_color ( imulFix ( r1, r0 + a1 ), imulFix ( g1, g0 + a1 ), imulFix ( b1, b0 + a1 ) ); #endif } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif } break; case 2: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] == z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix1 ( a1, r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); a1 = FIX_POINT_ONE - a1; dst[i] = fix_to_color ( imulFix ( imulFix ( r1, r0 + a1 ), r2 ), imulFix ( imulFix ( g1, g0 + a1 ), g2 ), imulFix ( imulFix ( b1, b0 + a1 ), b2 ) ); #else dst[i] = fix_to_color ( imulFix ( r1, r0 + a1 ), imulFix ( g1, g0 + a1 ), imulFix ( b1, b0 + a1 ) ); #endif } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif }break; } // zcompare } /*! */ void CTRTextureBlend::fragment_dst_color_zero () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif f32 iw = FIX_POINT_F32_MUL; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; s32 i; switch ( ZCompare ) { case 1: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix1 ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); dst[i] = fix_to_color ( imulFix ( imulFix ( r0, r1 ), r2 ), imulFix ( imulFix ( g0, g1 ), g2 ), imulFix ( imulFix ( b0, b1 ), b2 ) ); #else dst[i] = fix_to_color ( imulFix ( r0, r1 ), imulFix ( g0, g1 ), imulFix ( b0, b1 ) ); #endif } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif } break; case 2: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] == z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix1 ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); dst[i] = fix_to_color ( imulFix ( imulFix ( r0, r1 ), r2 ), imulFix ( imulFix ( g0, g1 ), g2 ), imulFix ( imulFix ( b0, b1 ), b2 ) ); #else dst[i] = fix_to_color ( imulFix ( r0, r1 ), imulFix ( g0, g1 ), imulFix ( b0, b1 ) ); #endif } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif }break; } // zcompare } /*! */ void CTRTextureBlend::fragment_dst_color_one () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif f32 iw = FIX_POINT_F32_MUL; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; s32 i; switch ( ZCompare ) { case 1: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) ); #else dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) ); #endif } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif } break; case 2: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] == z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) ); #else dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) ); #endif } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif }break; } // zcompare } /*! */ void CTRTextureBlend::fragment_zero_one_minus_scr_color () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif f32 iw = FIX_POINT_F32_MUL; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; s32 i; switch ( ZCompare ) { case 1: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix1 ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), imulFix ( FIX_POINT_ONE - g0, g1 ), imulFix ( FIX_POINT_ONE - b0, b1 ) ); #else dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), imulFix ( FIX_POINT_ONE - g0, g1 ), imulFix ( FIX_POINT_ONE - b0, b1 ) ); #endif } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif } break; case 2: for ( i = 0; i <= dx; ++i ) { #ifdef CMP_W if ( line.w[0] == z[i] ) #endif { #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef INVERSE_W iw = fix_inverse32 ( line.w[0] ); #endif getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); color_to_fix1 ( r1, g1, b1, dst[i] ); #ifdef IPOL_C0 getSample_color ( r2, g2, b2, line.c[0][0],iw ); dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), imulFix ( FIX_POINT_ONE - g0, g1 ), imulFix ( FIX_POINT_ONE - b0, b1 ) ); #else dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), imulFix ( FIX_POINT_ONE - g0, g1 ), imulFix ( FIX_POINT_ONE - b0, b1 ) ); #endif } #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif }break; } // zcompare } void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { if ( 0 == fragmentShader ) return; // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTRTextureBlend(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRTextureBlend(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRStencilShadow.cpp0000644000000000000000000004622312574354552020770 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef USE_SBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 #undef IPOL_T2 #undef IPOL_L0 // define render case #define SUBTEXEL //#define INVERSE_W #define USE_ZBUFFER #define USE_SBUFFER #define IPOL_W #define CMP_W //#define WRITE_W // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRStencilShadow : public IBurningShader { public: //! constructor CTRStencilShadow(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); virtual void setParam ( u32 index, f32 value); private: // fragment shader typedef void (CTRStencilShadow::*tFragmentShader) (); void fragment_zfail_decr (); void fragment_zfail_incr (); tFragmentShader fragmentShader; sScanConvertData scan; sScanLineData line; }; //! constructor CTRStencilShadow::CTRStencilShadow(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRStencilShadow"); #endif } /*! */ void CTRStencilShadow::setParam ( u32 index, f32 value) { u32 val = (u32) value; // glStencilOp (fail,zfail,zpass if ( index == 1 && val == 1 ) { fragmentShader = &CTRStencilShadow::fragment_zfail_incr; } else if ( index == 1 && val == 2 ) { fragmentShader = &CTRStencilShadow::fragment_zfail_decr; } } /*! */ void CTRStencilShadow::fragment_zfail_decr () { if (!Stencil) return; //tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif #ifdef USE_SBUFFER u32 *stencil; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif #ifdef IPOL_L0 sVec3 slopeL[BURNING_MATERIAL_MAX_TANGENT]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef IPOL_T2 slopeT[2] = (line.t[2][1] - line.t[2][0]) * invDeltaX; #endif #ifdef IPOL_L0 slopeL[0] = (line.l[0][1] - line.l[0][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #ifdef IPOL_T2 line.t[2][0] += slopeT[2] * subPixel; #endif #ifdef IPOL_L0 line.l[0][0] += slopeL[0] * subPixel; #endif #endif //dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef USE_SBUFFER stencil = (u32*) Stencil->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef INVERSE_W f32 inversew; #endif #ifdef IPOL_C0 tFixPoint r3, g3, b3; #endif for ( s32 i = 0; i <= dx; i++ ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] < z[i] ) #endif { // zfail stencil[i] -= 1; } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif #ifdef IPOL_T2 line.t[2][0] += slopeT[2]; #endif #ifdef IPOL_L0 line.l[0][0] += slopeL[0]; #endif } } /*! */ void CTRStencilShadow::fragment_zfail_incr() { if (!Stencil) return; //tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif #ifdef USE_SBUFFER u32 *stencil; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif #ifdef IPOL_L0 sVec3 slopeL[BURNING_MATERIAL_MAX_TANGENT]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef IPOL_T2 slopeT[2] = (line.t[2][1] - line.t[2][0]) * invDeltaX; #endif #ifdef IPOL_L0 slopeL[0] = (line.l[0][1] - line.l[0][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #ifdef IPOL_T2 line.t[2][0] += slopeT[2] * subPixel; #endif #ifdef IPOL_L0 line.l[0][0] += slopeL[0] * subPixel; #endif #endif //dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef USE_SBUFFER stencil = (u32*) Stencil->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef INVERSE_W f32 inversew; #endif #ifdef IPOL_C0 tFixPoint r3, g3, b3; #endif for ( s32 i = 0; i <= dx; i++ ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] < z[i] ) #endif { // zfail stencil[i] += 1; } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif #ifdef IPOL_T2 line.t[2][0] += slopeT[2]; #endif #ifdef IPOL_L0 line.l[0][0] += slopeL[0]; #endif } } void CTRStencilShadow::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif #ifdef IPOL_T2 scan.slopeT[2][0] = (c->Tex[2] - a->Tex[2]) * scan.invDeltaY[0]; scan.t[2][0] = a->Tex[2]; #endif #ifdef IPOL_L0 scan.slopeL[0][0] = (c->LightTangent[0] - a->LightTangent[0]) * scan.invDeltaY[0]; scan.l[0][0] = a->LightTangent[0]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle //if ( (f32) 0.0 != scan.invDeltaY[1] ) if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif #ifdef IPOL_T2 scan.slopeT[2][1] = (b->Tex[2] - a->Tex[2]) * scan.invDeltaY[1]; scan.t[2][1] = a->Tex[2]; #endif #ifdef IPOL_L0 scan.slopeL[0][1] = (b->LightTangent[0] - a->LightTangent[0]) * scan.invDeltaY[1]; scan.l[0][1] = a->LightTangent[0]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #ifdef IPOL_T2 scan.t[2][0] += scan.slopeT[2][0] * subPixel; scan.t[2][1] += scan.slopeT[2][1] * subPixel; #endif #ifdef IPOL_L0 scan.l[0][0] += scan.slopeL[0][0] * subPixel; scan.l[0][1] += scan.slopeL[0][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif #ifdef IPOL_T2 line.t[2][scan.left] = scan.t[2][0]; line.t[2][scan.right] = scan.t[2][1]; #endif #ifdef IPOL_L0 line.l[0][scan.left] = scan.l[0][0]; line.l[0][scan.right] = scan.l[0][1]; #endif // render a scanline (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif #ifdef IPOL_T2 scan.t[2][0] += scan.slopeT[2][0]; scan.t[2][1] += scan.slopeT[2][1]; #endif #ifdef IPOL_L0 scan.l[0][0] += scan.slopeL[0][0]; scan.l[0][1] += scan.slopeL[0][1]; #endif } } // rasterize lower sub-triangle //if ( (f32) 0.0 != scan.invDeltaY[2] ) if ( F32_GREATER_0 ( scan.invDeltaY[2] ) ) { // advance to middle point //if( (f32) 0.0 != scan.invDeltaY[1] ) if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif #ifdef IPOL_T2 scan.t[2][0] = a->Tex[2] + scan.slopeT[2][0] * temp[0]; #endif #ifdef IPOL_L0 scan.l[0][0] = a->LightTangent[0] + scan.slopeL[0][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif #ifdef IPOL_T2 scan.slopeT[2][1] = (c->Tex[2] - b->Tex[2]) * scan.invDeltaY[2]; scan.t[2][1] = b->Tex[2]; #endif #ifdef IPOL_L0 scan.slopeL[0][1] = (c->LightTangent[0] - b->LightTangent[0]) * scan.invDeltaY[2]; scan.l[0][1] = b->LightTangent[0]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #ifdef IPOL_T2 scan.t[2][0] += scan.slopeT[2][0] * subPixel; scan.t[2][1] += scan.slopeT[2][1] * subPixel; #endif #ifdef IPOL_L0 scan.l[0][0] += scan.slopeL[0][0] * subPixel; scan.l[0][1] += scan.slopeL[0][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif #ifdef IPOL_T2 line.t[2][scan.left] = scan.t[2][0]; line.t[2][scan.right] = scan.t[2][1]; #endif #ifdef IPOL_L0 line.l[0][scan.left] = scan.l[0][0]; line.l[0][scan.right] = scan.l[0][1]; #endif // render a scanline (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif #ifdef IPOL_T2 scan.t[2][0] += scan.slopeT[2][0]; scan.t[2][1] += scan.slopeT[2][1]; #endif #ifdef IPOL_L0 scan.l[0][0] += scan.slopeL[0][0]; scan.l[0][1] += scan.slopeL[0][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a triangle renderer IBurningShader* createTRStencilShadow(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRStencilShadow(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRNormalMap.cpp0000644000000000000000000004435612574354552020114 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 #undef IPOL_T2 #undef IPOL_L0 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W #define IPOL_C0 #define IPOL_T0 #define IPOL_T1 #define IPOL_L0 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRNormalMap : public IBurningShader { public: //! constructor CTRNormalMap(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; }; //! constructor CTRNormalMap::CTRNormalMap(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRNormalMap"); #endif } /*! */ void CTRNormalMap::scanline_bilinear () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif #ifdef IPOL_L0 sVec3 slopeL[BURNING_MATERIAL_MAX_TANGENT]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef IPOL_T2 slopeT[2] = (line.t[2][1] - line.t[2][0]) * invDeltaX; #endif #ifdef IPOL_L0 slopeL[0] = (line.l[0][1] - line.l[0][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #ifdef IPOL_T2 line.t[2][0] += slopeT[2] * subPixel; #endif #ifdef IPOL_L0 line.l[0][0] += slopeL[0] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef INVERSE_W f32 inversew; #endif tFixPoint tx0, tx1; tFixPoint ty0, ty1; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; tFixPoint lx, ly, lz; tFixPoint ndotl; sVec3 light; #ifdef IPOL_C0 tFixPoint r3, g3, b3; #endif for ( s32 i = 0; i <= dx; i++ ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); tx0 = tofix ( line.t[0][0].x,inversew); ty0 = tofix ( line.t[0][0].y,inversew); tx1 = tofix ( line.t[1][0].x,inversew); ty1 = tofix ( line.t[1][0].y,inversew); #ifdef IPOL_C0 r3 = tofix ( line.c[0][0].y ,inversew ); g3 = tofix ( line.c[0][0].z ,inversew ); b3 = tofix ( line.c[0][0].w ,inversew ); #endif #else tx0 = tofix ( line.t[0][0].x ); ty0 = tofix ( line.t[0][0].y ); tx1 = tofix ( line.t[1][0].x ); ty1 = tofix ( line.t[1][0].y ); #ifdef IPOL_C0 r3 = tofix ( line.c[0][0].y ); g3 = tofix ( line.c[0][0].z ); b3 = tofix ( line.c[0][0].w ); #endif #endif getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); // normal map getSample_texture ( r1, g1, b1, &IT[1], tx1, ty1 ); r1 = ( r1 - FIX_POINT_HALF_COLOR) >> (COLOR_MAX_LOG2-1); g1 = ( g1 - FIX_POINT_HALF_COLOR) >> (COLOR_MAX_LOG2-1); b1 = ( b1 - FIX_POINT_HALF_COLOR) >> (COLOR_MAX_LOG2-1); /* sVec3 l = line.l[0][0] * inversew; l.setLength( 2.f ); lx = tofix ( l.x - 0.5f ); ly = tofix ( l.y - 0.5f ); lz = tofix ( l.z - 0.5f ); */ lx = tofix ( line.l[0][0].x, inversew ); ly = tofix ( line.l[0][0].y, inversew ); lz = tofix ( line.l[0][0].z, inversew ); // DOT 3 Normal Map light in tangent space ndotl = saturateFix ( FIX_POINT_HALF_COLOR + (( imulFix ( r1, lx ) + imulFix ( g1, ly ) + imulFix ( b1, lz ) ) << (COLOR_MAX_LOG2-1)) ); #ifdef IPOL_C0 // N . L r2 = imulFix ( imulFix_tex1 ( r0, ndotl ), r3 ); g2 = imulFix ( imulFix_tex1 ( g0, ndotl ), g3 ); b2 = imulFix ( imulFix_tex1 ( b0, ndotl ), b3 ); /* // heightmap: (1 - neu ) + alt - 0.5, on_minus_srcalpha + add signed // emboss bump map a4 -= a1; r2 = clampfix_maxcolor ( clampfix_mincolor ( imulFix ( r0 + a4, r3 ) ) ); g2 = clampfix_maxcolor ( clampfix_mincolor ( imulFix ( g0 + a4, g3 ) ) ); b2 = clampfix_maxcolor ( clampfix_mincolor ( imulFix ( b0 + a4, b3 ) ) ); */ /* r2 = clampfix_maxcolor ( imulFix_tex1 ( r2, r1 ) ); g2 = clampfix_maxcolor ( imulFix_tex1 ( g2, g1 ) ); b2 = clampfix_maxcolor ( imulFix_tex1 ( b2, b1 ) ); */ #else r2 = clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ); g2 = clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ); b2 = clampfix_maxcolor ( imulFix_tex4 ( b0, b1 ) ); #endif dst[i] = fix_to_color ( r2, g2, b2 ); #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC[0]; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif #ifdef IPOL_T2 line.t[2][0] += slopeT[2]; #endif #ifdef IPOL_L0 line.l[0][0] += slopeL[0]; #endif } } void CTRNormalMap::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif #ifdef IPOL_T2 scan.slopeT[2][0] = (c->Tex[2] - a->Tex[2]) * scan.invDeltaY[0]; scan.t[2][0] = a->Tex[2]; #endif #ifdef IPOL_L0 scan.slopeL[0][0] = (c->LightTangent[0] - a->LightTangent[0]) * scan.invDeltaY[0]; scan.l[0][0] = a->LightTangent[0]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle //if ( (f32) 0.0 != scan.invDeltaY[1] ) if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif #ifdef IPOL_T2 scan.slopeT[2][1] = (b->Tex[2] - a->Tex[2]) * scan.invDeltaY[1]; scan.t[2][1] = a->Tex[2]; #endif #ifdef IPOL_L0 scan.slopeL[0][1] = (b->LightTangent[0] - a->LightTangent[0]) * scan.invDeltaY[1]; scan.l[0][1] = a->LightTangent[0]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #ifdef IPOL_T2 scan.t[2][0] += scan.slopeT[2][0] * subPixel; scan.t[2][1] += scan.slopeT[2][1] * subPixel; #endif #ifdef IPOL_L0 scan.l[0][0] += scan.slopeL[0][0] * subPixel; scan.l[0][1] += scan.slopeL[0][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif #ifdef IPOL_T2 line.t[2][scan.left] = scan.t[2][0]; line.t[2][scan.right] = scan.t[2][1]; #endif #ifdef IPOL_L0 line.l[0][scan.left] = scan.l[0][0]; line.l[0][scan.right] = scan.l[0][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif #ifdef IPOL_T2 scan.t[2][0] += scan.slopeT[2][0]; scan.t[2][1] += scan.slopeT[2][1]; #endif #ifdef IPOL_L0 scan.l[0][0] += scan.slopeL[0][0]; scan.l[0][1] += scan.slopeL[0][1]; #endif } } // rasterize lower sub-triangle //if ( (f32) 0.0 != scan.invDeltaY[2] ) if ( F32_GREATER_0 ( scan.invDeltaY[2] ) ) { // advance to middle point //if( (f32) 0.0 != scan.invDeltaY[1] ) if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif #ifdef IPOL_T2 scan.t[2][0] = a->Tex[2] + scan.slopeT[2][0] * temp[0]; #endif #ifdef IPOL_L0 scan.l[0][0] = a->LightTangent[0] + scan.slopeL[0][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif #ifdef IPOL_T2 scan.slopeT[2][1] = (c->Tex[2] - b->Tex[2]) * scan.invDeltaY[2]; scan.t[2][1] = b->Tex[2]; #endif #ifdef IPOL_L0 scan.slopeL[0][1] = (c->LightTangent[0] - b->LightTangent[0]) * scan.invDeltaY[2]; scan.l[0][1] = b->LightTangent[0]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #ifdef IPOL_T2 scan.t[2][0] += scan.slopeT[2][0] * subPixel; scan.t[2][1] += scan.slopeT[2][1] * subPixel; #endif #ifdef IPOL_L0 scan.l[0][0] += scan.slopeL[0][0] * subPixel; scan.l[0][1] += scan.slopeL[0][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif #ifdef IPOL_T2 line.t[2][scan.left] = scan.t[2][0]; line.t[2][scan.right] = scan.t[2][1]; #endif #ifdef IPOL_L0 line.l[0][scan.left] = scan.l[0][0]; line.l[0][scan.right] = scan.l[0][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif #ifdef IPOL_T2 scan.t[2][0] += scan.slopeT[2][0]; scan.t[2][1] += scan.slopeT[2][1]; #endif #ifdef IPOL_L0 scan.l[0][0] += scan.slopeL[0][0]; scan.l[0][1] += scan.slopeL[0][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a triangle renderer IBurningShader* createTRNormalMap(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRNormalMap(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTriangleSelector.h0000644000000000000000000000602712574354552020664 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_TRIANGLE_SELECTOR_H_INCLUDED__ #define __C_TRIANGLE_SELECTOR_H_INCLUDED__ #include "ITriangleSelector.h" #include "IMesh.h" #include "irrArray.h" #include "aabbox3d.h" namespace irr { namespace scene { class ISceneNode; class IAnimatedMeshSceneNode; //! Stupid triangle selector without optimization class CTriangleSelector : public ITriangleSelector { public: //! Constructs a selector based on a mesh CTriangleSelector(ISceneNode* node); //! Constructs a selector based on a mesh CTriangleSelector(const IMesh* mesh, ISceneNode* node); //! Constructs a selector based on an animated mesh scene node //!\param node An animated mesh scene node, which must have a valid mesh CTriangleSelector(IAnimatedMeshSceneNode* node); //! Constructs a selector based on a bounding box CTriangleSelector(const core::aabbox3d& box, ISceneNode* node); //! Gets all triangles. void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::matrix4* transform=0) const; //! Gets all triangles which lie within a specific bounding box. void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::aabbox3d& box, const core::matrix4* transform=0) const; //! Gets all triangles which have or may have contact with a 3d line. virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform=0) const; //! Returns amount of all available triangles in this selector virtual s32 getTriangleCount() const; //! Return the scene node associated with a given triangle. virtual ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const { return SceneNode; } // Get the number of TriangleSelectors that are part of this one virtual u32 getSelectorCount() const; // Get the TriangleSelector based on index based on getSelectorCount virtual ITriangleSelector* getSelector(u32 index); // Get the TriangleSelector based on index based on getSelectorCount virtual const ITriangleSelector* getSelector(u32 index) const; protected: //! Create from a mesh virtual void createFromMesh(const IMesh* mesh); //! Update when the mesh has changed virtual void updateFromMesh(const IMesh* mesh) const; //! Update the triangle selector, which will only have an effect if it //! was built from an animated mesh and that mesh's frame has changed //! since the last time it was updated. virtual void update(void) const; ISceneNode* SceneNode; mutable core::array Triangles; // (mutable for CTriangleBBSelector) mutable core::aabbox3df BoundingBox; // Allows for trivial rejection IAnimatedMeshSceneNode* AnimatedNode; mutable u32 LastMeshFrame; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CTriangleSelector.cpp0000644000000000000000000001610512574354552021215 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CTriangleSelector.h" #include "ISceneNode.h" #include "IMeshBuffer.h" #include "IAnimatedMeshSceneNode.h" namespace irr { namespace scene { //! constructor CTriangleSelector::CTriangleSelector(ISceneNode* node) : SceneNode(node), AnimatedNode(0), LastMeshFrame(0) { #ifdef _DEBUG setDebugName("CTriangleSelector"); #endif BoundingBox.reset(0.f, 0.f, 0.f); } //! constructor CTriangleSelector::CTriangleSelector(const core::aabbox3d& box, ISceneNode* node) : SceneNode(node), AnimatedNode(0), LastMeshFrame(0) { #ifdef _DEBUG setDebugName("CTriangleSelector"); #endif BoundingBox=box; // TODO } //! constructor CTriangleSelector::CTriangleSelector(const IMesh* mesh, ISceneNode* node) : SceneNode(node), AnimatedNode(0), LastMeshFrame(0) { #ifdef _DEBUG setDebugName("CTriangleSelector"); #endif createFromMesh(mesh); } CTriangleSelector::CTriangleSelector(IAnimatedMeshSceneNode* node) : SceneNode(node), AnimatedNode(node), LastMeshFrame(0) { #ifdef _DEBUG setDebugName("CTriangleSelector"); #endif if (!AnimatedNode) return; IAnimatedMesh* animatedMesh = AnimatedNode->getMesh(); if (!animatedMesh) return; LastMeshFrame = (u32)AnimatedNode->getFrameNr(); IMesh* mesh = animatedMesh->getMesh(LastMeshFrame); if (mesh) createFromMesh(mesh); } void CTriangleSelector::createFromMesh(const IMesh* mesh) { const u32 cnt = mesh->getMeshBufferCount(); u32 totalFaceCount = 0; for (u32 j=0; jgetMeshBuffer(j)->getIndexCount(); totalFaceCount /= 3; Triangles.reallocate(totalFaceCount); BoundingBox.reset(0.f, 0.f, 0.f); for (u32 i=0; igetMeshBuffer(i); const u32 idxCnt = buf->getIndexCount(); const u16* const indices = buf->getIndices(); for (u32 j=0; jgetPosition(indices[j+0]), buf->getPosition(indices[j+1]), buf->getPosition(indices[j+2]))); const core::triangle3df& tri = Triangles.getLast(); BoundingBox.addInternalPoint(tri.pointA); BoundingBox.addInternalPoint(tri.pointB); BoundingBox.addInternalPoint(tri.pointC); } } } void CTriangleSelector::updateFromMesh(const IMesh* mesh) const { if (!mesh) return; u32 meshBuffers = mesh->getMeshBufferCount(); u32 triangleCount = 0; BoundingBox.reset(0.f, 0.f, 0.f); for (u32 i = 0; i < meshBuffers; ++i) { IMeshBuffer* buf = mesh->getMeshBuffer(i); u32 idxCnt = buf->getIndexCount(); const u16* indices = buf->getIndices(); for (u32 index = 0; index < idxCnt; index += 3) { core::triangle3df& tri = Triangles[triangleCount++]; tri.pointA = buf->getPosition(indices[index + 0]); tri.pointB = buf->getPosition(indices[index + 1]); tri.pointC = buf->getPosition(indices[index + 2]); BoundingBox.addInternalPoint(tri.pointA); BoundingBox.addInternalPoint(tri.pointB); BoundingBox.addInternalPoint(tri.pointC); } } } void CTriangleSelector::update(void) const { if (!AnimatedNode) return; //< harmless no-op const u32 currentFrame = (u32)AnimatedNode->getFrameNr(); if (currentFrame == LastMeshFrame) return; //< Nothing to do LastMeshFrame = currentFrame; IAnimatedMesh * animatedMesh = AnimatedNode->getMesh(); if (animatedMesh) { IMesh * mesh = animatedMesh->getMesh(LastMeshFrame); if (mesh) updateFromMesh(mesh); } } //! Gets all triangles. void CTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::matrix4* transform) const { // Update my triangles if necessary update(); u32 cnt = Triangles.size(); if (cnt > (u32)arraySize) cnt = (u32)arraySize; core::matrix4 mat; if (transform) mat = *transform; if (SceneNode) mat *= SceneNode->getAbsoluteTransformation(); for (u32 i=0; i& box, const core::matrix4* transform) const { // Update my triangles if necessary update(); core::matrix4 mat(core::matrix4::EM4CONST_NOTHING); core::aabbox3df tBox(box); if (SceneNode) { SceneNode->getAbsoluteTransformation().getInverse(mat); mat.transformBoxEx(tBox); } if (transform) mat = *transform; else mat.makeIdentity(); if (SceneNode) mat *= SceneNode->getAbsoluteTransformation(); outTriangleCount = 0; if (!tBox.intersectsWithBox(BoundingBox)) return; s32 triangleCount = 0; const u32 cnt = Triangles.size(); for (u32 i=0; i& line, const core::matrix4* transform) const { // Update my triangles if necessary update(); core::aabbox3d box(line.start); box.addInternalPoint(line.end); // TODO: Could be optimized for line a little bit more. getTriangles(triangles, arraySize, outTriangleCount, box, transform); } //! Returns amount of all available triangles in this selector s32 CTriangleSelector::getTriangleCount() const { return Triangles.size(); } /* Get the number of TriangleSelectors that are part of this one. Only useful for MetaTriangleSelector others return 1 */ u32 CTriangleSelector::getSelectorCount() const { return 1; } /* Get the TriangleSelector based on index based on getSelectorCount. Only useful for MetaTriangleSelector others return 'this' or 0 */ ITriangleSelector* CTriangleSelector::getSelector(u32 index) { if (index) return 0; else return this; } /* Get the TriangleSelector based on index based on getSelectorCount. Only useful for MetaTriangleSelector others return 'this' or 0 */ const ITriangleSelector* CTriangleSelector::getSelector(u32 index) const { if (index) return 0; else return this; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTriangleBBSelector.h0000644000000000000000000000236612574354552021072 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_TRIANGLE_BB_SELECTOR_H_INCLUDED__ #define __C_TRIANGLE_BB_SELECTOR_H_INCLUDED__ #include "CTriangleSelector.h" namespace irr { namespace scene { //! Stupid triangle selector without optimization class CTriangleBBSelector : public CTriangleSelector { public: //! Constructs a selector based on a mesh CTriangleBBSelector(ISceneNode* node); //! Gets all triangles. virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::matrix4* transform=0) const; //! Gets all triangles which lie within a specific bounding box. void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::aabbox3d& box, const core::matrix4* transform=0) const; //! Gets all triangles which have or may have contact with a 3d line. virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform=0) const; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CTriangleBBSelector.cpp0000644000000000000000000000424312574354552021421 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CTriangleBBSelector.h" #include "ISceneNode.h" namespace irr { namespace scene { //! constructor CTriangleBBSelector::CTriangleBBSelector(ISceneNode* node) : CTriangleSelector(node) { #ifdef _DEBUG setDebugName("CTriangleBBSelector"); #endif Triangles.set_used(12); // a box has 12 triangles. } //! Gets all triangles. void CTriangleBBSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::matrix4* transform) const { if (!SceneNode) return; // construct triangles const core::aabbox3d& box = SceneNode->getBoundingBox(); core::vector3df edges[8]; box.getEdges(edges); Triangles[0].set( edges[3], edges[0], edges[2]); Triangles[1].set( edges[3], edges[1], edges[0]); Triangles[2].set( edges[3], edges[2], edges[7]); Triangles[3].set( edges[7], edges[2], edges[6]); Triangles[4].set( edges[7], edges[6], edges[4]); Triangles[5].set( edges[5], edges[7], edges[4]); Triangles[6].set( edges[5], edges[4], edges[0]); Triangles[7].set( edges[5], edges[0], edges[1]); Triangles[8].set( edges[1], edges[3], edges[7]); Triangles[9].set( edges[1], edges[7], edges[5]); Triangles[10].set(edges[0], edges[6], edges[2]); Triangles[11].set(edges[0], edges[4], edges[6]); // call parent CTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, transform); } void CTriangleBBSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::aabbox3d& box, const core::matrix4* transform) const { return getTriangles(triangles, arraySize, outTriangleCount, transform); } void CTriangleBBSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform) const { return getTriangles(triangles, arraySize, outTriangleCount, transform); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRGouraudWire.cpp0000644000000000000000000002261112574354552020451 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CTRTextureGouraud.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { class CTRGouraudWire : public CTRTextureGouraud { public: CTRGouraudWire(IZBuffer* zbuffer) : CTRTextureGouraud(zbuffer) { #ifdef _DEBUG setDebugName("CTRGouraudWire"); #endif } //! draws an indexed triangle list virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) { const S2DVertex *v1, *v2, *v3; f32 tmpDiv; // temporary division factor f32 longest; // saves the longest span s32 height; // saves height of triangle u16* targetSurface; // target pointer where to plot pixels s32 spanEnd; // saves end of spans f32 leftdeltaxf; // amount of pixels to increase on left side of triangle f32 rightdeltaxf; // amount of pixels to increase on right side of triangle s32 leftx, rightx; // position where we are f32 leftxf, rightxf; // same as above, but as f32 values s32 span; // current span s32 leftR, leftG, leftB, rightR, rightG, rightB; // color values s32 leftStepR, leftStepG, leftStepB, rightStepR, rightStepG, rightStepB; // color steps core::rect TriangleRect; s32 leftZValue, rightZValue; s32 leftZStep, rightZStep; TZBufferType* zTarget; // target of ZBuffer; lockedSurface = (u16*)RenderTarget->lock(); lockedZBuffer = ZBuffer->lock(); for (s32 i=0; iPos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) - ((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X)); if (z < 0) continue; } //near plane clipping if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0) continue; // sort for width for inscreen clipping if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2); if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3); if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3); if ((v1->Pos.X - v3->Pos.X) == 0) continue; TriangleRect.UpperLeftCorner.X = v1->Pos.X; TriangleRect.LowerRightCorner.X = v3->Pos.X; // sort for height for faster drawing. if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2); if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3); if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3); TriangleRect.UpperLeftCorner.Y = v1->Pos.Y; TriangleRect.LowerRightCorner.Y = v3->Pos.Y; if (!TriangleRect.isRectCollided(ViewPortRect)) continue; // calculate height of triangle height = v3->Pos.Y - v1->Pos.Y; if (!height) continue; // calculate longest span longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X); spanEnd = v2->Pos.Y; span = v1->Pos.Y; leftxf = (f32)v1->Pos.X; rightxf = (f32)v1->Pos.X; leftZValue = v1->ZValue; rightZValue = v1->ZValue; leftR = rightR = video::getRed(v1->Color)<<11; leftG = rightG = video::getGreen(v1->Color)<<11; leftB = rightB = video::getBlue(v1->Color)<<11; targetSurface = lockedSurface + span * SurfaceWidth; zTarget = lockedZBuffer + span * SurfaceWidth; if (longest < 0.0f) { tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); rightStepR = (s32)(((s32)(video::getRed(v2->Color)<<11) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v2->Color)<<11) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v2->Color)<<11) - rightB) * tmpDiv); tmpDiv = 1.0f / (f32)height; leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<11) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<11) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<11) - leftB) * tmpDiv); } else { tmpDiv = 1.0f / (f32)height; rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<11) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<11) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<11) - rightB) * tmpDiv); tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); leftStepR = (s32)(((s32)(video::getRed(v2->Color)<<11) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v2->Color)<<11) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v2->Color)<<11) - leftB) * tmpDiv); } // do it twice, once for the first half of the triangle, // end then for the second half. for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf) { if (spanEnd > ViewPortRect.LowerRightCorner.Y) spanEnd = ViewPortRect.LowerRightCorner.Y; // if the span <0, than we can skip these spans, // and proceed to the next spans which are really on the screen. if (span < ViewPortRect.UpperLeftCorner.Y) { // we'll use leftx as temp variable if (spanEnd < ViewPortRect.UpperLeftCorner.Y) { leftx = spanEnd - span; span = spanEnd; } else { leftx = ViewPortRect.UpperLeftCorner.Y - span; span = ViewPortRect.UpperLeftCorner.Y; } leftxf += leftdeltaxf*leftx; rightxf += rightdeltaxf*leftx; targetSurface += SurfaceWidth*leftx; zTarget += SurfaceWidth*leftx; leftZValue += leftZStep*leftx; rightZValue += rightZStep*leftx; leftR += leftStepR*leftx; leftG += leftStepG*leftx; leftB += leftStepB*leftx; rightR += rightStepR*leftx; rightG += rightStepG*leftx; rightB += rightStepB*leftx; } // the main loop. Go through every span and draw it. while (span < spanEnd) { leftx = (s32)(leftxf); rightx = (s32)(rightxf + 0.5f); // perform some clipping if (leftx>=ViewPortRect.UpperLeftCorner.X && leftx<=ViewPortRect.LowerRightCorner.X) { if (leftZValue > *(zTarget + leftx)) { *(zTarget + leftx) = leftZValue; *(targetSurface + leftx) = video::RGB16(leftR>>8, leftG>>8, leftB>>8); } } if (rightx>=ViewPortRect.UpperLeftCorner.X && rightx<=ViewPortRect.LowerRightCorner.X) { if (rightZValue > *(zTarget + rightx)) { *(zTarget + rightx) = rightZValue; *(targetSurface + rightx) = video::RGB16(rightR, rightG, rightB); } } leftxf += leftdeltaxf; rightxf += rightdeltaxf; ++span; targetSurface += SurfaceWidth; zTarget += SurfaceWidth; leftZValue += leftZStep; rightZValue += rightZStep; leftR += leftStepR; leftG += leftStepG; leftB += leftStepB; rightR += rightStepR; rightG += rightStepG; rightB += rightStepB; } if (triangleHalf>0) // break, we've gout only two halves break; // setup variables for second half of the triangle. if (longest < 0.0f) { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; rightxf = (f32)v2->Pos.X; rightZValue = v2->ZValue; rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); rightR = video::getRed(v2->Color)<<11; rightG = video::getGreen(v2->Color)<<11; rightB = video::getBlue(v2->Color)<<11; rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<11) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<11) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<11) - rightB) * tmpDiv); } else { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; leftxf = (f32)v2->Pos.X; leftZValue = v2->ZValue; leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); leftR = video::getRed(v2->Color)<<11; leftG = video::getGreen(v2->Color)<<11; leftB = video::getBlue(v2->Color)<<11; leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<11) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<11) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<11) - leftB) * tmpDiv); } spanEnd = v3->Pos.Y; } } RenderTarget->unlock(); ZBuffer->unlock(); } }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! creates a flat triangle renderer ITriangleRenderer* createTriangleRendererGouraudWire(IZBuffer* zbuffer) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CTRGouraudWire(zbuffer); #else return 0; #endif // _IRR_COMPILE_WITH_SOFTWARE_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp0000644000000000000000000003244212574354552021304 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL //#define INVERSE_W //#define USE_ZBUFFER //#define IPOL_W //#define CMP_W //#define WRITE_W #define IPOL_C0 //#define IPOL_T0 //#define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif //#define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRGouraudAlphaNoZ2 : public IBurningShader { public: //! constructor CTRGouraudAlphaNoZ2(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; }; //! constructor CTRGouraudAlphaNoZ2::CTRGouraudAlphaNoZ2(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRGouraudAlphaNoZ2"); #endif } /*! */ void CTRGouraudAlphaNoZ2::scanline_bilinear () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef IPOL_C0 #ifdef INVERSE_W f32 inversew; #endif tFixPoint a0; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; #endif for ( s32 i = 0; i <= dx; ++i ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif #ifdef IPOL_C0 #ifdef IPOL_W inversew = core::reciprocal ( line.w[0] ); getSample_color ( a0, r0, g0, b0, line.c[0][0] * inversew ); #else getSample_color ( a0, r0, g0, b0, line.c[0][0] ); #endif color_to_fix ( r1, g1, b1, dst[i] ); r2 = r1 + imulFix ( a0, r0 - r1 ); g2 = g1 + imulFix ( a0, g0 - g1 ); b2 = b1 + imulFix ( a0, b0 - b1 ); dst[i] = fix_to_color ( r2, g2, b2 ); #else dst[i] = COLOR_BRIGHT_WHITE; #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRGouraudAlphaNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTRGouraudAlphaNoZ2(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRGouraudAlphaNoZ2(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRGouraudAlpha2.cpp0000644000000000000000000003243512574354552020657 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W #define IPOL_C0 //#define IPOL_T0 //#define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRGouraudAlpha2 : public IBurningShader { public: //! constructor CTRGouraudAlpha2(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; }; //! constructor CTRGouraudAlpha2::CTRGouraudAlpha2(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRGouraudAlpha2"); #endif } /*! */ void CTRGouraudAlpha2::scanline_bilinear () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC; #endif #ifdef IPOL_T0 sVec2 slopeT[0]; #endif #ifdef IPOL_T1 sVec2 slopeT[1]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef IPOL_C0 #ifdef INVERSE_W f32 inversew; #endif tFixPoint a0; tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; tFixPoint r2, g2, b2; #endif for ( s32 i = 0; i <= dx; ++i ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef IPOL_C0 #ifdef INVERSE_W inversew = core::reciprocal ( line.w[0] ); getSample_color ( a0, r0, g0, b0, line.c[0][0] * inversew ); #else getSample_color ( a0, r0, g0, b0, line.c[0][0] ); #endif color_to_fix ( r1, g1, b1, dst[i] ); r2 = r1 + imulFix ( a0, r0 - r1 ); g2 = g1 + imulFix ( a0, g0 - g1 ); b2 = b1 + imulFix ( a0, b0 - b1 ); dst[i] = fix_to_color ( r2, g2, b2 ); #else dst[i] = COLOR_BRIGHT_WHITE; #endif #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear ( ); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear ( ); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTriangleRendererGouraudAlpha2(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRGouraudAlpha2(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRGouraud2.cpp0000644000000000000000000003167112574354552017712 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ // compile flag for this file #undef USE_ZBUFFER #undef IPOL_Z #undef CMP_Z #undef WRITE_Z #undef IPOL_W #undef CMP_W #undef WRITE_W #undef SUBTEXEL #undef INVERSE_W #undef IPOL_C0 #undef IPOL_T0 #undef IPOL_T1 // define render case #define SUBTEXEL #define INVERSE_W #define USE_ZBUFFER #define IPOL_W #define CMP_W #define WRITE_W #define IPOL_C0 //#define IPOL_T0 //#define IPOL_T1 // apply global override #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef INVERSE_W #endif #ifndef SOFTWARE_DRIVER_2_SUBTEXEL #undef SUBTEXEL #endif #ifndef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #undef IPOL_C0 #endif #if !defined ( SOFTWARE_DRIVER_2_USE_WBUFFER ) && defined ( USE_ZBUFFER ) #ifndef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #undef IPOL_W #endif #define IPOL_Z #ifdef CMP_W #undef CMP_W #define CMP_Z #endif #ifdef WRITE_W #undef WRITE_W #define WRITE_Z #endif #endif namespace irr { namespace video { class CTRGouraud2 : public IBurningShader { public: //! constructor CTRGouraud2(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); private: void scanline_bilinear (); sScanConvertData scan; sScanLineData line; }; //! constructor CTRGouraud2::CTRGouraud2(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CTRGouraud2"); #endif } /*! */ void CTRGouraud2::scanline_bilinear () { tVideoSample *dst; #ifdef USE_ZBUFFER fp24 *z; #endif s32 xStart; s32 xEnd; s32 dx; #ifdef SUBTEXEL f32 subPixel; #endif #ifdef IPOL_Z f32 slopeZ; #endif #ifdef IPOL_W fp24 slopeW; #endif #ifdef IPOL_C0 sVec4 slopeC; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; #endif // apply top-left fill-convention, left xStart = core::ceil32( line.x[0] ); xEnd = core::ceil32( line.x[1] ) - 1; dx = xEnd - xStart; if ( dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); #ifdef IPOL_Z slopeZ = (line.z[1] - line.z[0]) * invDeltaX; #endif #ifdef IPOL_W slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 slopeC = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; #endif #ifdef IPOL_T1 slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; #endif #ifdef SUBTEXEL subPixel = ( (f32) xStart ) - line.x[0]; #ifdef IPOL_Z line.z[0] += slopeZ * subPixel; #endif #ifdef IPOL_W line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1] * subPixel; #endif #endif dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif #ifdef IPOL_C0 tFixPoint r0, g0, b0; #ifdef INVERSE_W f32 inversew; #endif #endif for ( s32 i = 0; i <= dx; ++i ) { #ifdef CMP_Z if ( line.z[0] < z[i] ) #endif #ifdef CMP_W if ( line.w[0] >= z[i] ) #endif { #ifdef IPOL_C0 #ifdef INVERSE_W inversew = core::reciprocal ( line.w[0] ); getSample_color ( r0, g0, b0, line.c[0][0] * inversew ); #else getSample_color ( r0, g0, b0, line.c[0][0] ); #endif dst[i] = fix_to_color ( r0, g0, b0 ); #else dst[i] = COLOR_BRIGHT_WHITE; #endif #ifdef WRITE_Z z[i] = line.z[0]; #endif #ifdef WRITE_W z[i] = line.w[0]; #endif } #ifdef IPOL_Z line.z[0] += slopeZ; #endif #ifdef IPOL_W line.w[0] += slopeW; #endif #ifdef IPOL_C0 line.c[0][0] += slopeC; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; #endif #ifdef IPOL_T1 line.t[1][0] += slopeT[1]; #endif } } void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { // sort on height, y if ( a->Pos.y > b->Pos.y ) swapVertexPointer(&a, &b); if ( a->Pos.y > c->Pos.y ) swapVertexPointer(&a, &c); if ( b->Pos.y > c->Pos.y ) swapVertexPointer(&b, &c); const f32 ca = c->Pos.y - a->Pos.y; const f32 ba = b->Pos.y - a->Pos.y; const f32 cb = c->Pos.y - b->Pos.y; // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal( ca ); scan.invDeltaY[1] = core::reciprocal( ba ); scan.invDeltaY[2] = core::reciprocal( cb ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = -ca; temp[2] = b->Pos.x - a->Pos.x; temp[3] = ba; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > 0.f ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[0] = (c->Pos.z - a->Pos.z) * scan.invDeltaY[0]; scan.z[0] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][0] = (c->Tex[0] - a->Tex[0]) * scan.invDeltaY[0]; scan.t[0][0] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][0] = (c->Tex[1] - a->Tex[1]) * scan.invDeltaY[0]; scan.t[1][0] = a->Tex[1]; #endif // top left fill convention y run s32 yStart; s32 yEnd; #ifdef SUBTEXEL f32 subPixel; #endif // rasterize upper sub-triangle if ( (f32) 0.0 != scan.invDeltaY[1] ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (b->Pos.z - a->Pos.z) * scan.invDeltaY[1]; scan.z[1] = a->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (b->Tex[0] - a->Tex[0]) * scan.invDeltaY[1]; scan.t[0][1] = a->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (b->Tex[1] - a->Tex[1]) * scan.invDeltaY[1]; scan.t[1][1] = a->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } // rasterize lower sub-triangle if ( (f32) 0.0 != scan.invDeltaY[2] ) { // advance to middle point if( (f32) 0.0 != scan.invDeltaY[1] ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; #ifdef IPOL_Z scan.z[0] = a->Pos.z + scan.slopeZ[0] * temp[0]; #endif #ifdef IPOL_W scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; #endif #ifdef IPOL_T1 scan.t[1][0] = a->Tex[1] + scan.slopeT[1][0] * temp[0]; #endif } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; #ifdef IPOL_Z scan.slopeZ[1] = (c->Pos.z - b->Pos.z) * scan.invDeltaY[2]; scan.z[1] = b->Pos.z; #endif #ifdef IPOL_W scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #endif #ifdef IPOL_C0 scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 scan.slopeT[0][1] = (c->Tex[0] - b->Tex[0]) * scan.invDeltaY[2]; scan.t[0][1] = b->Tex[0]; #endif #ifdef IPOL_T1 scan.slopeT[1][1] = (c->Tex[1] - b->Tex[1]) * scan.invDeltaY[2]; scan.t[1][1] = b->Tex[1]; #endif // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; #ifdef SUBTEXEL subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0] * subPixel; scan.z[1] += scan.slopeZ[1] * subPixel; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0] * subPixel; scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0] * subPixel; scan.t[0][1] += scan.slopeT[0][1] * subPixel; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0] * subPixel; scan.t[1][1] += scan.slopeT[1][1] * subPixel; #endif #endif // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.x[scan.right] = scan.x[1]; #ifdef IPOL_Z line.z[scan.left] = scan.z[0]; line.z[scan.right] = scan.z[1]; #endif #ifdef IPOL_W line.w[scan.left] = scan.w[0]; line.w[scan.right] = scan.w[1]; #endif #ifdef IPOL_C0 line.c[0][scan.left] = scan.c[0][0]; line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 line.t[0][scan.left] = scan.t[0][0]; line.t[0][scan.right] = scan.t[0][1]; #endif #ifdef IPOL_T1 line.t[1][scan.left] = scan.t[1][0]; line.t[1][scan.right] = scan.t[1][1]; #endif // render a scanline scanline_bilinear (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; #ifdef IPOL_Z scan.z[0] += scan.slopeZ[0]; scan.z[1] += scan.slopeZ[1]; #endif #ifdef IPOL_W scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; #endif #ifdef IPOL_C0 scan.c[0][0] += scan.slopeC[0][0]; scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 scan.t[0][0] += scan.slopeT[0][0]; scan.t[0][1] += scan.slopeT[0][1]; #endif #ifdef IPOL_T1 scan.t[1][0] += scan.slopeT[1][0]; scan.t[1][1] += scan.slopeT[1][1]; #endif } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTriangleRendererGouraud2(CBurningVideoDriver* driver) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CTRGouraud2(driver); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRGouraud.cpp0000644000000000000000000002467212574354552017633 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CTRTextureGouraud.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { class CTRGouraud : public CTRTextureGouraud { public: CTRGouraud(IZBuffer* zbuffer) : CTRTextureGouraud(zbuffer) { #ifdef _DEBUG setDebugName("CTRGouraud"); #endif } //! draws an indexed triangle list virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) { const S2DVertex *v1, *v2, *v3; f32 tmpDiv; // temporary division factor f32 longest; // saves the longest span s32 height; // saves height of triangle u16* targetSurface; // target pointer where to plot pixels s32 spanEnd; // saves end of spans f32 leftdeltaxf; // amount of pixels to increase on left side of triangle f32 rightdeltaxf; // amount of pixels to increase on right side of triangle s32 leftx, rightx; // position where we are f32 leftxf, rightxf; // same as above, but as f32 values s32 span; // current span u16 *hSpanBegin, *hSpanEnd; // pointer used when plotting pixels s32 leftR, leftG, leftB, rightR, rightG, rightB; // color values s32 leftStepR, leftStepG, leftStepB, rightStepR, rightStepG, rightStepB; // color steps s32 spanR, spanG, spanB, spanStepR, spanStepG, spanStepB; // color interpolating values while drawing a span. core::rect TriangleRect; s32 leftZValue, rightZValue; s32 leftZStep, rightZStep; s32 spanZValue, spanZStep; // ZValues when drawing a span TZBufferType* zTarget, *spanZTarget; // target of ZBuffer; lockedSurface = (u16*)RenderTarget->lock(); lockedZBuffer = ZBuffer->lock(); for (s32 i=0; iPos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) - ((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X)); if (z < 0) continue; } //near plane clipping if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0) continue; // sort for width for inscreen clipping if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2); if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3); if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3); if ((v1->Pos.X - v3->Pos.X) == 0) continue; TriangleRect.UpperLeftCorner.X = v1->Pos.X; TriangleRect.LowerRightCorner.X = v3->Pos.X; // sort for height for faster drawing. if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2); if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3); if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3); TriangleRect.UpperLeftCorner.Y = v1->Pos.Y; TriangleRect.LowerRightCorner.Y = v3->Pos.Y; if (!TriangleRect.isRectCollided(ViewPortRect)) continue; // calculate height of triangle height = v3->Pos.Y - v1->Pos.Y; if (!height) continue; // calculate longest span longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X); spanEnd = v2->Pos.Y; span = v1->Pos.Y; leftxf = (f32)v1->Pos.X; rightxf = (f32)v1->Pos.X; leftZValue = v1->ZValue; rightZValue = v1->ZValue; leftR = rightR = video::getRed(v1->Color)<<11; leftG = rightG = video::getGreen(v1->Color)<<11; leftB = rightB = video::getBlue(v1->Color)<<11; targetSurface = lockedSurface + span * SurfaceWidth; zTarget = lockedZBuffer + span * SurfaceWidth; if (longest < 0.0f) { tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); rightStepR = (s32)(((s32)(video::getRed(v2->Color)<<11) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v2->Color)<<11) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v2->Color)<<11) - rightB) * tmpDiv); tmpDiv = 1.0f / (f32)height; leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<11) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<11) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<11) - leftB) * tmpDiv); } else { tmpDiv = 1.0f / (f32)height; rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<11) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<11) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<11) - rightB) * tmpDiv); tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); leftStepR = (s32)(((s32)(video::getRed(v2->Color)<<11) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v2->Color)<<11) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v2->Color)<<11) - leftB) * tmpDiv); } // do it twice, once for the first half of the triangle, // end then for the second half. for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf) { if (spanEnd > ViewPortRect.LowerRightCorner.Y) spanEnd = ViewPortRect.LowerRightCorner.Y; // if the span <0, than we can skip these spans, // and proceed to the next spans which are really on the screen. if (span < ViewPortRect.UpperLeftCorner.Y) { // we'll use leftx as temp variable if (spanEnd < ViewPortRect.UpperLeftCorner.Y) { leftx = spanEnd - span; span = spanEnd; } else { leftx = ViewPortRect.UpperLeftCorner.Y - span; span = ViewPortRect.UpperLeftCorner.Y; } leftxf += leftdeltaxf*leftx; rightxf += rightdeltaxf*leftx; targetSurface += SurfaceWidth*leftx; zTarget += SurfaceWidth*leftx; leftZValue += leftZStep*leftx; rightZValue += rightZStep*leftx; leftR += leftStepR*leftx; leftG += leftStepG*leftx; leftB += leftStepB*leftx; rightR += rightStepR*leftx; rightG += rightStepG*leftx; rightB += rightStepB*leftx; } // the main loop. Go through every span and draw it. while (span < spanEnd) { leftx = (s32)(leftxf); rightx = (s32)(rightxf + 0.5f); // perform some clipping // TODO: clipping is not correct when leftx is clipped. if (leftxViewPortRect.LowerRightCorner.X) leftx = ViewPortRect.LowerRightCorner.X; if (rightxViewPortRect.LowerRightCorner.X) rightx = ViewPortRect.LowerRightCorner.X; // draw the span if (rightx - leftx != 0) { tmpDiv = 1.0f / (rightx - leftx); spanZValue = leftZValue; spanZStep = (s32)((rightZValue - leftZValue) * tmpDiv); hSpanBegin = targetSurface + leftx; spanZTarget = zTarget + leftx; hSpanEnd = targetSurface + rightx; spanR = leftR; spanG = leftG; spanB = leftB; spanStepR = (s32)((rightR - leftR) * tmpDiv); spanStepG = (s32)((rightG - leftG) * tmpDiv); spanStepB = (s32)((rightB - leftB) * tmpDiv); while (hSpanBegin < hSpanEnd) { if (spanZValue > *spanZTarget) { *spanZTarget = spanZValue; *hSpanBegin = video::RGB16(spanR>>8, spanG>>8, spanB>>8); } spanR += spanStepR; spanG += spanStepG; spanB += spanStepB; spanZValue += spanZStep; ++hSpanBegin; ++spanZTarget; } } leftxf += leftdeltaxf; rightxf += rightdeltaxf; ++span; targetSurface += SurfaceWidth; zTarget += SurfaceWidth; leftZValue += leftZStep; rightZValue += rightZStep; leftR += leftStepR; leftG += leftStepG; leftB += leftStepB; rightR += rightStepR; rightG += rightStepG; rightB += rightStepB; } if (triangleHalf>0) // break, we've gout only two halves break; // setup variables for second half of the triangle. if (longest < 0.0f) { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; rightxf = (f32)v2->Pos.X; rightZValue = v2->ZValue; rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); rightR = video::getRed(v2->Color)<<11; rightG = video::getGreen(v2->Color)<<11; rightB = video::getBlue(v2->Color)<<11; rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<11) - rightR) * tmpDiv); rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<11) - rightG) * tmpDiv); rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<11) - rightB) * tmpDiv); } else { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; leftxf = (f32)v2->Pos.X; leftZValue = v2->ZValue; leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); leftR = video::getRed(v2->Color)<<11; leftG = video::getGreen(v2->Color)<<11; leftB = video::getBlue(v2->Color)<<11; leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<11) - leftR) * tmpDiv); leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<11) - leftG) * tmpDiv); leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<11) - leftB) * tmpDiv); } spanEnd = v3->Pos.Y; } } RenderTarget->unlock(); ZBuffer->unlock(); } }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! creates a flat triangle renderer ITriangleRenderer* createTriangleRendererGouraud(IZBuffer* zbuffer) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CTRGouraud(zbuffer); #else return 0; #endif // _IRR_COMPILE_WITH_SOFTWARE_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRFlatWire.cpp0000644000000000000000000001574212574354552017740 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CTRTextureGouraud.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { class CTRFlatWire : public CTRTextureGouraud { public: CTRFlatWire(IZBuffer* zbuffer) : CTRTextureGouraud(zbuffer) { #ifdef _DEBUG setDebugName("CTRWire"); #endif } //! draws an indexed triangle list virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) { const S2DVertex *v1, *v2, *v3; u16 color; f32 tmpDiv; // temporary division factor f32 longest; // saves the longest span s32 height; // saves height of triangle u16* targetSurface; // target pointer where to plot pixels s32 spanEnd; // saves end of spans f32 leftdeltaxf; // amount of pixels to increase on left side of triangle f32 rightdeltaxf; // amount of pixels to increase on right side of triangle s32 leftx, rightx; // position where we are f32 leftxf, rightxf; // same as above, but as f32 values s32 span; // current span core::rect TriangleRect; s32 leftZValue, rightZValue; s32 leftZStep, rightZStep; TZBufferType* zTarget; // target of ZBuffer; lockedSurface = (u16*)RenderTarget->lock(); lockedZBuffer = ZBuffer->lock(); for (s32 i=0; iPos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) - ((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X)); if (z < 0) continue; } //near plane clipping if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0) continue; // sort for width for inscreen clipping if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2); if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3); if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3); if ((v1->Pos.X - v3->Pos.X) == 0) continue; TriangleRect.UpperLeftCorner.X = v1->Pos.X; TriangleRect.LowerRightCorner.X = v3->Pos.X; // sort for height for faster drawing. if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2); if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3); if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3); TriangleRect.UpperLeftCorner.Y = v1->Pos.Y; TriangleRect.LowerRightCorner.Y = v3->Pos.Y; if (!TriangleRect.isRectCollided(ViewPortRect)) continue; // calculate height of triangle height = v3->Pos.Y - v1->Pos.Y; if (!height) continue; // calculate longest span longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X); spanEnd = v2->Pos.Y; span = v1->Pos.Y; leftxf = (f32)v1->Pos.X; rightxf = (f32)v1->Pos.X; leftZValue = v1->ZValue; rightZValue = v1->ZValue; color = v1->Color; targetSurface = lockedSurface + span * SurfaceWidth; zTarget = lockedZBuffer + span * SurfaceWidth; if (longest < 0.0f) { tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); tmpDiv = 1.0f / (f32)height; leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); } else { tmpDiv = 1.0f / (f32)height; rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); } // do it twice, once for the first half of the triangle, // end then for the second half. for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf) { if (spanEnd > ViewPortRect.LowerRightCorner.Y) spanEnd = ViewPortRect.LowerRightCorner.Y; // if the span <0, than we can skip these spans, // and proceed to the next spans which are really on the screen. if (span < ViewPortRect.UpperLeftCorner.Y) { // we'll use leftx as temp variable if (spanEnd < ViewPortRect.UpperLeftCorner.Y) { leftx = spanEnd - span; span = spanEnd; } else { leftx = ViewPortRect.UpperLeftCorner.Y - span; span = ViewPortRect.UpperLeftCorner.Y; } leftxf += leftdeltaxf*leftx; rightxf += rightdeltaxf*leftx; targetSurface += SurfaceWidth*leftx; zTarget += SurfaceWidth*leftx; leftZValue += leftZStep*leftx; rightZValue += rightZStep*leftx; } // the main loop. Go through every span and draw it. while (span < spanEnd) { leftx = (s32)(leftxf); rightx = (s32)(rightxf + 0.5f); // perform some clipping if (leftx>=ViewPortRect.UpperLeftCorner.X && leftx<=ViewPortRect.LowerRightCorner.X) { if (leftZValue > *(zTarget + leftx)) { *(zTarget + leftx) = leftZValue; *(targetSurface + leftx) = color; } } if (rightx>=ViewPortRect.UpperLeftCorner.X && rightx<=ViewPortRect.LowerRightCorner.X) { if (rightZValue > *(zTarget + rightx)) { *(zTarget + rightx) = rightZValue; *(targetSurface + rightx) = color; } } // draw the span leftxf += leftdeltaxf; rightxf += rightdeltaxf; ++span; targetSurface += SurfaceWidth; zTarget += SurfaceWidth; leftZValue += leftZStep; rightZValue += rightZStep; } if (triangleHalf>0) // break, we've gout only two halves break; // setup variables for second half of the triangle. if (longest < 0.0f) { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; rightxf = (f32)v2->Pos.X; rightZValue = v2->ZValue; rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); } else { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; leftxf = (f32)v2->Pos.X; leftZValue = v2->ZValue; leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); } spanEnd = v3->Pos.Y; } } RenderTarget->unlock(); ZBuffer->unlock(); } }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! creates a flat triangle renderer ITriangleRenderer* createTriangleRendererFlatWire(IZBuffer* zbuffer) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CTRFlatWire(zbuffer); #else return 0; #endif // _IRR_COMPILE_WITH_SOFTWARE_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTRFlat.cpp0000644000000000000000000001715412574354552017110 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CTRTextureGouraud.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { class CTRFlat : public CTRTextureGouraud { public: CTRFlat(IZBuffer* zbuffer) : CTRTextureGouraud(zbuffer) { #ifdef _DEBUG setDebugName("CTRFlat"); #endif } //! draws an indexed triangle list virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) { const S2DVertex *v1, *v2, *v3; u16 color; f32 tmpDiv; // temporary division factor f32 longest; // saves the longest span s32 height; // saves height of triangle u16* targetSurface; // target pointer where to plot pixels s32 spanEnd; // saves end of spans f32 leftdeltaxf; // amount of pixels to increase on left side of triangle f32 rightdeltaxf; // amount of pixels to increase on right side of triangle s32 leftx, rightx; // position where we are f32 leftxf, rightxf; // same as above, but as f32 values s32 span; // current span u16 *hSpanBegin, *hSpanEnd; // pointer used when plotting pixels core::rect TriangleRect; s32 leftZValue, rightZValue; s32 leftZStep, rightZStep; s32 spanZValue, spanZStep; // ZValues when drawing a span TZBufferType* zTarget, *spanZTarget; // target of ZBuffer; lockedSurface = (u16*)RenderTarget->lock(); lockedZBuffer = ZBuffer->lock(); for (s32 i=0; iPos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) - ((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X)); if (z < 0) continue; } //near plane clipping if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0) continue; // sort for width for inscreen clipping if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2); if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3); if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3); if ((v1->Pos.X - v3->Pos.X) == 0) continue; TriangleRect.UpperLeftCorner.X = v1->Pos.X; TriangleRect.LowerRightCorner.X = v3->Pos.X; // sort for height for faster drawing. if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2); if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3); if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3); TriangleRect.UpperLeftCorner.Y = v1->Pos.Y; TriangleRect.LowerRightCorner.Y = v3->Pos.Y; if (!TriangleRect.isRectCollided(ViewPortRect)) continue; // calculate height of triangle height = v3->Pos.Y - v1->Pos.Y; if (!height) continue; // calculate longest span longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X); spanEnd = v2->Pos.Y; span = v1->Pos.Y; leftxf = (f32)v1->Pos.X; rightxf = (f32)v1->Pos.X; leftZValue = v1->ZValue; rightZValue = v1->ZValue; color = v1->Color; targetSurface = lockedSurface + span * SurfaceWidth; zTarget = lockedZBuffer + span * SurfaceWidth; if (longest < 0.0f) { tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); tmpDiv = 1.0f / (f32)height; leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); } else { tmpDiv = 1.0f / (f32)height; rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv; rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv); tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y); leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv; leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv); } // do it twice, once for the first half of the triangle, // end then for the second half. for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf) { if (spanEnd > ViewPortRect.LowerRightCorner.Y) spanEnd = ViewPortRect.LowerRightCorner.Y; // if the span <0, than we can skip these spans, // and proceed to the next spans which are really on the screen. if (span < ViewPortRect.UpperLeftCorner.Y) { // we'll use leftx as temp variable if (spanEnd < ViewPortRect.UpperLeftCorner.Y) { leftx = spanEnd - span; span = spanEnd; } else { leftx = ViewPortRect.UpperLeftCorner.Y - span; span = ViewPortRect.UpperLeftCorner.Y; } leftxf += leftdeltaxf*leftx; rightxf += rightdeltaxf*leftx; targetSurface += SurfaceWidth*leftx; zTarget += SurfaceWidth*leftx; leftZValue += leftZStep*leftx; rightZValue += rightZStep*leftx; } // the main loop. Go through every span and draw it. while (span < spanEnd) { leftx = (s32)(leftxf); rightx = (s32)(rightxf + 0.5f); // perform some clipping // TODO: clipping is not correct when leftx is clipped. if (leftxViewPortRect.LowerRightCorner.X) leftx = ViewPortRect.LowerRightCorner.X; if (rightxViewPortRect.LowerRightCorner.X) rightx = ViewPortRect.LowerRightCorner.X; // draw the span if (rightx - leftx != 0) { tmpDiv = 1.0f / (rightx - leftx); spanZValue = leftZValue; spanZStep = (s32)((rightZValue - leftZValue) * tmpDiv); hSpanBegin = targetSurface + leftx; spanZTarget = zTarget + leftx; hSpanEnd = targetSurface + rightx; while (hSpanBegin < hSpanEnd) { if (spanZValue > *spanZTarget) { *spanZTarget = spanZValue; *hSpanBegin = color; } spanZValue += spanZStep; ++hSpanBegin; ++spanZTarget; } } leftxf += leftdeltaxf; rightxf += rightdeltaxf; ++span; targetSurface += SurfaceWidth; zTarget += SurfaceWidth; leftZValue += leftZStep; rightZValue += rightZStep; } if (triangleHalf>0) // break, we've gout only two halves break; // setup variables for second half of the triangle. if (longest < 0.0f) { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; rightxf = (f32)v2->Pos.X; rightZValue = v2->ZValue; rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); } else { tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y); leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv; leftxf = (f32)v2->Pos.X; leftZValue = v2->ZValue; leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv); } spanEnd = v3->Pos.Y; } } RenderTarget->unlock(); ZBuffer->unlock(); } }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! creates a flat triangle renderer ITriangleRenderer* createTriangleRendererFlat(IZBuffer* zbuffer) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CTRFlat(zbuffer); #else return 0; #endif // _IRR_COMPILE_WITH_SOFTWARE_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTimer.h0000644000000000000000000000577612574354552016510 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IRR_C_TIMER_H_INCLUDED__ #define __C_IRR_C_TIMER_H_INCLUDED__ #include "ITimer.h" #include "os.h" namespace irr { //! Device independent implementation of the timer class CTimer : public ITimer { public: CTimer(bool usePerformanceTimer=true) { os::Timer::initTimer(usePerformanceTimer); } //! Returns current real time in milliseconds of the system. /** This value does not start with 0 when the application starts. For example in one implementation the value returned could be the amount of milliseconds which have elapsed since the system was started. */ virtual u32 getRealTime() const { return os::Timer::getRealTime(); } //! Get current time and date in calendar form virtual RealTimeDate getRealTimeAndDate() const { return os::Timer::getRealTimeAndDate(); } //! Returns current virtual time in milliseconds. /** This value starts with 0 and can be manipulated using setTime(), stopTimer(), startTimer(), etc. This value depends on the set speed of the timer if the timer is stopped, etc. If you need the system time, use getRealTime() */ virtual u32 getTime() const { return os::Timer::getTime(); } //! sets current virtual time virtual void setTime(u32 time) { os::Timer::setTime(time); } //! Stops the game timer. /** The timer is reference counted, which means everything which calls stopTimer() will also have to call startTimer(), otherwise the timer may not start/stop corretly again. */ virtual void stop() { os::Timer::stopTimer(); } //! Starts the game timer. /** The timer is reference counted, which means everything which calls stopTimer() will also have to call startTimer(), otherwise the timer may not start/stop corretly again. */ virtual void start() { os::Timer::startTimer(); } //! Sets the speed of the timer /** The speed is the factor with which the time is running faster or slower then the real system time. */ virtual void setSpeed(f32 speed = 1.0f) { os::Timer::setSpeed(speed); } //! Returns current speed of the timer /** The speed is the factor with which the time is running faster or slower then the real system time. */ virtual f32 getSpeed() const { return os::Timer::getSpeed(); } //! Returns if game timer is currently stopped virtual bool isStopped() const { bool ret = os::Timer::isStopped(); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! Advances the virtual time /** Makes the virtual timer update the time value based on the real time. This is called automaticly when calling IrrlichtDevice::run(), but you can call it manually if you don't use this method. */ virtual void tick() { os::Timer::tick(); } }; } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/CTextSceneNode.h0000644000000000000000000001052612574354552020125 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_TEXT_SCENE_NODE_H_INCLUDED__ #define __C_TEXT_SCENE_NODE_H_INCLUDED__ #include "ITextSceneNode.h" #include "IBillboardTextSceneNode.h" #include "IGUIFont.h" #include "IGUIFontBitmap.h" #include "ISceneCollisionManager.h" #include "SMesh.h" namespace irr { namespace scene { class CTextSceneNode : public ITextSceneNode { public: //! constructor CTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, gui::IGUIFont* font, scene::ISceneCollisionManager* coll, const core::vector3df& position = core::vector3df(0,0,0), const wchar_t* text=0, video::SColor color=video::SColor(100,0,0,0)); //! destructor virtual ~CTextSceneNode(); virtual void OnRegisterSceneNode(); //! renders the node. virtual void render(); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! sets the text string virtual void setText(const wchar_t* text); //! sets the color of the text virtual void setTextColor(video::SColor color); //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_TEXT; } private: core::stringw Text; video::SColor Color; gui::IGUIFont* Font; scene::ISceneCollisionManager* Coll; core::aabbox3d Box; }; class CBillboardTextSceneNode : public IBillboardTextSceneNode { public: CBillboardTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, gui::IGUIFont* font,const wchar_t* text, const core::vector3df& position, const core::dimension2d& size, video::SColor colorTop, video::SColor shade_bottom); //! destructor virtual ~CBillboardTextSceneNode(); //! sets the vertex positions etc virtual void OnAnimate(u32 timeMs); //! registers the node into the transparent pass virtual void OnRegisterSceneNode(); //! renders the node. virtual void render(); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! sets the text string virtual void setText(const wchar_t* text); //! sets the color of the text virtual void setTextColor(video::SColor color); //! sets the size of the billboard virtual void setSize(const core::dimension2d& size); //! gets the size of the billboard virtual const core::dimension2d& getSize() const; virtual video::SMaterial& getMaterial(u32 i); //! returns amount of materials used by this scene node. virtual u32 getMaterialCount() const; //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_TEXT; } //! Set the color of all vertices of the billboard //! \param overallColor: the color to set virtual void setColor(const video::SColor & overallColor); //! Set the color of the top and bottom vertices of the billboard //! \param topColor: the color to set the top vertices //! \param bottomColor: the color to set the bottom vertices virtual void setColor(const video::SColor & topColor, const video::SColor & bottomColor); //! Gets the color of the top and bottom vertices of the billboard //! \param topColor: stores the color of the top vertices //! \param bottomColor: stores the color of the bottom vertices virtual void getColor(video::SColor & topColor, video::SColor & bottomColor) const; virtual void setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth) { setSize(core::dimension2df(bottomEdgeWidth, height)); } virtual void getSize(f32& height, f32& bottomEdgeWidth, f32& topEdgeWidth) const { height = Size.Height; bottomEdgeWidth = Size.Width; topEdgeWidth = Size.Width; } private: core::stringw Text; video::SColor Color; gui::IGUIFontBitmap* Font; core::dimension2d Size; core::aabbox3d BBox; video::SMaterial Material; video::SColor ColorTop; video::SColor ColorBottom; struct SSymbolInfo { u32 bufNo; f32 Width; f32 Kerning; u32 firstInd; u32 firstVert; }; core::array < SSymbolInfo > Symbol; SMesh *Mesh; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CTextSceneNode.cpp0000644000000000000000000003006212574354552020455 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CTextSceneNode.h" #include "ISceneManager.h" #include "IVideoDriver.h" #include "ICameraSceneNode.h" #include "IGUISpriteBank.h" #include "SMeshBuffer.h" #include "os.h" namespace irr { namespace scene { //! constructor CTextSceneNode::CTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, gui::IGUIFont* font, scene::ISceneCollisionManager* coll, const core::vector3df& position, const wchar_t* text, video::SColor color) : ITextSceneNode(parent, mgr, id, position), Text(text), Color(color), Font(font), Coll(coll) { #ifdef _DEBUG setDebugName("CTextSceneNode"); #endif if (Font) Font->grab(); setAutomaticCulling(scene::EAC_OFF); } //! destructor CTextSceneNode::~CTextSceneNode() { if (Font) Font->drop(); } void CTextSceneNode::OnRegisterSceneNode() { if (IsVisible) SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT); ISceneNode::OnRegisterSceneNode(); } //! renders the node. void CTextSceneNode::render() { if (!Font || !Coll) return; core::position2d pos = Coll->getScreenCoordinatesFrom3DPosition(getAbsolutePosition(), SceneManager->getActiveCamera()); core::rect r(pos, core::dimension2d(1,1)); Font->draw(Text.c_str(), r, Color, true, true); } //! returns the axis aligned bounding box of this node const core::aabbox3d& CTextSceneNode::getBoundingBox() const { return Box; } //! sets the text string void CTextSceneNode::setText(const wchar_t* text) { Text = text; } //! sets the color of the text void CTextSceneNode::setTextColor(video::SColor color) { Color = color; } //!--------------------------------- CBillboardTextSceneNode ---------------------------------------------- //! constructor CBillboardTextSceneNode::CBillboardTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, gui::IGUIFont* font,const wchar_t* text, const core::vector3df& position, const core::dimension2d& size, video::SColor colorTop,video::SColor shade_bottom ) : IBillboardTextSceneNode(parent, mgr, id, position), Font(0), ColorTop(colorTop), ColorBottom(shade_bottom), Mesh(0) { #ifdef _DEBUG setDebugName("CBillboardTextSceneNode"); #endif Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; Material.MaterialTypeParam = 1.f / 255.f; Material.BackfaceCulling = false; Material.Lighting = false; Material.ZBuffer = video::ECFN_LESSEQUAL; Material.ZWriteEnable = false; if (font) { // doesn't support other font types if (font->getType() == gui::EGFT_BITMAP) { Font = (gui::IGUIFontBitmap*)font; Font->grab(); // mesh with one buffer per texture Mesh = new SMesh(); for (u32 i=0; igetSpriteBank()->getTextureCount(); ++i) { SMeshBuffer *mb = new SMeshBuffer(); mb->Material = Material; mb->Material.setTexture(0, Font->getSpriteBank()->getTexture(i)); Mesh->addMeshBuffer(mb); mb->drop(); } } else { os::Printer::log("Sorry, CBillboardTextSceneNode does not support this font type", ELL_INFORMATION); } } setText(text); setSize(size); setAutomaticCulling ( scene::EAC_BOX ); } CBillboardTextSceneNode::~CBillboardTextSceneNode() { if (Font) Font->drop(); if (Mesh) Mesh->drop(); } //! sets the text string void CBillboardTextSceneNode::setText(const wchar_t* text) { if ( !Mesh ) return; Text = text; Symbol.clear(); // clear mesh for (u32 j=0; j < Mesh->getMeshBufferCount(); ++j) { ((SMeshBuffer*)Mesh->getMeshBuffer(j))->Indices.clear(); ((SMeshBuffer*)Mesh->getMeshBuffer(j))->Vertices.clear(); } if (!Font) return; const core::array< core::rect > &sourceRects = Font->getSpriteBank()->getPositions(); const core::array< gui::SGUISprite > &sprites = Font->getSpriteBank()->getSprites(); f32 dim[2]; f32 tex[4]; u32 i; for ( i = 0; i != Text.size (); ++i ) { SSymbolInfo info; u32 spriteno = Font->getSpriteNoFromChar( &text[i] ); u32 rectno = sprites[spriteno].Frames[0].rectNumber; u32 texno = sprites[spriteno].Frames[0].textureNumber; dim[0] = core::reciprocal ( (f32) Font->getSpriteBank()->getTexture(texno)->getSize().Width ); dim[1] = core::reciprocal ( (f32) Font->getSpriteBank()->getTexture(texno)->getSize().Height ); const core::rect& s = sourceRects[rectno]; // add space for letter to buffer SMeshBuffer* buf = (SMeshBuffer*)Mesh->getMeshBuffer(texno); u32 firstInd = buf->Indices.size(); u32 firstVert = buf->Vertices.size(); buf->Indices.set_used(firstInd + 6); buf->Vertices.set_used(firstVert + 4); tex[0] = (s.LowerRightCorner.X * dim[0]) + 0.5f*dim[0]; // half pixel tex[1] = (s.LowerRightCorner.Y * dim[1]) + 0.5f*dim[1]; tex[2] = (s.UpperLeftCorner.Y * dim[1]) - 0.5f*dim[1]; tex[3] = (s.UpperLeftCorner.X * dim[0]) - 0.5f*dim[0]; buf->Vertices[firstVert+0].TCoords.set(tex[0], tex[1]); buf->Vertices[firstVert+1].TCoords.set(tex[0], tex[2]); buf->Vertices[firstVert+2].TCoords.set(tex[3], tex[2]); buf->Vertices[firstVert+3].TCoords.set(tex[3], tex[1]); buf->Vertices[firstVert+0].Color = ColorBottom; buf->Vertices[firstVert+3].Color = ColorBottom; buf->Vertices[firstVert+1].Color = ColorTop; buf->Vertices[firstVert+2].Color = ColorTop; buf->Indices[firstInd+0] = (u16)firstVert+0; buf->Indices[firstInd+1] = (u16)firstVert+2; buf->Indices[firstInd+2] = (u16)firstVert+1; buf->Indices[firstInd+3] = (u16)firstVert+0; buf->Indices[firstInd+4] = (u16)firstVert+3; buf->Indices[firstInd+5] = (u16)firstVert+2; wchar_t *tp = 0; if (i>0) tp = &Text[i-1]; info.Width = (f32)s.getWidth(); info.bufNo = texno; info.Kerning = (f32)Font->getKerningWidth(&Text[i], tp); info.firstInd = firstInd; info.firstVert = firstVert; Symbol.push_back(info); } } //! pre render event void CBillboardTextSceneNode::OnAnimate(u32 timeMs) { ISceneNode::OnAnimate(timeMs); if (!IsVisible || !Font || !Mesh) return; ICameraSceneNode* camera = SceneManager->getActiveCamera(); if (!camera) return; // get text width f32 textLength = 0.f; u32 i; for(i=0; i!=Symbol.size(); ++i) { SSymbolInfo &info = Symbol[i]; textLength += info.Kerning + info.Width; } if (textLength<0.0f) textLength=1.0f; //const core::matrix4 &m = camera->getViewFrustum()->Matrices[ video::ETS_VIEW ]; // make billboard look to camera core::vector3df pos = getAbsolutePosition(); core::vector3df campos = camera->getAbsolutePosition(); core::vector3df target = camera->getTarget(); core::vector3df up = camera->getUpVector(); core::vector3df view = target - campos; view.normalize(); core::vector3df horizontal = up.crossProduct(view); if ( horizontal.getLength() == 0 ) { horizontal.set(up.Y,up.X,up.Z); } horizontal.normalize(); core::vector3df space = horizontal; horizontal *= 0.5f * Size.Width; core::vector3df vertical = horizontal.crossProduct(view); vertical.normalize(); vertical *= 0.5f * Size.Height; view *= -1.0f; // center text pos += space * (Size.Width * -0.5f); for ( i = 0; i!= Symbol.size(); ++i ) { SSymbolInfo &info = Symbol[i]; f32 infw = info.Width / textLength; f32 infk = info.Kerning / textLength; f32 w = (Size.Width * infw * 0.5f); pos += space * w; SMeshBuffer* buf = (SMeshBuffer*)Mesh->getMeshBuffer(info.bufNo); buf->Vertices[info.firstVert+0].Normal = view; buf->Vertices[info.firstVert+1].Normal = view; buf->Vertices[info.firstVert+2].Normal = view; buf->Vertices[info.firstVert+3].Normal = view; buf->Vertices[info.firstVert+0].Pos = pos + (space * w) + vertical; buf->Vertices[info.firstVert+1].Pos = pos + (space * w) - vertical; buf->Vertices[info.firstVert+2].Pos = pos - (space * w) - vertical; buf->Vertices[info.firstVert+3].Pos = pos - (space * w) + vertical; pos += space * (Size.Width*infk + w); } // make bounding box for (i=0; i< Mesh->getMeshBufferCount() ; ++i) Mesh->getMeshBuffer(i)->recalculateBoundingBox(); Mesh->recalculateBoundingBox(); BBox = Mesh->getBoundingBox(); core::matrix4 mat( getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE ); mat.transformBoxEx(BBox); } void CBillboardTextSceneNode::OnRegisterSceneNode() { SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT); ISceneNode::OnRegisterSceneNode(); } //! render void CBillboardTextSceneNode::render() { if ( !Mesh ) return; video::IVideoDriver* driver = SceneManager->getVideoDriver(); // draw core::matrix4 mat; driver->setTransform(video::ETS_WORLD, mat); for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) { driver->setMaterial(Mesh->getMeshBuffer(i)->getMaterial()); driver->drawMeshBuffer(Mesh->getMeshBuffer(i)); } if ( DebugDataVisible & scene::EDS_BBOX ) { driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); video::SMaterial m; m.Lighting = false; driver->setMaterial(m); driver->draw3DBox(BBox, video::SColor(0,208,195,152)); } } //! returns the axis aligned bounding box of this node const core::aabbox3d& CBillboardTextSceneNode::getBoundingBox() const { return BBox; } //! sets the size of the billboard void CBillboardTextSceneNode::setSize(const core::dimension2d& size) { Size = size; if (Size.Width == 0.0f) Size.Width = 1.0f; if (Size.Height == 0.0f ) Size.Height = 1.0f; //f32 avg = (size.Width + size.Height)/6; //BBox.MinEdge.set(-avg,-avg,-avg); //BBox.MaxEdge.set(avg,avg,avg); } video::SMaterial& CBillboardTextSceneNode::getMaterial(u32 i) { if (Mesh && Mesh->getMeshBufferCount() > i ) return Mesh->getMeshBuffer(i)->getMaterial(); else return Material; } //! returns amount of materials used by this scene node. u32 CBillboardTextSceneNode::getMaterialCount() const { if (Mesh) return Mesh->getMeshBufferCount(); else return 0; } //! gets the size of the billboard const core::dimension2d& CBillboardTextSceneNode::getSize() const { return Size; } //! sets the color of the text void CBillboardTextSceneNode::setTextColor(video::SColor color) { Color = color; } //! Set the color of all vertices of the billboard //! \param overallColor: the color to set void CBillboardTextSceneNode::setColor(const video::SColor & overallColor) { if ( !Mesh ) return; for ( u32 i = 0; i != Text.size (); ++i ) { const SSymbolInfo &info = Symbol[i]; SMeshBuffer* buf = (SMeshBuffer*)Mesh->getMeshBuffer(info.bufNo); buf->Vertices[info.firstVert+0].Color = overallColor; buf->Vertices[info.firstVert+1].Color = overallColor; buf->Vertices[info.firstVert+2].Color = overallColor; buf->Vertices[info.firstVert+3].Color = overallColor; } } //! Set the color of the top and bottom vertices of the billboard //! \param topColor: the color to set the top vertices //! \param bottomColor: the color to set the bottom vertices void CBillboardTextSceneNode::setColor(const video::SColor & topColor, const video::SColor & bottomColor) { if ( !Mesh ) return; ColorBottom = bottomColor; ColorTop = topColor; for ( u32 i = 0; i != Text.size (); ++i ) { const SSymbolInfo &info = Symbol[i]; SMeshBuffer* buf = (SMeshBuffer*)Mesh->getMeshBuffer(info.bufNo); buf->Vertices[info.firstVert+0].Color = ColorBottom; buf->Vertices[info.firstVert+3].Color = ColorBottom; buf->Vertices[info.firstVert+1].Color = ColorTop; buf->Vertices[info.firstVert+2].Color = ColorTop; } } //! Gets the color of the top and bottom vertices of the billboard //! \param topColor: stores the color of the top vertices //! \param bottomColor: stores the color of the bottom vertices void CBillboardTextSceneNode::getColor(video::SColor & topColor, video::SColor & bottomColor) const { topColor = ColorTop; bottomColor = ColorBottom; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTerrainTriangleSelector.h0000644000000000000000000000611312574354552022205 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // The code for the TerrainTriangleSelector is based on the GeoMipMapSelector // developed by Spintz. He made it available for Irrlicht and allowed it to be // distributed under this licence. I only modified some parts. A lot of thanks go to him. #ifndef __C_TERRAIN_TRIANGLE_SELECTOR_H__ #define __C_TERRAIN_TRIANGLE_SELECTOR_H__ #include "ITriangleSelector.h" #include "irrArray.h" namespace irr { namespace scene { class ITerrainSceneNode; //! Triangle Selector for the TerrainSceneNode /** The code for the TerrainTriangleSelector is based on the GeoMipMapSelector developed by Spintz. He made it available for Irrlicht and allowed it to be distributed under this licence. I only modified some parts. A lot of thanks go to him. */ class CTerrainTriangleSelector : public ITriangleSelector { public: //! Constructs a selector based on an ITerrainSceneNode CTerrainTriangleSelector(ITerrainSceneNode* node, s32 LOD); //! Destructor virtual ~CTerrainTriangleSelector(); //! Clears and sets triangle data virtual void setTriangleData (ITerrainSceneNode* node, s32 LOD); //! Gets all triangles. void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::matrix4* transform=0) const; //! Gets all triangles which lie within a specific bounding box. void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::aabbox3d& box, const core::matrix4* transform=0) const; //! Gets all triangles which have or may have contact with a 3d line. virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform=0) const; //! Returns amount of all available triangles in this selector virtual s32 getTriangleCount() const; //! Return the scene node associated with a given triangle. virtual ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const; // Get the number of TriangleSelectors that are part of this one virtual u32 getSelectorCount() const; // Get the TriangleSelector based on index based on getSelectorCount virtual ITriangleSelector* getSelector(u32 index); // Get the TriangleSelector based on index based on getSelectorCount virtual const ITriangleSelector* getSelector(u32 index) const; private: friend class CTerrainSceneNode; struct SGeoMipMapTrianglePatch { core::array Triangles; s32 NumTriangles; core::aabbox3df Box; }; struct SGeoMipMapTrianglePatches { SGeoMipMapTrianglePatches() : NumPatches(0), TotalTriangles(0) { } core::array TrianglePatchArray; s32 NumPatches; u32 TotalTriangles; }; ITerrainSceneNode* SceneNode; SGeoMipMapTrianglePatches TrianglePatches; }; } // end namespace scene } // end namespace irr #endif // __C_TERRAIN_TRIANGLE_SELECTOR_H__ irrlicht-1.8.3/source/Irrlicht/CTerrainTriangleSelector.cpp0000644000000000000000000001423412574354552022543 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CTerrainTriangleSelector.h" #include "CTerrainSceneNode.h" #include "os.h" namespace irr { namespace scene { //! constructor CTerrainTriangleSelector::CTerrainTriangleSelector ( ITerrainSceneNode* node, s32 LOD ) : SceneNode(node) { #ifdef _DEBUG setDebugName ("CTerrainTriangleSelector"); #endif setTriangleData(node, LOD); } //! destructor CTerrainTriangleSelector::~CTerrainTriangleSelector() { TrianglePatches.TrianglePatchArray.clear(); } //! Clears and sets triangle data void CTerrainTriangleSelector::setTriangleData(ITerrainSceneNode* node, s32 LOD) { // Get pointer to the GeoMipMaps vertices const video::S3DVertex2TCoords* vertices = static_cast(node->getRenderBuffer()->getVertices()); // Clear current data const s32 count = (static_cast(node))->TerrainData.PatchCount; TrianglePatches.TotalTriangles = 0; TrianglePatches.NumPatches = count*count; TrianglePatches.TrianglePatchArray.reallocate(TrianglePatches.NumPatches); for (s32 o=0; o indices; s32 tIndex = 0; for(s32 x = 0; x < count; ++x ) { for(s32 z = 0; z < count; ++z ) { TrianglePatches.TrianglePatchArray[tIndex].NumTriangles = 0; TrianglePatches.TrianglePatchArray[tIndex].Box = node->getBoundingBox( x, z ); u32 indexCount = node->getIndicesForPatch( indices, x, z, LOD ); TrianglePatches.TrianglePatchArray[tIndex].Triangles.reallocate(indexCount/3); for(u32 i = 0; i < indexCount; i += 3 ) { tri.pointA = vertices[indices[i+0]].Pos; tri.pointB = vertices[indices[i+1]].Pos; tri.pointC = vertices[indices[i+2]].Pos; TrianglePatches.TrianglePatchArray[tIndex].Triangles.push_back(tri); ++TrianglePatches.TrianglePatchArray[tIndex].NumTriangles; } TrianglePatches.TotalTriangles += TrianglePatches.TrianglePatchArray[tIndex].NumTriangles; ++tIndex; } } } //! Gets all triangles. void CTerrainTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::matrix4* transform) const { s32 count = TrianglePatches.TotalTriangles; if (count > arraySize) count = arraySize; core::matrix4 mat; if (transform) mat = (*transform); s32 tIndex = 0; for (s32 i=0; i& box, const core::matrix4* transform) const { s32 count = TrianglePatches.TotalTriangles; if (count > arraySize) count = arraySize; core::matrix4 mat; if (transform) mat = (*transform); s32 tIndex = 0; for (s32 i=0; i& line, const core::matrix4* transform) const { const s32 count = core::min_((s32)TrianglePatches.TotalTriangles, arraySize); core::matrix4 mat; if (transform) mat = (*transform); s32 tIndex = 0; for (s32 i=0; i& getBoundingBox() const; //! Return the bounding box of a patch virtual const core::aabbox3d& getBoundingBox(s32 patchX, s32 patchZ) const; //! Return the number of indices currently used to draw the scene node. virtual u32 getIndexCount() const { return IndicesToRender; } //! Returns the mesh virtual IMesh* getMesh(); //! Returns a pointer to the buffer used by the terrain (most users will not need this) virtual IMeshBuffer* getRenderBuffer() { return RenderBuffer; } //! Gets the meshbuffer data based on a specified Level of Detail. //! \param mb: A reference to an IDynamicMeshBuffer object //! \param LOD: The Level Of Detail you want the indices from. virtual void getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD=0) const; //! Gets the indices for a specified patch at a specified Level of Detail. //! \param indices: A reference to an array of u32 indices. //! \param patchX: Patch x coordinate. //! \param patchZ: Patch z coordinate. //! \param LOD: The level of detail to get for that patch. If -1, then get //! the CurrentLOD. If the CurrentLOD is set to -1, meaning it's not shown, //! then it will retrieve the triangles at the highest LOD (0). //! \return: Number of indices put into the buffer. virtual s32 getIndicesForPatch(core::array& indices, s32 patchX, s32 patchZ, s32 LOD=0); //! Populates an array with the CurrentLOD of each patch. //! \param LODs: A reference to a core::array to hold the values //! \return Returns the number of elements in the array virtual s32 getCurrentLODOfPatches(core::array& LODs) const; //! Manually sets the LOD of a patch //! \param patchX: Patch x coordinate. //! \param patchZ: Patch z coordinate. //! \param LOD: The level of detail to set the patch to. virtual void setLODOfPatch(s32 patchX, s32 patchZ, s32 LOD=0); //! Returns center of terrain. virtual const core::vector3df& getTerrainCenter() const { return TerrainData.Center; } //! Returns center of terrain. virtual f32 getHeight( f32 x, f32 y ) const; //! Sets the movement camera threshold which is used to determine when to recalculate //! indices for the scene node. The default value is 10.0f. virtual void setCameraMovementDelta(f32 delta) { CameraMovementDelta = delta; } //! Sets the rotation camera threshold which is used to determine when to recalculate //! indices for the scene node. The default value is 1.0f. virtual void setCameraRotationDelta(f32 delta) { CameraRotationDelta = delta; } //! Sets whether or not the node should dynamically update it its associated selector when //! the geomipmap data changes. //! param bVal: Boolean value representing whether or not to update selector dynamically. //! NOTE: Temporarily disabled while working out issues with DynamicSelectorUpdate virtual void setDynamicSelectorUpdate(bool bVal ) { DynamicSelectorUpdate = false; } //! Override the default generation of distance thresholds for determining the LOD a patch //! is rendered at. If any LOD is overridden, then the scene node will no longer apply //! scaling factors to these values. If you override these distances and then apply //! a scale to the scene node, it is your responsibility to update the new distances to //! work best with your new terrain size. virtual bool overrideLODDistance( s32 LOD, f64 newDistance ); //! Scales the two textures virtual void scaleTexture(f32 scale = 1.0f, f32 scale2 = 0.0f); //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const {return ESNT_TERRAIN;} //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent, ISceneManager* newManager); private: friend class CTerrainTriangleSelector; struct SPatch { SPatch() : Top(0), Bottom(0), Right(0), Left(0), CurrentLOD(-1) { } SPatch* Top; SPatch* Bottom; SPatch* Right; SPatch* Left; s32 CurrentLOD; core::aabbox3df BoundingBox; core::vector3df Center; }; struct STerrainData { STerrainData(s32 patchSize, s32 maxLOD, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) : Patches(0), Size(0), Position(position), Rotation(rotation), Scale(scale), PatchSize(patchSize), CalcPatchSize(patchSize-1), PatchCount(0), MaxLOD(maxLOD) { } SPatch* Patches; s32 Size; core::vector3df Position; core::vector3df Rotation; core::vector3df RotationPivot; core::vector3df Scale; core::vector3df Center; s32 PatchSize; s32 CalcPatchSize; s32 PatchCount; s32 MaxLOD; core::aabbox3df BoundingBox; core::array LODDistanceThreshold; }; virtual void preRenderCalculationsIfNeeded(); virtual void preRenderLODCalculations(); virtual void preRenderIndicesCalculations(); //! get indices when generating index data for patches at varying levels of detail. u32 getIndex(const s32 PatchX, const s32 PatchZ, const s32 PatchIndex, u32 vX, u32 vZ) const; //! smooth the terrain void smoothTerrain(IDynamicMeshBuffer* mb, s32 smoothFactor); //! calculate smooth normals void calculateNormals(IDynamicMeshBuffer* mb); //! create patches, stuff that needs to only be done once for patches goes here. void createPatches(); //! calculate the internal STerrainData structure void calculatePatchData(); //! calculate or recalculate the distance thresholds void calculateDistanceThresholds(bool scalechanged = false); //! sets the CurrentLOD of all patches to the specified LOD void setCurrentLODOfPatches(s32 i); //! sets the CurrentLOD of TerrainData patches to the LODs specified in the array void setCurrentLODOfPatches(const core::array& lodarray); //! Apply transformation changes( scale, position, rotation ) void applyTransformation(); STerrainData TerrainData; SMesh* Mesh; IDynamicMeshBuffer *RenderBuffer; u32 VerticesToRender; u32 IndicesToRender; bool DynamicSelectorUpdate; bool OverrideDistanceThreshold; bool UseDefaultRotationPivot; bool ForceRecalculation; core::vector3df OldCameraPosition; core::vector3df OldCameraRotation; core::vector3df OldCameraUp; f32 OldCameraFOV; f32 CameraMovementDelta; f32 CameraRotationDelta; f32 CameraFOVDelta; // needed for (de)serialization f32 TCoordScale1; f32 TCoordScale2; s32 SmoothFactor; io::path HeightmapFile; io::IFileSystem* FileSystem; }; } // end namespace scene } // end namespace irr #endif // __C_TERRAIN_SCENE_NODE_H__ irrlicht-1.8.3/source/Irrlicht/CTerrainSceneNode.cpp0000644000000000000000000012524012574354552021140 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // The code for the TerrainSceneNode is based on the GeoMipMapSceneNode // developed by Spintz. He made it available for Irrlicht and allowed it to be // distributed under this licence. I only modified some parts. A lot of thanks // go to him. #include "CTerrainSceneNode.h" #include "CTerrainTriangleSelector.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "ICameraSceneNode.h" #include "SViewFrustum.h" #include "irrMath.h" #include "os.h" #include "IGUIFont.h" #include "IFileSystem.h" #include "IReadFile.h" #include "ITextSceneNode.h" #include "IAnimatedMesh.h" #include "SMesh.h" #include "CDynamicMeshBuffer.h" namespace irr { namespace scene { //! constructor CTerrainSceneNode::CTerrainSceneNode(ISceneNode* parent, ISceneManager* mgr, io::IFileSystem* fs, s32 id, s32 maxLOD, E_TERRAIN_PATCH_SIZE patchSize, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) : ITerrainSceneNode(parent, mgr, id, position, rotation, scale), TerrainData(patchSize, maxLOD, position, rotation, scale), RenderBuffer(0), VerticesToRender(0), IndicesToRender(0), DynamicSelectorUpdate(false), OverrideDistanceThreshold(false), UseDefaultRotationPivot(true), ForceRecalculation(true), CameraMovementDelta(10.0f), CameraRotationDelta(1.0f),CameraFOVDelta(0.1f), TCoordScale1(1.0f), TCoordScale2(1.0f), SmoothFactor(0), FileSystem(fs) { #ifdef _DEBUG setDebugName("CTerrainSceneNode"); #endif Mesh = new SMesh(); RenderBuffer = new CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); RenderBuffer->setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX); RenderBuffer->setHardwareMappingHint(scene::EHM_DYNAMIC, scene::EBT_INDEX); if (FileSystem) FileSystem->grab(); setAutomaticCulling(scene::EAC_OFF); } //! destructor CTerrainSceneNode::~CTerrainSceneNode() { delete [] TerrainData.Patches; if (FileSystem) FileSystem->drop(); if (Mesh) Mesh->drop(); if (RenderBuffer) RenderBuffer->drop(); } //! Initializes the terrain data. Loads the vertices from the heightMapFile bool CTerrainSceneNode::loadHeightMap(io::IReadFile* file, video::SColor vertexColor, s32 smoothFactor) { if (!file) return false; Mesh->MeshBuffers.clear(); const u32 startTime = os::Timer::getRealTime(); video::IImage* heightMap = SceneManager->getVideoDriver()->createImageFromFile(file); if (!heightMap) { os::Printer::log("Unable to load heightmap."); return false; } HeightmapFile = file->getFileName(); SmoothFactor = smoothFactor; // Get the dimension of the heightmap data TerrainData.Size = heightMap->getDimension().Width; switch (TerrainData.PatchSize) { case ETPS_9: if (TerrainData.MaxLOD > 3) { TerrainData.MaxLOD = 3; } break; case ETPS_17: if (TerrainData.MaxLOD > 4) { TerrainData.MaxLOD = 4; } break; case ETPS_33: if (TerrainData.MaxLOD > 5) { TerrainData.MaxLOD = 5; } break; case ETPS_65: if (TerrainData.MaxLOD > 6) { TerrainData.MaxLOD = 6; } break; case ETPS_129: if (TerrainData.MaxLOD > 7) { TerrainData.MaxLOD = 7; } break; } // --- Generate vertex data from heightmap ---- // resize the vertex array for the mesh buffer one time (makes loading faster) scene::CDynamicMeshBuffer *mb=0; const u32 numVertices = TerrainData.Size * TerrainData.Size; if (numVertices <= 65536) { //small enough for 16bit buffers mb=new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); RenderBuffer->getIndexBuffer().setType(video::EIT_16BIT); } else { //we need 32bit buffers mb=new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_32BIT); RenderBuffer->getIndexBuffer().setType(video::EIT_32BIT); } mb->getVertexBuffer().set_used(numVertices); // Read the heightmap to get the vertex data // Apply positions changes, scaling changes const f32 tdSize = 1.0f/(f32)(TerrainData.Size-1); s32 index = 0; float fx=0.f; float fx2=0.f; for (s32 x = 0; x < TerrainData.Size; ++x) { float fz=0.f; float fz2=0.f; for (s32 z = 0; z < TerrainData.Size; ++z) { video::S3DVertex2TCoords& vertex= static_cast(mb->getVertexBuffer().pointer())[index++]; vertex.Normal.set(0.0f, 1.0f, 0.0f); vertex.Color = vertexColor; vertex.Pos.X = fx; vertex.Pos.Y = (f32) heightMap->getPixel(TerrainData.Size-x-1,z).getLightness(); vertex.Pos.Z = fz; vertex.TCoords.X = vertex.TCoords2.X = 1.f-fx2; vertex.TCoords.Y = vertex.TCoords2.Y = fz2; ++fz; fz2 += tdSize; } ++fx; fx2 += tdSize; } // drop heightMap, no longer needed heightMap->drop(); smoothTerrain(mb, smoothFactor); // calculate smooth normals for the vertices calculateNormals(mb); // add the MeshBuffer to the mesh Mesh->addMeshBuffer(mb); // We copy the data to the renderBuffer, after the normals have been calculated. RenderBuffer->getVertexBuffer().set_used(numVertices); for (u32 i = 0; i < numVertices; ++i) { RenderBuffer->getVertexBuffer()[i] = mb->getVertexBuffer()[i]; RenderBuffer->getVertexBuffer()[i].Pos *= TerrainData.Scale; RenderBuffer->getVertexBuffer()[i].Pos += TerrainData.Position; } // We no longer need the mb mb->drop(); // calculate all the necessary data for the patches and the terrain calculateDistanceThresholds(); createPatches(); calculatePatchData(); // set the default rotation pivot point to the terrain nodes center TerrainData.RotationPivot = TerrainData.Center; // Rotate the vertices of the terrain by the rotation // specified. Must be done after calculating the terrain data, // so we know what the current center of the terrain is. setRotation(TerrainData.Rotation); // Pre-allocate memory for indices RenderBuffer->getIndexBuffer().set_used( TerrainData.PatchCount * TerrainData.PatchCount * TerrainData.CalcPatchSize * TerrainData.CalcPatchSize * 6); RenderBuffer->setDirty(); const u32 endTime = os::Timer::getRealTime(); c8 tmp[255]; snprintf(tmp, 255, "Generated terrain data (%dx%d) in %.4f seconds", TerrainData.Size, TerrainData.Size, (endTime - startTime) / 1000.0f ); os::Printer::log(tmp); return true; } //! Initializes the terrain data. Loads the vertices from the heightMapFile bool CTerrainSceneNode::loadHeightMapRAW(io::IReadFile* file, s32 bitsPerPixel, bool signedData, bool floatVals, s32 width, video::SColor vertexColor, s32 smoothFactor) { if (!file) return false; if (floatVals && bitsPerPixel != 32) return false; // start reading const u32 startTime = os::Timer::getTime(); Mesh->MeshBuffers.clear(); const s32 bytesPerPixel = bitsPerPixel / 8; // Get the dimension of the heightmap data const s32 filesize = file->getSize(); if (!width) TerrainData.Size = core::floor32(sqrtf((f32)(filesize / bytesPerPixel))); else { if ((filesize-file->getPos())/bytesPerPixel>width*width) { os::Printer::log("Error reading heightmap RAW file", "File is too small."); return false; } TerrainData.Size = width; } switch (TerrainData.PatchSize) { case ETPS_9: if (TerrainData.MaxLOD > 3) { TerrainData.MaxLOD = 3; } break; case ETPS_17: if (TerrainData.MaxLOD > 4) { TerrainData.MaxLOD = 4; } break; case ETPS_33: if (TerrainData.MaxLOD > 5) { TerrainData.MaxLOD = 5; } break; case ETPS_65: if (TerrainData.MaxLOD > 6) { TerrainData.MaxLOD = 6; } break; case ETPS_129: if (TerrainData.MaxLOD > 7) { TerrainData.MaxLOD = 7; } break; } // --- Generate vertex data from heightmap ---- // resize the vertex array for the mesh buffer one time (makes loading faster) scene::CDynamicMeshBuffer *mb=0; const u32 numVertices = TerrainData.Size * TerrainData.Size; if (numVertices <= 65536) { //small enough for 16bit buffers mb=new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); RenderBuffer->getIndexBuffer().setType(video::EIT_16BIT); } else { //we need 32bit buffers mb=new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_32BIT); RenderBuffer->getIndexBuffer().setType(video::EIT_32BIT); } mb->getVertexBuffer().reallocate(numVertices); video::S3DVertex2TCoords vertex; vertex.Normal.set(0.0f, 1.0f, 0.0f); vertex.Color = vertexColor; // Read the heightmap to get the vertex data // Apply positions changes, scaling changes const f32 tdSize = 1.0f/(f32)(TerrainData.Size-1); float fx=0.f; float fx2=0.f; for (s32 x = 0; x < TerrainData.Size; ++x) { float fz=0.f; float fz2=0.f; for (s32 z = 0; z < TerrainData.Size; ++z) { bool failure=false; vertex.Pos.X = fx; if (floatVals) { if (file->read(&vertex.Pos.Y, bytesPerPixel) != bytesPerPixel) failure=true; } else if (signedData) { switch (bytesPerPixel) { case 1: { s8 val; if (file->read(&val, bytesPerPixel) != bytesPerPixel) failure=true; vertex.Pos.Y=val; } break; case 2: { s16 val; if (file->read(&val, bytesPerPixel) != bytesPerPixel) failure=true; vertex.Pos.Y=val/256.f; } break; case 4: { s32 val; if (file->read(&val, bytesPerPixel) != bytesPerPixel) failure=true; vertex.Pos.Y=val/16777216.f; } break; } } else { switch (bytesPerPixel) { case 1: { u8 val; if (file->read(&val, bytesPerPixel) != bytesPerPixel) failure=true; vertex.Pos.Y=val; } break; case 2: { u16 val; if (file->read(&val, bytesPerPixel) != bytesPerPixel) failure=true; vertex.Pos.Y=val/256.f; } break; case 4: { u32 val; if (file->read(&val, bytesPerPixel) != bytesPerPixel) failure=true; vertex.Pos.Y=val/16777216.f; } break; } } if (failure) { os::Printer::log("Error reading heightmap RAW file."); mb->drop(); return false; } vertex.Pos.Z = fz; vertex.TCoords.X = vertex.TCoords2.X = 1.f-fx2; vertex.TCoords.Y = vertex.TCoords2.Y = fz2; mb->getVertexBuffer().push_back(vertex); ++fz; fz2 += tdSize; } ++fx; fx2 += tdSize; } smoothTerrain(mb, smoothFactor); // calculate smooth normals for the vertices calculateNormals(mb); // add the MeshBuffer to the mesh Mesh->addMeshBuffer(mb); const u32 vertexCount = mb->getVertexCount(); // We copy the data to the renderBuffer, after the normals have been calculated. RenderBuffer->getVertexBuffer().set_used(vertexCount); for (u32 i = 0; i < vertexCount; i++) { RenderBuffer->getVertexBuffer()[i] = mb->getVertexBuffer()[i]; RenderBuffer->getVertexBuffer()[i].Pos *= TerrainData.Scale; RenderBuffer->getVertexBuffer()[i].Pos += TerrainData.Position; } // We no longer need the mb mb->drop(); // calculate all the necessary data for the patches and the terrain calculateDistanceThresholds(); createPatches(); calculatePatchData(); // set the default rotation pivot point to the terrain nodes center TerrainData.RotationPivot = TerrainData.Center; // Rotate the vertices of the terrain by the rotation specified. Must be done // after calculating the terrain data, so we know what the current center of the // terrain is. setRotation(TerrainData.Rotation); // Pre-allocate memory for indices RenderBuffer->getIndexBuffer().set_used( TerrainData.PatchCount*TerrainData.PatchCount* TerrainData.CalcPatchSize*TerrainData.CalcPatchSize*6); const u32 endTime = os::Timer::getTime(); c8 tmp[255]; snprintf(tmp, 255, "Generated terrain data (%dx%d) in %.4f seconds", TerrainData.Size, TerrainData.Size, (endTime - startTime) / 1000.0f); os::Printer::log(tmp); return true; } //! Returns the mesh IMesh* CTerrainSceneNode::getMesh() { return Mesh; } //! Returns the material based on the zero based index i. video::SMaterial& CTerrainSceneNode::getMaterial(u32 i) { return Mesh->getMeshBuffer(i)->getMaterial(); } //! Returns amount of materials used by this scene node ( always 1 ) u32 CTerrainSceneNode::getMaterialCount() const { return Mesh->getMeshBufferCount(); } //! Sets the scale of the scene node. //! \param scale: New scale of the node void CTerrainSceneNode::setScale(const core::vector3df& scale) { TerrainData.Scale = scale; applyTransformation(); calculateNormals(RenderBuffer); ForceRecalculation = true; } //! Sets the rotation of the node. This only modifies //! the relative rotation of the node. //! \param rotation: New rotation of the node in degrees. void CTerrainSceneNode::setRotation(const core::vector3df& rotation) { TerrainData.Rotation = rotation; applyTransformation(); ForceRecalculation = true; } //! Sets the pivot point for rotation of this node. This is useful for the TiledTerrainManager to //! rotate all terrain tiles around a global world point. //! NOTE: The default for the RotationPivot will be the center of the individual tile. void CTerrainSceneNode::setRotationPivot(const core::vector3df& pivot) { UseDefaultRotationPivot = false; TerrainData.RotationPivot = pivot; } //! Sets the position of the node. //! \param newpos: New postition of the scene node. void CTerrainSceneNode::setPosition(const core::vector3df& newpos) { TerrainData.Position = newpos; applyTransformation(); ForceRecalculation = true; } //! Apply transformation changes(scale, position, rotation) void CTerrainSceneNode::applyTransformation() { if (!Mesh->getMeshBufferCount()) return; core::matrix4 rotMatrix; rotMatrix.setRotationDegrees(TerrainData.Rotation); const s32 vtxCount = Mesh->getMeshBuffer(0)->getVertexCount(); for (s32 i = 0; i < vtxCount; ++i) { RenderBuffer->getVertexBuffer()[i].Pos = Mesh->getMeshBuffer(0)->getPosition(i) * TerrainData.Scale + TerrainData.Position; RenderBuffer->getVertexBuffer()[i].Pos -= TerrainData.RotationPivot; rotMatrix.inverseRotateVect(RenderBuffer->getVertexBuffer()[i].Pos); RenderBuffer->getVertexBuffer()[i].Pos += TerrainData.RotationPivot; } calculateDistanceThresholds(true); calculatePatchData(); RenderBuffer->setDirty(EBT_VERTEX); } //! Updates the scene nodes indices if the camera has moved or rotated by a certain //! threshold, which can be changed using the SetCameraMovementDeltaThreshold and //! SetCameraRotationDeltaThreshold functions. This also determines if a given patch //! for the scene node is within the view frustum and if it's not the indices are not //! generated for that patch. void CTerrainSceneNode::OnRegisterSceneNode() { if (!IsVisible || !SceneManager->getActiveCamera()) return; SceneManager->registerNodeForRendering(this); preRenderCalculationsIfNeeded(); // Do Not call ISceneNode::OnRegisterSceneNode(), this node should have no children (luke: is this comment still true, as ISceneNode::OnRegisterSceneNode() is called?) ISceneNode::OnRegisterSceneNode(); ForceRecalculation = false; } void CTerrainSceneNode::preRenderCalculationsIfNeeded() { scene::ICameraSceneNode * camera = SceneManager->getActiveCamera(); if (!camera) return; // Determine the camera rotation, based on the camera direction. const core::vector3df cameraPosition = camera->getAbsolutePosition(); const core::vector3df cameraRotation = core::line3d(cameraPosition, camera->getTarget()).getVector().getHorizontalAngle(); core::vector3df cameraUp = camera->getUpVector(); cameraUp.normalize(); const f32 CameraFOV = SceneManager->getActiveCamera()->getFOV(); // Only check on the Camera's Y Rotation if (!ForceRecalculation) { if ((fabsf(cameraRotation.X - OldCameraRotation.X) < CameraRotationDelta) && (fabsf(cameraRotation.Y - OldCameraRotation.Y) < CameraRotationDelta)) { if ((fabs(cameraPosition.X - OldCameraPosition.X) < CameraMovementDelta) && (fabs(cameraPosition.Y - OldCameraPosition.Y) < CameraMovementDelta) && (fabs(cameraPosition.Z - OldCameraPosition.Z) < CameraMovementDelta)) { if (fabs(CameraFOV-OldCameraFOV) < CameraFOVDelta && cameraUp.dotProduct(OldCameraUp) > (1.f - (cos(core::DEGTORAD * CameraRotationDelta)))) { return; } } } } //we need to redo calculations... OldCameraPosition = cameraPosition; OldCameraRotation = cameraRotation; OldCameraUp = cameraUp; OldCameraFOV = CameraFOV; preRenderLODCalculations(); preRenderIndicesCalculations(); } void CTerrainSceneNode::preRenderLODCalculations() { scene::ICameraSceneNode * camera = SceneManager->getActiveCamera(); if (!camera) return; const core::vector3df cameraPosition = camera->getAbsolutePosition(); const SViewFrustum* frustum = camera->getViewFrustum(); // Determine each patches LOD based on distance from camera (and whether or not they are in // the view frustum). const s32 count = TerrainData.PatchCount * TerrainData.PatchCount; for (s32 j = 0; j < count; ++j) { if (frustum->getBoundingBox().intersectsWithBox(TerrainData.Patches[j].BoundingBox)) { const f32 distance = cameraPosition.getDistanceFromSQ(TerrainData.Patches[j].Center); TerrainData.Patches[j].CurrentLOD = 0; for (s32 i = TerrainData.MaxLOD - 1; i>0; --i) { if (distance >= TerrainData.LODDistanceThreshold[i]) { TerrainData.Patches[j].CurrentLOD = i; break; } } } else { TerrainData.Patches[j].CurrentLOD = -1; } } } void CTerrainSceneNode::preRenderIndicesCalculations() { scene::IIndexBuffer& indexBuffer = RenderBuffer->getIndexBuffer(); IndicesToRender = 0; indexBuffer.set_used(0); s32 index = 0; // Then generate the indices for all patches that are visible. for (s32 i = 0; i < TerrainData.PatchCount; ++i) { for (s32 j = 0; j < TerrainData.PatchCount; ++j) { if (TerrainData.Patches[index].CurrentLOD >= 0) { s32 x = 0; s32 z = 0; // calculate the step we take this patch, based on the patches current LOD const s32 step = 1 << TerrainData.Patches[index].CurrentLOD; // Loop through patch and generate indices while (z < TerrainData.CalcPatchSize) { const s32 index11 = getIndex(j, i, index, x, z); const s32 index21 = getIndex(j, i, index, x + step, z); const s32 index12 = getIndex(j, i, index, x, z + step); const s32 index22 = getIndex(j, i, index, x + step, z + step); indexBuffer.push_back(index12); indexBuffer.push_back(index11); indexBuffer.push_back(index22); indexBuffer.push_back(index22); indexBuffer.push_back(index11); indexBuffer.push_back(index21); IndicesToRender+=6; // increment index position horizontally x += step; // we've hit an edge if (x >= TerrainData.CalcPatchSize) { x = 0; z += step; } } } ++index; } } RenderBuffer->setDirty(EBT_INDEX); if (DynamicSelectorUpdate && TriangleSelector) { CTerrainTriangleSelector* selector = (CTerrainTriangleSelector*)TriangleSelector; selector->setTriangleData(this, -1); } } //! Render the scene node void CTerrainSceneNode::render() { if (!IsVisible || !SceneManager->getActiveCamera()) return; if (!Mesh->getMeshBufferCount()) return; video::IVideoDriver* driver = SceneManager->getVideoDriver(); driver->setTransform (video::ETS_WORLD, core::IdentityMatrix); driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial()); RenderBuffer->getIndexBuffer().set_used(IndicesToRender); // For use with geomorphing driver->drawMeshBuffer(RenderBuffer); RenderBuffer->getIndexBuffer().set_used(RenderBuffer->getIndexBuffer().allocated_size()); // for debug purposes only: if (DebugDataVisible) { video::SMaterial m; m.Lighting = false; driver->setMaterial(m); if (DebugDataVisible & scene::EDS_BBOX) driver->draw3DBox(TerrainData.BoundingBox, video::SColor(255,255,255,255)); const s32 count = TerrainData.PatchCount * TerrainData.PatchCount; s32 visible = 0; if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) { for (s32 j = 0; j < count; ++j) { driver->draw3DBox(TerrainData.Patches[j].BoundingBox, video::SColor(255,255,0,0)); visible += (TerrainData.Patches[j].CurrentLOD >= 0); } } if (DebugDataVisible & scene::EDS_NORMALS) { // draw normals const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); driver->drawMeshBufferNormals(RenderBuffer, debugNormalLength, debugNormalColor); } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); static u32 lastTime = 0; const u32 now = os::Timer::getRealTime(); if (now - lastTime > 1000) { char buf[64]; snprintf(buf, 64, "Count: %d, Visible: %d", count, visible); os::Printer::log(buf); lastTime = now; } } } //! Return the bounding box of the entire terrain. const core::aabbox3d& CTerrainSceneNode::getBoundingBox() const { return TerrainData.BoundingBox; } //! Return the bounding box of a patch const core::aabbox3d& CTerrainSceneNode::getBoundingBox(s32 patchX, s32 patchZ) const { return TerrainData.Patches[patchX * TerrainData.PatchCount + patchZ].BoundingBox; } //! Gets the meshbuffer data based on a specified Level of Detail. //! \param mb: A reference to an SMeshBuffer object //! \param LOD: The Level Of Detail you want the indices from. void CTerrainSceneNode::getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD ) const { if (!Mesh->getMeshBufferCount()) return; LOD = core::clamp(LOD, 0, TerrainData.MaxLOD - 1); const u32 numVertices = Mesh->getMeshBuffer(0)->getVertexCount(); mb.getVertexBuffer().reallocate(numVertices); video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)Mesh->getMeshBuffer(0)->getVertices(); for (u32 n=0; ngetIndexBuffer().getType()); // calculate the step we take for all patches, since LOD is the same const s32 step = 1 << LOD; // Generate the indices for all patches at the specified LOD s32 index = 0; for (s32 i=0; i= TerrainData.CalcPatchSize) // we've hit an edge { x = 0; z += step; } } ++index; } } } //! Gets the indices for a specified patch at a specified Level of Detail. //! \param mb: A reference to an array of u32 indices. //! \param patchX: Patch x coordinate. //! \param patchZ: Patch z coordinate. //! \param LOD: The level of detail to get for that patch. If -1, then get //! the CurrentLOD. If the CurrentLOD is set to -1, meaning it's not shown, //! then it will retrieve the triangles at the highest LOD (0). //! \return: Number if indices put into the buffer. s32 CTerrainSceneNode::getIndicesForPatch(core::array& indices, s32 patchX, s32 patchZ, s32 LOD) { if (patchX < 0 || patchX > TerrainData.PatchCount-1 || patchZ < 0 || patchZ > TerrainData.PatchCount-1) return -1; if (LOD < -1 || LOD > TerrainData.MaxLOD - 1) return -1; core::array cLODs; bool setLODs = false; // If LOD of -1 was passed in, use the CurrentLOD of the patch specified if (LOD == -1) { LOD = TerrainData.Patches[patchX * TerrainData.PatchCount + patchZ].CurrentLOD; } else { getCurrentLODOfPatches(cLODs); setCurrentLODOfPatches(LOD); setLODs = true; } if (LOD < 0) return -2; // Patch not visible, don't generate indices. // calculate the step we take for this LOD const s32 step = 1 << LOD; // Generate the indices for the specified patch at the specified LOD const s32 index = patchX * TerrainData.PatchCount + patchZ; s32 x = 0; s32 z = 0; indices.set_used(TerrainData.PatchSize * TerrainData.PatchSize * 6); // Loop through patch and generate indices s32 rv=0; while (z= TerrainData.CalcPatchSize) // we've hit an edge { x = 0; z += step; } } if (setLODs) setCurrentLODOfPatches(cLODs); return rv; } //! Populates an array with the CurrentLOD of each patch. //! \param LODs: A reference to a core::array to hold the values //! \return Returns the number of elements in the array s32 CTerrainSceneNode::getCurrentLODOfPatches(core::array& LODs) const { s32 numLODs; LODs.clear(); const s32 count = TerrainData.PatchCount * TerrainData.PatchCount; for (numLODs = 0; numLODs < count; numLODs++) LODs.push_back(TerrainData.Patches[numLODs].CurrentLOD); return LODs.size(); } //! Manually sets the LOD of a patch //! \param patchX: Patch x coordinate. //! \param patchZ: Patch z coordinate. //! \param LOD: The level of detail to set the patch to. void CTerrainSceneNode::setLODOfPatch(s32 patchX, s32 patchZ, s32 LOD) { TerrainData.Patches[patchX * TerrainData.PatchCount + patchZ].CurrentLOD = LOD; } //! Override the default generation of distance thresholds for determining the LOD a patch //! is rendered at. bool CTerrainSceneNode::overrideLODDistance(s32 LOD, f64 newDistance) { OverrideDistanceThreshold = true; if (LOD < 0 || LOD > TerrainData.MaxLOD - 1) return false; TerrainData.LODDistanceThreshold[LOD] = newDistance * newDistance; return true; } //! Creates a planar texture mapping on the terrain //! \param resolution: resolution of the planar mapping. This is the value //! specifying the relation between world space and texture coordinate space. void CTerrainSceneNode::scaleTexture(f32 resolution, f32 resolution2) { TCoordScale1 = resolution; TCoordScale2 = resolution2; const f32 resBySize = resolution / (f32)(TerrainData.Size-1); const f32 res2BySize = resolution2 / (f32)(TerrainData.Size-1); u32 index = 0; f32 xval = 0.f; f32 x2val = 0.f; for (s32 x=0; xgetVertexBuffer()[index].TCoords.X = 1.f-xval; RenderBuffer->getVertexBuffer()[index].TCoords.Y = zval; if (RenderBuffer->getVertexType()==video::EVT_2TCOORDS) { if (resolution2 == 0) { ((video::S3DVertex2TCoords&)RenderBuffer->getVertexBuffer()[index]).TCoords2 = RenderBuffer->getVertexBuffer()[index].TCoords; } else { ((video::S3DVertex2TCoords&)RenderBuffer->getVertexBuffer()[index]).TCoords2.X = 1.f-x2val; ((video::S3DVertex2TCoords&)RenderBuffer->getVertexBuffer()[index]).TCoords2.Y = z2val; } } ++index; zval += resBySize; z2val += res2BySize; } xval += resBySize; x2val += res2BySize; } RenderBuffer->setDirty(EBT_VERTEX); } //! used to get the indices when generating index data for patches at varying levels of detail. u32 CTerrainSceneNode::getIndex(const s32 PatchX, const s32 PatchZ, const s32 PatchIndex, u32 vX, u32 vZ) const { // top border if (vZ == 0) { if (TerrainData.Patches[PatchIndex].Top && TerrainData.Patches[PatchIndex].CurrentLOD < TerrainData.Patches[PatchIndex].Top->CurrentLOD && (vX % (1 << TerrainData.Patches[PatchIndex].Top->CurrentLOD)) != 0 ) { vX -= vX % (1 << TerrainData.Patches[PatchIndex].Top->CurrentLOD); } } else if (vZ == (u32)TerrainData.CalcPatchSize) // bottom border { if (TerrainData.Patches[PatchIndex].Bottom && TerrainData.Patches[PatchIndex].CurrentLOD < TerrainData.Patches[PatchIndex].Bottom->CurrentLOD && (vX % (1 << TerrainData.Patches[PatchIndex].Bottom->CurrentLOD)) != 0) { vX -= vX % (1 << TerrainData.Patches[PatchIndex].Bottom->CurrentLOD); } } // left border if (vX == 0) { if (TerrainData.Patches[PatchIndex].Left && TerrainData.Patches[PatchIndex].CurrentLOD < TerrainData.Patches[PatchIndex].Left->CurrentLOD && (vZ % (1 << TerrainData.Patches[PatchIndex].Left->CurrentLOD)) != 0) { vZ -= vZ % (1 << TerrainData.Patches[PatchIndex].Left->CurrentLOD); } } else if (vX == (u32)TerrainData.CalcPatchSize) // right border { if (TerrainData.Patches[PatchIndex].Right && TerrainData.Patches[PatchIndex].CurrentLOD < TerrainData.Patches[PatchIndex].Right->CurrentLOD && (vZ % (1 << TerrainData.Patches[PatchIndex].Right->CurrentLOD)) != 0) { vZ -= vZ % (1 << TerrainData.Patches[PatchIndex].Right->CurrentLOD); } } if (vZ >= (u32)TerrainData.PatchSize) vZ = TerrainData.CalcPatchSize; if (vX >= (u32)TerrainData.PatchSize) vX = TerrainData.CalcPatchSize; return (vZ + ((TerrainData.CalcPatchSize) * PatchZ)) * TerrainData.Size + (vX + ((TerrainData.CalcPatchSize) * PatchX)); } //! smooth the terrain void CTerrainSceneNode::smoothTerrain(IDynamicMeshBuffer* mb, s32 smoothFactor) { for (s32 run = 0; run < smoothFactor; ++run) { s32 yd = TerrainData.Size; for (s32 y = 1; y < TerrainData.Size - 1; ++y) { for (s32 x = 1; x < TerrainData.Size - 1; ++x) { mb->getVertexBuffer()[x + yd].Pos.Y = (mb->getVertexBuffer()[x-1 + yd].Pos.Y + //left mb->getVertexBuffer()[x+1 + yd].Pos.Y + //right mb->getVertexBuffer()[x + yd - TerrainData.Size].Pos.Y + //above mb->getVertexBuffer()[x + yd + TerrainData.Size].Pos.Y) * 0.25f; //below } yd += TerrainData.Size; } } } //! calculate smooth normals void CTerrainSceneNode::calculateNormals(IDynamicMeshBuffer* mb) { s32 count; core::vector3df a, b, c, t; for (s32 x=0; x0 && z>0) { a = mb->getVertexBuffer()[(x-1)*TerrainData.Size+z-1].Pos; b = mb->getVertexBuffer()[(x-1)*TerrainData.Size+z].Pos; c = mb->getVertexBuffer()[x*TerrainData.Size+z].Pos; b -= a; c -= a; t = b.crossProduct(c); t.normalize(); normal += t; a = mb->getVertexBuffer()[(x-1)*TerrainData.Size+z-1].Pos; b = mb->getVertexBuffer()[x*TerrainData.Size+z-1].Pos; c = mb->getVertexBuffer()[x*TerrainData.Size+z].Pos; b -= a; c -= a; t = b.crossProduct(c); t.normalize(); normal += t; count += 2; } // top right if (x>0 && zgetVertexBuffer()[(x-1)*TerrainData.Size+z].Pos; b = mb->getVertexBuffer()[(x-1)*TerrainData.Size+z+1].Pos; c = mb->getVertexBuffer()[x*TerrainData.Size+z+1].Pos; b -= a; c -= a; t = b.crossProduct(c); t.normalize(); normal += t; a = mb->getVertexBuffer()[(x-1)*TerrainData.Size+z].Pos; b = mb->getVertexBuffer()[x*TerrainData.Size+z+1].Pos; c = mb->getVertexBuffer()[x*TerrainData.Size+z].Pos; b -= a; c -= a; t = b.crossProduct(c); t.normalize(); normal += t; count += 2; } // bottom right if (xgetVertexBuffer()[x*TerrainData.Size+z+1].Pos; b = mb->getVertexBuffer()[x*TerrainData.Size+z].Pos; c = mb->getVertexBuffer()[(x+1)*TerrainData.Size+z+1].Pos; b -= a; c -= a; t = b.crossProduct(c); t.normalize(); normal += t; a = mb->getVertexBuffer()[x*TerrainData.Size+z+1].Pos; b = mb->getVertexBuffer()[(x+1)*TerrainData.Size+z+1].Pos; c = mb->getVertexBuffer()[(x+1)*TerrainData.Size+z].Pos; b -= a; c -= a; t = b.crossProduct(c); t.normalize(); normal += t; count += 2; } // bottom left if (x0) { a = mb->getVertexBuffer()[x*TerrainData.Size+z-1].Pos; b = mb->getVertexBuffer()[x*TerrainData.Size+z].Pos; c = mb->getVertexBuffer()[(x+1)*TerrainData.Size+z].Pos; b -= a; c -= a; t = b.crossProduct(c); t.normalize(); normal += t; a = mb->getVertexBuffer()[x*TerrainData.Size+z-1].Pos; b = mb->getVertexBuffer()[(x+1)*TerrainData.Size+z].Pos; c = mb->getVertexBuffer()[(x+1)*TerrainData.Size+z-1].Pos; b -= a; c -= a; t = b.crossProduct(c); t.normalize(); normal += t; count += 2; } if (count != 0) { normal.normalize(); } else { normal.set(0.0f, 1.0f, 0.0f); } mb->getVertexBuffer()[x * TerrainData.Size + z].Normal = normal; } } } //! create patches, stuff that needs to be done only once for patches goes here. void CTerrainSceneNode::createPatches() { TerrainData.PatchCount = (TerrainData.Size - 1) / (TerrainData.CalcPatchSize); if (TerrainData.Patches) delete [] TerrainData.Patches; TerrainData.Patches = new SPatch[TerrainData.PatchCount * TerrainData.PatchCount]; } //! used to calculate the internal STerrainData structure both at creation and after scaling/position calls. void CTerrainSceneNode::calculatePatchData() { // Reset the Terrains Bounding Box for re-calculation TerrainData.BoundingBox.reset(RenderBuffer->getPosition(0)); for (s32 x = 0; x < TerrainData.PatchCount; ++x) { for (s32 z = 0; z < TerrainData.PatchCount; ++z) { const s32 index = x * TerrainData.PatchCount + z; SPatch& patch = TerrainData.Patches[index]; patch.CurrentLOD = 0; const s32 xstart = x*TerrainData.CalcPatchSize; const s32 xend = xstart+TerrainData.CalcPatchSize; const s32 zstart = z*TerrainData.CalcPatchSize; const s32 zend = zstart+TerrainData.CalcPatchSize; // For each patch, calculate the bounding box (mins and maxes) patch.BoundingBox.reset(RenderBuffer->getPosition(xstart*TerrainData.Size + zstart)); for (s32 xx = xstart; xx <= xend; ++xx) for (s32 zz = zstart; zz <= zend; ++zz) patch.BoundingBox.addInternalPoint(RenderBuffer->getVertexBuffer()[xx * TerrainData.Size + zz].Pos); // Reconfigure the bounding box of the terrain as a whole TerrainData.BoundingBox.addInternalBox(patch.BoundingBox); // get center of Patch patch.Center = patch.BoundingBox.getCenter(); // Assign Neighbours // Top if (x > 0) patch.Top = &TerrainData.Patches[(x-1) * TerrainData.PatchCount + z]; else patch.Top = 0; // Bottom if (x < TerrainData.PatchCount - 1) patch.Bottom = &TerrainData.Patches[(x+1) * TerrainData.PatchCount + z]; else patch.Bottom = 0; // Left if (z > 0) patch.Left = &TerrainData.Patches[x * TerrainData.PatchCount + z - 1]; else patch.Left = 0; // Right if (z < TerrainData.PatchCount - 1) patch.Right = &TerrainData.Patches[x * TerrainData.PatchCount + z + 1]; else patch.Right = 0; } } // get center of Terrain TerrainData.Center = TerrainData.BoundingBox.getCenter(); // if the default rotation pivot is still being used, update it. if (UseDefaultRotationPivot) { TerrainData.RotationPivot = TerrainData.Center; } } //! used to calculate or recalculate the distance thresholds void CTerrainSceneNode::calculateDistanceThresholds(bool scalechanged) { // Only update the LODDistanceThreshold if it's not manually changed if (!OverrideDistanceThreshold) { TerrainData.LODDistanceThreshold.set_used(0); // Determine new distance threshold for determining what LOD to draw patches at TerrainData.LODDistanceThreshold.reallocate(TerrainData.MaxLOD); const f64 size = TerrainData.PatchSize * TerrainData.PatchSize * TerrainData.Scale.X * TerrainData.Scale.Z; for (s32 i=0; i& lodarray) { const s32 count = TerrainData.PatchCount * TerrainData.PatchCount; for (s32 i=0; igetMeshBufferCount()) return 0; core::matrix4 rotMatrix; rotMatrix.setRotationDegrees(TerrainData.Rotation); core::vector3df pos(x, 0.0f, z); rotMatrix.rotateVect(pos); pos -= TerrainData.Position; pos /= TerrainData.Scale; s32 X(core::floor32(pos.X)); s32 Z(core::floor32(pos.Z)); f32 height = -FLT_MAX; if (X >= 0 && X < TerrainData.Size-1 && Z >= 0 && Z < TerrainData.Size-1) { const video::S3DVertex2TCoords* Vertices = (const video::S3DVertex2TCoords*)Mesh->getMeshBuffer(0)->getVertices(); const core::vector3df& a = Vertices[X * TerrainData.Size + Z].Pos; const core::vector3df& b = Vertices[(X + 1) * TerrainData.Size + Z].Pos; const core::vector3df& c = Vertices[X * TerrainData.Size + (Z + 1)].Pos; const core::vector3df& d = Vertices[(X + 1) * TerrainData.Size + (Z + 1)].Pos; // offset from integer position const f32 dx = pos.X - X; const f32 dz = pos.Z - Z; if (dx > dz) height = a.Y + (d.Y - b.Y)*dz + (b.Y - a.Y)*dx; else height = a.Y + (d.Y - c.Y)*dx + (c.Y - a.Y)*dz; height *= TerrainData.Scale.Y; height += TerrainData.Position.Y; } return height; } //! Writes attributes of the scene node. void CTerrainSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { ISceneNode::serializeAttributes(out, options); out->addString("Heightmap", HeightmapFile.c_str()); out->addFloat("TextureScale1", TCoordScale1); out->addFloat("TextureScale2", TCoordScale2); out->addInt("SmoothFactor", SmoothFactor); } //! Reads attributes of the scene node. void CTerrainSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { io::path newHeightmap = in->getAttributeAsString("Heightmap"); f32 tcoordScale1 = in->getAttributeAsFloat("TextureScale1"); f32 tcoordScale2 = in->getAttributeAsFloat("TextureScale2"); s32 smoothFactor = in->getAttributeAsInt("SmoothFactor"); // set possible new heightmap if (newHeightmap.size() != 0 && newHeightmap != HeightmapFile) { io::IReadFile* file = FileSystem->createAndOpenFile(newHeightmap.c_str()); if (file) { loadHeightMap(file, video::SColor(255,255,255,255), smoothFactor); file->drop(); } else os::Printer::log("could not open heightmap", newHeightmap.c_str()); } // set possible new scale if (core::equals(tcoordScale1, 0.f)) tcoordScale1 = 1.0f; if (core::equals(tcoordScale2, 0.f)) tcoordScale2 = 1.0f; if (!core::equals(tcoordScale1, TCoordScale1) || !core::equals(tcoordScale2, TCoordScale2)) { scaleTexture(tcoordScale1, tcoordScale2); } ISceneNode::deserializeAttributes(in, options); } //! Creates a clone of this scene node and its children. ISceneNode* CTerrainSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CTerrainSceneNode* nb = new CTerrainSceneNode( newParent, newManager, FileSystem, ID, 4, ETPS_17, getPosition(), getRotation(), getScale()); nb->cloneMembers(this, newManager); // instead of cloning the data structures, recreate the terrain. // (temporary solution) // load file io::IReadFile* file = FileSystem->createAndOpenFile(HeightmapFile.c_str()); if (file) { nb->loadHeightMap(file, video::SColor(255,255,255,255), 0); file->drop(); } // scale textures nb->scaleTexture(TCoordScale1, TCoordScale2); // copy materials for (unsigned int m = 0; mgetMeshBufferCount(); ++m) { if (nb->Mesh->getMeshBufferCount()>m && nb->Mesh->getMeshBuffer(m) && Mesh->getMeshBuffer(m)) { nb->Mesh->getMeshBuffer(m)->getMaterial() = Mesh->getMeshBuffer(m)->getMaterial(); } } nb->RenderBuffer->getMaterial() = RenderBuffer->getMaterial(); // finish if ( newParent ) nb->drop(); return nb; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CTarReader.h0000644000000000000000000000700612574354552017265 0ustar rootroot// Copyright (C) 2009-2012 Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_TAR_READER_H_INCLUDED__ #define __C_TAR_READER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ #include "IReferenceCounted.h" #include "IReadFile.h" #include "irrArray.h" #include "irrString.h" #include "IFileSystem.h" #include "CFileList.h" namespace irr { namespace io { enum E_TAR_LINK_INDICATOR { ETLI_REGULAR_FILE_OLD = 0 , ETLI_REGULAR_FILE = '0', ETLI_LINK_TO_ARCHIVED_FILE = '1', // Hard link ETLI_SYMBOLIC_LINK = '2', ETLI_CHAR_SPECIAL_DEVICE = '3', ETLI_BLOCK_SPECIAL_DEVICE = '4', ETLI_DIRECTORY = '5', ETLI_FIFO_SPECIAL_FILE = '6', ETLI_CONTIGUOUS_FILE = '7' }; // byte-align structures #include "irrpack.h" struct STarHeader { c8 FileName[100]; c8 FileMode[8]; c8 UserID[8]; c8 GroupID[8]; c8 Size[12]; c8 ModifiedTime[12]; c8 Checksum[8]; c8 Link; c8 LinkName[100]; c8 Magic[6]; c8 USTARVersion[2]; c8 UserName[32]; c8 GroupName[32]; c8 DeviceMajor[8]; c8 DeviceMinor[8]; c8 FileNamePrefix[155]; } PACK_STRUCT; // Default alignment #include "irrunpack.h" //! Archiveloader capable of loading ZIP Archives class CArchiveLoaderTAR : public IArchiveLoader { public: //! Constructor CArchiveLoaderTAR(io::IFileSystem* fs); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tar") virtual bool isALoadableFileFormat(const io::path& filename) const; //! Check if the file might be loaded by this class /** Check might look into the file. \param file File handle to check. \return True if file seems to be loadable. */ virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! Check to see if the loader can create archives of this type. /** Check based on the archive type. \param fileType The archive type to check. \return True if the archile loader supports this type, false if not */ virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const; //! Creates an archive from the filename /** \param file File handle to check. \return Pointer to newly created archive, or 0 upon error. */ virtual IFileArchive* createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const; //! creates/loads an archive from the file. //! \return Pointer to the created archive. Returns 0 if loading failed. virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; private: io::IFileSystem* FileSystem; }; class CTarReader : public virtual IFileArchive, virtual CFileList { public: CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths); virtual ~CTarReader(); //! opens a file by file name virtual IReadFile* createAndOpenFile(const io::path& filename); //! opens a file by index virtual IReadFile* createAndOpenFile(u32 index); //! returns the list of files virtual const IFileList* getFileList() const; //! get the class Type virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_TAR; } private: u32 populateFileList(); IReadFile* File; }; } // end namespace io } // end namespace irr #endif // __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ #endif // __C_TAR_READER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CTarReader.cpp0000644000000000000000000001333712574354552017624 0ustar rootroot// Copyright (C) 2009-2012 Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CTarReader.h" #ifdef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ #include "CFileList.h" #include "CLimitReadFile.h" #include "os.h" #include "coreutil.h" #if !defined(_IRR_WINDOWS_CE_PLATFORM_) #include "errno.h" #endif namespace irr { namespace io { //! Constructor CArchiveLoaderTAR::CArchiveLoaderTAR(io::IFileSystem* fs) : FileSystem(fs) { #ifdef _DEBUG setDebugName("CArchiveLoaderTAR"); #endif } //! returns true if the file maybe is able to be loaded by this class bool CArchiveLoaderTAR::isALoadableFileFormat(const io::path& filename) const { return core::hasFileExtension(filename, "tar"); } //! Check to see if the loader can create archives of this type. bool CArchiveLoaderTAR::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const { return fileType == EFAT_TAR; } //! Creates an archive from the filename /** \param file File handle to check. \return Pointer to newly created archive, or 0 upon error. */ IFileArchive* CArchiveLoaderTAR::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const { IFileArchive *archive = 0; io::IReadFile* file = FileSystem->createAndOpenFile(filename); if (file) { archive = createArchive(file, ignoreCase, ignorePaths); file->drop(); } return archive; } //! creates/loads an archive from the file. //! \return Pointer to the created archive. Returns 0 if loading failed. IFileArchive* CArchiveLoaderTAR::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const { IFileArchive *archive = 0; if (file) { file->seek(0); archive = new CTarReader(file, ignoreCase, ignorePaths); } return archive; } //! Check if the file might be loaded by this class /** Check might look into the file. \param file File handle to check. \return True if file seems to be loadable. */ bool CArchiveLoaderTAR::isALoadableFileFormat(io::IReadFile* file) const { // TAR files consist of blocks of 512 bytes // if it isn't a multiple of 512 then it's not a TAR file. if (file->getSize() % 512) return false; file->seek(0); // read header of first file STarHeader fHead; file->read(&fHead, sizeof(STarHeader)); u32 checksum = 0; sscanf(fHead.Checksum, "%o", &checksum); // verify checksum // some old TAR writers assume that chars are signed, others assume unsigned // USTAR archives have a longer header, old TAR archives end after linkname u32 checksum1=0; s32 checksum2=0; // remember to blank the checksum field! memset(fHead.Checksum, ' ', 8); // old header for (u8* p = (u8*)(&fHead); p < (u8*)(&fHead.Magic[0]); ++p) { checksum1 += *p; checksum2 += c8(*p); } if (!strncmp(fHead.Magic, "ustar", 5)) { for (u8* p = (u8*)(&fHead.Magic[0]); p < (u8*)(&fHead) + sizeof(fHead); ++p) { checksum1 += *p; checksum2 += c8(*p); } } return checksum1 == checksum || checksum2 == (s32)checksum; } /* TAR Archive */ CTarReader::CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths) : CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file) { #ifdef _DEBUG setDebugName("CTarReader"); #endif if (File) { File->grab(); // fill the file list populateFileList(); sort(); } } CTarReader::~CTarReader() { if (File) File->drop(); } const IFileList* CTarReader::getFileList() const { return this; } u32 CTarReader::populateFileList() { STarHeader fHead; Files.clear(); u32 pos = 0; while ( s32(pos + sizeof(STarHeader)) < File->getSize()) { // seek to next file header File->seek(pos); // read the header File->read(&fHead, sizeof(fHead)); // only add standard files for now if (fHead.Link == ETLI_REGULAR_FILE || ETLI_REGULAR_FILE_OLD) { io::path fullPath = ""; fullPath.reserve(255); // USTAR archives have a filename prefix // may not be null terminated, copy carefully! if (!strncmp(fHead.Magic, "ustar", 5)) { c8* np = fHead.FileNamePrefix; while(*np && (np - fHead.FileNamePrefix) < 155) fullPath.append(*np); np++; } // append the file name c8* np = fHead.FileName; while(*np && (np - fHead.FileName) < 100) { fullPath.append(*np); np++; } // get size core::stringc sSize = ""; sSize.reserve(12); np = fHead.Size; while(*np && (np - fHead.Size) < 12) { sSize.append(*np); np++; } u32 size = strtoul(sSize.c_str(), NULL, 8); #if !defined(_IRR_WINDOWS_CE_PLATFORM_) if (errno == ERANGE) os::Printer::log("File too large", fullPath, ELL_WARNING); #endif // save start position u32 offset = pos + 512; // move to next file header block pos = offset + (size / 512) * 512 + ((size % 512) ? 512 : 0); // add file to list addItem(fullPath, offset, size, false ); } else { // todo: ETLI_DIRECTORY, ETLI_LINK_TO_ARCHIVED_FILE // move to next block pos += 512; } } return Files.size(); } //! opens a file by file name IReadFile* CTarReader::createAndOpenFile(const io::path& filename) { const s32 index = findFile(filename, false); if (index != -1) return createAndOpenFile(index); return 0; } //! opens a file by index IReadFile* CTarReader::createAndOpenFile(u32 index) { if (index >= Files.size() ) return 0; const SFileListEntry &entry = Files[index]; return createLimitReadFile( entry.FullName, File, entry.Offset, entry.Size ); } } // end namespace io } // end namespace irr #endif // __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ irrlicht-1.8.3/source/Irrlicht/CSTLMeshWriter.h0000644000000000000000000000265312574354552020073 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_STL_MESH_WRITER_H_INCLUDED__ #define __IRR_STL_MESH_WRITER_H_INCLUDED__ #include "IMeshWriter.h" #include "S3DVertex.h" #include "irrString.h" namespace irr { namespace scene { class IMeshBuffer; class ISceneManager; //! class to write meshes, implementing a STL writer class CSTLMeshWriter : public IMeshWriter { public: CSTLMeshWriter(scene::ISceneManager* smgr); virtual ~CSTLMeshWriter(); //! Returns the type of the mesh writer virtual EMESH_WRITER_TYPE getType() const; //! writes a mesh virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE); protected: // write binary format bool writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s32 flags); // write text format bool writeMeshASCII(io::IWriteFile* file, scene::IMesh* mesh, s32 flags); // create vector output with line end into string void getVectorAsStringLine(const core::vector3df& v, core::stringc& s) const; // write face information to file void writeFace(io::IWriteFile* file, const core::vector3df& v1, const core::vector3df& v2, const core::vector3df& v3); scene::ISceneManager* SceneManager; }; } // end namespace } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/CSTLMeshWriter.cpp0000644000000000000000000001063512574354552020425 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_STL_WRITER_ #include "CSTLMeshWriter.h" #include "os.h" #include "IMesh.h" #include "IMeshBuffer.h" #include "IAttributes.h" #include "ISceneManager.h" #include "IMeshCache.h" #include "IWriteFile.h" namespace irr { namespace scene { CSTLMeshWriter::CSTLMeshWriter(scene::ISceneManager* smgr) : SceneManager(smgr) { #ifdef _DEBUG setDebugName("CSTLMeshWriter"); #endif if (SceneManager) SceneManager->grab(); } CSTLMeshWriter::~CSTLMeshWriter() { if (SceneManager) SceneManager->drop(); } //! Returns the type of the mesh writer EMESH_WRITER_TYPE CSTLMeshWriter::getType() const { return EMWT_STL; } //! writes a mesh bool CSTLMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { if (!file) return false; os::Printer::log("Writing mesh", file->getFileName()); if (flags & scene::EMWF_WRITE_COMPRESSED) return writeMeshBinary(file, mesh, flags); else return writeMeshASCII(file, mesh, flags); } bool CSTLMeshWriter::writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { // write STL MESH header file->write("binary ",7); const core::stringc name(SceneManager->getMeshCache()->getMeshName(mesh)); const s32 sizeleft = 73-name.size(); // 80 byte header if (sizeleft<0) file->write(name.c_str(),73); else { char* buf = new char[80]; memset(buf, 0, 80); file->write(name.c_str(),name.size()); file->write(buf,sizeleft); delete [] buf; } u32 facenum = 0; for (u32 j=0; jgetMeshBufferCount(); ++j) facenum += mesh->getMeshBuffer(j)->getIndexCount()/3; file->write(&facenum,4); // write mesh buffers for (u32 i=0; igetMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { const u32 indexCount = buffer->getIndexCount(); const u16 attributes = 0; for (u32 j=0; jgetPosition(buffer->getIndices()[j]); const core::vector3df& v2 = buffer->getPosition(buffer->getIndices()[j+1]); const core::vector3df& v3 = buffer->getPosition(buffer->getIndices()[j+2]); const core::plane3df tmpplane(v1,v2,v3); file->write(&tmpplane.Normal, 12); file->write(&v1, 12); file->write(&v2, 12); file->write(&v3, 12); file->write(&attributes, 2); } } } return true; } bool CSTLMeshWriter::writeMeshASCII(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { // write STL MESH header file->write("solid ",6); const core::stringc name(SceneManager->getMeshCache()->getMeshName(mesh)); file->write(name.c_str(),name.size()); file->write("\n\n",2); // write mesh buffers for (u32 i=0; igetMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { const u32 indexCount = buffer->getIndexCount(); for (u32 j=0; jgetPosition(buffer->getIndices()[j]), buffer->getPosition(buffer->getIndices()[j+1]), buffer->getPosition(buffer->getIndices()[j+2])); } file->write("\n",1); } } file->write("endsolid ",9); file->write(name.c_str(),name.size()); return true; } void CSTLMeshWriter::getVectorAsStringLine(const core::vector3df& v, core::stringc& s) const { s = core::stringc(v.X); s += " "; s += core::stringc(v.Y); s += " "; s += core::stringc(v.Z); s += "\n"; } void CSTLMeshWriter::writeFace(io::IWriteFile* file, const core::vector3df& v1, const core::vector3df& v2, const core::vector3df& v3) { core::stringc tmp; file->write("facet normal ",13); getVectorAsStringLine(core::plane3df(v1,v2,v3).Normal, tmp); file->write(tmp.c_str(),tmp.size()); file->write(" outer loop\n",13); file->write(" vertex ",11); getVectorAsStringLine(v1, tmp); file->write(tmp.c_str(),tmp.size()); file->write(" vertex ",11); getVectorAsStringLine(v2, tmp); file->write(tmp.c_str(),tmp.size()); file->write(" vertex ",11); getVectorAsStringLine(v3, tmp); file->write(tmp.c_str(),tmp.size()); file->write(" endloop\n",10); file->write("endfacet\n",9); } } // end namespace } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/CSTLMeshFileLoader.h0000644000000000000000000000277012574354552020625 0ustar rootroot// Copyright (C) 2007-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_STL_MESH_FILE_LOADER_H_INCLUDED__ #define __C_STL_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "irrString.h" #include "vector3d.h" namespace irr { namespace scene { //! Meshloader capable of loading STL meshes. class CSTLMeshFileLoader : public IMeshLoader { public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (i.e. ".stl") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: // skips to the first non-space character available void goNextWord(io::IReadFile* file) const; // returns the next word const core::stringc& getNextToken(io::IReadFile* file, core::stringc& token) const; // skip to next printable character after the first line break void goNextLine(io::IReadFile* file) const; //! Read 3d vector of floats void getNextVector(io::IReadFile* file, core::vector3df& vec, bool binary) const; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSTLMeshFileLoader.cpp0000644000000000000000000001313312574354552021153 0ustar rootroot// Copyright (C) 2007-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_STL_LOADER_ #include "CSTLMeshFileLoader.h" #include "SMesh.h" #include "SMeshBuffer.h" #include "SAnimatedMesh.h" #include "IReadFile.h" #include "fast_atof.h" #include "coreutil.h" #include "os.h" namespace irr { namespace scene { //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool CSTLMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "stl" ); } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file) { const long filesize = file->getSize(); if (filesize < 6) // we need a header return 0; SMesh* mesh = new SMesh(); SMeshBuffer* meshBuffer = new SMeshBuffer(); mesh->addMeshBuffer(meshBuffer); meshBuffer->drop(); core::vector3df vertex[3]; core::vector3df normal; bool binary = false; core::stringc token; if (getNextToken(file, token) != "solid") binary = true; // read/skip header u32 binFaceCount = 0; if (binary) { file->seek(80); file->read(&binFaceCount, 4); #ifdef __BIG_ENDIAN__ binFaceCount = os::Byteswap::byteswap(binFaceCount); #endif } else goNextLine(file); u16 attrib=0; token.reserve(32); while (file->getPos() < filesize) { if (!binary) { if (getNextToken(file, token) != "facet") { if (token=="endsolid") break; mesh->drop(); return 0; } if (getNextToken(file, token) != "normal") { mesh->drop(); return 0; } } getNextVector(file, normal, binary); if (!binary) { if (getNextToken(file, token) != "outer") { mesh->drop(); return 0; } if (getNextToken(file, token) != "loop") { mesh->drop(); return 0; } } for (u32 i=0; i<3; ++i) { if (!binary) { if (getNextToken(file, token) != "vertex") { mesh->drop(); return 0; } } getNextVector(file, vertex[i], binary); } if (!binary) { if (getNextToken(file, token) != "endloop") { mesh->drop(); return 0; } if (getNextToken(file, token) != "endfacet") { mesh->drop(); return 0; } } else { file->read(&attrib, 2); #ifdef __BIG_ENDIAN__ attrib = os::Byteswap::byteswap(attrib); #endif } SMeshBuffer* mb = reinterpret_cast(mesh->getMeshBuffer(mesh->getMeshBufferCount()-1)); u32 vCount = mb->getVertexCount(); video::SColor color(0xffffffff); if (attrib & 0x8000) color = video::A1R5G5B5toA8R8G8B8(attrib); if (normal==core::vector3df()) normal=core::plane3df(vertex[2],vertex[1],vertex[0]).Normal; mb->Vertices.push_back(video::S3DVertex(vertex[2],normal,color, core::vector2df())); mb->Vertices.push_back(video::S3DVertex(vertex[1],normal,color, core::vector2df())); mb->Vertices.push_back(video::S3DVertex(vertex[0],normal,color, core::vector2df())); mb->Indices.push_back(vCount); mb->Indices.push_back(vCount+1); mb->Indices.push_back(vCount+2); } // end while (file->getPos() < filesize) mesh->getMeshBuffer(0)->recalculateBoundingBox(); // Create the Animated mesh if there's anything in the mesh SAnimatedMesh* pAM = 0; if ( 0 != mesh->getMeshBufferCount() ) { mesh->recalculateBoundingBox(); pAM = new SAnimatedMesh(); pAM->Type = EAMT_OBJ; pAM->addMesh(mesh); pAM->recalculateBoundingBox(); } mesh->drop(); return pAM; } //! Read 3d vector of floats void CSTLMeshFileLoader::getNextVector(io::IReadFile* file, core::vector3df& vec, bool binary) const { if (binary) { file->read(&vec.X, 4); file->read(&vec.Y, 4); file->read(&vec.Z, 4); #ifdef __BIG_ENDIAN__ vec.X = os::Byteswap::byteswap(vec.X); vec.Y = os::Byteswap::byteswap(vec.Y); vec.Z = os::Byteswap::byteswap(vec.Z); #endif } else { goNextWord(file); core::stringc tmp; getNextToken(file, tmp); core::fast_atof_move(tmp.c_str(), vec.X); getNextToken(file, tmp); core::fast_atof_move(tmp.c_str(), vec.Y); getNextToken(file, tmp); core::fast_atof_move(tmp.c_str(), vec.Z); } vec.X=-vec.X; } //! Read next word const core::stringc& CSTLMeshFileLoader::getNextToken(io::IReadFile* file, core::stringc& token) const { goNextWord(file); u8 c; token = ""; while(file->getPos() != file->getSize()) { file->read(&c, 1); // found it, so leave if (core::isspace(c)) break; token.append(c); } return token; } //! skip to next word void CSTLMeshFileLoader::goNextWord(io::IReadFile* file) const { u8 c; while(file->getPos() != file->getSize()) { file->read(&c, 1); // found it, so leave if (!core::isspace(c)) { file->seek(-1, true); break; } } } //! Read until line break is reached and stop at the next non-space character void CSTLMeshFileLoader::goNextLine(io::IReadFile* file) const { u8 c; // look for newline characters while(file->getPos() != file->getSize()) { file->read(&c, 1); // found it, so leave if (c=='\n' || c=='\r') break; } } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_STL_LOADER_ irrlicht-1.8.3/source/Irrlicht/CSphereSceneNode.h0000644000000000000000000000650112574354552020425 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SHPERE_SCENE_NODE_H_INCLUDED__ #define __C_SHPERE_SCENE_NODE_H_INCLUDED__ #include "IMeshSceneNode.h" #include "IMesh.h" namespace irr { namespace scene { class CSphereSceneNode : public IMeshSceneNode { public: //! constructor CSphereSceneNode(f32 size, u32 polyCountX, u32 polyCountY, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); //! destructor virtual ~CSphereSceneNode(); virtual void OnRegisterSceneNode(); //! renders the node. virtual void render(); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. virtual video::SMaterial& getMaterial(u32 i); //! returns amount of materials used by this scene node. virtual u32 getMaterialCount() const; //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_SPHERE; } //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); //! The mesh cannot be changed virtual void setMesh(IMesh* mesh) {} //! Returns the current mesh virtual IMesh* getMesh() { return Mesh; } //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. /* In this way it is possible to change the materials a mesh causing all mesh scene nodes referencing this mesh to change too. */ virtual void setReadOnlyMaterials(bool readonly) {} //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style virtual bool isReadOnlyMaterials() const { return false; } //! Creates shadow volume scene node as child of this node //! and returns a pointer to it. virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh, s32 id, bool zfailmethod=true, f32 infinity=10000.0f); //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. virtual bool removeChild(ISceneNode* child); private: IMesh* Mesh; IShadowVolumeSceneNode* Shadow; core::aabbox3d Box; f32 Radius; u32 PolyCountX; u32 PolyCountY; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSphereSceneNode.cpp0000644000000000000000000001262712574354552020766 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSphereSceneNode.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "S3DVertex.h" #include "os.h" #include "CShadowVolumeSceneNode.h" namespace irr { namespace scene { //! constructor CSphereSceneNode::CSphereSceneNode(f32 radius, u32 polyCountX, u32 polyCountY, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) : IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), Shadow(0), Radius(radius), PolyCountX(polyCountX), PolyCountY(polyCountY) { #ifdef _DEBUG setDebugName("CSphereSceneNode"); #endif Mesh = SceneManager->getGeometryCreator()->createSphereMesh(radius, polyCountX, polyCountY); } //! destructor CSphereSceneNode::~CSphereSceneNode() { if (Shadow) Shadow->drop(); if (Mesh) Mesh->drop(); } //! renders the node. void CSphereSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); if (Mesh && driver) { driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial()); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); if (Shadow) Shadow->updateShadowVolumes(); driver->drawMeshBuffer(Mesh->getMeshBuffer(0)); if ( DebugDataVisible & scene::EDS_BBOX ) { video::SMaterial m; m.Lighting = false; driver->setMaterial(m); driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(), video::SColor(255,255,255,255)); } } } //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. bool CSphereSceneNode::removeChild(ISceneNode* child) { if (child && Shadow == child) { Shadow->drop(); Shadow = 0; } return ISceneNode::removeChild(child); } //! Creates shadow volume scene node as child of this node //! and returns a pointer to it. IShadowVolumeSceneNode* CSphereSceneNode::addShadowVolumeSceneNode( const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity) { if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) return 0; if (!shadowMesh) shadowMesh = Mesh; // if null is given, use the mesh of node if (Shadow) Shadow->drop(); Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity); return Shadow; } //! returns the axis aligned bounding box of this node const core::aabbox3d& CSphereSceneNode::getBoundingBox() const { return Mesh ? Mesh->getBoundingBox() : Box; } void CSphereSceneNode::OnRegisterSceneNode() { if (IsVisible) SceneManager->registerNodeForRendering(this); ISceneNode::OnRegisterSceneNode(); } //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. video::SMaterial& CSphereSceneNode::getMaterial(u32 i) { if (i>0 || !Mesh) return ISceneNode::getMaterial(i); else return Mesh->getMeshBuffer(i)->getMaterial(); } //! returns amount of materials used by this scene node. u32 CSphereSceneNode::getMaterialCount() const { return 1; } //! Writes attributes of the scene node. void CSphereSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { ISceneNode::serializeAttributes(out, options); out->addFloat("Radius", Radius); out->addInt("PolyCountX", PolyCountX); out->addInt("PolyCountY", PolyCountY); } //! Reads attributes of the scene node. void CSphereSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { f32 oldRadius = Radius; u32 oldPolyCountX = PolyCountX; u32 oldPolyCountY = PolyCountY; Radius = in->getAttributeAsFloat("Radius"); PolyCountX = in->getAttributeAsInt("PolyCountX"); PolyCountY = in->getAttributeAsInt("PolyCountY"); // legacy values read for compatibility with older versions u32 polyCount = in->getAttributeAsInt("PolyCount"); if (PolyCountX ==0 && PolyCountY == 0) PolyCountX = PolyCountY = polyCount; Radius = core::max_(Radius, 0.0001f); if ( !core::equals(Radius, oldRadius) || PolyCountX != oldPolyCountX || PolyCountY != oldPolyCountY) { if (Mesh) Mesh->drop(); Mesh = SceneManager->getGeometryCreator()->createSphereMesh(Radius, PolyCountX, PolyCountY); } ISceneNode::deserializeAttributes(in, options); } //! Creates a clone of this scene node and its children. ISceneNode* CSphereSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CSphereSceneNode* nb = new CSphereSceneNode(Radius, PolyCountX, PolyCountY, newParent, newManager, ID, RelativeTranslation); nb->cloneMembers(this, newManager); nb->getMaterial(0) = Mesh->getMeshBuffer(0)->getMaterial(); nb->Shadow = Shadow; if ( nb->Shadow ) nb->Shadow->grab(); if ( newParent ) nb->drop(); return nb; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSoftwareTexture2.h0000644000000000000000000000573112574354552020654 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SOFTWARE_2_TEXTURE_H_INCLUDED__ #define __C_SOFTWARE_2_TEXTURE_H_INCLUDED__ #include "SoftwareDriver2_compile_config.h" #include "ITexture.h" #include "CImage.h" namespace irr { namespace video { /*! interface for a Video Driver dependent Texture. */ class CSoftwareTexture2 : public ITexture { public: //! constructor enum eTex2Flags { GEN_MIPMAP = 1, IS_RENDERTARGET = 2, NP2_SIZE = 4, HAS_ALPHA = 8 }; CSoftwareTexture2(IImage* surface, const io::path& name, u32 flags, void* mipmapData=0); //! destructor virtual ~CSoftwareTexture2(); //! lock function virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0) { if (Flags & GEN_MIPMAP) MipMapLOD=mipmapLevel; return MipMap[MipMapLOD]->lock(); } //! unlock function virtual void unlock() { MipMap[MipMapLOD]->unlock(); } //! Returns original size of the texture. virtual const core::dimension2d& getOriginalSize() const { //return MipMap[0]->getDimension(); return OrigSize; } //! Returns the size of the largest mipmap. f32 getLODFactor( const f32 texArea ) const { return OrigImageDataSizeInPixels * texArea; //return MipMap[0]->getImageDataSizeInPixels () * texArea; } //! Returns (=size) of the texture. virtual const core::dimension2d& getSize() const { return MipMap[MipMapLOD]->getDimension(); } //! returns unoptimized surface virtual CImage* getImage() const { return MipMap[0]; } //! returns texture surface virtual CImage* getTexture() const { return MipMap[MipMapLOD]; } //! returns driver type of texture (=the driver, who created the texture) virtual E_DRIVER_TYPE getDriverType() const { return EDT_BURNINGSVIDEO; } //! returns color format of texture virtual ECOLOR_FORMAT getColorFormat() const { return BURNINGSHADER_COLOR_FORMAT; } //! returns pitch of texture (in bytes) virtual u32 getPitch() const { return MipMap[MipMapLOD]->getPitch(); } //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture virtual void regenerateMipMapLevels(void* mipmapData=0); //! support mipmaps virtual bool hasMipMaps() const { return (Flags & GEN_MIPMAP ) != 0; } //! Returns if the texture has an alpha channel virtual bool hasAlpha() const { return (Flags & HAS_ALPHA ) != 0; } //! is a render target virtual bool isRenderTarget() const { return (Flags & IS_RENDERTARGET) != 0; } private: f32 OrigImageDataSizeInPixels; core::dimension2d OrigSize; CImage * MipMap[SOFTWARE_DRIVER_2_MIPMAPPING_MAX]; u32 MipMapLOD; u32 Flags; ECOLOR_FORMAT OriginalFormat; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSoftwareTexture2.cpp0000644000000000000000000001043212574354552021201 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ #include "SoftwareDriver2_compile_config.h" #include "SoftwareDriver2_helper.h" #include "CSoftwareTexture2.h" #include "os.h" namespace irr { namespace video { //! constructor CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 flags, void* mipmapData) : ITexture(name), MipMapLOD(0), Flags ( flags ), OriginalFormat(video::ECF_UNKNOWN) { #ifdef _DEBUG setDebugName("CSoftwareTexture2"); #endif #ifndef SOFTWARE_DRIVER_2_MIPMAPPING Flags &= ~GEN_MIPMAP; #endif memset32 ( MipMap, 0, sizeof ( MipMap ) ); if (image) { OrigSize = image->getDimension(); OriginalFormat = image->getColorFormat(); core::setbit_cond(Flags, image->getColorFormat () == video::ECF_A8R8G8B8 || image->getColorFormat () == video::ECF_A1R5G5B5, HAS_ALPHA); core::dimension2d optSize( OrigSize.getOptimalSize( 0 != ( Flags & NP2_SIZE ), false, false, ( Flags & NP2_SIZE ) ? SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE : 0) ); if ( OrigSize == optSize ) { MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, image->getDimension()); image->copyTo(MipMap[0]); } else { char buf[256]; core::stringw showName ( name ); snprintf ( buf, 256, "Burningvideo: Warning Texture %ls reformat %dx%d -> %dx%d,%d", showName.c_str(), OrigSize.Width, OrigSize.Height, optSize.Width, optSize.Height, BURNINGSHADER_COLOR_FORMAT ); OrigSize = optSize; os::Printer::log ( buf, ELL_WARNING ); MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, optSize); image->copyToScalingBoxFilter ( MipMap[0],0, false ); } OrigImageDataSizeInPixels = (f32) 0.3f * MipMap[0]->getImageDataSizeInPixels(); } regenerateMipMapLevels(mipmapData); } //! destructor CSoftwareTexture2::~CSoftwareTexture2() { for ( s32 i = 0; i!= SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) { if ( MipMap[i] ) MipMap[i]->drop(); } } //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture void CSoftwareTexture2::regenerateMipMapLevels(void* mipmapData) { if ( !hasMipMaps () ) return; s32 i; // release for ( i = 1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) { if ( MipMap[i] ) MipMap[i]->drop(); } core::dimension2d newSize; core::dimension2d origSize=OrigSize; for (i=1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i) { newSize = MipMap[i-1]->getDimension(); newSize.Width = core::s32_max ( 1, newSize.Width >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE ); newSize.Height = core::s32_max ( 1, newSize.Height >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE ); origSize.Width = core::s32_max(1, origSize.Width >> 1); origSize.Height = core::s32_max(1, origSize.Height >> 1); if (mipmapData) { if (OriginalFormat != BURNINGSHADER_COLOR_FORMAT) { IImage* tmpImage = new CImage(OriginalFormat, origSize, mipmapData, true, false); MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); if (origSize==newSize) tmpImage->copyTo(MipMap[i]); else tmpImage->copyToScalingBoxFilter(MipMap[i]); tmpImage->drop(); } else { if (origSize==newSize) MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize, mipmapData, false); else { MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); IImage* tmpImage = new CImage(BURNINGSHADER_COLOR_FORMAT, origSize, mipmapData, true, false); tmpImage->copyToScalingBoxFilter(MipMap[i]); tmpImage->drop(); } } mipmapData = (u8*)mipmapData+origSize.getArea()*IImage::getBitsPerPixelFromFormat(OriginalFormat)/8; } else { MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); //static u32 color[] = { 0, 0xFFFF0000, 0xFF00FF00,0xFF0000FF,0xFFFFFF00,0xFFFF00FF,0xFF00FFFF,0xFF0F0F0F }; MipMap[i]->fill ( 0 ); MipMap[0]->copyToScalingBoxFilter( MipMap[i], 0, false ); } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ irrlicht-1.8.3/source/Irrlicht/CSoftwareTexture.h0000644000000000000000000000345212574354552020570 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SOFTWARE_TEXTURE_H_INCLUDED__ #define __C_SOFTWARE_TEXTURE_H_INCLUDED__ #include "ITexture.h" #include "CImage.h" namespace irr { namespace video { /*! interface for a Video Driver dependent Texture. */ class CSoftwareTexture : public ITexture { public: //! constructor CSoftwareTexture(IImage* surface, const io::path& name, bool renderTarget=false, void* mipmapData=0); //! destructor virtual ~CSoftwareTexture(); //! lock function virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0); //! unlock function virtual void unlock(); //! Returns original size of the texture. virtual const core::dimension2d& getOriginalSize() const; //! Returns (=size) of the texture. virtual const core::dimension2d& getSize() const; //! returns unoptimized surface virtual CImage* getImage(); //! returns texture surface virtual CImage* getTexture(); //! returns driver type of texture (=the driver, who created the texture) virtual E_DRIVER_TYPE getDriverType() const; //! returns color format of texture virtual ECOLOR_FORMAT getColorFormat() const; //! returns pitch of texture (in bytes) virtual u32 getPitch() const; //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture virtual void regenerateMipMapLevels(void* mipmapData=0); //! is it a render target? virtual bool isRenderTarget() const; private: CImage* Image; CImage* Texture; core::dimension2d OrigSize; bool IsRenderTarget; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSoftwareTexture.cpp0000644000000000000000000000535712574354552021131 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ #include "CSoftwareTexture.h" #include "os.h" namespace irr { namespace video { //! constructor CSoftwareTexture::CSoftwareTexture(IImage* image, const io::path& name, bool renderTarget, void* mipmapData) : ITexture(name), Texture(0), IsRenderTarget(renderTarget) { #ifdef _DEBUG setDebugName("CSoftwareTexture"); #endif if (image) { OrigSize = image->getDimension(); core::dimension2d optSize=OrigSize.getOptimalSize(); Image = new CImage(ECF_A1R5G5B5, OrigSize); image->copyTo(Image); if (optSize == OrigSize) { Texture = Image; Texture->grab(); } else { Texture = new CImage(ECF_A1R5G5B5, optSize); Image->copyToScaling(Texture); } } } //! destructor CSoftwareTexture::~CSoftwareTexture() { if (Image) Image->drop(); if (Texture) Texture->drop(); } //! lock function void* CSoftwareTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) { return Image->lock(); } //! unlock function void CSoftwareTexture::unlock() { if (Image != Texture) { os::Printer::log("Performance warning, slow unlock of non power of 2 texture.", ELL_WARNING); Image->copyToScaling(Texture); } Image->unlock(); } //! Returns original size of the texture. const core::dimension2d& CSoftwareTexture::getOriginalSize() const { return OrigSize; } //! Returns (=size) of the texture. const core::dimension2d& CSoftwareTexture::getSize() const { return Image->getDimension(); } //! returns unoptimized surface CImage* CSoftwareTexture::getImage() { return Image; } //! returns texture surface CImage* CSoftwareTexture::getTexture() { return Texture; } //! returns driver type of texture (=the driver, who created the texture) E_DRIVER_TYPE CSoftwareTexture::getDriverType() const { return EDT_SOFTWARE; } //! returns color format of texture ECOLOR_FORMAT CSoftwareTexture::getColorFormat() const { return ECF_A1R5G5B5; } //! returns pitch of texture (in bytes) u32 CSoftwareTexture::getPitch() const { return Image->getDimension().Width * 2; } //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture void CSoftwareTexture::regenerateMipMapLevels(void* mipmapData) { // our software textures don't have mip maps } bool CSoftwareTexture::isRenderTarget() const { return IsRenderTarget; } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ irrlicht-1.8.3/source/Irrlicht/CSoftwareDriver2.h0000644000000000000000000002447212574354552020452 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_VIDEO_2_SOFTWARE_H_INCLUDED__ #define __C_VIDEO_2_SOFTWARE_H_INCLUDED__ #include "SoftwareDriver2_compile_config.h" #include "IBurningShader.h" #include "CNullDriver.h" #include "CImage.h" #include "os.h" #include "irrString.h" #include "SIrrCreationParameters.h" namespace irr { namespace video { class CBurningVideoDriver : public CNullDriver { public: //! constructor CBurningVideoDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, video::IImagePresenter* presenter); //! destructor virtual ~CBurningVideoDriver(); //! queries the features of the driver, returns true if feature is available virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const; //! sets transformation virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat); //! sets a material virtual void setMaterial(const SMaterial& material); virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color); //! sets a viewport virtual void setViewPort(const core::rect& area); //! clears the zbuffer virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! presents the rendered scene on the screen, returns false if failed virtual bool endScene(); //! Only used by the internal engine. Used to notify the driver that //! the window was resized. virtual void OnResize(const core::dimension2d& size); //! returns size of the current render target virtual const core::dimension2d& getCurrentRenderTargetSize() const; //! deletes all dynamic lights there are virtual void deleteAllDynamicLights(); //! adds a dynamic light, returning an index to the light //! \param light: the light data to use to create the light //! \return An index to the light, or -1 if an error occurs virtual s32 addDynamicLight(const SLight& light); //! Turns a dynamic light on or off //! \param lightIndex: the index returned by addDynamicLight //! \param turnOn: true to turn the light on, false to turn it off virtual void turnLightOn(s32 lightIndex, bool turnOn); //! returns the maximal amount of dynamic lights the device can handle virtual u32 getMaximalDynamicLightAmount() const; //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. virtual void setAmbientLight(const SColorf& color); //! draws a vertex primitive list void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect = 0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false); //! Draws a part of the texture into the rectangle. virtual void draw2DImage(const video::ITexture* texture, const core::rect& destRect, const core::rect& sourceRect, const core::rect* clipRect = 0, const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false); //! Draws a 3d line. virtual void draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color = SColor(255,255,255,255)); //! draw an 2d rectangle virtual void draw2DRectangle(SColor color, const core::rect& pos, const core::rect* clip = 0); //!Draws an 2d rectangle with a gradient. virtual void draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip = 0); //! Draws a 2d line. virtual void draw2DLine(const core::position2d& start, const core::position2d& end, SColor color=SColor(255,255,255,255)); //! Draws a single pixel virtual void drawPixel(u32 x, u32 y, const SColor & color); //! \return Returns the name of the video driver. Example: In case of the DirectX8 //! driver, it would return "Direct3D8.1". virtual const wchar_t* getName() const; //! Returns type of video driver virtual E_DRIVER_TYPE getDriverType() const; //! get color format of the current color buffer virtual ECOLOR_FORMAT getColorFormat() const; //! Returns the transformation set by setTransform virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const; //! Creates a render target texture. virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! Clears the DepthBuffer. virtual void clearZBuffer(); //! Returns an image created from the last rendered frame. virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER); //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. virtual u32 getMaximalPrimitiveCount() const; //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do //! this: First, draw all geometry. Then use this method, to draw the shadow //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. virtual void drawStencilShadowVolume(const core::array& triangles, bool zfail=true, u32 debugDataVisible=0); //! Fills the stencil shadow with color. After the shadow volume has been drawn //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this //! to draw the color of the shadow. virtual void drawStencilShadow(bool clearStencilBuffer=false, video::SColor leftUpEdge = video::SColor(0,0,0,0), video::SColor rightUpEdge = video::SColor(0,0,0,0), video::SColor leftDownEdge = video::SColor(0,0,0,0), video::SColor rightDownEdge = video::SColor(0,0,0,0)); //! Returns the graphics card vendor name. virtual core::stringc getVendorInfo(); //! Returns the maximum texture size supported. virtual core::dimension2du getMaxTextureSize() const; virtual IDepthBuffer * getDepthBuffer () { return DepthBuffer; } virtual IStencilBuffer * getStencilBuffer () { return StencilBuffer; } protected: //! sets a render target void setRenderTarget(video::CImage* image); //! sets the current Texture //bool setTexture(u32 stage, video::ITexture* texture); //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); video::CImage* BackBuffer; video::IImagePresenter* Presenter; void* WindowId; core::rect* SceneSourceRect; video::ITexture* RenderTargetTexture; video::IImage* RenderTargetSurface; core::dimension2d RenderTargetSize; //! selects the right triangle renderer based on the render states. void setCurrentShader(); IBurningShader* CurrentShader; IBurningShader* BurningShader[ETR2_COUNT]; IDepthBuffer* DepthBuffer; IStencilBuffer* StencilBuffer; /* extend Matrix Stack -> combined CameraProjection -> combined CameraProjectionWorld -> ClipScale from NDC to DC Space */ enum E_TRANSFORMATION_STATE_BURNING_VIDEO { ETS_VIEW_PROJECTION = ETS_COUNT, ETS_CURRENT, ETS_CLIPSCALE, ETS_VIEW_INVERSE, ETS_WORLD_INVERSE, ETS_COUNT_BURNING }; enum E_TRANSFORMATION_FLAG { ETF_IDENTITY = 1, ETF_TEXGEN_CAMERA_NORMAL = 2, ETF_TEXGEN_CAMERA_REFLECTION = 4, }; u32 TransformationFlag[ETS_COUNT_BURNING]; core::matrix4 Transformation[ETS_COUNT_BURNING]; void getCameraPosWorldSpace (); void getLightPosObjectSpace (); // Vertex Cache static const SVSize vSize[]; SVertexCache VertexCache; void VertexCache_reset (const void* vertices, u32 vertexCount, const void* indices, u32 indexCount, E_VERTEX_TYPE vType,scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); void VertexCache_get ( const s4DVertex ** face ); void VertexCache_getbypass ( s4DVertex ** face ); void VertexCache_fill ( const u32 sourceIndex,const u32 destIndex ); s4DVertex * VertexCache_getVertex ( const u32 sourceIndex ); // culling & clipping u32 clipToHyperPlane ( s4DVertex * dest, const s4DVertex * source, u32 inCount, const sVec4 &plane ); u32 clipToFrustumTest ( const s4DVertex * v ) const; u32 clipToFrustum ( s4DVertex *source, s4DVertex * temp, const u32 vIn ); #ifdef SOFTWARE_DRIVER_2_LIGHTING void lightVertex ( s4DVertex *dest, u32 vertexargb ); //! Sets the fog mode. virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog); #endif // holds transformed, clipped vertices SAlignedVertex CurrentOut; SAlignedVertex Temp; void ndc_2_dc_and_project ( s4DVertex *dest,s4DVertex *source, u32 vIn ) const; f32 screenarea ( const s4DVertex *v0 ) const; void select_polygon_mipmap ( s4DVertex *source, u32 vIn, u32 tex, const core::dimension2du& texSize ) const; f32 texelarea ( const s4DVertex *v0, int tex ) const; void ndc_2_dc_and_project2 ( const s4DVertex **v, const u32 size ) const; f32 screenarea2 ( const s4DVertex **v ) const; f32 texelarea2 ( const s4DVertex **v, int tex ) const; void select_polygon_mipmap2 ( s4DVertex **source, u32 tex, const core::dimension2du& texSize ) const; SBurningShaderLightSpace LightSpace; SBurningShaderMaterial Material; static const sVec4 NDCPlane[6]; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSoftwareDriver2.cpp0000644000000000000000000023243012574354552021000 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CSoftwareDriver2.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ #include "SoftwareDriver2_helper.h" #include "CSoftwareTexture2.h" #include "CSoftware2MaterialRenderer.h" #include "S3DVertex.h" #include "S4DVertex.h" #include "CBlit.h" #define MAT_TEXTURE(tex) ( (video::CSoftwareTexture2*) Material.org.getTexture ( tex ) ) namespace irr { namespace video { namespace glsl { typedef sVec4 vec4; typedef sVec3 vec3; typedef sVec2 vec2; #define in #define uniform #define attribute #define varying #ifdef _MSC_VER #pragma warning(disable:4244) #endif struct mat4{ float m[4][4]; vec4 operator* ( const vec4 &in ) const { vec4 out; return out; } }; struct mat3{ float m[3][3]; vec3 operator* ( const vec3 &in ) const { vec3 out; return out; } }; const int gl_MaxLights = 8; inline float dot (float x, float y) { return x * y; } inline float dot ( const vec2 &x, const vec2 &y) { return x.x * y.x + x.y * y.y; } inline float dot ( const vec3 &x, const vec3 &y) { return x.x * y.x + x.y * y.y + x.z * y.z; } inline float dot ( const vec4 &x, const vec4 &y) { return x.x * y.x + x.y * y.y + x.z * y.z + x.w * y.w; } inline float reflect (float I, float N) { return I - 2.0 * dot (N, I) * N; } inline vec2 reflect (const vec2 &I, const vec2 &N) { return I - N * 2.0 * dot (N, I); } inline vec3 reflect (const vec3 &I, const vec3 &N) { return I - N * 2.0 * dot (N, I); } inline vec4 reflect (const vec4 &I, const vec4 &N) { return I - N * 2.0 * dot (N, I); } inline float refract (float I, float N, float eta){ const float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I)); if (k < 0.0) return 0.0; return eta * I - (eta * dot (N, I) + sqrt (k)) * N; } inline vec2 refract (const vec2 &I, const vec2 &N, float eta){ const float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I)); if (k < 0.0) return vec2 (0.0); return I * eta - N * (eta * dot (N, I) + sqrt (k)); } inline vec3 refract (const vec3 &I, const vec3 &N, float eta) { const float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I)); if (k < 0.0) return vec3 (0.0); return I * eta - N * (eta * dot (N, I) + sqrt (k)); } inline vec4 refract (const vec4 &I, const vec4 &N, float eta) { const float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I)); if (k < 0.0) return vec4 (0.0); return I * eta - N * (eta * dot (N, I) + sqrt (k)); } inline float length ( const vec3 &v ) { return sqrtf ( v.x * v.x + v.y * v.y + v.z * v.z ); } vec3 normalize ( const vec3 &v ) { float l = 1.f / length ( v ); return vec3 ( v.x * l, v.y * l, v.z * l ); } float max ( float a, float b ) { return a > b ? a : b; } float min ( float a, float b ) { return a < b ? a : b; } vec4 clamp ( const vec4 &a, f32 low, f32 high ) { return vec4 ( min (max(a.x,low), high), min (max(a.y,low), high), min (max(a.z,low), high), min (max(a.w,low), high) ); } typedef int sampler2D; sampler2D texUnit0; vec4 texture2D (sampler2D sampler, const vec2 &coord) { return vec4 (0.0); } struct gl_LightSourceParameters { vec4 ambient; // Acli vec4 diffuse; // Dcli vec4 specular; // Scli vec4 position; // Ppli vec4 halfVector; // Derived: Hi vec3 spotDirection; // Sdli float spotExponent; // Srli float spotCutoff; // Crli // (range: [0.0,90.0], 180.0) float spotCosCutoff; // Derived: cos(Crli) // (range: [1.0,0.0],-1.0) float constantAttenuation; // K0 float linearAttenuation; // K1 float quadraticAttenuation;// K2 }; uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights]; struct gl_LightModelParameters { vec4 ambient; }; uniform gl_LightModelParameters gl_LightModel; struct gl_LightModelProducts { vec4 sceneColor; }; uniform gl_LightModelProducts gl_FrontLightModelProduct; uniform gl_LightModelProducts gl_BackLightModelProduct; struct gl_LightProducts { vec4 ambient; vec4 diffuse; vec4 specular; }; uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights]; uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights]; struct gl_MaterialParameters { vec4 emission; // Ecm vec4 ambient; // Acm vec4 diffuse; // Dcm vec4 specular; // Scm float shininess; // Srm }; uniform gl_MaterialParameters gl_FrontMaterial; uniform gl_MaterialParameters gl_BackMaterial; // GLSL has some built-in attributes in a vertex shader: attribute vec4 gl_Vertex; // 4D vector representing the vertex position attribute vec3 gl_Normal; // 3D vector representing the vertex normal attribute vec4 gl_Color; // 4D vector representing the vertex color attribute vec4 gl_MultiTexCoord0; // 4D vector representing the texture coordinate of texture unit X attribute vec4 gl_MultiTexCoord1; // 4D vector representing the texture coordinate of texture unit X uniform mat4 gl_ModelViewMatrix; //4x4 Matrix representing the model-view matrix. uniform mat4 gl_ModelViewProjectionMatrix; //4x4 Matrix representing the model-view-projection matrix. uniform mat3 gl_NormalMatrix; //3x3 Matrix representing the inverse transpose model-view matrix. This matrix is used for normal transformation. varying vec4 gl_FrontColor; // 4D vector representing the primitives front color varying vec4 gl_FrontSecondaryColor; // 4D vector representing the primitives second front color varying vec4 gl_BackColor; // 4D vector representing the primitives back color varying vec4 gl_TexCoord[4]; // 4D vector representing the Xth texture coordinate // shader output varying vec4 gl_Position; // 4D vector representing the final processed vertex position. Only available in vertex shader. varying vec4 gl_FragColor; // 4D vector representing the final color which is written in the frame buffer. Only available in fragment shader. varying float gl_FragDepth; // float representing the depth which is written in the depth buffer. Only available in fragment shader. varying vec4 gl_SecondaryColor; varying float gl_FogFragCoord; vec4 ftransform(void) { return gl_ModelViewProjectionMatrix * gl_Vertex; } vec3 fnormal(void) { //Compute the normal vec3 normal = gl_NormalMatrix * gl_Normal; normal = normalize(normal); return normal; } struct program1 { vec4 Ambient; vec4 Diffuse; vec4 Specular; void pointLight(in int i, in vec3 normal, in vec3 eye, in vec3 ecPosition3) { float nDotVP; // normal . light direction float nDotHV; // normal . light half vector float pf; // power factor float attenuation; // computed attenuation factor float d; // distance from surface to light source vec3 VP; // direction from surface to light position vec3 halfVector; // direction of maximum highlights // Compute vector from surface to light position VP = vec3 (gl_LightSource[i].position) - ecPosition3; // Compute distance between surface and light position d = length(VP); // Normalize the vector from surface to light position VP = normalize(VP); // Compute attenuation attenuation = 1.0 / (gl_LightSource[i].constantAttenuation + gl_LightSource[i].linearAttenuation * d + gl_LightSource[i].quadraticAttenuation * d * d); halfVector = normalize(VP + eye); nDotVP = max(0.0, dot(normal, VP)); nDotHV = max(0.0, dot(normal, halfVector)); if (nDotVP == 0.0) { pf = 0.0; } else { pf = pow(nDotHV, gl_FrontMaterial.shininess); } Ambient += gl_LightSource[i].ambient * attenuation; Diffuse += gl_LightSource[i].diffuse * nDotVP * attenuation; Specular += gl_LightSource[i].specular * pf * attenuation; } vec3 fnormal(void) { //Compute the normal vec3 normal = gl_NormalMatrix * gl_Normal; normal = normalize(normal); return normal; } void ftexgen(in vec3 normal, in vec4 ecPosition) { gl_TexCoord[0] = gl_MultiTexCoord0; } void flight(in vec3 normal, in vec4 ecPosition, float alphaFade) { vec4 color; vec3 ecPosition3; vec3 eye; ecPosition3 = (vec3 (ecPosition)) / ecPosition.w; eye = vec3 (0.0, 0.0, 1.0); // Clear the light intensity accumulators Ambient = vec4 (0.0); Diffuse = vec4 (0.0); Specular = vec4 (0.0); pointLight(0, normal, eye, ecPosition3); pointLight(1, normal, eye, ecPosition3); color = gl_FrontLightModelProduct.sceneColor + Ambient * gl_FrontMaterial.ambient + Diffuse * gl_FrontMaterial.diffuse; gl_FrontSecondaryColor = Specular * gl_FrontMaterial.specular; color = clamp( color, 0.0, 1.0 ); gl_FrontColor = color; gl_FrontColor.a *= alphaFade; } void vertexshader_main (void) { vec3 transformedNormal; float alphaFade = 1.0; // Eye-coordinate position of vertex, needed in various calculations vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex; // Do fixed functionality vertex transform gl_Position = ftransform(); transformedNormal = fnormal(); flight(transformedNormal, ecPosition, alphaFade); ftexgen(transformedNormal, ecPosition); } void fragmentshader_main (void) { vec4 color; color = gl_Color; color *= texture2D(texUnit0, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y) ); color += gl_SecondaryColor; color = clamp(color, 0.0, 1.0); gl_FragColor = color; } }; } //! constructor CBurningVideoDriver::CBurningVideoDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, video::IImagePresenter* presenter) : CNullDriver(io, params.WindowSize), BackBuffer(0), Presenter(presenter), WindowId(0), SceneSourceRect(0), RenderTargetTexture(0), RenderTargetSurface(0), CurrentShader(0), DepthBuffer(0), StencilBuffer ( 0 ), CurrentOut ( 12 * 2, 128 ), Temp ( 12 * 2, 128 ) { #ifdef _DEBUG setDebugName("CBurningVideoDriver"); #endif // create backbuffer BackBuffer = new CImage(BURNINGSHADER_COLOR_FORMAT, params.WindowSize); if (BackBuffer) { BackBuffer->fill(SColor(0)); // create z buffer if ( params.ZBufferBits ) DepthBuffer = video::createDepthBuffer(BackBuffer->getDimension()); // create stencil buffer if ( params.Stencilbuffer ) StencilBuffer = video::createStencilBuffer(BackBuffer->getDimension()); } DriverAttributes->setAttribute("MaxTextures", 2); DriverAttributes->setAttribute("MaxIndices", 1<<16); DriverAttributes->setAttribute("MaxTextureSize", 1024); DriverAttributes->setAttribute("MaxLights", glsl::gl_MaxLights); DriverAttributes->setAttribute("MaxTextureLODBias", 16.f); DriverAttributes->setAttribute("Version", 47); // create triangle renderers irr::memset32 ( BurningShader, 0, sizeof ( BurningShader ) ); //BurningShader[ETR_FLAT] = createTRFlat2(DepthBuffer); //BurningShader[ETR_FLAT_WIRE] = createTRFlatWire2(DepthBuffer); BurningShader[ETR_GOURAUD] = createTriangleRendererGouraud2(this); BurningShader[ETR_GOURAUD_ALPHA] = createTriangleRendererGouraudAlpha2(this ); BurningShader[ETR_GOURAUD_ALPHA_NOZ] = createTRGouraudAlphaNoZ2(this ); //BurningShader[ETR_GOURAUD_WIRE] = createTriangleRendererGouraudWire2(DepthBuffer); //BurningShader[ETR_TEXTURE_FLAT] = createTriangleRendererTextureFlat2(DepthBuffer); //BurningShader[ETR_TEXTURE_FLAT_WIRE] = createTriangleRendererTextureFlatWire2(DepthBuffer); BurningShader[ETR_TEXTURE_GOURAUD] = createTriangleRendererTextureGouraud2(this); BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_M1] = createTriangleRendererTextureLightMap2_M1(this); BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_M2] = createTriangleRendererTextureLightMap2_M2(this); BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_M4] = createTriangleRendererGTextureLightMap2_M4(this); BurningShader[ETR_TEXTURE_LIGHTMAP_M4] = createTriangleRendererTextureLightMap2_M4(this); BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD] = createTriangleRendererTextureLightMap2_Add(this); BurningShader[ETR_TEXTURE_GOURAUD_DETAIL_MAP] = createTriangleRendererTextureDetailMap2(this); BurningShader[ETR_TEXTURE_GOURAUD_WIRE] = createTriangleRendererTextureGouraudWire2(this); BurningShader[ETR_TEXTURE_GOURAUD_NOZ] = createTRTextureGouraudNoZ2(this); BurningShader[ETR_TEXTURE_GOURAUD_ADD] = createTRTextureGouraudAdd2(this); BurningShader[ETR_TEXTURE_GOURAUD_ADD_NO_Z] = createTRTextureGouraudAddNoZ2(this); BurningShader[ETR_TEXTURE_GOURAUD_VERTEX_ALPHA] = createTriangleRendererTextureVertexAlpha2 ( this ); BurningShader[ETR_TEXTURE_GOURAUD_ALPHA] = createTRTextureGouraudAlpha(this ); BurningShader[ETR_TEXTURE_GOURAUD_ALPHA_NOZ] = createTRTextureGouraudAlphaNoZ( this ); BurningShader[ETR_NORMAL_MAP_SOLID] = createTRNormalMap ( this ); BurningShader[ETR_STENCIL_SHADOW] = createTRStencilShadow ( this ); BurningShader[ETR_TEXTURE_BLEND] = createTRTextureBlend( this ); BurningShader[ETR_REFERENCE] = createTriangleRendererReference ( this ); // add the same renderer for all solid types CSoftware2MaterialRenderer_SOLID* smr = new CSoftware2MaterialRenderer_SOLID( this); CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR* tmr = new CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR( this); CSoftware2MaterialRenderer_UNSUPPORTED * umr = new CSoftware2MaterialRenderer_UNSUPPORTED ( this ); //!TODO: addMaterialRenderer depends on pushing order.... addMaterialRenderer ( smr ); // EMT_SOLID addMaterialRenderer ( smr ); // EMT_SOLID_2_LAYER, addMaterialRenderer ( smr ); // EMT_LIGHTMAP, addMaterialRenderer ( tmr ); // EMT_LIGHTMAP_ADD, addMaterialRenderer ( smr ); // EMT_LIGHTMAP_M2, addMaterialRenderer ( smr ); // EMT_LIGHTMAP_M4, addMaterialRenderer ( smr ); // EMT_LIGHTMAP_LIGHTING, addMaterialRenderer ( smr ); // EMT_LIGHTMAP_LIGHTING_M2, addMaterialRenderer ( smr ); // EMT_LIGHTMAP_LIGHTING_M4, addMaterialRenderer ( smr ); // EMT_DETAIL_MAP, addMaterialRenderer ( umr ); // EMT_SPHERE_MAP, addMaterialRenderer ( smr ); // EMT_REFLECTION_2_LAYER, addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_ADD_COLOR, addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_ALPHA_CHANNEL, addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_ALPHA_CHANNEL_REF, addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_VERTEX_ALPHA, addMaterialRenderer ( smr ); // EMT_TRANSPARENT_REFLECTION_2_LAYER, addMaterialRenderer ( smr ); // EMT_NORMAL_MAP_SOLID, addMaterialRenderer ( umr ); // EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR, addMaterialRenderer ( tmr ); // EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA, addMaterialRenderer ( smr ); // EMT_PARALLAX_MAP_SOLID, addMaterialRenderer ( tmr ); // EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR, addMaterialRenderer ( tmr ); // EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA, addMaterialRenderer ( tmr ); // EMT_ONETEXTURE_BLEND smr->drop (); tmr->drop (); umr->drop (); // select render target setRenderTarget(BackBuffer); //reset Lightspace LightSpace.reset (); // select the right renderer setCurrentShader(); } //! destructor CBurningVideoDriver::~CBurningVideoDriver() { // delete Backbuffer if (BackBuffer) BackBuffer->drop(); // delete triangle renderers for (s32 i=0; idrop(); } // delete Additional buffer if (StencilBuffer) StencilBuffer->drop(); if (DepthBuffer) DepthBuffer->drop(); if (RenderTargetTexture) RenderTargetTexture->drop(); if (RenderTargetSurface) RenderTargetSurface->drop(); } /*! selects the right triangle renderer based on the render states. */ void CBurningVideoDriver::setCurrentShader() { ITexture *texture0 = Material.org.getTexture(0); ITexture *texture1 = Material.org.getTexture(1); bool zMaterialTest = Material.org.ZBuffer != ECFN_NEVER && Material.org.ZWriteEnable && ( AllowZWriteOnTransparent || !Material.org.isTransparent() ); EBurningFFShader shader = zMaterialTest ? ETR_TEXTURE_GOURAUD : ETR_TEXTURE_GOURAUD_NOZ; TransformationFlag[ ETS_TEXTURE_0] &= ~(ETF_TEXGEN_CAMERA_NORMAL|ETF_TEXGEN_CAMERA_REFLECTION); LightSpace.Flags &= ~VERTEXTRANSFORM; switch ( Material.org.MaterialType ) { case EMT_ONETEXTURE_BLEND: shader = ETR_TEXTURE_BLEND; break; case EMT_TRANSPARENT_ALPHA_CHANNEL_REF: Material.org.MaterialTypeParam = 0.5f; // fall through case EMT_TRANSPARENT_ALPHA_CHANNEL: if ( texture0 && texture0->hasAlpha () ) { shader = zMaterialTest ? ETR_TEXTURE_GOURAUD_ALPHA : ETR_TEXTURE_GOURAUD_ALPHA_NOZ; break; } // fall through case EMT_TRANSPARENT_ADD_COLOR: shader = zMaterialTest ? ETR_TEXTURE_GOURAUD_ADD : ETR_TEXTURE_GOURAUD_ADD_NO_Z; break; case EMT_TRANSPARENT_VERTEX_ALPHA: shader = ETR_TEXTURE_GOURAUD_VERTEX_ALPHA; break; case EMT_LIGHTMAP: case EMT_LIGHTMAP_LIGHTING: shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M1; break; case EMT_LIGHTMAP_M2: case EMT_LIGHTMAP_LIGHTING_M2: shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M2; break; case EMT_LIGHTMAP_LIGHTING_M4: if ( texture1 ) shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M4; break; case EMT_LIGHTMAP_M4: if ( texture1 ) shader = ETR_TEXTURE_LIGHTMAP_M4; break; case EMT_LIGHTMAP_ADD: if ( texture1 ) shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD; break; case EMT_DETAIL_MAP: if ( texture1 ) shader = ETR_TEXTURE_GOURAUD_DETAIL_MAP; break; case EMT_SPHERE_MAP: TransformationFlag[ ETS_TEXTURE_0] |= ETF_TEXGEN_CAMERA_REFLECTION; // ETF_TEXGEN_CAMERA_NORMAL; LightSpace.Flags |= VERTEXTRANSFORM; break; case EMT_REFLECTION_2_LAYER: shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M1; TransformationFlag[ ETS_TEXTURE_1] |= ETF_TEXGEN_CAMERA_REFLECTION; LightSpace.Flags |= VERTEXTRANSFORM; break; case EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA: case EMT_NORMAL_MAP_SOLID: case EMT_PARALLAX_MAP_SOLID: case EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA: shader = ETR_NORMAL_MAP_SOLID; LightSpace.Flags |= VERTEXTRANSFORM; break; default: break; } if ( !texture0 ) { shader = ETR_GOURAUD; } if ( Material.org.Wireframe ) { shader = ETR_TEXTURE_GOURAUD_WIRE; } //shader = ETR_REFERENCE; // switchToTriangleRenderer CurrentShader = BurningShader[shader]; if ( CurrentShader ) { CurrentShader->setZCompareFunc ( Material.org.ZBuffer ); CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); CurrentShader->setMaterial ( Material ); switch ( shader ) { case ETR_TEXTURE_GOURAUD_ALPHA: case ETR_TEXTURE_GOURAUD_ALPHA_NOZ: case ETR_TEXTURE_BLEND: CurrentShader->setParam ( 0, Material.org.MaterialTypeParam ); break; default: break; } } } //! queries the features of the driver, returns true if feature is available bool CBurningVideoDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const { if (!FeatureEnabled[feature]) return false; switch (feature) { #ifdef SOFTWARE_DRIVER_2_BILINEAR case EVDF_BILINEAR_FILTER: return true; #endif #ifdef SOFTWARE_DRIVER_2_MIPMAPPING case EVDF_MIP_MAP: return true; #endif case EVDF_STENCIL_BUFFER: case EVDF_RENDER_TO_TARGET: case EVDF_MULTITEXTURE: case EVDF_HARDWARE_TL: case EVDF_TEXTURE_NSQUARE: return true; default: return false; } } //! sets transformation void CBurningVideoDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) { Transformation[state] = mat; core::setbit_cond ( TransformationFlag[state], mat.isIdentity(), ETF_IDENTITY ); switch ( state ) { case ETS_VIEW: Transformation[ETS_VIEW_PROJECTION].setbyproduct_nocheck ( Transformation[ETS_PROJECTION], Transformation[ETS_VIEW] ); getCameraPosWorldSpace (); break; case ETS_WORLD: if ( TransformationFlag[state] & ETF_IDENTITY ) { Transformation[ETS_WORLD_INVERSE] = Transformation[ETS_WORLD]; TransformationFlag[ETS_WORLD_INVERSE] |= ETF_IDENTITY; Transformation[ETS_CURRENT] = Transformation[ETS_VIEW_PROJECTION]; } else { //Transformation[ETS_WORLD].getInversePrimitive ( Transformation[ETS_WORLD_INVERSE] ); Transformation[ETS_CURRENT].setbyproduct_nocheck ( Transformation[ETS_VIEW_PROJECTION], Transformation[ETS_WORLD] ); } TransformationFlag[ETS_CURRENT] = 0; //getLightPosObjectSpace (); break; case ETS_TEXTURE_0: case ETS_TEXTURE_1: case ETS_TEXTURE_2: case ETS_TEXTURE_3: if ( 0 == (TransformationFlag[state] & ETF_IDENTITY ) ) LightSpace.Flags |= VERTEXTRANSFORM; default: break; } } //! clears the zbuffer bool CBurningVideoDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, const SExposedVideoData& videoData, core::rect* sourceRect) { CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); WindowId = videoData.D3D9.HWnd; SceneSourceRect = sourceRect; if (backBuffer && BackBuffer) BackBuffer->fill(color); if (zBuffer && DepthBuffer) DepthBuffer->clear(); memset ( TransformationFlag, 0, sizeof ( TransformationFlag ) ); return true; } //! presents the rendered scene on the screen, returns false if failed bool CBurningVideoDriver::endScene() { CNullDriver::endScene(); return Presenter->present(BackBuffer, WindowId, SceneSourceRect); } //! sets a render target bool CBurningVideoDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color) { if (texture && texture->getDriverType() != EDT_BURNINGSVIDEO) { os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); return false; } if (RenderTargetTexture) RenderTargetTexture->drop(); RenderTargetTexture = texture; if (RenderTargetTexture) { RenderTargetTexture->grab(); setRenderTarget(((CSoftwareTexture2*)RenderTargetTexture)->getTexture()); } else { setRenderTarget(BackBuffer); } if (RenderTargetSurface && (clearBackBuffer || clearZBuffer)) { if (clearZBuffer) DepthBuffer->clear(); if (clearBackBuffer) RenderTargetSurface->fill( color ); } return true; } //! sets a render target void CBurningVideoDriver::setRenderTarget(video::CImage* image) { if (RenderTargetSurface) RenderTargetSurface->drop(); RenderTargetSurface = image; RenderTargetSize.Width = 0; RenderTargetSize.Height = 0; if (RenderTargetSurface) { RenderTargetSurface->grab(); RenderTargetSize = RenderTargetSurface->getDimension(); } setViewPort(core::rect(0,0,RenderTargetSize.Width,RenderTargetSize.Height)); if (DepthBuffer) DepthBuffer->setSize(RenderTargetSize); if (StencilBuffer) StencilBuffer->setSize(RenderTargetSize); } //! sets a viewport void CBurningVideoDriver::setViewPort(const core::rect& area) { ViewPort = area; core::rect rendert(0,0,RenderTargetSize.Width,RenderTargetSize.Height); ViewPort.clipAgainst(rendert); Transformation [ ETS_CLIPSCALE ].buildNDCToDCMatrix ( ViewPort, 1 ); if (CurrentShader) CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); } /* generic plane clipping in homogenous coordinates special case ndc frustum <-w,w>,<-w,w>,<-w,w> can be rewritten with compares e.q near plane, a.z < -a.w and b.z < -b.w */ const sVec4 CBurningVideoDriver::NDCPlane[6] = { sVec4( 0.f, 0.f, -1.f, -1.f ), // near sVec4( 0.f, 0.f, 1.f, -1.f ), // far sVec4( 1.f, 0.f, 0.f, -1.f ), // left sVec4( -1.f, 0.f, 0.f, -1.f ), // right sVec4( 0.f, 1.f, 0.f, -1.f ), // bottom sVec4( 0.f, -1.f, 0.f, -1.f ) // top }; /* test a vertex if it's inside the standard frustum this is the generic one.. f32 dotPlane; for ( u32 i = 0; i!= 6; ++i ) { dotPlane = v->Pos.dotProduct ( NDCPlane[i] ); core::setbit_cond( flag, dotPlane <= 0.f, 1 << i ); } // this is the base for ndc frustum <-w,w>,<-w,w>,<-w,w> core::setbit_cond( flag, ( v->Pos.z - v->Pos.w ) <= 0.f, 1 ); core::setbit_cond( flag, (-v->Pos.z - v->Pos.w ) <= 0.f, 2 ); core::setbit_cond( flag, ( v->Pos.x - v->Pos.w ) <= 0.f, 4 ); core::setbit_cond( flag, (-v->Pos.x - v->Pos.w ) <= 0.f, 8 ); core::setbit_cond( flag, ( v->Pos.y - v->Pos.w ) <= 0.f, 16 ); core::setbit_cond( flag, (-v->Pos.y - v->Pos.w ) <= 0.f, 32 ); */ #ifdef IRRLICHT_FAST_MATH REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v ) const { f32 test[6]; u32 flag; const f32 w = - v->Pos.w; // a conditional move is needed....FCOMI ( but we don't have it ) // so let the fpu calculate and write it back. // cpu makes the compare, interleaving test[0] = v->Pos.z + w; test[1] = -v->Pos.z + w; test[2] = v->Pos.x + w; test[3] = -v->Pos.x + w; test[4] = v->Pos.y + w; test[5] = -v->Pos.y + w; flag = (IR ( test[0] ) ) >> 31; flag |= (IR ( test[1] ) & 0x80000000 ) >> 30; flag |= (IR ( test[2] ) & 0x80000000 ) >> 29; flag |= (IR ( test[3] ) & 0x80000000 ) >> 28; flag |= (IR ( test[4] ) & 0x80000000 ) >> 27; flag |= (IR ( test[5] ) & 0x80000000 ) >> 26; /* flag = F32_LOWER_EQUAL_0 ( test[0] ); flag |= F32_LOWER_EQUAL_0 ( test[1] ) << 1; flag |= F32_LOWER_EQUAL_0 ( test[2] ) << 2; flag |= F32_LOWER_EQUAL_0 ( test[3] ) << 3; flag |= F32_LOWER_EQUAL_0 ( test[4] ) << 4; flag |= F32_LOWER_EQUAL_0 ( test[5] ) << 5; */ return flag; } #else REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v ) const { u32 flag = 0; if ( v->Pos.z <= v->Pos.w ) flag |= 1; if (-v->Pos.z <= v->Pos.w ) flag |= 2; if ( v->Pos.x <= v->Pos.w ) flag |= 4; if (-v->Pos.x <= v->Pos.w ) flag |= 8; if ( v->Pos.y <= v->Pos.w ) flag |= 16; if (-v->Pos.y <= v->Pos.w ) flag |= 32; /* for ( u32 i = 0; i!= 6; ++i ) { core::setbit_cond( flag, v->Pos.dotProduct ( NDCPlane[i] ) <= 0.f, 1 << i ); } */ return flag; } #endif // _MSC_VER u32 CBurningVideoDriver::clipToHyperPlane ( s4DVertex * dest, const s4DVertex * source, u32 inCount, const sVec4 &plane ) { u32 outCount = 0; s4DVertex * out = dest; const s4DVertex * a; const s4DVertex * b = source; f32 bDotPlane; bDotPlane = b->Pos.dotProduct ( plane ); for( u32 i = 1; i < inCount + 1; ++i) { const s32 condition = i - inCount; const s32 index = (( ( condition >> 31 ) & ( i ^ condition ) ) ^ condition ) << 1; a = &source[ index ]; // current point inside if ( a->Pos.dotProduct ( plane ) <= 0.f ) { // last point outside if ( F32_GREATER_0 ( bDotPlane ) ) { // intersect line segment with plane out->interpolate ( *b, *a, bDotPlane / (b->Pos - a->Pos).dotProduct ( plane ) ); out += 2; outCount += 1; } // copy current to out //*out = *a; irr::memcpy32_small ( out, a, SIZEOF_SVERTEX * 2 ); b = out; out += 2; outCount += 1; } else { // current point outside if ( F32_LOWER_EQUAL_0 ( bDotPlane ) ) { // previous was inside // intersect line segment with plane out->interpolate ( *b, *a, bDotPlane / (b->Pos - a->Pos).dotProduct ( plane ) ); out += 2; outCount += 1; } // pointer b = a; } bDotPlane = b->Pos.dotProduct ( plane ); } return outCount; } u32 CBurningVideoDriver::clipToFrustum ( s4DVertex *v0, s4DVertex * v1, const u32 vIn ) { u32 vOut = vIn; vOut = clipToHyperPlane ( v1, v0, vOut, NDCPlane[0] ); if ( vOut < vIn ) return vOut; vOut = clipToHyperPlane ( v0, v1, vOut, NDCPlane[1] ); if ( vOut < vIn ) return vOut; vOut = clipToHyperPlane ( v1, v0, vOut, NDCPlane[2] ); if ( vOut < vIn ) return vOut; vOut = clipToHyperPlane ( v0, v1, vOut, NDCPlane[3] ); if ( vOut < vIn ) return vOut; vOut = clipToHyperPlane ( v1, v0, vOut, NDCPlane[4] ); if ( vOut < vIn ) return vOut; vOut = clipToHyperPlane ( v0, v1, vOut, NDCPlane[5] ); return vOut; } /*! Part I: apply Clip Scale matrix From Normalized Device Coordiante ( NDC ) Space to Device Coordinate Space ( DC ) Part II: Project homogeneous vector homogeneous to non-homogenous coordinates ( dividebyW ) Incoming: ( xw, yw, zw, w, u, v, 1, R, G, B, A ) Outgoing: ( xw/w, yw/w, zw/w, w/w, u/w, v/w, 1/w, R/w, G/w, B/w, A/w ) replace w/w by 1/w */ inline void CBurningVideoDriver::ndc_2_dc_and_project ( s4DVertex *dest,s4DVertex *source, u32 vIn ) const { u32 g; for ( g = 0; g != vIn; g += 2 ) { if ( (dest[g].flag & VERTEX4D_PROJECTED ) == VERTEX4D_PROJECTED ) continue; dest[g].flag = source[g].flag | VERTEX4D_PROJECTED; const f32 w = source[g].Pos.w; const f32 iw = core::reciprocal ( w ); // to device coordinates dest[g].Pos.x = iw * ( source[g].Pos.x * Transformation [ ETS_CLIPSCALE ][ 0] + w * Transformation [ ETS_CLIPSCALE ][12] ); dest[g].Pos.y = iw * ( source[g].Pos.y * Transformation [ ETS_CLIPSCALE ][ 5] + w * Transformation [ ETS_CLIPSCALE ][13] ); #ifndef SOFTWARE_DRIVER_2_USE_WBUFFER dest[g].Pos.z = iw * source[g].Pos.z; #endif #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT dest[g].Color[0] = source[g].Color[0] * iw; #else dest[g].Color[0] = source[g].Color[0]; #endif #endif dest[g].LightTangent[0] = source[g].LightTangent[0] * iw; dest[g].Pos.w = iw; } } inline void CBurningVideoDriver::ndc_2_dc_and_project2 ( const s4DVertex **v, const u32 size ) const { u32 g; for ( g = 0; g != size; g += 1 ) { s4DVertex * a = (s4DVertex*) v[g]; if ( (a[1].flag & VERTEX4D_PROJECTED ) == VERTEX4D_PROJECTED ) continue; a[1].flag = a->flag | VERTEX4D_PROJECTED; // project homogenous vertex, store 1/w const f32 w = a->Pos.w; const f32 iw = core::reciprocal ( w ); // to device coordinates const f32 * p = Transformation [ ETS_CLIPSCALE ].pointer(); a[1].Pos.x = iw * ( a->Pos.x * p[ 0] + w * p[12] ); a[1].Pos.y = iw * ( a->Pos.y * p[ 5] + w * p[13] ); #ifndef SOFTWARE_DRIVER_2_USE_WBUFFER a[1].Pos.z = a->Pos.z * iw; #endif #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT a[1].Color[0] = a->Color[0] * iw; #else a[1].Color[0] = a->Color[0]; #endif #endif a[1].LightTangent[0] = a[0].LightTangent[0] * iw; a[1].Pos.w = iw; } } /*! crossproduct in projected 2D -> screen area triangle */ inline f32 CBurningVideoDriver::screenarea ( const s4DVertex *v ) const { return ( ( v[3].Pos.x - v[1].Pos.x ) * ( v[5].Pos.y - v[1].Pos.y ) ) - ( ( v[3].Pos.y - v[1].Pos.y ) * ( v[5].Pos.x - v[1].Pos.x ) ); } /*! */ inline f32 CBurningVideoDriver::texelarea ( const s4DVertex *v, int tex ) const { f32 z; z = ( (v[2].Tex[tex].x - v[0].Tex[tex].x ) * (v[4].Tex[tex].y - v[0].Tex[tex].y ) ) - ( (v[4].Tex[tex].x - v[0].Tex[tex].x ) * (v[2].Tex[tex].y - v[0].Tex[tex].y ) ); return MAT_TEXTURE ( tex )->getLODFactor ( z ); } /*! crossproduct in projected 2D */ inline f32 CBurningVideoDriver::screenarea2 ( const s4DVertex **v ) const { return ( (( v[1] + 1 )->Pos.x - (v[0] + 1 )->Pos.x ) * ( (v[2] + 1 )->Pos.y - (v[0] + 1 )->Pos.y ) ) - ( (( v[1] + 1 )->Pos.y - (v[0] + 1 )->Pos.y ) * ( (v[2] + 1 )->Pos.x - (v[0] + 1 )->Pos.x ) ); } /*! */ inline f32 CBurningVideoDriver::texelarea2 ( const s4DVertex **v, s32 tex ) const { f32 z; z = ( (v[1]->Tex[tex].x - v[0]->Tex[tex].x ) * (v[2]->Tex[tex].y - v[0]->Tex[tex].y ) ) - ( (v[2]->Tex[tex].x - v[0]->Tex[tex].x ) * (v[1]->Tex[tex].y - v[0]->Tex[tex].y ) ); return MAT_TEXTURE ( tex )->getLODFactor ( z ); } /*! */ inline void CBurningVideoDriver::select_polygon_mipmap ( s4DVertex *v, u32 vIn, u32 tex, const core::dimension2du& texSize ) const { f32 f[2]; f[0] = (f32) texSize.Width - 0.25f; f[1] = (f32) texSize.Height - 0.25f; #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT for ( u32 g = 0; g != vIn; g += 2 ) { (v + g + 1 )->Tex[tex].x = (v + g + 0)->Tex[tex].x * ( v + g + 1 )->Pos.w * f[0]; (v + g + 1 )->Tex[tex].y = (v + g + 0)->Tex[tex].y * ( v + g + 1 )->Pos.w * f[1]; } #else for ( u32 g = 0; g != vIn; g += 2 ) { (v + g + 1 )->Tex[tex].x = (v + g + 0)->Tex[tex].x * f[0]; (v + g + 1 )->Tex[tex].y = (v + g + 0)->Tex[tex].y * f[1]; } #endif } inline void CBurningVideoDriver::select_polygon_mipmap2 ( s4DVertex **v, u32 tex, const core::dimension2du& texSize ) const { f32 f[2]; f[0] = (f32) texSize.Width - 0.25f; f[1] = (f32) texSize.Height - 0.25f; #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT (v[0] + 1 )->Tex[tex].x = v[0]->Tex[tex].x * ( v[0] + 1 )->Pos.w * f[0]; (v[0] + 1 )->Tex[tex].y = v[0]->Tex[tex].y * ( v[0] + 1 )->Pos.w * f[1]; (v[1] + 1 )->Tex[tex].x = v[1]->Tex[tex].x * ( v[1] + 1 )->Pos.w * f[0]; (v[1] + 1 )->Tex[tex].y = v[1]->Tex[tex].y * ( v[1] + 1 )->Pos.w * f[1]; (v[2] + 1 )->Tex[tex].x = v[2]->Tex[tex].x * ( v[2] + 1 )->Pos.w * f[0]; (v[2] + 1 )->Tex[tex].y = v[2]->Tex[tex].y * ( v[2] + 1 )->Pos.w * f[1]; #else (v[0] + 1 )->Tex[tex].x = v[0]->Tex[tex].x * f[0]; (v[0] + 1 )->Tex[tex].y = v[0]->Tex[tex].y * f[1]; (v[1] + 1 )->Tex[tex].x = v[1]->Tex[tex].x * f[0]; (v[1] + 1 )->Tex[tex].y = v[1]->Tex[tex].y * f[1]; (v[2] + 1 )->Tex[tex].x = v[2]->Tex[tex].x * f[0]; (v[2] + 1 )->Tex[tex].y = v[2]->Tex[tex].y * f[1]; #endif } // Vertex Cache const SVSize CBurningVideoDriver::vSize[] = { { VERTEX4D_FORMAT_TEXTURE_1 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex), 1 }, { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex2TCoords),2 }, { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1 | VERTEX4D_FORMAT_BUMP_DOT3, sizeof(S3DVertexTangents),2 }, { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex), 2 }, // reflection map { 0, sizeof(f32) * 3, 0 }, // core::vector3df* }; /*! fill a cache line with transformed, light and clipp test triangles */ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 destIndex) { u8 * source; s4DVertex *dest; source = (u8*) VertexCache.vertices + ( sourceIndex * vSize[VertexCache.vType].Pitch ); // it's a look ahead so we never hit it.. // but give priority... //VertexCache.info[ destIndex ].hit = hitCount; // store info VertexCache.info[ destIndex ].index = sourceIndex; VertexCache.info[ destIndex ].hit = 0; // destination Vertex dest = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( destIndex << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ); // transform Model * World * Camera * Projection * NDCSpace matrix const S3DVertex *base = ((S3DVertex*) source ); Transformation [ ETS_CURRENT].transformVect ( &dest->Pos.x, base->Pos ); //mhm ;-) maybe no goto if ( VertexCache.vType == 4 ) goto clipandproject; #if defined (SOFTWARE_DRIVER_2_LIGHTING) || defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM ) // vertex normal in light space if ( Material.org.Lighting || (LightSpace.Flags & VERTEXTRANSFORM) ) { if ( TransformationFlag[ETS_WORLD] & ETF_IDENTITY ) { LightSpace.normal.set ( base->Normal.X, base->Normal.Y, base->Normal.Z, 1.f ); LightSpace.vertex.set ( base->Pos.X, base->Pos.Y, base->Pos.Z, 1.f ); } else { Transformation[ETS_WORLD].rotateVect ( &LightSpace.normal.x, base->Normal ); // vertex in light space if ( LightSpace.Flags & ( POINTLIGHT | FOG | SPECULAR | VERTEXTRANSFORM) ) Transformation[ETS_WORLD].transformVect ( &LightSpace.vertex.x, base->Pos ); } if ( LightSpace.Flags & NORMALIZE ) LightSpace.normal.normalize_xyz(); } #endif #if defined ( SOFTWARE_DRIVER_2_USE_VERTEX_COLOR ) // apply lighting model #if defined (SOFTWARE_DRIVER_2_LIGHTING) if ( Material.org.Lighting ) { lightVertex ( dest, base->Color.color ); } else { dest->Color[0].setA8R8G8B8 ( base->Color.color ); } #else dest->Color[0].setA8R8G8B8 ( base->Color.color ); #endif #endif // Texture Transform #if !defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM ) irr::memcpy32_small ( &dest->Tex[0],&base->TCoords, vSize[VertexCache.vType].TexSize << 3 // * ( sizeof ( f32 ) * 2 ) ); #else if ( 0 == (LightSpace.Flags & VERTEXTRANSFORM) ) { irr::memcpy32_small ( &dest->Tex[0],&base->TCoords, vSize[VertexCache.vType].TexSize << 3 // * ( sizeof ( f32 ) * 2 ) ); } else { /* Generate texture coordinates as linear functions so that: u = Ux*x + Uy*y + Uz*z + Uw v = Vx*x + Vy*y + Vz*z + Vw The matrix M for this case is: Ux Vx 0 0 Uy Vy 0 0 Uz Vz 0 0 Uw Vw 0 0 */ u32 t; sVec4 n; sVec2 srcT; for ( t = 0; t != vSize[VertexCache.vType].TexSize; ++t ) { const core::matrix4& M = Transformation [ ETS_TEXTURE_0 + t ]; // texgen if ( TransformationFlag [ ETS_TEXTURE_0 + t ] & (ETF_TEXGEN_CAMERA_NORMAL|ETF_TEXGEN_CAMERA_REFLECTION) ) { n.x = LightSpace.campos.x - LightSpace.vertex.x; n.y = LightSpace.campos.x - LightSpace.vertex.y; n.z = LightSpace.campos.x - LightSpace.vertex.z; n.normalize_xyz(); n.x += LightSpace.normal.x; n.y += LightSpace.normal.y; n.z += LightSpace.normal.z; n.normalize_xyz(); const f32 *view = Transformation[ETS_VIEW].pointer(); if ( TransformationFlag [ ETS_TEXTURE_0 + t ] & ETF_TEXGEN_CAMERA_REFLECTION ) { srcT.x = 0.5f * ( 1.f + (n.x * view[0] + n.y * view[4] + n.z * view[8] )); srcT.y = 0.5f * ( 1.f + (n.x * view[1] + n.y * view[5] + n.z * view[9] )); } else { srcT.x = 0.5f * ( 1.f + (n.x * view[0] + n.y * view[1] + n.z * view[2] )); srcT.y = 0.5f * ( 1.f + (n.x * view[4] + n.y * view[5] + n.z * view[6] )); } } else { irr::memcpy32_small ( &srcT,(&base->TCoords) + t, sizeof ( f32 ) * 2 ); } switch ( Material.org.TextureLayer[t].TextureWrapU ) { case ETC_CLAMP: case ETC_CLAMP_TO_EDGE: case ETC_CLAMP_TO_BORDER: dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f ); break; case ETC_MIRROR: dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8]; if (core::fract(dest->Tex[t].x)>0.5f) dest->Tex[t].x=1.f-dest->Tex[t].x; break; case ETC_MIRROR_CLAMP: case ETC_MIRROR_CLAMP_TO_EDGE: case ETC_MIRROR_CLAMP_TO_BORDER: dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f ); if (core::fract(dest->Tex[t].x)>0.5f) dest->Tex[t].x=1.f-dest->Tex[t].x; break; case ETC_REPEAT: default: dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8]; break; } switch ( Material.org.TextureLayer[t].TextureWrapV ) { case ETC_CLAMP: case ETC_CLAMP_TO_EDGE: case ETC_CLAMP_TO_BORDER: dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f ); break; case ETC_MIRROR: dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9]; if (core::fract(dest->Tex[t].y)>0.5f) dest->Tex[t].y=1.f-dest->Tex[t].y; break; case ETC_MIRROR_CLAMP: case ETC_MIRROR_CLAMP_TO_EDGE: case ETC_MIRROR_CLAMP_TO_BORDER: dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f ); if (core::fract(dest->Tex[t].y)>0.5f) dest->Tex[t].y=1.f-dest->Tex[t].y; break; case ETC_REPEAT: default: dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9]; break; } } } #if 0 // tangent space light vector, emboss if ( Lights.size () && ( vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_BUMP_DOT3 ) ) { const S3DVertexTangents *tangent = ((S3DVertexTangents*) source ); const SBurningShaderLight &light = LightSpace.Light[0]; sVec4 vp; vp.x = light.pos.x - LightSpace.vertex.x; vp.y = light.pos.y - LightSpace.vertex.y; vp.z = light.pos.z - LightSpace.vertex.z; vp.normalize_xyz(); LightSpace.tangent.x = vp.x * tangent->Tangent.X + vp.y * tangent->Tangent.Y + vp.z * tangent->Tangent.Z; LightSpace.tangent.y = vp.x * tangent->Binormal.X + vp.y * tangent->Binormal.Y + vp.z * tangent->Binormal.Z; //LightSpace.tangent.z = vp.x * tangent->Normal.X + vp.y * tangent->Normal.Y + vp.z * tangent->Normal.Z; LightSpace.tangent.z = 0.f; LightSpace.tangent.normalize_xyz(); f32 scale = 1.f / 128.f; if ( Material.org.MaterialTypeParam > 0.f ) scale = Material.org.MaterialTypeParam; // emboss, shift coordinates dest->Tex[1].x = dest->Tex[0].x + LightSpace.tangent.x * scale; dest->Tex[1].y = dest->Tex[0].y + LightSpace.tangent.y * scale; //dest->Tex[1].z = LightSpace.tangent.z * scale; } #endif if ( LightSpace.Light.size () && ( vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_BUMP_DOT3 ) ) { const S3DVertexTangents *tangent = ((S3DVertexTangents*) source ); sVec4 vp; dest->LightTangent[0].x = 0.f; dest->LightTangent[0].y = 0.f; dest->LightTangent[0].z = 0.f; for ( u32 i = 0; i < 2 && i < LightSpace.Light.size (); ++i ) { const SBurningShaderLight &light = LightSpace.Light[i]; if ( !light.LightIsOn ) continue; vp.x = light.pos.x - LightSpace.vertex.x; vp.y = light.pos.y - LightSpace.vertex.y; vp.z = light.pos.z - LightSpace.vertex.z; /* vp.x = light.pos_objectspace.x - base->Pos.X; vp.y = light.pos_objectspace.y - base->Pos.Y; vp.z = light.pos_objectspace.z - base->Pos.Z; */ vp.normalize_xyz(); // transform by tangent matrix sVec3 l; #if 1 l.x = (vp.x * tangent->Tangent.X + vp.y * tangent->Tangent.Y + vp.z * tangent->Tangent.Z ); l.y = (vp.x * tangent->Binormal.X + vp.y * tangent->Binormal.Y + vp.z * tangent->Binormal.Z ); l.z = (vp.x * tangent->Normal.X + vp.y * tangent->Normal.Y + vp.z * tangent->Normal.Z ); #else l.x = (vp.x * tangent->Tangent.X + vp.y * tangent->Binormal.X + vp.z * tangent->Normal.X ); l.y = (vp.x * tangent->Tangent.Y + vp.y * tangent->Binormal.Y + vp.z * tangent->Normal.Y ); l.z = (vp.x * tangent->Tangent.Z + vp.y * tangent->Binormal.Z + vp.z * tangent->Normal.Z ); #endif /* f32 scale = 1.f / 128.f; scale /= dest->LightTangent[0].b; // emboss, shift coordinates dest->Tex[1].x = dest->Tex[0].x + l.r * scale; dest->Tex[1].y = dest->Tex[0].y + l.g * scale; */ dest->Tex[1].x = dest->Tex[0].x; dest->Tex[1].y = dest->Tex[0].y; // scale bias dest->LightTangent[0].x += l.x; dest->LightTangent[0].y += l.y; dest->LightTangent[0].z += l.z; } dest->LightTangent[0].setLength ( 0.5f ); dest->LightTangent[0].x += 0.5f; dest->LightTangent[0].y += 0.5f; dest->LightTangent[0].z += 0.5f; } #endif clipandproject: dest[0].flag = dest[1].flag = vSize[VertexCache.vType].Format; // test vertex dest[0].flag |= clipToFrustumTest ( dest); // to DC Space, project homogenous vertex if ( (dest[0].flag & VERTEX4D_CLIPMASK ) == VERTEX4D_INSIDE ) { ndc_2_dc_and_project2 ( (const s4DVertex**) &dest, 1 ); } //return dest; } // REALINLINE s4DVertex * CBurningVideoDriver::VertexCache_getVertex ( const u32 sourceIndex ) { for ( s32 i = 0; i < VERTEXCACHE_ELEMENT; ++i ) { if ( VertexCache.info[ i ].index == sourceIndex ) { return (s4DVertex *) ( (u8*) VertexCache.mem.data + ( i << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ); } } return 0; } /* Cache based on linear walk indices fill blockwise on the next 16(Cache_Size) unique vertices in indexlist merge the next 16 vertices with the current */ REALINLINE void CBurningVideoDriver::VertexCache_get(const s4DVertex ** face) { SCacheInfo info[VERTEXCACHE_ELEMENT]; // next primitive must be complete in cache if ( VertexCache.indicesIndex - VertexCache.indicesRun < 3 && VertexCache.indicesIndex < VertexCache.indexCount ) { // rewind to start of primitive VertexCache.indicesIndex = VertexCache.indicesRun; irr::memset32 ( info, VERTEXCACHE_MISS, sizeof ( info ) ); // get the next unique vertices cache line u32 fillIndex = 0; u32 dIndex; u32 i; u32 sourceIndex; while ( VertexCache.indicesIndex < VertexCache.indexCount && fillIndex < VERTEXCACHE_ELEMENT ) { switch ( VertexCache.iType ) { case 1: sourceIndex = ((u16*)VertexCache.indices) [ VertexCache.indicesIndex ]; break; case 2: sourceIndex = ((u32*)VertexCache.indices) [ VertexCache.indicesIndex ]; break; case 4: sourceIndex = VertexCache.indicesIndex; break; } VertexCache.indicesIndex += 1; // if not exist, push back s32 exist = 0; for ( dIndex = 0; dIndex < fillIndex; ++dIndex ) { if ( info[ dIndex ].index == sourceIndex ) { exist = 1; break; } } if ( 0 == exist ) { info[fillIndex++].index = sourceIndex; } } // clear marks for ( i = 0; i!= VERTEXCACHE_ELEMENT; ++i ) { VertexCache.info[i].hit = 0; } // mark all existing for ( i = 0; i!= fillIndex; ++i ) { for ( dIndex = 0; dIndex < VERTEXCACHE_ELEMENT; ++dIndex ) { if ( VertexCache.info[ dIndex ].index == info[i].index ) { info[i].hit = dIndex; VertexCache.info[ dIndex ].hit = 1; break; } } } // fill new for ( i = 0; i!= fillIndex; ++i ) { if ( info[i].hit != VERTEXCACHE_MISS ) continue; for ( dIndex = 0; dIndex < VERTEXCACHE_ELEMENT; ++dIndex ) { if ( 0 == VertexCache.info[dIndex].hit ) { VertexCache_fill ( info[i].index, dIndex ); VertexCache.info[dIndex].hit += 1; info[i].hit = dIndex; break; } } } } const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun ); switch ( VertexCache.iType ) { case 1: { const u16 *p = (const u16 *) VertexCache.indices; face[0] = VertexCache_getVertex ( p[ i0 ] ); face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] ); face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] ); } break; case 2: { const u32 *p = (const u32 *) VertexCache.indices; face[0] = VertexCache_getVertex ( p[ i0 ] ); face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] ); face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] ); } break; case 4: face[0] = VertexCache_getVertex ( VertexCache.indicesRun + 0 ); face[1] = VertexCache_getVertex ( VertexCache.indicesRun + 1 ); face[2] = VertexCache_getVertex ( VertexCache.indicesRun + 2 ); break; default: face[0] = face[1] = face[2] = VertexCache_getVertex(VertexCache.indicesRun + 0); break; } VertexCache.indicesRun += VertexCache.primitivePitch; } /*! */ REALINLINE void CBurningVideoDriver::VertexCache_getbypass ( s4DVertex ** face ) { const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun ); if ( VertexCache.iType == 1 ) { const u16 *p = (const u16 *) VertexCache.indices; VertexCache_fill ( p[ i0 ], 0 ); VertexCache_fill ( p[ VertexCache.indicesRun + 1], 1 ); VertexCache_fill ( p[ VertexCache.indicesRun + 2], 2 ); } else { const u32 *p = (const u32 *) VertexCache.indices; VertexCache_fill ( p[ i0 ], 0 ); VertexCache_fill ( p[ VertexCache.indicesRun + 1], 1 ); VertexCache_fill ( p[ VertexCache.indicesRun + 2], 2 ); } VertexCache.indicesRun += VertexCache.primitivePitch; face[0] = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( 0 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ); face[1] = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( 1 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ); face[2] = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( 2 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ); } /*! */ void CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCount, const void* indices, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { VertexCache.vertices = vertices; VertexCache.vertexCount = vertexCount; VertexCache.indices = indices; VertexCache.indicesIndex = 0; VertexCache.indicesRun = 0; if ( Material.org.MaterialType == video::EMT_REFLECTION_2_LAYER ) VertexCache.vType = 3; else VertexCache.vType = vType; VertexCache.pType = pType; switch ( iType ) { case EIT_16BIT: VertexCache.iType = 1; break; case EIT_32BIT: VertexCache.iType = 2; break; default: VertexCache.iType = iType; break; } switch ( VertexCache.pType ) { // most types here will not work as expected, only triangles/triangle_fan // is known to work. case scene::EPT_POINTS: VertexCache.indexCount = primitiveCount; VertexCache.primitivePitch = 1; break; case scene::EPT_LINE_STRIP: VertexCache.indexCount = primitiveCount+1; VertexCache.primitivePitch = 1; break; case scene::EPT_LINE_LOOP: VertexCache.indexCount = primitiveCount+1; VertexCache.primitivePitch = 1; break; case scene::EPT_LINES: VertexCache.indexCount = 2*primitiveCount; VertexCache.primitivePitch = 2; break; case scene::EPT_TRIANGLE_STRIP: VertexCache.indexCount = primitiveCount+2; VertexCache.primitivePitch = 1; break; case scene::EPT_TRIANGLES: VertexCache.indexCount = primitiveCount + primitiveCount + primitiveCount; VertexCache.primitivePitch = 3; break; case scene::EPT_TRIANGLE_FAN: VertexCache.indexCount = primitiveCount + 2; VertexCache.primitivePitch = 1; break; case scene::EPT_QUAD_STRIP: VertexCache.indexCount = 2*primitiveCount + 2; VertexCache.primitivePitch = 2; break; case scene::EPT_QUADS: VertexCache.indexCount = 4*primitiveCount; VertexCache.primitivePitch = 4; break; case scene::EPT_POLYGON: VertexCache.indexCount = primitiveCount+1; VertexCache.primitivePitch = 1; break; case scene::EPT_POINT_SPRITES: VertexCache.indexCount = primitiveCount; VertexCache.primitivePitch = 1; break; } irr::memset32 ( VertexCache.info, VERTEXCACHE_MISS, sizeof ( VertexCache.info ) ); } void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { if (!checkPrimitiveCount(primitiveCount)) return; CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType); // These calls would lead to crashes due to wrong index usage. // The vertex cache needs to be rewritten for these primitives. if (pType==scene::EPT_POINTS || pType==scene::EPT_LINE_STRIP || pType==scene::EPT_LINE_LOOP || pType==scene::EPT_LINES || pType==scene::EPT_POLYGON || pType==scene::EPT_POINT_SPRITES) return; if ( 0 == CurrentShader ) return; VertexCache_reset ( vertices, vertexCount, indexList, primitiveCount, vType, pType, iType ); const s4DVertex * face[3]; f32 dc_area; s32 lodLevel; u32 i; u32 g; u32 m; video::CSoftwareTexture2* tex; for ( i = 0; i < (u32) primitiveCount; ++i ) { VertexCache_get(face); // if fully outside or outside on same side if ( ( (face[0]->flag | face[1]->flag | face[2]->flag) & VERTEX4D_CLIPMASK ) != VERTEX4D_INSIDE ) continue; // if fully inside if ( ( face[0]->flag & face[1]->flag & face[2]->flag & VERTEX4D_CLIPMASK ) == VERTEX4D_INSIDE ) { dc_area = screenarea2 ( face ); if ( Material.org.BackfaceCulling && F32_LOWER_EQUAL_0( dc_area ) ) continue; else if ( Material.org.FrontfaceCulling && F32_GREATER_EQUAL_0( dc_area ) ) continue; // select mipmap dc_area = core::reciprocal ( dc_area ); for ( m = 0; m != vSize[VertexCache.vType].TexSize; ++m ) { if ( 0 == (tex = MAT_TEXTURE ( m )) ) { CurrentShader->setTextureParam(m, 0, 0); continue; } lodLevel = s32_log2_f32 ( texelarea2 ( face, m ) * dc_area ); CurrentShader->setTextureParam(m, tex, lodLevel ); select_polygon_mipmap2 ( (s4DVertex**) face, m, tex->getSize() ); } // rasterize CurrentShader->drawTriangle ( face[0] + 1, face[1] + 1, face[2] + 1 ); continue; } // else if not complete inside clipping necessary irr::memcpy32_small ( ( (u8*) CurrentOut.data + ( 0 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ), face[0], SIZEOF_SVERTEX * 2 ); irr::memcpy32_small ( ( (u8*) CurrentOut.data + ( 1 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ), face[1], SIZEOF_SVERTEX * 2 ); irr::memcpy32_small ( ( (u8*) CurrentOut.data + ( 2 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ), face[2], SIZEOF_SVERTEX * 2 ); const u32 flag = CurrentOut.data->flag & VERTEX4D_FORMAT_MASK; for ( g = 0; g != CurrentOut.ElementSize; ++g ) { CurrentOut.data[g].flag = flag; Temp.data[g].flag = flag; } u32 vOut; vOut = clipToFrustum ( CurrentOut.data, Temp.data, 3 ); if ( vOut < 3 ) continue; vOut <<= 1; // to DC Space, project homogenous vertex ndc_2_dc_and_project ( CurrentOut.data + 1, CurrentOut.data, vOut ); /* // TODO: don't stick on 32 Bit Pointer #define PointerAsValue(x) ( (u32) (u32*) (x) ) // if not complete inside clipping necessary if ( ( test & VERTEX4D_INSIDE ) != VERTEX4D_INSIDE ) { u32 v[2] = { PointerAsValue ( Temp ) , PointerAsValue ( CurrentOut ) }; for ( g = 0; g != 6; ++g ) { vOut = clipToHyperPlane ( (s4DVertex*) v[0], (s4DVertex*) v[1], vOut, NDCPlane[g] ); if ( vOut < 3 ) break; v[0] ^= v[1]; v[1] ^= v[0]; v[0] ^= v[1]; } if ( vOut < 3 ) continue; } */ // check 2d backface culling on first dc_area = screenarea ( CurrentOut.data ); if ( Material.org.BackfaceCulling && F32_LOWER_EQUAL_0 ( dc_area ) ) continue; else if ( Material.org.FrontfaceCulling && F32_GREATER_EQUAL_0( dc_area ) ) continue; // select mipmap dc_area = core::reciprocal ( dc_area ); for ( m = 0; m != vSize[VertexCache.vType].TexSize; ++m ) { if ( 0 == (tex = MAT_TEXTURE ( m )) ) { CurrentShader->setTextureParam(m, 0, 0); continue; } lodLevel = s32_log2_f32 ( texelarea ( CurrentOut.data, m ) * dc_area ); CurrentShader->setTextureParam(m, tex, lodLevel ); select_polygon_mipmap ( CurrentOut.data, vOut, m, tex->getSize() ); } // re-tesselate ( triangle-fan, 0-1-2,0-2-3.. ) for ( g = 0; g <= vOut - 6; g += 2 ) { // rasterize CurrentShader->drawTriangle ( CurrentOut.data + 0 + 1, CurrentOut.data + g + 3, CurrentOut.data + g + 5); } } // dump statistics /* char buf [64]; sprintf ( buf,"VCount:%d PCount:%d CacheMiss: %d", vertexCount, primitiveCount, VertexCache.CacheMiss ); os::Printer::log( buf ); */ } //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. void CBurningVideoDriver::setAmbientLight(const SColorf& color) { LightSpace.Global_AmbientLight.setColorf ( color ); } //! adds a dynamic light s32 CBurningVideoDriver::addDynamicLight(const SLight& dl) { (void) CNullDriver::addDynamicLight( dl ); SBurningShaderLight l; // l.org = dl; l.Type = dl.Type; l.LightIsOn = true; l.AmbientColor.setColorf ( dl.AmbientColor ); l.DiffuseColor.setColorf ( dl.DiffuseColor ); l.SpecularColor.setColorf ( dl.SpecularColor ); switch ( dl.Type ) { case video::ELT_DIRECTIONAL: l.pos.x = -dl.Direction.X; l.pos.y = -dl.Direction.Y; l.pos.z = -dl.Direction.Z; l.pos.w = 1.f; break; case ELT_POINT: case ELT_SPOT: LightSpace.Flags |= POINTLIGHT; l.pos.x = dl.Position.X; l.pos.y = dl.Position.Y; l.pos.z = dl.Position.Z; l.pos.w = 1.f; /* l.radius = (1.f / dl.Attenuation.Y) * (1.f / dl.Attenuation.Y); l.constantAttenuation = dl.Attenuation.X; l.linearAttenuation = dl.Attenuation.Y; l.quadraticAttenuation = dl.Attenuation.Z; */ l.radius = dl.Radius * dl.Radius; l.constantAttenuation = dl.Attenuation.X; l.linearAttenuation = 1.f / dl.Radius; l.quadraticAttenuation = dl.Attenuation.Z; break; default: break; } LightSpace.Light.push_back ( l ); return LightSpace.Light.size() - 1; } //! Turns a dynamic light on or off void CBurningVideoDriver::turnLightOn(s32 lightIndex, bool turnOn) { if(lightIndex > -1 && lightIndex < (s32)LightSpace.Light.size()) { LightSpace.Light[lightIndex].LightIsOn = turnOn; } } //! deletes all dynamic lights there are void CBurningVideoDriver::deleteAllDynamicLights() { LightSpace.reset (); CNullDriver::deleteAllDynamicLights(); } //! returns the maximal amount of dynamic lights the device can handle u32 CBurningVideoDriver::getMaximalDynamicLightAmount() const { return 8; } //! sets a material void CBurningVideoDriver::setMaterial(const SMaterial& material) { Material.org = material; #ifdef SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM for (u32 i = 0; i < 2; ++i) { setTransform((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + i), material.getTextureMatrix(i)); } #endif #ifdef SOFTWARE_DRIVER_2_LIGHTING Material.AmbientColor.setR8G8B8 ( Material.org.AmbientColor.color ); Material.DiffuseColor.setR8G8B8 ( Material.org.DiffuseColor.color ); Material.EmissiveColor.setR8G8B8 ( Material.org.EmissiveColor.color ); Material.SpecularColor.setR8G8B8 ( Material.org.SpecularColor.color ); core::setbit_cond ( LightSpace.Flags, Material.org.Shininess != 0.f, SPECULAR ); core::setbit_cond ( LightSpace.Flags, Material.org.FogEnable, FOG ); core::setbit_cond ( LightSpace.Flags, Material.org.NormalizeNormals, NORMALIZE ); #endif setCurrentShader(); } /*! Camera Position in World Space */ void CBurningVideoDriver::getCameraPosWorldSpace () { Transformation[ETS_VIEW_INVERSE] = Transformation[ ETS_VIEW ]; Transformation[ETS_VIEW_INVERSE].makeInverse (); TransformationFlag[ETS_VIEW_INVERSE] = 0; const f32 *M = Transformation[ETS_VIEW_INVERSE].pointer (); /* The viewpoint is at (0., 0., 0.) in eye space. Turning this into a vector [0 0 0 1] and multiply it by the inverse of the view matrix, the resulting vector is the object space location of the camera. */ LightSpace.campos.x = M[12]; LightSpace.campos.y = M[13]; LightSpace.campos.z = M[14]; LightSpace.campos.w = 1.f; } void CBurningVideoDriver::getLightPosObjectSpace () { if ( TransformationFlag[ETS_WORLD] & ETF_IDENTITY ) { Transformation[ETS_WORLD_INVERSE] = Transformation[ETS_WORLD]; TransformationFlag[ETS_WORLD_INVERSE] |= ETF_IDENTITY; } else { Transformation[ETS_WORLD].getInverse ( Transformation[ETS_WORLD_INVERSE] ); TransformationFlag[ETS_WORLD_INVERSE] &= ~ETF_IDENTITY; } for ( u32 i = 0; i < 1 && i < LightSpace.Light.size(); ++i ) { SBurningShaderLight &l = LightSpace.Light[i]; Transformation[ETS_WORLD_INVERSE].transformVec3 ( &l.pos_objectspace.x, &l.pos.x ); } } #ifdef SOFTWARE_DRIVER_2_LIGHTING //! Sets the fog mode. void CBurningVideoDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog) { CNullDriver::setFog(color, fogType, start, end, density, pixelFog, rangeFog); LightSpace.FogColor.setA8R8G8B8 ( color.color ); } /*! applies lighting model */ void CBurningVideoDriver::lightVertex ( s4DVertex *dest, u32 vertexargb ) { sVec3 dColor; dColor = LightSpace.Global_AmbientLight; dColor.add ( Material.EmissiveColor ); if ( Lights.size () == 0 ) { dColor.saturate( dest->Color[0], vertexargb); return; } sVec3 ambient; sVec3 diffuse; sVec3 specular; // the universe started in darkness.. ambient.set ( 0.f, 0.f, 0.f ); diffuse.set ( 0.f, 0.f, 0.f ); specular.set ( 0.f, 0.f, 0.f ); u32 i; f32 dot; f32 len; f32 attenuation; sVec4 vp; // unit vector vertex to light sVec4 lightHalf; // blinn-phong reflection for ( i = 0; i!= LightSpace.Light.size (); ++i ) { const SBurningShaderLight &light = LightSpace.Light[i]; if ( !light.LightIsOn ) continue; // accumulate ambient ambient.add ( light.AmbientColor ); switch ( light.Type ) { case video::ELT_SPOT: case video::ELT_POINT: // surface to light vp.x = light.pos.x - LightSpace.vertex.x; vp.y = light.pos.y - LightSpace.vertex.y; vp.z = light.pos.z - LightSpace.vertex.z; //vp.x = light.pos_objectspace.x - LightSpace.vertex.x; //vp.y = light.pos_objectspace.y - LightSpace.vertex.x; //vp.z = light.pos_objectspace.z - LightSpace.vertex.x; len = vp.get_length_xyz_square(); if ( light.radius < len ) continue; len = core::reciprocal_squareroot ( len ); // build diffuse reflection //angle between normal and light vector vp.mul ( len ); dot = LightSpace.normal.dot_xyz ( vp ); if ( dot < 0.f ) continue; attenuation = light.constantAttenuation + ( 1.f - ( len * light.linearAttenuation ) ); // diffuse component diffuse.mulAdd ( light.DiffuseColor, 3.f * dot * attenuation ); if ( !(LightSpace.Flags & SPECULAR) ) continue; // build specular // surface to view lightHalf.x = LightSpace.campos.x - LightSpace.vertex.x; lightHalf.y = LightSpace.campos.y - LightSpace.vertex.y; lightHalf.z = LightSpace.campos.z - LightSpace.vertex.z; lightHalf.normalize_xyz(); lightHalf += vp; lightHalf.normalize_xyz(); // specular dot = LightSpace.normal.dot_xyz ( lightHalf ); if ( dot < 0.f ) continue; //specular += light.SpecularColor * ( powf ( Material.org.Shininess ,dot ) * attenuation ); specular.mulAdd ( light.SpecularColor, dot * attenuation ); break; case video::ELT_DIRECTIONAL: //angle between normal and light vector dot = LightSpace.normal.dot_xyz ( light.pos ); if ( dot < 0.f ) continue; // diffuse component diffuse.mulAdd ( light.DiffuseColor, dot ); break; default: break; } } // sum up lights dColor.mulAdd (ambient, Material.AmbientColor ); dColor.mulAdd (diffuse, Material.DiffuseColor); dColor.mulAdd (specular, Material.SpecularColor); dColor.saturate ( dest->Color[0], vertexargb ); } #endif //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect, SColor color, bool useAlphaChannelOfTexture) { if (texture) { if (texture->getDriverType() != EDT_BURNINGSVIDEO) { os::Printer::log("Fatal Error: Tried to copy from a surface not owned by this driver.", ELL_ERROR); return; } #if 0 // 2d methods don't use viewPort core::position2di dest = destPos; core::recti clip=ViewPort; if (ViewPort.getSize().Width != ScreenSize.Width) { dest.X=ViewPort.UpperLeftCorner.X+core::round32(destPos.X*ViewPort.getWidth()/(f32)ScreenSize.Width); dest.Y=ViewPort.UpperLeftCorner.Y+core::round32(destPos.Y*ViewPort.getHeight()/(f32)ScreenSize.Height); if (clipRect) { clip.constrainTo(*clipRect); } clipRect = &clip; } #endif if (useAlphaChannelOfTexture) ((CSoftwareTexture2*)texture)->getImage()->copyToWithAlpha( RenderTargetSurface, destPos, sourceRect, color, clipRect); else ((CSoftwareTexture2*)texture)->getImage()->copyTo( RenderTargetSurface, destPos, sourceRect, clipRect); } } //! Draws a part of the texture into the rectangle. void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core::rect& destRect, const core::rect& sourceRect, const core::rect* clipRect, const video::SColor* const colors, bool useAlphaChannelOfTexture) { if (texture) { if (texture->getDriverType() != EDT_BURNINGSVIDEO) { os::Printer::log("Fatal Error: Tried to copy from a surface not owned by this driver.", ELL_ERROR); return; } if (useAlphaChannelOfTexture) StretchBlit(BLITTER_TEXTURE_ALPHA_BLEND, RenderTargetSurface, &destRect, &sourceRect, ((CSoftwareTexture2*)texture)->getImage(), (colors ? colors[0].color : 0)); else StretchBlit(BLITTER_TEXTURE, RenderTargetSurface, &destRect, &sourceRect, ((CSoftwareTexture2*)texture)->getImage(), (colors ? colors[0].color : 0)); } } //! Draws a 2d line. void CBurningVideoDriver::draw2DLine(const core::position2d& start, const core::position2d& end, SColor color) { drawLine(BackBuffer, start, end, color ); } //! Draws a pixel void CBurningVideoDriver::drawPixel(u32 x, u32 y, const SColor & color) { BackBuffer->setPixel(x, y, color, true); } //! draw an 2d rectangle void CBurningVideoDriver::draw2DRectangle(SColor color, const core::rect& pos, const core::rect* clip) { if (clip) { core::rect p(pos); p.clipAgainst(*clip); if(!p.isValid()) return; drawRectangle(BackBuffer, p, color); } else { if(!pos.isValid()) return; drawRectangle(BackBuffer, pos, color); } } //! Only used by the internal engine. Used to notify the driver that //! the window was resized. void CBurningVideoDriver::OnResize(const core::dimension2d& size) { // make sure width and height are multiples of 2 core::dimension2d realSize(size); if (realSize.Width % 2) realSize.Width += 1; if (realSize.Height % 2) realSize.Height += 1; if (ScreenSize != realSize) { if (ViewPort.getWidth() == (s32)ScreenSize.Width && ViewPort.getHeight() == (s32)ScreenSize.Height) { ViewPort.UpperLeftCorner.X = 0; ViewPort.UpperLeftCorner.Y = 0; ViewPort.LowerRightCorner.X = realSize.Width; ViewPort.LowerRightCorner.X = realSize.Height; } ScreenSize = realSize; bool resetRT = (RenderTargetSurface == BackBuffer); if (BackBuffer) BackBuffer->drop(); BackBuffer = new CImage(BURNINGSHADER_COLOR_FORMAT, realSize); if (resetRT) setRenderTarget(BackBuffer); } } //! returns the current render target size const core::dimension2d& CBurningVideoDriver::getCurrentRenderTargetSize() const { return RenderTargetSize; } //!Draws an 2d rectangle with a gradient. void CBurningVideoDriver::draw2DRectangle(const core::rect& position, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip) { #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR core::rect pos = position; if (clip) pos.clipAgainst(*clip); if (!pos.isValid()) return; const core::dimension2d renderTargetSize ( ViewPort.getSize() ); const s32 xPlus = -(renderTargetSize.Width>>1); const f32 xFact = 1.0f / (renderTargetSize.Width>>1); const s32 yPlus = renderTargetSize.Height-(renderTargetSize.Height>>1); const f32 yFact = 1.0f / (renderTargetSize.Height>>1); // fill VertexCache direct s4DVertex *v; VertexCache.vertexCount = 4; VertexCache.info[0].index = 0; VertexCache.info[1].index = 1; VertexCache.info[2].index = 2; VertexCache.info[3].index = 3; v = &VertexCache.mem.data [ 0 ]; v[0].Pos.set ( (f32)(pos.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-pos.UpperLeftCorner.Y) * yFact, 0.f, 1.f ); v[0].Color[0].setA8R8G8B8 ( colorLeftUp.color ); v[2].Pos.set ( (f32)(pos.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus- pos.UpperLeftCorner.Y) * yFact, 0.f, 1.f ); v[2].Color[0].setA8R8G8B8 ( colorRightUp.color ); v[4].Pos.set ( (f32)(pos.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus-pos.LowerRightCorner.Y) * yFact, 0.f ,1.f ); v[4].Color[0].setA8R8G8B8 ( colorRightDown.color ); v[6].Pos.set ( (f32)(pos.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-pos.LowerRightCorner.Y) * yFact, 0.f, 1.f ); v[6].Color[0].setA8R8G8B8 ( colorLeftDown.color ); s32 i; u32 g; for ( i = 0; i!= 8; i += 2 ) { v[i + 0].flag = clipToFrustumTest ( v + i ); v[i + 1].flag = 0; if ( (v[i].flag & VERTEX4D_INSIDE ) == VERTEX4D_INSIDE ) { ndc_2_dc_and_project ( v + i + 1, v + i, 2 ); } } IBurningShader * render; render = BurningShader [ ETR_GOURAUD_ALPHA_NOZ ]; render->setRenderTarget(RenderTargetSurface, ViewPort); static const s16 indexList[6] = {0,1,2,0,2,3}; s4DVertex * face[3]; for ( i = 0; i!= 6; i += 3 ) { face[0] = VertexCache_getVertex ( indexList [ i + 0 ] ); face[1] = VertexCache_getVertex ( indexList [ i + 1 ] ); face[2] = VertexCache_getVertex ( indexList [ i + 2 ] ); // test clipping u32 test = face[0]->flag & face[1]->flag & face[2]->flag & VERTEX4D_INSIDE; if ( test == VERTEX4D_INSIDE ) { render->drawTriangle ( face[0] + 1, face[1] + 1, face[2] + 1 ); continue; } // Todo: all vertices are clipped in 2d.. // is this true ? u32 vOut = 6; memcpy ( CurrentOut.data + 0, face[0], sizeof ( s4DVertex ) * 2 ); memcpy ( CurrentOut.data + 2, face[1], sizeof ( s4DVertex ) * 2 ); memcpy ( CurrentOut.data + 4, face[2], sizeof ( s4DVertex ) * 2 ); vOut = clipToFrustum ( CurrentOut.data, Temp.data, 3 ); if ( vOut < 3 ) continue; vOut <<= 1; // to DC Space, project homogenous vertex ndc_2_dc_and_project ( CurrentOut.data + 1, CurrentOut.data, vOut ); // re-tesselate ( triangle-fan, 0-1-2,0-2-3.. ) for ( g = 0; g <= vOut - 6; g += 2 ) { // rasterize render->drawTriangle ( CurrentOut.data + 1, &CurrentOut.data[g + 3], &CurrentOut.data[g + 5] ); } } #else draw2DRectangle ( colorLeftUp, position, clip ); #endif } //! Draws a 3d line. void CBurningVideoDriver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color) { Transformation [ ETS_CURRENT].transformVect ( &CurrentOut.data[0].Pos.x, start ); Transformation [ ETS_CURRENT].transformVect ( &CurrentOut.data[2].Pos.x, end ); u32 g; u32 vOut; // no clipping flags for ( g = 0; g != CurrentOut.ElementSize; ++g ) { CurrentOut.data[g].flag = 0; Temp.data[g].flag = 0; } // vertices count per line vOut = clipToFrustum ( CurrentOut.data, Temp.data, 2 ); if ( vOut < 2 ) return; vOut <<= 1; IBurningShader * line; line = BurningShader [ ETR_TEXTURE_GOURAUD_WIRE ]; line->setRenderTarget(RenderTargetSurface, ViewPort); // to DC Space, project homogenous vertex ndc_2_dc_and_project ( CurrentOut.data + 1, CurrentOut.data, vOut ); // unproject vertex color #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR for ( g = 0; g != vOut; g+= 2 ) { CurrentOut.data[ g + 1].Color[0].setA8R8G8B8 ( color.color ); } #endif for ( g = 0; g <= vOut - 4; g += 2 ) { // rasterize line->drawLine ( CurrentOut.data + 1, CurrentOut.data + g + 3 ); } } //! \return Returns the name of the video driver. Example: In case of the DirectX8 //! driver, it would return "Direct3D8.1". const wchar_t* CBurningVideoDriver::getName() const { #ifdef BURNINGVIDEO_RENDERER_BEAUTIFUL return L"Burning's Video 0.47 beautiful"; #elif defined ( BURNINGVIDEO_RENDERER_ULTRA_FAST ) return L"Burning's Video 0.47 ultra fast"; #elif defined ( BURNINGVIDEO_RENDERER_FAST ) return L"Burning's Video 0.47 fast"; #else return L"Burning's Video 0.47"; #endif } //! Returns the graphics card vendor name. core::stringc CBurningVideoDriver::getVendorInfo() { return "Burning's Video: Ing. Thomas Alten (c) 2006-2012"; } //! Returns type of video driver E_DRIVER_TYPE CBurningVideoDriver::getDriverType() const { return EDT_BURNINGSVIDEO; } //! returns color format ECOLOR_FORMAT CBurningVideoDriver::getColorFormat() const { return BURNINGSHADER_COLOR_FORMAT; } //! Returns the transformation set by setTransform const core::matrix4& CBurningVideoDriver::getTransform(E_TRANSFORMATION_STATE state) const { return Transformation[state]; } //! Creates a render target texture. ITexture* CBurningVideoDriver::addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format) { IImage* img = createImage(BURNINGSHADER_COLOR_FORMAT, size); ITexture* tex = new CSoftwareTexture2(img, name, CSoftwareTexture2::IS_RENDERTARGET ); img->drop(); addTexture(tex); tex->drop(); return tex; } //! Clears the DepthBuffer. void CBurningVideoDriver::clearZBuffer() { if (DepthBuffer) DepthBuffer->clear(); } //! Returns an image created from the last rendered frame. IImage* CBurningVideoDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target) { if (target != video::ERT_FRAME_BUFFER) return 0; if (BackBuffer) { IImage* tmp = createImage(BackBuffer->getColorFormat(), BackBuffer->getDimension()); BackBuffer->copyTo(tmp); return tmp; } else return 0; } //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES ITexture* CBurningVideoDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) { return new CSoftwareTexture2( surface, name, (getTextureCreationFlag(ETCF_CREATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP : 0 ) | (getTextureCreationFlag(ETCF_ALLOW_NON_POWER_2) ? 0 : CSoftwareTexture2::NP2_SIZE ), mipmapData); } //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. u32 CBurningVideoDriver::getMaximalPrimitiveCount() const { return 0xFFFFFFFF; } //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do //! this: First, draw all geometry. Then use this method, to draw the shadow //! volume. Next use IVideoDriver::drawStencilShadow() to visualize the shadow. void CBurningVideoDriver::drawStencilShadowVolume(const core::array& triangles, bool zfail, u32 debugDataVisible) { const u32 count = triangles.size(); IBurningShader *shader = BurningShader [ ETR_STENCIL_SHADOW ]; CurrentShader = shader; shader->setRenderTarget(RenderTargetSurface, ViewPort); Material.org.MaterialType = video::EMT_SOLID; Material.org.Lighting = false; Material.org.ZWriteEnable = false; Material.org.ZBuffer = ECFN_LESSEQUAL; LightSpace.Flags &= ~VERTEXTRANSFORM; //glStencilMask(~0); //glStencilFunc(GL_ALWAYS, 0, ~0); if (true)// zpass does not work yet { Material.org.BackfaceCulling = true; Material.org.FrontfaceCulling = false; shader->setParam ( 0, 0 ); shader->setParam ( 1, 1 ); shader->setParam ( 2, 0 ); drawVertexPrimitiveList (triangles.const_pointer(), count, 0, count/3, (video::E_VERTEX_TYPE) 4, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) 4 ); //glStencilOp(GL_KEEP, incr, GL_KEEP); //glDrawArrays(GL_TRIANGLES,0,count); Material.org.BackfaceCulling = false; Material.org.FrontfaceCulling = true; shader->setParam ( 0, 0 ); shader->setParam ( 1, 2 ); shader->setParam ( 2, 0 ); drawVertexPrimitiveList (triangles.const_pointer(), count, 0, count/3, (video::E_VERTEX_TYPE) 4, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) 4 ); //glStencilOp(GL_KEEP, decr, GL_KEEP); //glDrawArrays(GL_TRIANGLES,0,count); } else // zpass { Material.org.BackfaceCulling = true; Material.org.FrontfaceCulling = false; shader->setParam ( 0, 0 ); shader->setParam ( 1, 0 ); shader->setParam ( 2, 1 ); //glStencilOp(GL_KEEP, GL_KEEP, incr); //glDrawArrays(GL_TRIANGLES,0,count); Material.org.BackfaceCulling = false; Material.org.FrontfaceCulling = true; shader->setParam ( 0, 0 ); shader->setParam ( 1, 0 ); shader->setParam ( 2, 2 ); //glStencilOp(GL_KEEP, GL_KEEP, decr); //glDrawArrays(GL_TRIANGLES,0,count); } } //! Fills the stencil shadow with color. After the shadow volume has been drawn //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this //! to draw the color of the shadow. void CBurningVideoDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge, video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge) { if (!StencilBuffer) return; // draw a shadow rectangle covering the entire screen using stencil buffer const u32 h = RenderTargetSurface->getDimension().Height; const u32 w = RenderTargetSurface->getDimension().Width; tVideoSample *dst; u32 *stencil; u32* const stencilBase=(u32*) StencilBuffer->lock(); for ( u32 y = 0; y < h; ++y ) { dst = (tVideoSample*)RenderTargetSurface->lock() + ( y * w ); stencil = stencilBase + ( y * w ); for ( u32 x = 0; x < w; ++x ) { if ( stencil[x] > 1 ) { dst[x] = PixelBlend32 ( dst[x], leftUpEdge.color ); } } } StencilBuffer->clear(); } core::dimension2du CBurningVideoDriver::getMaxTextureSize() const { return core::dimension2du(SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE, SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE); } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a video driver IVideoDriver* createBurningVideoDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, video::IImagePresenter* presenter) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CBurningVideoDriver(params, io, presenter); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSoftwareDriver.h0000644000000000000000000001430512574354552020362 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_VIDEO_SOFTWARE_H_INCLUDED__ #define __C_VIDEO_SOFTWARE_H_INCLUDED__ #include "ITriangleRenderer.h" #include "CNullDriver.h" #include "SViewFrustum.h" #include "CImage.h" namespace irr { namespace video { class CSoftwareDriver : public CNullDriver { public: //! constructor CSoftwareDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter); //! destructor virtual ~CSoftwareDriver(); //! queries the features of the driver, returns true if feature is available virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const; //! sets transformation virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat); //! sets a material virtual void setMaterial(const SMaterial& material); virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color); //! sets a viewport virtual void setViewPort(const core::rect& area); //! clears the zbuffer virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! presents the rendered scene on the screen, returns false if failed virtual bool endScene(); //! Only used by the internal engine. Used to notify the driver that //! the window was resized. virtual void OnResize(const core::dimension2d& size); //! returns size of the current render target virtual const core::dimension2d& getCurrentRenderTargetSize() const; //! draws a vertex primitive list void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); //! Draws a 3d line. virtual void draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color = SColor(255,255,255,255)); //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect = 0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false); //! draw an 2d rectangle virtual void draw2DRectangle(SColor color, const core::rect& pos, const core::rect* clip = 0); //!Draws an 2d rectangle with a gradient. virtual void draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip = 0); //! Draws a 2d line. virtual void draw2DLine(const core::position2d& start, const core::position2d& end, SColor color=SColor(255,255,255,255)); //! Draws a single pixel virtual void drawPixel(u32 x, u32 y, const SColor & color); //! \return Returns the name of the video driver. Example: In case of the Direct3D8 //! driver, it would return "Direct3D8.1". virtual const wchar_t* getName() const; //! Returns type of video driver virtual E_DRIVER_TYPE getDriverType() const; //! get color format of the current color buffer virtual ECOLOR_FORMAT getColorFormat() const; //! Returns the transformation set by setTransform virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const; //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); //! Creates a render target texture. virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! Clears the ZBuffer. virtual void clearZBuffer(); //! Returns an image created from the last rendered frame. virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER); //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. virtual u32 getMaximalPrimitiveCount() const; protected: //! sets a render target void setRenderTarget(video::CImage* image); //! sets the current Texture bool setActiveTexture(u32 stage, video::ITexture* texture); //! switches to a triangle renderer void switchToTriangleRenderer(ETriangleRenderer renderer); //! void selects the right triangle renderer based on the render states. void selectRightTriangleRenderer(); //! clips a triangle agains the viewing frustum void clipTriangle(f32* transformedPos); //! draws a vertex primitive list void drawVertexPrimitiveList16(const void* vertices, u32 vertexCount, const u16* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType); template void drawClippedIndexedTriangleListT(const VERTEXTYPE* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount); video::CImage* BackBuffer; video::IImagePresenter* Presenter; void* WindowId; core::rect* SceneSourceRect; core::array TransformedPoints; video::ITexture* RenderTargetTexture; video::CImage* RenderTargetSurface; core::position2d Render2DTranslation; core::dimension2d RenderTargetSize; core::dimension2d ViewPortSize; core::matrix4 TransformationMatrix[ETS_COUNT]; ITriangleRenderer* CurrentTriangleRenderer; ITriangleRenderer* TriangleRenderers[ETR_COUNT]; ETriangleRenderer CurrentRenderer; IZBuffer* ZBuffer; video::ITexture* Texture; SMaterial Material; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSoftwareDriver.cpp0000644000000000000000000006441512574354552020724 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CSoftwareDriver.h" #ifdef _IRR_COMPILE_WITH_SOFTWARE_ #include "CSoftwareTexture.h" #include "CBlit.h" #include "os.h" #include "S3DVertex.h" namespace irr { namespace video { //! constructor CSoftwareDriver::CSoftwareDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter) : CNullDriver(io, windowSize), BackBuffer(0), Presenter(presenter), WindowId(0), SceneSourceRect(0), RenderTargetTexture(0), RenderTargetSurface(0), CurrentTriangleRenderer(0), ZBuffer(0), Texture(0) { #ifdef _DEBUG setDebugName("CSoftwareDriver"); #endif // create backbuffer BackBuffer = new CImage(ECF_A1R5G5B5, windowSize); if (BackBuffer) { BackBuffer->fill(SColor(0)); // create z buffer ZBuffer = video::createZBuffer(BackBuffer->getDimension()); } DriverAttributes->setAttribute("MaxTextures", 1); DriverAttributes->setAttribute("MaxIndices", 1<<16); DriverAttributes->setAttribute("MaxTextureSize", 1024); DriverAttributes->setAttribute("Version", 1); // create triangle renderers TriangleRenderers[ETR_FLAT] = createTriangleRendererFlat(ZBuffer); TriangleRenderers[ETR_FLAT_WIRE] = createTriangleRendererFlatWire(ZBuffer); TriangleRenderers[ETR_GOURAUD] = createTriangleRendererGouraud(ZBuffer); TriangleRenderers[ETR_GOURAUD_WIRE] = createTriangleRendererGouraudWire(ZBuffer); TriangleRenderers[ETR_TEXTURE_FLAT] = createTriangleRendererTextureFlat(ZBuffer); TriangleRenderers[ETR_TEXTURE_FLAT_WIRE] = createTriangleRendererTextureFlatWire(ZBuffer); TriangleRenderers[ETR_TEXTURE_GOURAUD] = createTriangleRendererTextureGouraud(ZBuffer); TriangleRenderers[ETR_TEXTURE_GOURAUD_WIRE] = createTriangleRendererTextureGouraudWire(ZBuffer); TriangleRenderers[ETR_TEXTURE_GOURAUD_NOZ] = createTriangleRendererTextureGouraudNoZ(); TriangleRenderers[ETR_TEXTURE_GOURAUD_ADD] = createTriangleRendererTextureGouraudAdd(ZBuffer); // select render target setRenderTarget(BackBuffer); // select the right renderer selectRightTriangleRenderer(); } //! destructor CSoftwareDriver::~CSoftwareDriver() { // delete Backbuffer if (BackBuffer) BackBuffer->drop(); // delete triangle renderers for (s32 i=0; idrop(); // delete zbuffer if (ZBuffer) ZBuffer->drop(); // delete current texture if (Texture) Texture->drop(); if (RenderTargetTexture) RenderTargetTexture->drop(); if (RenderTargetSurface) RenderTargetSurface->drop(); } //! switches to a triangle renderer void CSoftwareDriver::switchToTriangleRenderer(ETriangleRenderer renderer) { video::IImage* s = 0; if (Texture) s = ((CSoftwareTexture*)Texture)->getTexture(); CurrentTriangleRenderer = TriangleRenderers[renderer]; CurrentTriangleRenderer->setBackfaceCulling(Material.BackfaceCulling == true); CurrentTriangleRenderer->setTexture(s); CurrentTriangleRenderer->setRenderTarget(RenderTargetSurface, ViewPort); } //! void selects the right triangle renderer based on the render states. void CSoftwareDriver::selectRightTriangleRenderer() { ETriangleRenderer renderer = ETR_FLAT; if (Texture) { if (!Material.GouraudShading) renderer = (!Material.Wireframe) ? ETR_TEXTURE_FLAT : ETR_TEXTURE_FLAT_WIRE; else { if (Material.Wireframe) renderer = ETR_TEXTURE_GOURAUD_WIRE; else { if (Material.MaterialType == EMT_TRANSPARENT_ADD_COLOR || Material.MaterialType == EMT_TRANSPARENT_ALPHA_CHANNEL || Material.MaterialType == EMT_TRANSPARENT_VERTEX_ALPHA) { // simply draw all transparent stuff with the same renderer. at // least it is transparent then. renderer = ETR_TEXTURE_GOURAUD_ADD; } else if ((Material.ZBuffer==ECFN_NEVER) && !Material.ZWriteEnable) renderer = ETR_TEXTURE_GOURAUD_NOZ; else { renderer = ETR_TEXTURE_GOURAUD; } } } } else { if (!Material.GouraudShading) renderer = (!Material.Wireframe) ? ETR_FLAT : ETR_FLAT_WIRE; else renderer = (!Material.Wireframe) ? ETR_GOURAUD : ETR_GOURAUD_WIRE; } switchToTriangleRenderer(renderer); } //! queries the features of the driver, returns true if feature is available bool CSoftwareDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const { switch (feature) { case EVDF_RENDER_TO_TARGET: case EVDF_TEXTURE_NSQUARE: return FeatureEnabled[feature]; default: return false; }; } //! sets transformation void CSoftwareDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) { TransformationMatrix[state] = mat; } //! sets the current Texture bool CSoftwareDriver::setActiveTexture(u32 stage, video::ITexture* texture) { if (texture && texture->getDriverType() != EDT_SOFTWARE) { os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); return false; } if (Texture) Texture->drop(); Texture = texture; if (Texture) Texture->grab(); selectRightTriangleRenderer(); return true; } //! sets a material void CSoftwareDriver::setMaterial(const SMaterial& material) { Material = material; OverrideMaterial.apply(Material); for (u32 i = 0; i < 1; ++i) { setActiveTexture(i, Material.getTexture(i)); setTransform ((E_TRANSFORMATION_STATE) ( ETS_TEXTURE_0 + i ), material.getTextureMatrix(i)); } } //! clears the zbuffer bool CSoftwareDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, const SExposedVideoData& videoData, core::rect* sourceRect) { CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); WindowId=videoData.D3D9.HWnd; SceneSourceRect = sourceRect; if (backBuffer && BackBuffer) BackBuffer->fill(color); if (ZBuffer && zBuffer) ZBuffer->clear(); return true; } //! presents the rendered scene on the screen, returns false if failed bool CSoftwareDriver::endScene() { CNullDriver::endScene(); return Presenter->present(BackBuffer, WindowId, SceneSourceRect); } //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES ITexture* CSoftwareDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) { return new CSoftwareTexture(surface, name, false, mipmapData); } //! sets a render target bool CSoftwareDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color) { if (texture && texture->getDriverType() != EDT_SOFTWARE) { os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); return false; } if (RenderTargetTexture) RenderTargetTexture->drop(); RenderTargetTexture = texture; if (RenderTargetTexture) { RenderTargetTexture->grab(); setRenderTarget(((CSoftwareTexture*)RenderTargetTexture)->getTexture()); } else { setRenderTarget(BackBuffer); } if (RenderTargetSurface && (clearBackBuffer || clearZBuffer)) { if (clearZBuffer) ZBuffer->clear(); if (clearBackBuffer) RenderTargetSurface->fill(color); } return true; } //! sets a render target void CSoftwareDriver::setRenderTarget(video::CImage* image) { if (RenderTargetSurface) RenderTargetSurface->drop(); RenderTargetSurface = image; RenderTargetSize.Width = 0; RenderTargetSize.Height = 0; Render2DTranslation.X = 0; Render2DTranslation.Y = 0; if (RenderTargetSurface) { RenderTargetSurface->grab(); RenderTargetSize = RenderTargetSurface->getDimension(); } setViewPort(core::rect(0,0,RenderTargetSize.Width,RenderTargetSize.Height)); if (ZBuffer) ZBuffer->setSize(RenderTargetSize); } //! sets a viewport void CSoftwareDriver::setViewPort(const core::rect& area) { ViewPort = area; //TODO: the clipping is not correct, because the projection is affected. // to correct this, ViewPortSize and Render2DTranslation will have to be corrected. core::rect rendert(0,0,RenderTargetSize.Width,RenderTargetSize.Height); ViewPort.clipAgainst(rendert); ViewPortSize = core::dimension2du(ViewPort.getSize()); Render2DTranslation.X = (ViewPortSize.Width / 2) + ViewPort.UpperLeftCorner.X; Render2DTranslation.Y = ViewPort.UpperLeftCorner.Y + ViewPortSize.Height - (ViewPortSize.Height / 2);// + ViewPort.UpperLeftCorner.Y; if (CurrentTriangleRenderer) CurrentTriangleRenderer->setRenderTarget(RenderTargetSurface, ViewPort); } void CSoftwareDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { switch (iType) { case (EIT_16BIT): { drawVertexPrimitiveList16(vertices, vertexCount, (const u16*)indexList, primitiveCount, vType, pType); break; } case (EIT_32BIT): { os::Printer::log("Software driver can not render 32bit buffers", ELL_ERROR); break; } } } //! draws a vertex primitive list void CSoftwareDriver::drawVertexPrimitiveList16(const void* vertices, u32 vertexCount, const u16* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType) { const u16* indexPointer=0; core::array newBuffer; switch (pType) { case scene::EPT_LINE_STRIP: { switch (vType) { case EVT_STANDARD: { for (u32 i=0; i < primitiveCount-1; ++i) draw3DLine(((S3DVertex*)vertices)[indexList[i]].Pos, ((S3DVertex*)vertices)[indexList[i+1]].Pos, ((S3DVertex*)vertices)[indexList[i]].Color); } break; case EVT_2TCOORDS: { for (u32 i=0; i < primitiveCount-1; ++i) draw3DLine(((S3DVertex2TCoords*)vertices)[indexList[i]].Pos, ((S3DVertex2TCoords*)vertices)[indexList[i+1]].Pos, ((S3DVertex2TCoords*)vertices)[indexList[i]].Color); } break; case EVT_TANGENTS: { for (u32 i=0; i < primitiveCount-1; ++i) draw3DLine(((S3DVertexTangents*)vertices)[indexList[i]].Pos, ((S3DVertexTangents*)vertices)[indexList[i+1]].Pos, ((S3DVertexTangents*)vertices)[indexList[i]].Color); } break; } } return; case scene::EPT_LINE_LOOP: drawVertexPrimitiveList16(vertices, vertexCount, indexList, primitiveCount-1, vType, scene::EPT_LINE_STRIP); switch (vType) { case EVT_STANDARD: draw3DLine(((S3DVertex*)vertices)[indexList[primitiveCount-1]].Pos, ((S3DVertex*)vertices)[indexList[0]].Pos, ((S3DVertex*)vertices)[indexList[primitiveCount-1]].Color); break; case EVT_2TCOORDS: draw3DLine(((S3DVertex2TCoords*)vertices)[indexList[primitiveCount-1]].Pos, ((S3DVertex2TCoords*)vertices)[indexList[0]].Pos, ((S3DVertex2TCoords*)vertices)[indexList[primitiveCount-1]].Color); break; case EVT_TANGENTS: draw3DLine(((S3DVertexTangents*)vertices)[indexList[primitiveCount-1]].Pos, ((S3DVertexTangents*)vertices)[indexList[0]].Pos, ((S3DVertexTangents*)vertices)[indexList[primitiveCount-1]].Color); break; } return; case scene::EPT_LINES: { switch (vType) { case EVT_STANDARD: { for (u32 i=0; i < 2*primitiveCount; i+=2) draw3DLine(((S3DVertex*)vertices)[indexList[i]].Pos, ((S3DVertex*)vertices)[indexList[i+1]].Pos, ((S3DVertex*)vertices)[indexList[i]].Color); } break; case EVT_2TCOORDS: { for (u32 i=0; i < 2*primitiveCount; i+=2) draw3DLine(((S3DVertex2TCoords*)vertices)[indexList[i]].Pos, ((S3DVertex2TCoords*)vertices)[indexList[i+1]].Pos, ((S3DVertex2TCoords*)vertices)[indexList[i]].Color); } break; case EVT_TANGENTS: { for (u32 i=0; i < 2*primitiveCount; i+=2) draw3DLine(((S3DVertexTangents*)vertices)[indexList[i]].Pos, ((S3DVertexTangents*)vertices)[indexList[i+1]].Pos, ((S3DVertexTangents*)vertices)[indexList[i]].Color); } break; } } return; case scene::EPT_TRIANGLE_FAN: { // TODO: don't convert fan to list newBuffer.reallocate(primitiveCount*3); for( u32 t=0; t void CSoftwareDriver::drawClippedIndexedTriangleListT(const VERTEXTYPE* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) { if (!RenderTargetSurface || !ZBuffer || !triangleCount) return; if (!checkPrimitiveCount(triangleCount)) return; // arrays for storing clipped vertices core::array clippedVertices; core::array clippedIndices; // calculate inverse world transformation core::matrix4 worldinv(TransformationMatrix[ETS_WORLD]); worldinv.makeInverse(); // calculate view frustum planes scene::SViewFrustum frustum(TransformationMatrix[ETS_PROJECTION] * TransformationMatrix[ETS_VIEW]); // copy and transform clipping planes ignoring far plane core::plane3df planes[5]; // ordered by near, left, right, bottom, top for (int p=0; p<5; ++p) worldinv.transformPlane(frustum.planes[p+1], planes[p]); core::EIntersectionRelation3D inout[3]; // is point in front or back of plane? // temporary buffer for vertices to be clipped by all planes core::array tClpBuf; int t; int i; for (i=0; i textureSize(0,0); f32 zDiv; if (Texture) textureSize = ((CSoftwareTexture*)Texture)->getTexture()->getDimension(); f32 transformedPos[4]; // transform all points in the list core::matrix4 matrix(TransformationMatrix[ETS_PROJECTION]); matrix *= TransformationMatrix[ETS_VIEW]; matrix *= TransformationMatrix[ETS_WORLD]; s32 ViewTransformWidth = (ViewPortSize.Width>>1); s32 ViewTransformHeight = (ViewPortSize.Height>>1); for (i=0; i<(int)clippedVertices.size(); ++i) { transformedPos[0] = currentVertex->Pos.X; transformedPos[1] = currentVertex->Pos.Y; transformedPos[2] = currentVertex->Pos.Z; transformedPos[3] = 1.0f; matrix.multiplyWith1x4Matrix(transformedPos); zDiv = transformedPos[3] == 0.0f ? 1.0f : (1.0f / transformedPos[3]); tp->Pos.X = (s32)(ViewTransformWidth * (transformedPos[0] * zDiv) + (Render2DTranslation.X)); tp->Pos.Y = (Render2DTranslation.Y - (s32)(ViewTransformHeight * (transformedPos[1] * zDiv))); tp->Color = currentVertex->Color.toA1R5G5B5(); tp->ZValue = (TZBufferType)(32767.0f * zDiv); tp->TCoords.X = (s32)(currentVertex->TCoords.X * textureSize.Width); tp->TCoords.X <<= 8; tp->TCoords.Y = (s32)(currentVertex->TCoords.Y * textureSize.Height); tp->TCoords.Y <<= 8; ++currentVertex; ++tp; } // draw all transformed points from the index list CurrentTriangleRenderer->drawIndexedTriangleList(&TransformedPoints[0], clippedVertices.size(), clippedIndices.pointer(), clippedIndices.size()/3); } //! Draws a 3d line. void CSoftwareDriver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color) { core::vector3df vect = start.crossProduct(end); vect.normalize(); vect *= Material.Thickness*0.3f; S3DVertex vtx[4]; vtx[0].Color = color; vtx[1].Color = color; vtx[2].Color = color; vtx[3].Color = color; vtx[0].Pos = start; vtx[1].Pos = end; vtx[2].Pos = start + vect; vtx[3].Pos = end + vect; u16 idx[12] = {0,1,2, 0,2,1, 0,1,3, 0,3,1}; drawIndexedTriangleList(vtx, 4, idx, 4); } //! clips a triangle against the viewing frustum void CSoftwareDriver::clipTriangle(f32* transformedPos) { } //! Only used by the internal engine. Used to notify the driver that //! the window was resized. void CSoftwareDriver::OnResize(const core::dimension2d& size) { // make sure width and height are multiples of 2 core::dimension2d realSize(size); if (realSize.Width % 2) realSize.Width += 1; if (realSize.Height % 2) realSize.Height += 1; if (ScreenSize != realSize) { if (ViewPort.getWidth() == (s32)ScreenSize.Width && ViewPort.getHeight() == (s32)ScreenSize.Height) { ViewPort = core::rect(core::position2d(0,0), core::dimension2di(realSize)); } ScreenSize = realSize; bool resetRT = (RenderTargetSurface == BackBuffer); if (BackBuffer) BackBuffer->drop(); BackBuffer = new CImage(ECF_A1R5G5B5, realSize); if (resetRT) setRenderTarget(BackBuffer); } } //! returns the current render target size const core::dimension2d& CSoftwareDriver::getCurrentRenderTargetSize() const { return RenderTargetSize; } //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. void CSoftwareDriver::draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect, SColor color, bool useAlphaChannelOfTexture) { if (texture) { if (texture->getDriverType() != EDT_SOFTWARE) { os::Printer::log("Fatal Error: Tried to copy from a surface not owned by this driver.", ELL_ERROR); return; } if (useAlphaChannelOfTexture) ((CSoftwareTexture*)texture)->getImage()->copyToWithAlpha( RenderTargetSurface, destPos, sourceRect, color, clipRect); else ((CSoftwareTexture*)texture)->getImage()->copyTo( RenderTargetSurface, destPos, sourceRect, clipRect); } } //! Draws a 2d line. void CSoftwareDriver::draw2DLine(const core::position2d& start, const core::position2d& end, SColor color) { drawLine(RenderTargetSurface, start, end, color ); } //! Draws a pixel void CSoftwareDriver::drawPixel(u32 x, u32 y, const SColor & color) { BackBuffer->setPixel(x, y, color, true); } //! draw a 2d rectangle void CSoftwareDriver::draw2DRectangle(SColor color, const core::rect& pos, const core::rect* clip) { if (clip) { core::rect p(pos); p.clipAgainst(*clip); if(!p.isValid()) return; drawRectangle(RenderTargetSurface, p, color); } else { if(!pos.isValid()) return; drawRectangle(RenderTargetSurface, pos, color); } } //!Draws an 2d rectangle with a gradient. void CSoftwareDriver::draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip) { // TODO: implement draw2DRectangle(colorLeftUp, pos, clip); } //! \return Returns the name of the video driver. Example: In case of the Direct3D8 //! driver, it would return "Direct3D8.1". const wchar_t* CSoftwareDriver::getName() const { return L"Irrlicht Software Driver 1.0"; } //! Returns type of video driver E_DRIVER_TYPE CSoftwareDriver::getDriverType() const { return EDT_SOFTWARE; } //! returns color format ECOLOR_FORMAT CSoftwareDriver::getColorFormat() const { if (BackBuffer) return BackBuffer->getColorFormat(); else return CNullDriver::getColorFormat(); } //! Returns the transformation set by setTransform const core::matrix4& CSoftwareDriver::getTransform(E_TRANSFORMATION_STATE state) const { return TransformationMatrix[state]; } //! Creates a render target texture. ITexture* CSoftwareDriver::addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format) { IImage* img = createImage(video::ECF_A1R5G5B5, size); ITexture* tex = new CSoftwareTexture(img, name, true); img->drop(); addTexture(tex); tex->drop(); return tex; } //! Clears the ZBuffer. void CSoftwareDriver::clearZBuffer() { if (ZBuffer) ZBuffer->clear(); } //! Returns an image created from the last rendered frame. IImage* CSoftwareDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target) { if (target != video::ERT_FRAME_BUFFER) return 0; if (BackBuffer) { IImage* tmp = createImage(BackBuffer->getColorFormat(), BackBuffer->getDimension()); BackBuffer->copyTo(tmp); return tmp; } else return 0; } //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. u32 CSoftwareDriver::getMaximalPrimitiveCount() const { return 0x00800000; } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_SOFTWARE_ namespace irr { namespace video { //! creates a video driver IVideoDriver* createSoftwareDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CSoftwareDriver(windowSize, fullscreen, io, presenter); #else return 0; #endif } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSoftware2MaterialRenderer.h0000644000000000000000000000501512574354552022434 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SOFTWARE2_MATERIAL_RENDERER_H_INCLUDED__ #define __C_SOFTWARE2_MATERIAL_RENDERER_H_INCLUDED__ #include "SoftwareDriver2_compile_config.h" #include "IMaterialRenderer.h" #include "CSoftwareDriver2.h" namespace irr { namespace video { //! Base class for all internal Software2 material renderers class CSoftware2MaterialRenderer : public IMaterialRenderer { public: //! Constructor CSoftware2MaterialRenderer(video::CBurningVideoDriver* driver) : Driver(driver) { } protected: video::CBurningVideoDriver* Driver; }; //! solid material renderer class CSoftware2MaterialRenderer_SOLID : public CSoftware2MaterialRenderer { public: CSoftware2MaterialRenderer_SOLID ( video::CBurningVideoDriver* driver ) :CSoftware2MaterialRenderer ( driver ) {} //! Returns if the material is transparent. virtual bool isTransparent() const { return false; } }; //! Transparent material renderer class CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR : public CSoftware2MaterialRenderer { public: CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR ( video::CBurningVideoDriver* driver ) : CSoftware2MaterialRenderer ( driver ) {} //! Returns if the material is transparent. virtual bool isTransparent() const { return true; } }; //! unsupported material renderer class CSoftware2MaterialRenderer_UNSUPPORTED : public CSoftware2MaterialRenderer { public: CSoftware2MaterialRenderer_UNSUPPORTED ( video::CBurningVideoDriver* driver ) : CSoftware2MaterialRenderer ( driver ) {} virtual s32 getRenderCapability() const { return 1; } }; //! unsupported material renderer class CBurningShader_REFERENCE : public CSoftware2MaterialRenderer { public: CBurningShader_REFERENCE ( video::CBurningVideoDriver* driver ) : CSoftware2MaterialRenderer ( driver ) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { } virtual void OnUnsetMaterial() { } virtual bool isTransparent() const { return false; } virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { return true; }; virtual s32 getRenderCapability() const { return 1; } }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSMFMeshFileLoader.h0000644000000000000000000000336212574354552020606 0ustar rootroot// Copyright (C) 2010-2012 Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SMF_MESH_LOADER_H_INCLUDED__ #define __C_SMF_MESH_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "SMesh.h" namespace irr { namespace video { class IVideoDriver; } namespace scene { //! Class which can load class CSMFMeshFileLoader : public virtual IMeshLoader { public: CSMFMeshFileLoader(video::IVideoDriver* driver); //! Returns true if the file might be loaded by this class. virtual bool isALoadableFileExtension(const io::path& filename) const; //! Creates/loads an animated mesh from the file. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: void loadLimb(io::IReadFile* file, scene::SMesh* mesh, const core::matrix4 &parentTransformation); video::IVideoDriver* Driver; }; } // end namespace scene namespace io { class BinaryFile { public: //! reads most types from the given file, moving the file pointer along template static void read(io::IReadFile* file, T &out, bool bigEndian=false); //! reads a 3d vector from the file, moving the file pointer along static void read(io::IReadFile* file, core::vector3df &outVector2d, bool bigEndian=false); //! reads a 2d vector from the file, moving the file pointer along static void read(io::IReadFile* file, core::vector2df &outVector2d, bool bigEndian=false); //! reads a null terminated string from the file, moving the file pointer along static void read(io::IReadFile* file, core::stringc &outString, bool bigEndian=false); }; } } // end namespace irr #endif // __C_SMF_MESH_LOADER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CSMFMeshFileLoader.cpp0000644000000000000000000001400312574354552021133 0ustar rootroot// Copyright (C) 2010-2012 Gaz Davidson / Joseph Ellis // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_SMF_LOADER_ #include "CSMFMeshFileLoader.h" #include "SAnimatedMesh.h" #include "SMeshBuffer.h" #include "IReadFile.h" #include "coreutil.h" #include "os.h" #include "IVideoDriver.h" namespace irr { namespace scene { CSMFMeshFileLoader::CSMFMeshFileLoader(video::IVideoDriver* driver) : Driver(driver) { } //! Returns true if the file might be loaded by this class. bool CSMFMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension(filename, "smf"); } //! Creates/loads an animated mesh from the file. IAnimatedMesh* CSMFMeshFileLoader::createMesh(io::IReadFile* file) { // create empty mesh SMesh *mesh = new SMesh(); // load file u16 version; u8 flags; s32 limbCount; s32 i; io::BinaryFile::read(file, version); io::BinaryFile::read(file, flags); io::BinaryFile::read(file, limbCount); // load mesh data core::matrix4 identity; for (i=0; i < limbCount; ++i) loadLimb(file, mesh, identity); // recalculate buffer bounding boxes for (i=0; i < (s32)mesh->getMeshBufferCount(); ++i) mesh->getMeshBuffer(i)->recalculateBoundingBox(); mesh->recalculateBoundingBox(); SAnimatedMesh *am = new SAnimatedMesh(); am->addMesh(mesh); mesh->drop(); am->recalculateBoundingBox(); return am; } void CSMFMeshFileLoader::loadLimb(io::IReadFile* file, SMesh* mesh, const core::matrix4 &parentTransformation) { core::matrix4 transformation; // limb transformation core::vector3df translate, rotate, scale; io::BinaryFile::read(file, translate); io::BinaryFile::read(file, rotate); io::BinaryFile::read(file, scale); transformation.setTranslation(translate); transformation.setRotationDegrees(rotate); transformation.setScale(scale); transformation = parentTransformation * transformation; core::stringc textureName, textureGroupName; // texture information io::BinaryFile::read(file, textureGroupName); io::BinaryFile::read(file, textureName); // attempt to load texture using known formats video::ITexture* texture = 0; const c8* extensions[] = {".jpg", ".png", ".tga", ".bmp", 0}; for (const c8 **ext = extensions; !texture && *ext; ++ext) { texture = Driver->getTexture(textureName + *ext); if (texture) textureName = textureName + *ext; } // find the correct mesh buffer u32 i; for (i=0; iMeshBuffers.size(); ++i) if (mesh->MeshBuffers[i]->getMaterial().TextureLayer[0].Texture == texture) break; // create mesh buffer if none was found if (i == mesh->MeshBuffers.size()) { CMeshBuffer* mb = new CMeshBuffer(); mb->Material.TextureLayer[0].Texture = texture; // horribly hacky way to do this, maybe it's in the flags? if (core::hasFileExtension(textureName, "tga", "png")) mb->Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; else mb->Material.MaterialType = video::EMT_SOLID; mesh->MeshBuffers.push_back(mb); } CMeshBuffer* mb = (CMeshBuffer*)mesh->MeshBuffers[i]; u16 vertexCount, firstVertex = mb->getVertexCount(); io::BinaryFile::read(file, vertexCount); mb->Vertices.reallocate(mb->Vertices.size() + vertexCount); // add vertices and set positions for (i=0; iVertices.push_back(vert); } // set vertex normals for (i=0; i < vertexCount; ++i) { core::vector3df normal; io::BinaryFile::read(file, normal); transformation.rotateVect(normal); mb->Vertices[firstVertex + i].Normal = normal; } // set texture coordinates for (i=0; i < vertexCount; ++i) { core::vector2df tcoords; io::BinaryFile::read(file, tcoords); mb->Vertices[firstVertex + i].TCoords = tcoords; } // triangles u32 triangleCount; // vertexCount used as temporary io::BinaryFile::read(file, vertexCount); triangleCount=3*vertexCount; mb->Indices.reallocate(mb->Indices.size() + triangleCount); for (i=0; i < triangleCount; ++i) { u16 index; io::BinaryFile::read(file, index); mb->Indices.push_back(firstVertex + index); } // read limbs s32 limbCount; io::BinaryFile::read(file, limbCount); for (s32 l=0; l < limbCount; ++l) loadLimb(file, mesh, transformation); } } // namespace scene // todo: at some point in the future let's move these to a place where everyone can use them. namespace io { #if _BIGENDIAN #define _SYSTEM_BIG_ENDIAN_ (true) #else #define _SYSTEM_BIG_ENDIAN_ (false) #endif template void BinaryFile::read(io::IReadFile* file, T &out, bool bigEndian) { file->read((void*)&out, sizeof(out)); if (bigEndian != (_SYSTEM_BIG_ENDIAN_)) out = os::Byteswap::byteswap(out); } //! reads a 3d vector from the file, moving the file pointer along void BinaryFile::read(io::IReadFile* file, core::vector3df &outVector2d, bool bigEndian) { BinaryFile::read(file, outVector2d.X, bigEndian); BinaryFile::read(file, outVector2d.Y, bigEndian); BinaryFile::read(file, outVector2d.Z, bigEndian); } //! reads a 2d vector from the file, moving the file pointer along void BinaryFile::read(io::IReadFile* file, core::vector2df &outVector2d, bool bigEndian) { BinaryFile::read(file, outVector2d.X, bigEndian); BinaryFile::read(file, outVector2d.Y, bigEndian); } //! reads a null terminated string from the file, moving the file pointer along void BinaryFile::read(io::IReadFile* file, core::stringc &outString, bool bigEndian) { c8 c; file->read((void*)&c, 1); while (c) { outString += c; file->read((void*)&c, 1); } } } // namespace io } // namespace irr #endif // compile with SMF loader irrlicht-1.8.3/source/Irrlicht/CSkyDomeSceneNode.h0000644000000000000000000000272712574354552020560 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // Code for this scene node has been contributed by Anders la Cour-Harbo (alc) #ifndef __C_SKY_DOME_SCENE_NODE_H_INCLUDED__ #define __C_SKY_DOME_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" #include "SMeshBuffer.h" namespace irr { namespace scene { class CSkyDomeSceneNode : public ISceneNode { public: CSkyDomeSceneNode(video::ITexture* texture, u32 horiRes, u32 vertRes, f32 texturePercentage, f32 spherePercentage, f32 radius, ISceneNode* parent, ISceneManager* smgr, s32 id); virtual ~CSkyDomeSceneNode(); virtual void OnRegisterSceneNode(); virtual void render(); virtual const core::aabbox3d& getBoundingBox() const; virtual video::SMaterial& getMaterial(u32 i); virtual u32 getMaterialCount() const; virtual ESCENE_NODE_TYPE getType() const { return ESNT_SKY_DOME; } virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); private: void generateMesh(); SMeshBuffer* Buffer; u32 HorizontalResolution, VerticalResolution; f32 TexturePercentage, SpherePercentage, Radius; }; } } #endif irrlicht-1.8.3/source/Irrlicht/CSkyDomeSceneNode.cpp0000644000000000000000000002011112574354552021076 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // Code for this scene node has been contributed by Anders la Cour-Harbo (alc) #include "CSkyDomeSceneNode.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "ICameraSceneNode.h" #include "IAnimatedMesh.h" #include "os.h" namespace irr { namespace scene { /* horiRes and vertRes: Controls the number of faces along the horizontal axis (30 is a good value) and the number of faces along the vertical axis (8 is a good value). texturePercentage: Only the top texturePercentage of the image is used, e.g. 0.8 uses the top 80% of the image, 1.0 uses the entire image. This is useful as some landscape images have a small banner at the bottom that you don't want. spherePercentage: This controls how far around the sphere the sky dome goes. For value 1.0 you get exactly the upper hemisphere, for 1.1 you get slightly more, and for 2.0 you get a full sphere. It is sometimes useful to use a value slightly bigger than 1 to avoid a gap between some ground place and the sky. This parameters stretches the image to fit the chosen "sphere-size". */ CSkyDomeSceneNode::CSkyDomeSceneNode(video::ITexture* sky, u32 horiRes, u32 vertRes, f32 texturePercentage, f32 spherePercentage, f32 radius, ISceneNode* parent, ISceneManager* mgr, s32 id) : ISceneNode(parent, mgr, id), Buffer(0), HorizontalResolution(horiRes), VerticalResolution(vertRes), TexturePercentage(texturePercentage), SpherePercentage(spherePercentage), Radius(radius) { #ifdef _DEBUG setDebugName("CSkyDomeSceneNode"); #endif setAutomaticCulling(scene::EAC_OFF); Buffer = new SMeshBuffer(); Buffer->Material.Lighting = false; Buffer->Material.ZBuffer = video::ECFN_NEVER; Buffer->Material.ZWriteEnable = false; Buffer->Material.AntiAliasing = video::EAAM_OFF; Buffer->Material.setTexture(0, sky); Buffer->BoundingBox.MaxEdge.set(0,0,0); Buffer->BoundingBox.MinEdge.set(0,0,0); // regenerate the mesh generateMesh(); } CSkyDomeSceneNode::~CSkyDomeSceneNode() { if (Buffer) Buffer->drop(); } void CSkyDomeSceneNode::generateMesh() { f32 azimuth; u32 k; Buffer->Vertices.clear(); Buffer->Indices.clear(); const f32 azimuth_step = (core::PI * 2.f) / HorizontalResolution; if (SpherePercentage < 0.f) SpherePercentage = -SpherePercentage; if (SpherePercentage > 2.f) SpherePercentage = 2.f; const f32 elevation_step = SpherePercentage * core::HALF_PI / (f32)VerticalResolution; Buffer->Vertices.reallocate( (HorizontalResolution + 1) * (VerticalResolution + 1) ); Buffer->Indices.reallocate(3 * (2*VerticalResolution - 1) * HorizontalResolution); video::S3DVertex vtx; vtx.Color.set(255,255,255,255); vtx.Normal.set(0.0f,-1.f,0.0f); const f32 tcV = TexturePercentage / VerticalResolution; for (k = 0, azimuth = 0; k <= HorizontalResolution; ++k) { f32 elevation = core::HALF_PI; const f32 tcU = (f32)k / (f32)HorizontalResolution; const f32 sinA = sinf(azimuth); const f32 cosA = cosf(azimuth); for (u32 j = 0; j <= VerticalResolution; ++j) { const f32 cosEr = Radius * cosf(elevation); vtx.Pos.set(cosEr*sinA, Radius*sinf(elevation), cosEr*cosA); vtx.TCoords.set(tcU, j*tcV); vtx.Normal = -vtx.Pos; vtx.Normal.normalize(); Buffer->Vertices.push_back(vtx); elevation -= elevation_step; } azimuth += azimuth_step; } for (k = 0; k < HorizontalResolution; ++k) { Buffer->Indices.push_back(VerticalResolution + 2 + (VerticalResolution + 1)*k); Buffer->Indices.push_back(1 + (VerticalResolution + 1)*k); Buffer->Indices.push_back(0 + (VerticalResolution + 1)*k); for (u32 j = 1; j < VerticalResolution; ++j) { Buffer->Indices.push_back(VerticalResolution + 2 + (VerticalResolution + 1)*k + j); Buffer->Indices.push_back(1 + (VerticalResolution + 1)*k + j); Buffer->Indices.push_back(0 + (VerticalResolution + 1)*k + j); Buffer->Indices.push_back(VerticalResolution + 1 + (VerticalResolution + 1)*k + j); Buffer->Indices.push_back(VerticalResolution + 2 + (VerticalResolution + 1)*k + j); Buffer->Indices.push_back(0 + (VerticalResolution + 1)*k + j); } } Buffer->setHardwareMappingHint(scene::EHM_STATIC); } //! renders the node. void CSkyDomeSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); scene::ICameraSceneNode* camera = SceneManager->getActiveCamera(); if (!camera || !driver) return; if ( !camera->isOrthogonal() ) { core::matrix4 mat(AbsoluteTransformation); mat.setTranslation(camera->getAbsolutePosition()); driver->setTransform(video::ETS_WORLD, mat); driver->setMaterial(Buffer->Material); driver->drawMeshBuffer(Buffer); } // for debug purposes only: if ( DebugDataVisible ) { video::SMaterial m; m.Lighting = false; driver->setMaterial(m); if ( DebugDataVisible & scene::EDS_NORMALS ) { // draw normals const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); driver->drawMeshBufferNormals(Buffer, debugNormalLength, debugNormalColor); } // show mesh if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY ) { m.Wireframe = true; driver->setMaterial(m); driver->drawMeshBuffer(Buffer); } } } //! returns the axis aligned bounding box of this node const core::aabbox3d& CSkyDomeSceneNode::getBoundingBox() const { return Buffer->BoundingBox; } void CSkyDomeSceneNode::OnRegisterSceneNode() { if (IsVisible) { SceneManager->registerNodeForRendering(this, ESNRP_SKY_BOX ); } ISceneNode::OnRegisterSceneNode(); } //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. video::SMaterial& CSkyDomeSceneNode::getMaterial(u32 i) { return Buffer->Material; } //! returns amount of materials used by this scene node. u32 CSkyDomeSceneNode::getMaterialCount() const { return 1; } //! Writes attributes of the scene node. void CSkyDomeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { ISceneNode::serializeAttributes(out, options); out->addInt ("HorizontalResolution", HorizontalResolution); out->addInt ("VerticalResolution", VerticalResolution); out->addFloat("TexturePercentage", TexturePercentage); out->addFloat("SpherePercentage", SpherePercentage); out->addFloat("Radius", Radius); } //! Reads attributes of the scene node. void CSkyDomeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { HorizontalResolution = in->getAttributeAsInt ("HorizontalResolution"); VerticalResolution = in->getAttributeAsInt ("VerticalResolution"); TexturePercentage = in->getAttributeAsFloat("TexturePercentage"); SpherePercentage = in->getAttributeAsFloat("SpherePercentage"); Radius = in->getAttributeAsFloat("Radius"); ISceneNode::deserializeAttributes(in, options); // regenerate the mesh generateMesh(); } //! Creates a clone of this scene node and its children. ISceneNode* CSkyDomeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CSkyDomeSceneNode* nb = new CSkyDomeSceneNode(Buffer->Material.TextureLayer[0].Texture, HorizontalResolution, VerticalResolution, TexturePercentage, SpherePercentage, Radius, newParent, newManager, ID); nb->cloneMembers(this, newManager); if ( newParent ) nb->drop(); return nb; } } // namespace scene } // namespace irr irrlicht-1.8.3/source/Irrlicht/CSkyBoxSceneNode.h0000644000000000000000000000357712574354552020430 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SKY_BOX_SCENE_NODE_H_INCLUDED__ #define __C_SKY_BOX_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" #include "S3DVertex.h" namespace irr { namespace scene { // Skybox, rendered with zbuffer turned off, before all other nodes. class CSkyBoxSceneNode : public ISceneNode { public: //! constructor CSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, video::ITexture* left, video::ITexture* right, video::ITexture* front, video::ITexture* back, ISceneNode* parent, ISceneManager* mgr, s32 id); virtual void OnRegisterSceneNode(); //! renders the node. virtual void render(); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. virtual video::SMaterial& getMaterial(u32 i); //! returns amount of materials used by this scene node. virtual u32 getMaterialCount() const; //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_SKY_BOX; } //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); private: core::aabbox3d Box; u16 Indices[4]; video::S3DVertex Vertices[4*6]; video::SMaterial Material[6]; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSkyBoxSceneNode.cpp0000644000000000000000000001767212574354552020764 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSkyBoxSceneNode.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "ICameraSceneNode.h" #include "S3DVertex.h" #include "os.h" namespace irr { namespace scene { //! constructor CSkyBoxSceneNode::CSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, video::ITexture* left, video::ITexture* right, video::ITexture* front, video::ITexture* back, ISceneNode* parent, ISceneManager* mgr, s32 id) : ISceneNode(parent, mgr, id) { #ifdef _DEBUG setDebugName("CSkyBoxSceneNode"); #endif setAutomaticCulling(scene::EAC_OFF); Box.MaxEdge.set(0,0,0); Box.MinEdge.set(0,0,0); // create indices Indices[0] = 0; Indices[1] = 1; Indices[2] = 2; Indices[3] = 3; // create material video::SMaterial mat; mat.Lighting = false; mat.ZBuffer = video::ECFN_NEVER; mat.ZWriteEnable = false; mat.AntiAliasing=0; mat.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; mat.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; /* Hey, I am no artist, but look at that cool ASCII art I made! ;) -111 111 /6--------/5 y / | / | ^ z / | 11-1 | | / -11-1 3---------2 | |/ | 7- - -| -4 1-11 *---->x | -1-11 | / 3-------|2 |/ | / | //| 0---------1/ | // | -1-1-1 1-1-1 |// | 0--------1 */ video::ITexture* tex = front; if (!tex) tex = left; if (!tex) tex = back; if (!tex) tex = right; if (!tex) tex = top; if (!tex) tex = bottom; const f32 onepixel = tex?(1.0f / (tex->getSize().Width * 1.5f)) : 0.0f; const f32 t = 1.0f - onepixel; const f32 o = 0.0f + onepixel; // create front side Material[0] = mat; Material[0].setTexture(0, front); Vertices[0] = video::S3DVertex(-1,-1,-1, 0,0,1, video::SColor(255,255,255,255), t, t); Vertices[1] = video::S3DVertex( 1,-1,-1, 0,0,1, video::SColor(255,255,255,255), o, t); Vertices[2] = video::S3DVertex( 1, 1,-1, 0,0,1, video::SColor(255,255,255,255), o, o); Vertices[3] = video::S3DVertex(-1, 1,-1, 0,0,1, video::SColor(255,255,255,255), t, o); // create left side Material[1] = mat; Material[1].setTexture(0, left); Vertices[4] = video::S3DVertex( 1,-1,-1, -1,0,0, video::SColor(255,255,255,255), t, t); Vertices[5] = video::S3DVertex( 1,-1, 1, -1,0,0, video::SColor(255,255,255,255), o, t); Vertices[6] = video::S3DVertex( 1, 1, 1, -1,0,0, video::SColor(255,255,255,255), o, o); Vertices[7] = video::S3DVertex( 1, 1,-1, -1,0,0, video::SColor(255,255,255,255), t, o); // create back side Material[2] = mat; Material[2].setTexture(0, back); Vertices[8] = video::S3DVertex( 1,-1, 1, 0,0,-1, video::SColor(255,255,255,255), t, t); Vertices[9] = video::S3DVertex(-1,-1, 1, 0,0,-1, video::SColor(255,255,255,255), o, t); Vertices[10] = video::S3DVertex(-1, 1, 1, 0,0,-1, video::SColor(255,255,255,255), o, o); Vertices[11] = video::S3DVertex( 1, 1, 1, 0,0,-1, video::SColor(255,255,255,255), t, o); // create right side Material[3] = mat; Material[3].setTexture(0, right); Vertices[12] = video::S3DVertex(-1,-1, 1, 1,0,0, video::SColor(255,255,255,255), t, t); Vertices[13] = video::S3DVertex(-1,-1,-1, 1,0,0, video::SColor(255,255,255,255), o, t); Vertices[14] = video::S3DVertex(-1, 1,-1, 1,0,0, video::SColor(255,255,255,255), o, o); Vertices[15] = video::S3DVertex(-1, 1, 1, 1,0,0, video::SColor(255,255,255,255), t, o); // create top side Material[4] = mat; Material[4].setTexture(0, top); Vertices[16] = video::S3DVertex( 1, 1,-1, 0,-1,0, video::SColor(255,255,255,255), t, t); Vertices[17] = video::S3DVertex( 1, 1, 1, 0,-1,0, video::SColor(255,255,255,255), o, t); Vertices[18] = video::S3DVertex(-1, 1, 1, 0,-1,0, video::SColor(255,255,255,255), o, o); Vertices[19] = video::S3DVertex(-1, 1,-1, 0,-1,0, video::SColor(255,255,255,255), t, o); // create bottom side Material[5] = mat; Material[5].setTexture(0, bottom); Vertices[20] = video::S3DVertex( 1,-1, 1, 0,1,0, video::SColor(255,255,255,255), o, o); Vertices[21] = video::S3DVertex( 1,-1,-1, 0,1,0, video::SColor(255,255,255,255), t, o); Vertices[22] = video::S3DVertex(-1,-1,-1, 0,1,0, video::SColor(255,255,255,255), t, t); Vertices[23] = video::S3DVertex(-1,-1, 1, 0,1,0, video::SColor(255,255,255,255), o, t); } //! renders the node. void CSkyBoxSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); scene::ICameraSceneNode* camera = SceneManager->getActiveCamera(); if (!camera || !driver) return; if ( !camera->isOrthogonal() ) { // draw perspective skybox core::matrix4 translate(AbsoluteTransformation); translate.setTranslation(camera->getAbsolutePosition()); // Draw the sky box between the near and far clip plane const f32 viewDistance = (camera->getNearValue() + camera->getFarValue()) * 0.5f; core::matrix4 scale; scale.setScale(core::vector3df(viewDistance, viewDistance, viewDistance)); driver->setTransform(video::ETS_WORLD, translate * scale); for (s32 i=0; i<6; ++i) { driver->setMaterial(Material[i]); driver->drawIndexedTriangleFan(&Vertices[i*4], 4, Indices, 2); } } else { // draw orthogonal skybox, // simply choose one texture and draw it as 2d picture. // there could be better ways to do this, but currently I think this is ok. core::vector3df lookVect = camera->getTarget() - camera->getAbsolutePosition(); lookVect.normalize(); core::vector3df absVect( core::abs_(lookVect.X), core::abs_(lookVect.Y), core::abs_(lookVect.Z)); int idx = 0; if ( absVect.X >= absVect.Y && absVect.X >= absVect.Z ) { // x direction idx = lookVect.X > 0 ? 0 : 2; } else if ( absVect.Y >= absVect.X && absVect.Y >= absVect.Z ) { // y direction idx = lookVect.Y > 0 ? 4 : 5; } else if ( absVect.Z >= absVect.X && absVect.Z >= absVect.Y ) { // z direction idx = lookVect.Z > 0 ? 1 : 3; } video::ITexture* tex = Material[idx].getTexture(0); if ( tex ) { core::rect rctDest(core::position2d(-1,0), core::dimension2di(driver->getCurrentRenderTargetSize())); core::rect rctSrc(core::position2d(0,0), core::dimension2di(tex->getSize())); driver->draw2DImage(tex, rctDest, rctSrc); } } } //! returns the axis aligned bounding box of this node const core::aabbox3d& CSkyBoxSceneNode::getBoundingBox() const { return Box; } void CSkyBoxSceneNode::OnRegisterSceneNode() { if (IsVisible) SceneManager->registerNodeForRendering(this, ESNRP_SKY_BOX); ISceneNode::OnRegisterSceneNode(); } //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. video::SMaterial& CSkyBoxSceneNode::getMaterial(u32 i) { return Material[i]; } //! returns amount of materials used by this scene node. u32 CSkyBoxSceneNode::getMaterialCount() const { return 6; } //! Creates a clone of this scene node and its children. ISceneNode* CSkyBoxSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CSkyBoxSceneNode* nb = new CSkyBoxSceneNode(0,0,0,0,0,0, newParent, newManager, ID); nb->cloneMembers(this, newManager); for (u32 i=0; i<6; ++i) nb->Material[i] = Material[i]; if ( newParent ) nb->drop(); return nb; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSkinnedMesh.h0000644000000000000000000001602512574354552017625 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h //New skinned mesh #ifndef __C_SKINNED_MESH_H_INCLUDED__ #define __C_SKINNED_MESH_H_INCLUDED__ #include "ISkinnedMesh.h" #include "SMeshBuffer.h" #include "S3DVertex.h" #include "irrString.h" #include "matrix4.h" #include "quaternion.h" namespace irr { namespace scene { class IAnimatedMeshSceneNode; class IBoneSceneNode; class CSkinnedMesh: public ISkinnedMesh { public: //! constructor CSkinnedMesh(); //! destructor virtual ~CSkinnedMesh(); //! returns the amount of frames. If the amount is 1, it is a static (=non animated) mesh. virtual u32 getFrameCount() const; //! Gets the default animation speed of the animated mesh. /** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */ virtual f32 getAnimationSpeed() const; //! Gets the frame count of the animated mesh. /** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated. The actual speed is set in the scene node the mesh is instantiated in.*/ virtual void setAnimationSpeed(f32 fps); //! returns the animated mesh based on a detail level (which is ignored) virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1); //! Animates this mesh's joints based on frame input //! blend: {0-old position, 1-New position} virtual void animateMesh(f32 frame, f32 blend); //! Preforms a software skin on this mesh based of joint positions virtual void skinMesh(); //! returns amount of mesh buffers. virtual u32 getMeshBufferCount() const; //! returns pointer to a mesh buffer virtual IMeshBuffer* getMeshBuffer(u32 nr) const; //! Returns pointer to a mesh buffer which fits a material /** \param material: material to search for \return Returns the pointer to the mesh buffer or NULL if there is no such mesh buffer. */ virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const; //! returns an axis aligned bounding box virtual const core::aabbox3d& getBoundingBox() const; //! set user axis aligned bounding box virtual void setBoundingBox( const core::aabbox3df& box); //! sets a flag of all contained materials to a new value virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue); //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX); //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX); //! Returns the type of the animated mesh. virtual E_ANIMATED_MESH_TYPE getMeshType() const; //! Gets joint count. virtual u32 getJointCount() const; //! Gets the name of a joint. virtual const c8* getJointName(u32 number) const; //! Gets a joint number from its name virtual s32 getJointNumber(const c8* name) const; //! uses animation from another mesh virtual bool useAnimationFrom(const ISkinnedMesh *mesh); //! Update Normals when Animating //! False= Don't (default) //! True = Update normals, slower virtual void updateNormalsWhenAnimating(bool on); //! Sets Interpolation Mode virtual void setInterpolationMode(E_INTERPOLATION_MODE mode); //! Convertes the mesh to contain tangent information virtual void convertMeshToTangents(); //! Does the mesh have no animation virtual bool isStatic(); //! (This feature is not implemented in irrlicht yet) virtual bool setHardwareSkinning(bool on); //Interface for the mesh loaders (finalize should lock these functions, and they should have some prefix like loader_ //these functions will use the needed arrays, set values, etc to help the loaders //! exposed for loaders to add mesh buffers virtual core::array &getMeshBuffers(); //! alternative method for adding joints virtual core::array &getAllJoints(); //! alternative method for adding joints virtual const core::array &getAllJoints() const; //! loaders should call this after populating the mesh virtual void finalize(); //! Adds a new meshbuffer to the mesh, access it as last one virtual SSkinMeshBuffer *addMeshBuffer(); //! Adds a new joint to the mesh, access it as last one virtual SJoint *addJoint(SJoint *parent=0); //! Adds a new position key to the mesh, access it as last one virtual SPositionKey *addPositionKey(SJoint *joint); //! Adds a new rotation key to the mesh, access it as last one virtual SRotationKey *addRotationKey(SJoint *joint); //! Adds a new scale key to the mesh, access it as last one virtual SScaleKey *addScaleKey(SJoint *joint); //! Adds a new weight to the mesh, access it as last one virtual SWeight *addWeight(SJoint *joint); virtual void updateBoundingBox(void); //! Recovers the joints from the mesh void recoverJointsFromMesh(core::array &jointChildSceneNodes); //! Tranfers the joint data to the mesh void transferJointsToMesh(const core::array &jointChildSceneNodes); //! Tranfers the joint hints to the mesh void transferOnlyJointsHintsToMesh(const core::array &jointChildSceneNodes); //! Creates an array of joints from this mesh as children of node void addJoints(core::array &jointChildSceneNodes, IAnimatedMeshSceneNode* node, ISceneManager* smgr); private: void checkForAnimation(); void normalizeWeights(); void buildAllLocalAnimatedMatrices(); void buildAllGlobalAnimatedMatrices(SJoint *Joint=0, SJoint *ParentJoint=0); void getFrameData(f32 frame, SJoint *Node, core::vector3df &position, s32 &positionHint, core::vector3df &scale, s32 &scaleHint, core::quaternion &rotation, s32 &rotationHint); void calculateGlobalMatrices(SJoint *Joint,SJoint *ParentJoint); void skinJoint(SJoint *Joint, SJoint *ParentJoint); void calculateTangents(core::vector3df& normal, core::vector3df& tangent, core::vector3df& binormal, core::vector3df& vt1, core::vector3df& vt2, core::vector3df& vt3, core::vector2df& tc1, core::vector2df& tc2, core::vector2df& tc3); core::array *SkinningBuffers; //Meshbuffer to skin, default is to skin localBuffers core::array LocalBuffers; core::array AllJoints; core::array RootJoints; core::array< core::array > Vertices_Moved; core::aabbox3d BoundingBox; f32 AnimationFrames; f32 FramesPerSecond; f32 LastAnimatedFrame; bool SkinnedLastFrame; E_INTERPOLATION_MODE InterpolationMode:8; bool HasAnimation; bool PreparedForSkinning; bool AnimateNormals; bool HardwareSkinning; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSkinnedMesh.cpp0000644000000000000000000011056412574354552020163 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ #include "CSkinnedMesh.h" #include "CBoneSceneNode.h" #include "IAnimatedMeshSceneNode.h" #include "os.h" namespace irr { namespace scene { //! constructor CSkinnedMesh::CSkinnedMesh() : SkinningBuffers(0), AnimationFrames(0.f), FramesPerSecond(25.f), LastAnimatedFrame(-1), SkinnedLastFrame(false), InterpolationMode(EIM_LINEAR), HasAnimation(false), PreparedForSkinning(false), AnimateNormals(true), HardwareSkinning(false) { #ifdef _DEBUG setDebugName("CSkinnedMesh"); #endif SkinningBuffers=&LocalBuffers; } //! destructor CSkinnedMesh::~CSkinnedMesh() { for (u32 i=0; idrop(); } } //! returns the amount of frames in milliseconds. //! If the amount is 1, it is a static (=non animated) mesh. u32 CSkinnedMesh::getFrameCount() const { return core::floor32(AnimationFrames); } //! Gets the default animation speed of the animated mesh. /** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */ f32 CSkinnedMesh::getAnimationSpeed() const { return FramesPerSecond; } //! Gets the frame count of the animated mesh. /** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated. The actual speed is set in the scene node the mesh is instantiated in.*/ void CSkinnedMesh::setAnimationSpeed(f32 fps) { FramesPerSecond=fps; } //! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level. IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) { //animate(frame,startFrameLoop, endFrameLoop); if (frame==-1) return this; animateMesh((f32)frame, 1.0f); skinMesh(); return this; } //-------------------------------------------------------------------------- // Keyframe Animation //-------------------------------------------------------------------------- //! Animates this mesh's joints based on frame input //! blend: {0-old position, 1-New position} void CSkinnedMesh::animateMesh(f32 frame, f32 blend) { if (!HasAnimation || LastAnimatedFrame==frame) return; LastAnimatedFrame=frame; SkinnedLastFrame=false; if (blend<=0.f) return; //No need to animate for (u32 i=0; iAnimatedposition; const core::vector3df oldScale = joint->Animatedscale; const core::quaternion oldRotation = joint->Animatedrotation; core::vector3df position = oldPosition; core::vector3df scale = oldScale; core::quaternion rotation = oldRotation; getFrameData(frame, joint, position, joint->positionHint, scale, joint->scaleHint, rotation, joint->rotationHint); if (blend==1.0f) { //No blending needed joint->Animatedposition = position; joint->Animatedscale = scale; joint->Animatedrotation = rotation; } else { //Blend animation joint->Animatedposition = core::lerp(oldPosition, position, blend); joint->Animatedscale = core::lerp(oldScale, scale, blend); joint->Animatedrotation.slerp(oldRotation, rotation, blend); } } //Note: //LocalAnimatedMatrix needs to be built at some point, but this function may be called lots of times for //one render (to play two animations at the same time) LocalAnimatedMatrix only needs to be built once. //a call to buildAllLocalAnimatedMatrices is needed before skinning the mesh, and before the user gets the joints to move //---------------- // Temp! buildAllLocalAnimatedMatrices(); //----------------- updateBoundingBox(); } void CSkinnedMesh::buildAllLocalAnimatedMatrices() { for (u32 i=0; iUseAnimationFrom && (joint->UseAnimationFrom->PositionKeys.size() || joint->UseAnimationFrom->ScaleKeys.size() || joint->UseAnimationFrom->RotationKeys.size() )) { joint->GlobalSkinningSpace=false; // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched to getMatrix_transposed instead of getMatrix for downward compatibility. // Not tested so far if this was correct or wrong before quaternion fix! joint->Animatedrotation.getMatrix_transposed(joint->LocalAnimatedMatrix); // --- joint->LocalAnimatedMatrix *= joint->Animatedrotation.getMatrix() --- f32 *m1 = joint->LocalAnimatedMatrix.pointer(); core::vector3df &Pos = joint->Animatedposition; m1[0] += Pos.X*m1[3]; m1[1] += Pos.Y*m1[3]; m1[2] += Pos.Z*m1[3]; m1[4] += Pos.X*m1[7]; m1[5] += Pos.Y*m1[7]; m1[6] += Pos.Z*m1[7]; m1[8] += Pos.X*m1[11]; m1[9] += Pos.Y*m1[11]; m1[10] += Pos.Z*m1[11]; m1[12] += Pos.X*m1[15]; m1[13] += Pos.Y*m1[15]; m1[14] += Pos.Z*m1[15]; // ----------------------------------- if (joint->ScaleKeys.size()) { /* core::matrix4 scaleMatrix; scaleMatrix.setScale(joint->Animatedscale); joint->LocalAnimatedMatrix *= scaleMatrix; */ // -------- joint->LocalAnimatedMatrix *= scaleMatrix ----------------- core::matrix4& mat = joint->LocalAnimatedMatrix; mat[0] *= joint->Animatedscale.X; mat[1] *= joint->Animatedscale.X; mat[2] *= joint->Animatedscale.X; mat[3] *= joint->Animatedscale.X; mat[4] *= joint->Animatedscale.Y; mat[5] *= joint->Animatedscale.Y; mat[6] *= joint->Animatedscale.Y; mat[7] *= joint->Animatedscale.Y; mat[8] *= joint->Animatedscale.Z; mat[9] *= joint->Animatedscale.Z; mat[10] *= joint->Animatedscale.Z; mat[11] *= joint->Animatedscale.Z; // ----------------------------------- } } else { joint->LocalAnimatedMatrix=joint->LocalMatrix; } } SkinnedLastFrame=false; } void CSkinnedMesh::buildAllGlobalAnimatedMatrices(SJoint *joint, SJoint *parentJoint) { if (!joint) { for (u32 i=0; iGlobalSkinningSpace) joint->GlobalAnimatedMatrix = joint->LocalAnimatedMatrix; else joint->GlobalAnimatedMatrix = parentJoint->GlobalAnimatedMatrix * joint->LocalAnimatedMatrix; } for (u32 j=0; jChildren.size(); ++j) buildAllGlobalAnimatedMatrices(joint->Children[j], joint); } void CSkinnedMesh::getFrameData(f32 frame, SJoint *joint, core::vector3df &position, s32 &positionHint, core::vector3df &scale, s32 &scaleHint, core::quaternion &rotation, s32 &rotationHint) { s32 foundPositionIndex = -1; s32 foundScaleIndex = -1; s32 foundRotationIndex = -1; if (joint->UseAnimationFrom) { const core::array &PositionKeys=joint->UseAnimationFrom->PositionKeys; const core::array &ScaleKeys=joint->UseAnimationFrom->ScaleKeys; const core::array &RotationKeys=joint->UseAnimationFrom->RotationKeys; if (PositionKeys.size()) { foundPositionIndex = -1; //Test the Hints... if (positionHint>=0 && (u32)positionHint < PositionKeys.size()) { //check this hint if (positionHint>0 && PositionKeys[positionHint].frame>=frame && PositionKeys[positionHint-1].frame=frame && PositionKeys[positionHint+0].frame= frame) //Keys should to be sorted by frame { foundPositionIndex=i; positionHint=i; break; } } } //Do interpolation... if (foundPositionIndex!=-1) { if (InterpolationMode==EIM_CONSTANT || foundPositionIndex==0) { position = PositionKeys[foundPositionIndex].position; } else if (InterpolationMode==EIM_LINEAR) { const SPositionKey& KeyA = PositionKeys[foundPositionIndex]; const SPositionKey& KeyB = PositionKeys[foundPositionIndex-1]; const f32 fd1 = frame - KeyA.frame; const f32 fd2 = KeyB.frame - frame; position = ((KeyB.position-KeyA.position)/(fd1+fd2))*fd1 + KeyA.position; } } } //------------------------------------------------------------ if (ScaleKeys.size()) { foundScaleIndex = -1; //Test the Hints... if (scaleHint>=0 && (u32)scaleHint < ScaleKeys.size()) { //check this hint if (scaleHint>0 && ScaleKeys[scaleHint].frame>=frame && ScaleKeys[scaleHint-1].frame=frame && ScaleKeys[scaleHint+0].frame= frame) //Keys should to be sorted by frame { foundScaleIndex=i; scaleHint=i; break; } } } //Do interpolation... if (foundScaleIndex!=-1) { if (InterpolationMode==EIM_CONSTANT || foundScaleIndex==0) { scale = ScaleKeys[foundScaleIndex].scale; } else if (InterpolationMode==EIM_LINEAR) { const SScaleKey& KeyA = ScaleKeys[foundScaleIndex]; const SScaleKey& KeyB = ScaleKeys[foundScaleIndex-1]; const f32 fd1 = frame - KeyA.frame; const f32 fd2 = KeyB.frame - frame; scale = ((KeyB.scale-KeyA.scale)/(fd1+fd2))*fd1 + KeyA.scale; } } } //------------------------------------------------------------- if (RotationKeys.size()) { foundRotationIndex = -1; //Test the Hints... if (rotationHint>=0 && (u32)rotationHint < RotationKeys.size()) { //check this hint if (rotationHint>0 && RotationKeys[rotationHint].frame>=frame && RotationKeys[rotationHint-1].frame=frame && RotationKeys[rotationHint+0].frame= frame) //Keys should be sorted by frame { foundRotationIndex=i; rotationHint=i; break; } } } //Do interpolation... if (foundRotationIndex!=-1) { if (InterpolationMode==EIM_CONSTANT || foundRotationIndex==0) { rotation = RotationKeys[foundRotationIndex].rotation; } else if (InterpolationMode==EIM_LINEAR) { const SRotationKey& KeyA = RotationKeys[foundRotationIndex]; const SRotationKey& KeyB = RotationKeys[foundRotationIndex-1]; const f32 fd1 = frame - KeyA.frame; const f32 fd2 = KeyB.frame - frame; const f32 t = fd1/(fd1+fd2); /* f32 t = 0; if (KeyA.frame!=KeyB.frame) t = (frame-KeyA.frame) / (KeyB.frame - KeyA.frame); */ rotation.slerp(KeyA.rotation, KeyB.rotation, t); } } } } } //-------------------------------------------------------------------------- // Software Skinning //-------------------------------------------------------------------------- //! Preforms a software skin on this mesh based of joint positions void CSkinnedMesh::skinMesh() { if (!HasAnimation || SkinnedLastFrame) return; //---------------- // This is marked as "Temp!". A shiny dubloon to whomever can tell me why. buildAllGlobalAnimatedMatrices(); //----------------- SkinnedLastFrame=true; if (!HardwareSkinning) { //Software skin.... u32 i; //rigid animation for (i=0; iAttachedMeshes.size(); ++j) { SSkinMeshBuffer* Buffer=(*SkinningBuffers)[ AllJoints[i]->AttachedMeshes[j] ]; Buffer->Transformation=AllJoints[i]->GlobalAnimatedMatrix; } } //clear skinning helper array for (i=0; isize(); ++i) (*SkinningBuffers)[i]->setDirty(EBT_VERTEX); } updateBoundingBox(); } void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint) { if (joint->Weights.size()) { //Find this joints pull on vertices... core::matrix4 jointVertexPull(core::matrix4::EM4CONST_NOTHING); jointVertexPull.setbyproduct(joint->GlobalAnimatedMatrix, joint->GlobalInversedMatrix); core::vector3df thisVertexMove, thisNormalMove; core::array &buffersUsed=*SkinningBuffers; //Skin Vertices Positions and Normals... for (u32 i=0; iWeights.size(); ++i) { SWeight& weight = joint->Weights[i]; // Pull this vertex... jointVertexPull.transformVect(thisVertexMove, weight.StaticPos); if (AnimateNormals) jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal); if (! (*(weight.Moved)) ) { *(weight.Moved) = true; buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos = thisVertexMove * weight.strength; if (AnimateNormals) buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal = thisNormalMove * weight.strength; //*(weight._Pos) = thisVertexMove * weight.strength; } else { buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos += thisVertexMove * weight.strength; if (AnimateNormals) buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal += thisNormalMove * weight.strength; //*(weight._Pos) += thisVertexMove * weight.strength; } buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated(); } } //Skin all children for (u32 j=0; jChildren.size(); ++j) skinJoint(joint->Children[j], joint); } E_ANIMATED_MESH_TYPE CSkinnedMesh::getMeshType() const { return EAMT_SKINNED; } //! Gets joint count. u32 CSkinnedMesh::getJointCount() const { return AllJoints.size(); } //! Gets the name of a joint. const c8* CSkinnedMesh::getJointName(u32 number) const { if (number >= AllJoints.size()) return 0; return AllJoints[number]->Name.c_str(); } //! Gets a joint number from its name s32 CSkinnedMesh::getJointNumber(const c8* name) const { for (u32 i=0; iName == name) return i; } return -1; } //! returns amount of mesh buffers. u32 CSkinnedMesh::getMeshBufferCount() const { return LocalBuffers.size(); } //! returns pointer to a mesh buffer IMeshBuffer* CSkinnedMesh::getMeshBuffer(u32 nr) const { if (nr < LocalBuffers.size()) return LocalBuffers[nr]; else return 0; } //! Returns pointer to a mesh buffer which fits a material IMeshBuffer* CSkinnedMesh::getMeshBuffer(const video::SMaterial &material) const { for (u32 i=0; igetMaterial() == material) return LocalBuffers[i]; } return 0; } //! returns an axis aligned bounding box const core::aabbox3d& CSkinnedMesh::getBoundingBox() const { return BoundingBox; } //! set user axis aligned bounding box void CSkinnedMesh::setBoundingBox( const core::aabbox3df& box) { BoundingBox = box; } //! sets a flag of all contained materials to a new value void CSkinnedMesh::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) { for (u32 i=0; iMaterial.setFlag(flag,newvalue); } //! set the hardware mapping hint, for driver void CSkinnedMesh::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer) { for (u32 i=0; isetHardwareMappingHint(newMappingHint, buffer); } //! flags the meshbuffer as changed, reloads hardware buffers void CSkinnedMesh::setDirty(E_BUFFER_TYPE buffer) { for (u32 i=0; isetDirty(buffer); } //! uses animation from another mesh bool CSkinnedMesh::useAnimationFrom(const ISkinnedMesh *mesh) { bool unmatched=false; for(u32 i=0;iUseAnimationFrom=0; if (joint->Name=="") unmatched=true; else { for(u32 j=0;jgetAllJoints().size();++j) { SJoint *otherJoint=mesh->getAllJoints()[j]; if (joint->Name==otherJoint->Name) { joint->UseAnimationFrom=otherJoint; } } if (!joint->UseAnimationFrom) unmatched=true; } } checkForAnimation(); return !unmatched; } //!Update Normals when Animating //!False= Don't animate them, faster //!True= Update normals (default) void CSkinnedMesh::updateNormalsWhenAnimating(bool on) { AnimateNormals = on; } //!Sets Interpolation Mode void CSkinnedMesh::setInterpolationMode(E_INTERPOLATION_MODE mode) { InterpolationMode = mode; } core::array &CSkinnedMesh::getMeshBuffers() { return LocalBuffers; } core::array &CSkinnedMesh::getAllJoints() { return AllJoints; } const core::array &CSkinnedMesh::getAllJoints() const { return AllJoints; } //! (This feature is not implementated in irrlicht yet) bool CSkinnedMesh::setHardwareSkinning(bool on) { if (HardwareSkinning!=on) { if (on) { //set mesh to static pose... for (u32 i=0; iWeights.size(); ++j) { const u16 buffer_id=joint->Weights[j].buffer_id; const u32 vertex_id=joint->Weights[j].vertex_id; LocalBuffers[buffer_id]->getVertex(vertex_id)->Pos = joint->Weights[j].StaticPos; LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal = joint->Weights[j].StaticNormal; LocalBuffers[buffer_id]->boundingBoxNeedsRecalculated(); } } } HardwareSkinning=on; } return HardwareSkinning; } void CSkinnedMesh::calculateGlobalMatrices(SJoint *joint,SJoint *parentJoint) { if (!joint && parentJoint) // bit of protection from endless loops return; //Go through the root bones if (!joint) { for (u32 i=0; iGlobalMatrix = joint->LocalMatrix; else joint->GlobalMatrix = parentJoint->GlobalMatrix * joint->LocalMatrix; joint->LocalAnimatedMatrix=joint->LocalMatrix; joint->GlobalAnimatedMatrix=joint->GlobalMatrix; if (joint->GlobalInversedMatrix.isIdentity())//might be pre calculated { joint->GlobalInversedMatrix = joint->GlobalMatrix; joint->GlobalInversedMatrix.makeInverse(); // slow } for (u32 j=0; jChildren.size(); ++j) calculateGlobalMatrices(joint->Children[j],joint); SkinnedLastFrame=false; } void CSkinnedMesh::checkForAnimation() { u32 i,j; //Check for animation... HasAnimation = false; for(i=0;iUseAnimationFrom) { if (AllJoints[i]->UseAnimationFrom->PositionKeys.size() || AllJoints[i]->UseAnimationFrom->ScaleKeys.size() || AllJoints[i]->UseAnimationFrom->RotationKeys.size() ) { HasAnimation = true; } } } //meshes with weights, are still counted as animated for ragdolls, etc if (!HasAnimation) { for(i=0;iWeights.size()) HasAnimation = true; } } if (HasAnimation) { //--- Find the length of the animation --- AnimationFrames=0; for(i=0;iUseAnimationFrom) { if (AllJoints[i]->UseAnimationFrom->PositionKeys.size()) if (AllJoints[i]->UseAnimationFrom->PositionKeys.getLast().frame > AnimationFrames) AnimationFrames=AllJoints[i]->UseAnimationFrom->PositionKeys.getLast().frame; if (AllJoints[i]->UseAnimationFrom->ScaleKeys.size()) if (AllJoints[i]->UseAnimationFrom->ScaleKeys.getLast().frame > AnimationFrames) AnimationFrames=AllJoints[i]->UseAnimationFrom->ScaleKeys.getLast().frame; if (AllJoints[i]->UseAnimationFrom->RotationKeys.size()) if (AllJoints[i]->UseAnimationFrom->RotationKeys.getLast().frame > AnimationFrames) AnimationFrames=AllJoints[i]->UseAnimationFrom->RotationKeys.getLast().frame; } } } if (HasAnimation && !PreparedForSkinning) { PreparedForSkinning=true; //check for bugs: for(i=0; i < AllJoints.size(); ++i) { SJoint *joint = AllJoints[i]; for (j=0; jWeights.size(); ++j) { const u16 buffer_id=joint->Weights[j].buffer_id; const u32 vertex_id=joint->Weights[j].vertex_id; //check for invalid ids if (buffer_id>=LocalBuffers.size()) { os::Printer::log("Skinned Mesh: Weight buffer id too large", ELL_WARNING); joint->Weights[j].buffer_id = joint->Weights[j].vertex_id =0; } else if (vertex_id>=LocalBuffers[buffer_id]->getVertexCount()) { os::Printer::log("Skinned Mesh: Weight vertex id too large", ELL_WARNING); joint->Weights[j].buffer_id = joint->Weights[j].vertex_id =0; } } } //An array used in skinning for (i=0; iWeights.size(); ++j) { const u16 buffer_id=joint->Weights[j].buffer_id; const u32 vertex_id=joint->Weights[j].vertex_id; joint->Weights[j].Moved = &Vertices_Moved[buffer_id] [vertex_id]; joint->Weights[j].StaticPos = LocalBuffers[buffer_id]->getVertex(vertex_id)->Pos; joint->Weights[j].StaticNormal = LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal; //joint->Weights[j]._Pos=&Buffers[buffer_id]->getVertex(vertex_id)->Pos; } } // normalize weights normalizeWeights(); } SkinnedLastFrame=false; } //! called by loader after populating with mesh and bone data void CSkinnedMesh::finalize() { u32 i; // Make sure we recalc the next frame LastAnimatedFrame=-1; SkinnedLastFrame=false; //calculate bounding box for (i=0; irecalculateBoundingBox(); } if (AllJoints.size() || RootJoints.size()) { // populate AllJoints or RootJoints, depending on which is empty if (!RootJoints.size()) { for(u32 CheckingIdx=0; CheckingIdx < AllJoints.size(); ++CheckingIdx) { bool foundParent=false; for(i=0; i < AllJoints.size(); ++i) { for(u32 n=0; n < AllJoints[i]->Children.size(); ++n) { if (AllJoints[i]->Children[n] == AllJoints[CheckingIdx]) foundParent=true; } } if (!foundParent) RootJoints.push_back(AllJoints[CheckingIdx]); } } else { AllJoints=RootJoints; } } for(i=0; i < AllJoints.size(); ++i) { AllJoints[i]->UseAnimationFrom=AllJoints[i]; } //Set array sizes... for (i=0; i() ); Vertices_Moved[i].set_used(LocalBuffers[i]->getVertexCount()); } //Todo: optimise keys here... checkForAnimation(); if (HasAnimation) { //--- optimize and check keyframes --- for(i=0;i &PositionKeys =AllJoints[i]->PositionKeys; core::array &ScaleKeys = AllJoints[i]->ScaleKeys; core::array &RotationKeys = AllJoints[i]->RotationKeys; if (PositionKeys.size()>2) { for(u32 j=0;j1) { for(u32 j=0;j= PositionKeys[j+1].frame) //bad frame, unneed and may cause problems { PositionKeys.erase(j+1); --j; } } } if (ScaleKeys.size()>2) { for(u32 j=0;j1) { for(u32 j=0;j= ScaleKeys[j+1].frame) //bad frame, unneed and may cause problems { ScaleKeys.erase(j+1); --j; } } } if (RotationKeys.size()>2) { for(u32 j=0;j1) { for(u32 j=0;j= RotationKeys[j+1].frame) //bad frame, unneed and may cause problems { RotationKeys.erase(j+1); --j; } } } //Fill empty keyframe areas if (PositionKeys.size()) { SPositionKey *Key; Key=&PositionKeys[0];//getFirst if (Key->frame!=0) { PositionKeys.push_front(*Key); Key=&PositionKeys[0];//getFirst Key->frame=0; } Key=&PositionKeys.getLast(); if (Key->frame!=AnimationFrames) { PositionKeys.push_back(*Key); Key=&PositionKeys.getLast(); Key->frame=AnimationFrames; } } if (ScaleKeys.size()) { SScaleKey *Key; Key=&ScaleKeys[0];//getFirst if (Key->frame!=0) { ScaleKeys.push_front(*Key); Key=&ScaleKeys[0];//getFirst Key->frame=0; } Key=&ScaleKeys.getLast(); if (Key->frame!=AnimationFrames) { ScaleKeys.push_back(*Key); Key=&ScaleKeys.getLast(); Key->frame=AnimationFrames; } } if (RotationKeys.size()) { SRotationKey *Key; Key=&RotationKeys[0];//getFirst if (Key->frame!=0) { RotationKeys.push_front(*Key); Key=&RotationKeys[0];//getFirst Key->frame=0; } Key=&RotationKeys.getLast(); if (Key->frame!=AnimationFrames) { RotationKeys.push_back(*Key); Key=&RotationKeys.getLast(); Key->frame=AnimationFrames; } } } } //Needed for animation and skinning... calculateGlobalMatrices(0,0); //animateMesh(0, 1); //buildAllLocalAnimatedMatrices(); //buildAllGlobalAnimatedMatrices(); //rigid animation for non animated meshes for (i=0; iAttachedMeshes.size(); ++j) { SSkinMeshBuffer* Buffer=(*SkinningBuffers)[ AllJoints[i]->AttachedMeshes[j] ]; Buffer->Transformation=AllJoints[i]->GlobalAnimatedMatrix; } } //calculate bounding box if (LocalBuffers.empty()) BoundingBox.reset(0,0,0); else { irr::core::aabbox3df bb(LocalBuffers[0]->BoundingBox); LocalBuffers[0]->Transformation.transformBoxEx(bb); BoundingBox.reset(bb); for (u32 j=1; jBoundingBox; LocalBuffers[j]->Transformation.transformBoxEx(bb); BoundingBox.addInternalBox(bb); } } } void CSkinnedMesh::updateBoundingBox(void) { if(!SkinningBuffers) return; core::array & buffer = *SkinningBuffers; BoundingBox.reset(0,0,0); if (!buffer.empty()) { for (u32 j=0; jrecalculateBoundingBox(); core::aabbox3df bb = buffer[j]->BoundingBox; buffer[j]->Transformation.transformBoxEx(bb); BoundingBox.addInternalBox(bb); } } } scene::SSkinMeshBuffer *CSkinnedMesh::addMeshBuffer() { scene::SSkinMeshBuffer *buffer=new scene::SSkinMeshBuffer(); LocalBuffers.push_back(buffer); return buffer; } CSkinnedMesh::SJoint *CSkinnedMesh::addJoint(SJoint *parent) { SJoint *joint=new SJoint; AllJoints.push_back(joint); if (!parent) { //Add root joints to array in finalize() } else { //Set parent (Be careful of the mesh loader also setting the parent) parent->Children.push_back(joint); } return joint; } CSkinnedMesh::SPositionKey *CSkinnedMesh::addPositionKey(SJoint *joint) { if (!joint) return 0; joint->PositionKeys.push_back(SPositionKey()); return &joint->PositionKeys.getLast(); } CSkinnedMesh::SScaleKey *CSkinnedMesh::addScaleKey(SJoint *joint) { if (!joint) return 0; joint->ScaleKeys.push_back(SScaleKey()); return &joint->ScaleKeys.getLast(); } CSkinnedMesh::SRotationKey *CSkinnedMesh::addRotationKey(SJoint *joint) { if (!joint) return 0; joint->RotationKeys.push_back(SRotationKey()); return &joint->RotationKeys.getLast(); } CSkinnedMesh::SWeight *CSkinnedMesh::addWeight(SJoint *joint) { if (!joint) return 0; joint->Weights.push_back(SWeight()); return &joint->Weights.getLast(); } bool CSkinnedMesh::isStatic() { return !HasAnimation; } void CSkinnedMesh::normalizeWeights() { // note: unsure if weights ids are going to be used. // Normalise the weights on bones.... u32 i,j; core::array< core::array > verticesTotalWeight; verticesTotalWeight.reallocate(LocalBuffers.size()); for (i=0; i()); verticesTotalWeight[i].set_used(LocalBuffers[i]->getVertexCount()); } for (i=0; iWeights.size(); ++j) { if (joint->Weights[j].strength<=0)//Check for invalid weights { joint->Weights.erase(j); --j; } else { verticesTotalWeight[joint->Weights[j].buffer_id] [joint->Weights[j].vertex_id] += joint->Weights[j].strength; } } } for (i=0; iWeights.size(); ++j) { const f32 total = verticesTotalWeight[joint->Weights[j].buffer_id] [joint->Weights[j].vertex_id]; if (total != 0 && total != 1) joint->Weights[j].strength /= total; } } } void CSkinnedMesh::recoverJointsFromMesh(core::array &jointChildSceneNodes) { for (u32 i=0; isetPosition(joint->LocalAnimatedMatrix.getTranslation()); node->setRotation(joint->LocalAnimatedMatrix.getRotationDegrees()); node->setScale(joint->LocalAnimatedMatrix.getScale()); node->positionHint=joint->positionHint; node->scaleHint=joint->scaleHint; node->rotationHint=joint->rotationHint; node->updateAbsolutePosition(); } } void CSkinnedMesh::transferJointsToMesh(const core::array &jointChildSceneNodes) { for (u32 i=0; iLocalAnimatedMatrix.setRotationDegrees(node->getRotation()); joint->LocalAnimatedMatrix.setTranslation(node->getPosition()); joint->LocalAnimatedMatrix *= core::matrix4().setScale(node->getScale()); joint->positionHint=node->positionHint; joint->scaleHint=node->scaleHint; joint->rotationHint=node->rotationHint; joint->GlobalSkinningSpace=(node->getSkinningSpace()==EBSS_GLOBAL); } // Make sure we recalc the next frame LastAnimatedFrame=-1; SkinnedLastFrame=false; } void CSkinnedMesh::transferOnlyJointsHintsToMesh(const core::array &jointChildSceneNodes) { for (u32 i=0; ipositionHint=node->positionHint; joint->scaleHint=node->scaleHint; joint->rotationHint=node->rotationHint; } SkinnedLastFrame=false; } void CSkinnedMesh::addJoints(core::array &jointChildSceneNodes, IAnimatedMeshSceneNode* node, ISceneManager* smgr) { //Create new joints for (u32 i=0; iName.c_str())); } //Match up parents for (u32 i=0; iChildren.size(); ++n) { if (parentTest->Children[n]==joint) { parentID=j; break; } } } } IBoneSceneNode* bone=jointChildSceneNodes[i]; if (parentID!=-1) bone->setParent(jointChildSceneNodes[parentID]); else bone->setParent(node); bone->drop(); } SkinnedLastFrame=false; } void CSkinnedMesh::convertMeshToTangents() { // now calculate tangents for (u32 b=0; b < LocalBuffers.size(); ++b) { if (LocalBuffers[b]) { LocalBuffers[b]->convertToTangents(); const s32 idxCnt = LocalBuffers[b]->getIndexCount(); u16* idx = LocalBuffers[b]->getIndices(); video::S3DVertexTangents* v = (video::S3DVertexTangents*)LocalBuffers[b]->getVertices(); for (s32 i=0; i& getBoundingBox() const; //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_SHADOW_VOLUME; } private: typedef core::array SShadowVolume; void createShadowVolume(const core::vector3df& pos, bool isDirectional=false); u32 createEdgesAndCaps(const core::vector3df& light, SShadowVolume* svp, core::aabbox3d* bb); //! Generates adjacency information based on mesh indices. void calculateAdjacency(); core::aabbox3d Box; // a shadow volume for every light core::array ShadowVolumes; // a back cap bounding box for every light core::array > ShadowBBox; core::array Vertices; core::array Indices; core::array Adjacency; core::array Edges; // tells if face is front facing core::array FaceData; const scene::IMesh* ShadowMesh; u32 IndexCount; u32 VertexCount; u32 ShadowVolumesUsed; f32 Infinity; bool UseZFailMethod; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CShadowVolumeSceneNode.cpp0000644000000000000000000002447212574354552022156 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CShadowVolumeSceneNode.h" #include "ISceneManager.h" #include "IMesh.h" #include "IVideoDriver.h" #include "ICameraSceneNode.h" #include "SViewFrustum.h" #include "SLight.h" #include "os.h" namespace irr { namespace scene { //! constructor CShadowVolumeSceneNode::CShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent, ISceneManager* mgr, s32 id, bool zfailmethod, f32 infinity) : IShadowVolumeSceneNode(parent, mgr, id), ShadowMesh(0), IndexCount(0), VertexCount(0), ShadowVolumesUsed(0), Infinity(infinity), UseZFailMethod(zfailmethod) { #ifdef _DEBUG setDebugName("CShadowVolumeSceneNode"); #endif setShadowMesh(shadowMesh); setAutomaticCulling(scene::EAC_OFF); } //! destructor CShadowVolumeSceneNode::~CShadowVolumeSceneNode() { if (ShadowMesh) ShadowMesh->drop(); } void CShadowVolumeSceneNode::createShadowVolume(const core::vector3df& light, bool isDirectional) { SShadowVolume* svp = 0; core::aabbox3d* bb = 0; // builds the shadow volume and adds it to the shadow volume list. if (ShadowVolumes.size() > ShadowVolumesUsed) { // get the next unused buffer svp = &ShadowVolumes[ShadowVolumesUsed]; svp->set_used(0); bb = &ShadowBBox[ShadowVolumesUsed]; } else { ShadowVolumes.push_back(SShadowVolume()); svp = &ShadowVolumes.getLast(); ShadowBBox.push_back(core::aabbox3d()); bb = &ShadowBBox.getLast(); } svp->reallocate(IndexCount*5); ++ShadowVolumesUsed; // We use triangle lists Edges.set_used(IndexCount*2); u32 numEdges = 0; numEdges=createEdgesAndCaps(light, svp, bb); // for all edges add the near->far quads for (u32 i=0; isize() >= svp->allocated_size()-5) os::Printer::log("Allocation too small.", ELL_DEBUG); #endif svp->push_back(v1); svp->push_back(v2); svp->push_back(v3); svp->push_back(v2); svp->push_back(v4); svp->push_back(v3); } } #define IRR_USE_ADJACENCY #define IRR_USE_REVERSE_EXTRUDED u32 CShadowVolumeSceneNode::createEdgesAndCaps(const core::vector3df& light, SShadowVolume* svp, core::aabbox3d* bb) { u32 numEdges=0; const u32 faceCount = IndexCount / 3; if(faceCount >= 1) bb->reset(Vertices[Indices[0]]); else bb->reset(0,0,0); // Check every face if it is front or back facing the light. for (u32 i=0; isize() >= svp->allocated_size()-5) os::Printer::log("Allocation too small.", ELL_DEBUG); #endif // add front cap from light-facing faces svp->push_back(v2); svp->push_back(v1); svp->push_back(v0); // add back cap const core::vector3df i0 = v0+(v0-light).normalize()*Infinity; const core::vector3df i1 = v1+(v1-light).normalize()*Infinity; const core::vector3df i2 = v2+(v2-light).normalize()*Infinity; svp->push_back(i0); svp->push_back(i1); svp->push_back(i2); bb->addInternalPoint(i0); bb->addInternalPoint(i1); bb->addInternalPoint(i2); } } // Create edges for (u32 i=0; idrop(); ShadowMesh = mesh; if (ShadowMesh) { ShadowMesh->grab(); Box = ShadowMesh->getBoundingBox(); } } void CShadowVolumeSceneNode::updateShadowVolumes() { const u32 oldIndexCount = IndexCount; const u32 oldVertexCount = VertexCount; const IMesh* const mesh = ShadowMesh; if (!mesh) return; // create as much shadow volumes as there are lights but // do not ignore the max light settings. const u32 lightCount = SceneManager->getVideoDriver()->getDynamicLightCount(); if (!lightCount) return; // calculate total amount of vertices and indices VertexCount = 0; IndexCount = 0; ShadowVolumesUsed = 0; u32 i; u32 totalVertices = 0; u32 totalIndices = 0; const u32 bufcnt = mesh->getMeshBufferCount(); for (i=0; igetMeshBuffer(i); totalIndices += buf->getIndexCount(); totalVertices += buf->getVertexCount(); } // allocate memory if necessary Vertices.set_used(totalVertices); Indices.set_used(totalIndices); FaceData.set_used(totalIndices / 3); // copy mesh for (i=0; igetMeshBuffer(i); const u16* idxp = buf->getIndices(); const u16* idxpend = idxp + buf->getIndexCount(); for (; idxp!=idxpend; ++idxp) Indices[IndexCount++] = *idxp + VertexCount; const u32 vtxcnt = buf->getVertexCount(); for (u32 j=0; jgetPosition(j); } // recalculate adjacency if necessary if (oldVertexCount != VertexCount || oldIndexCount != IndexCount) calculateAdjacency(); core::matrix4 mat = Parent->getAbsoluteTransformation(); mat.makeInverse(); const core::vector3df parentpos = Parent->getAbsolutePosition(); // TODO: Only correct for point lights. for (i=0; igetVideoDriver()->getDynamicLight(i); core::vector3df lpos = dl.Position; if (dl.CastShadows && fabs((lpos - parentpos).getLengthSQ()) <= (dl.Radius*dl.Radius*4.0f)) { mat.transformVect(lpos); createShadowVolume(lpos); } } } //! pre render method void CShadowVolumeSceneNode::OnRegisterSceneNode() { if (IsVisible) { SceneManager->registerNodeForRendering(this, scene::ESNRP_SHADOW); ISceneNode::OnRegisterSceneNode(); } } //! renders the node. void CShadowVolumeSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); if (!ShadowVolumesUsed || !driver) return; driver->setTransform(video::ETS_WORLD, Parent->getAbsoluteTransformation()); for (u32 i=0; igetActiveCamera()) { // Disable shadows drawing, when back cap is behind of ZFar plane. SViewFrustum frust = *SceneManager->getActiveCamera()->getViewFrustum(); core::matrix4 invTrans(Parent->getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE); frust.transform(invTrans); core::vector3df edges[8]; ShadowBBox[i].getEdges(edges); core::vector3df largestEdge = edges[0]; f32 maxDistance = core::vector3df(SceneManager->getActiveCamera()->getPosition() - edges[0]).getLength(); f32 curDistance = 0.f; for(int j = 1; j < 8; ++j) { curDistance = core::vector3df(SceneManager->getActiveCamera()->getPosition() - edges[j]).getLength(); if(curDistance > maxDistance) { maxDistance = curDistance; largestEdge = edges[j]; } } if (!(frust.planes[scene::SViewFrustum::VF_FAR_PLANE].classifyPointRelation(largestEdge) != core::ISREL3D_FRONT)) drawShadow = false; } if(drawShadow) driver->drawStencilShadowVolume(ShadowVolumes[i], UseZFailMethod, DebugDataVisible); else { core::array triangles; driver->drawStencilShadowVolume(triangles, UseZFailMethod, DebugDataVisible); } } } //! returns the axis aligned bounding box of this node const core::aabbox3d& CShadowVolumeSceneNode::getBoundingBox() const { return Box; } //! Generates adjacency information based on mesh indices. void CShadowVolumeSceneNode::calculateAdjacency() { Adjacency.set_used(IndexCount); // go through all faces and fetch their three neighbours for (u32 f=0; f store face number, else store adjacent face if (of >= IndexCount) Adjacency[f + edge] = f/3; else Adjacency[f + edge] = of/3; } } } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorTexture.h0000644000000000000000000000322312574354552022330 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_NODE_ANIMATOR_TEXTURE_H_INCLUDED__ #define __C_SCENE_NODE_ANIMATOR_TEXTURE_H_INCLUDED__ #include "irrArray.h" #include "ISceneNodeAnimatorFinishing.h" namespace irr { namespace scene { class CSceneNodeAnimatorTexture : public ISceneNodeAnimatorFinishing { public: //! constructor CSceneNodeAnimatorTexture(const core::array& textures, s32 timePerFrame, bool loop, u32 now); //! destructor virtual ~CSceneNodeAnimatorTexture(); //! animates a scene node virtual void animateNode(ISceneNode* node, u32 timeMs); //! Writes attributes of the scene node animator. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node animator. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_TEXTURE; } //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer after calling this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); private: void clearTextures(); core::array Textures; u32 TimePerFrame; u32 StartTime; bool Loop; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorTexture.cpp0000644000000000000000000000602012574354552022661 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSceneNodeAnimatorTexture.h" #include "ITexture.h" namespace irr { namespace scene { //! constructor CSceneNodeAnimatorTexture::CSceneNodeAnimatorTexture(const core::array& textures, s32 timePerFrame, bool loop, u32 now) : ISceneNodeAnimatorFinishing(0), TimePerFrame(timePerFrame), StartTime(now), Loop(loop) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorTexture"); #endif for (u32 i=0; igrab(); Textures.push_back(textures[i]); } FinishTime = now + (timePerFrame * Textures.size()); } //! destructor CSceneNodeAnimatorTexture::~CSceneNodeAnimatorTexture() { clearTextures(); } void CSceneNodeAnimatorTexture::clearTextures() { for (u32 i=0; idrop(); } //! animates a scene node void CSceneNodeAnimatorTexture::animateNode(ISceneNode* node, u32 timeMs) { if(!node) return; if (Textures.size()) { const u32 t = (timeMs-StartTime); u32 idx = 0; if (!Loop && timeMs >= FinishTime) { idx = Textures.size() - 1; HasFinished = true; } else { idx = (t/TimePerFrame) % Textures.size(); } if (idx < Textures.size()) node->setMaterialTexture(0, Textures[idx]); } } //! Writes attributes of the scene node animator. void CSceneNodeAnimatorTexture::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addInt("TimePerFrame", TimePerFrame); out->addBool("Loop", Loop); // add one texture in addition when serializing for editors // to make it easier to add textures quickly u32 count = Textures.size(); if ( options && (options->Flags & io::EARWF_FOR_EDITOR)) count += 1; for (u32 i=0; iaddTexture(tname.c_str(), igetAttributeAsInt("TimePerFrame"); Loop = in->getAttributeAsBool("Loop"); clearTextures(); for(u32 i=1; true; ++i) { core::stringc tname = "Texture"; tname += (int)i; if (in->existsAttribute(tname.c_str())) { video::ITexture* tex = in->getAttributeAsTexture(tname.c_str()); if (tex) { tex->grab(); Textures.push_back(tex); } } else break; } } ISceneNodeAnimator* CSceneNodeAnimatorTexture::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorTexture * newAnimator = new CSceneNodeAnimatorTexture(Textures, TimePerFrame, Loop, StartTime); return newAnimator; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorRotation.h0000644000000000000000000000265512574354552022477 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_NODE_ANIMATOR_ROTATION_H_INCLUDED__ #define __C_SCENE_NODE_ANIMATOR_ROTATION_H_INCLUDED__ #include "ISceneNode.h" namespace irr { namespace scene { class CSceneNodeAnimatorRotation : public ISceneNodeAnimator { public: //! constructor CSceneNodeAnimatorRotation(u32 time, const core::vector3df& rotation); //! animates a scene node virtual void animateNode(ISceneNode* node, u32 timeMs); //! Writes attributes of the scene node animator. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node animator. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_ROTATION; } //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer after calling this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); private: core::vector3df Rotation; u32 StartTime; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorRotation.cpp0000644000000000000000000000351512574354552023026 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSceneNodeAnimatorRotation.h" namespace irr { namespace scene { //! constructor CSceneNodeAnimatorRotation::CSceneNodeAnimatorRotation(u32 time, const core::vector3df& rotation) : Rotation(rotation), StartTime(time) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorRotation"); #endif } //! animates a scene node void CSceneNodeAnimatorRotation::animateNode(ISceneNode* node, u32 timeMs) { if (node) // thanks to warui for this fix { const u32 diffTime = timeMs - StartTime; if (diffTime != 0) { // clip the rotation to small values, to avoid // precision problems with huge floats. core::vector3df rot = node->getRotation() + Rotation*(diffTime*0.1f); if (rot.X>360.f) rot.X=fmodf(rot.X, 360.f); if (rot.Y>360.f) rot.Y=fmodf(rot.Y, 360.f); if (rot.Z>360.f) rot.Z=fmodf(rot.Z, 360.f); node->setRotation(rot); StartTime=timeMs; } } } //! Writes attributes of the scene node animator. void CSceneNodeAnimatorRotation::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addVector3d("Rotation", Rotation); } //! Reads attributes of the scene node animator. void CSceneNodeAnimatorRotation::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Rotation = in->getAttributeAsVector3d("Rotation"); } ISceneNodeAnimator* CSceneNodeAnimatorRotation::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorRotation * newAnimator = new CSceneNodeAnimatorRotation(StartTime, Rotation); return newAnimator; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorFollowSpline.h0000644000000000000000000000366012574354552023312 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_NODE_ANIMATOR_FOLLOW_SPLINE_H_INCLUDED__ #define __C_SCENE_NODE_ANIMATOR_FOLLOW_SPLINE_H_INCLUDED__ #include "ISceneNode.h" #include "irrArray.h" #include "ISceneNodeAnimatorFinishing.h" namespace irr { namespace scene { //! Scene node animator based free code Matthias Gall wrote and sent in. (Most of //! this code is written by him, I only modified bits.) class CSceneNodeAnimatorFollowSpline : public ISceneNodeAnimatorFinishing { public: //! constructor CSceneNodeAnimatorFollowSpline(u32 startTime, const core::array< core::vector3df >& points, f32 speed = 1.0f, f32 tightness = 0.5f, bool loop=true, bool pingpong=false); //! animates a scene node virtual void animateNode(ISceneNode* node, u32 timeMs); //! Writes attributes of the scene node animator. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node animator. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_FOLLOW_SPLINE; } //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer after calling this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); protected: //! clamps a the value idx to fit into range 0..size-1 s32 clamp(s32 idx, s32 size); core::array< core::vector3df > Points; f32 Speed; f32 Tightness; u32 StartTime; bool Loop; bool PingPong; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorFollowSpline.cpp0000644000000000000000000001062312574354552023642 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSceneNodeAnimatorFollowSpline.h" namespace irr { namespace scene { //! constructor CSceneNodeAnimatorFollowSpline::CSceneNodeAnimatorFollowSpline(u32 time, const core::array& points, f32 speed, f32 tightness, bool loop, bool pingpong) : ISceneNodeAnimatorFinishing(0), Points(points), Speed(speed), Tightness(tightness), StartTime(time) , Loop(loop), PingPong(pingpong) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorFollowSpline"); #endif } inline s32 CSceneNodeAnimatorFollowSpline::clamp(s32 idx, s32 size) { return ( idx<0 ? size+idx : ( idx>=size ? idx-size : idx ) ); } //! animates a scene node void CSceneNodeAnimatorFollowSpline::animateNode(ISceneNode* node, u32 timeMs) { if(!node) return; const u32 pSize = Points.size(); if (pSize==0) { if ( !Loop ) HasFinished = true; return; } if (pSize==1) { if ( timeMs > StartTime ) { node->setPosition(Points[0]); if ( !Loop ) HasFinished = true; } return; } const f32 dt = ( (timeMs-StartTime) * Speed * 0.001f ); const s32 unwrappedIdx = core::floor32( dt ); if ( !Loop && unwrappedIdx >= (s32)pSize-1 ) { node->setPosition(Points[pSize-1]); HasFinished = true; return; } const bool pong = PingPong && (unwrappedIdx/(pSize-1))%2; const f32 u = pong ? 1.f-core::fract ( dt ) : core::fract ( dt ); const s32 idx = pong ? (pSize-2) - (unwrappedIdx % (pSize-1)) : (PingPong ? unwrappedIdx % (pSize-1) : unwrappedIdx % pSize); //const f32 u = 0.001f * fmodf( dt, 1000.0f ); const core::vector3df& p0 = Points[ clamp( idx - 1, pSize ) ]; const core::vector3df& p1 = Points[ clamp( idx + 0, pSize ) ]; // starting point const core::vector3df& p2 = Points[ clamp( idx + 1, pSize ) ]; // end point const core::vector3df& p3 = Points[ clamp( idx + 2, pSize ) ]; // hermite polynomials const f32 h1 = 2.0f * u * u * u - 3.0f * u * u + 1.0f; const f32 h2 = -2.0f * u * u * u + 3.0f * u * u; const f32 h3 = u * u * u - 2.0f * u * u + u; const f32 h4 = u * u * u - u * u; // tangents const core::vector3df t1 = ( p2 - p0 ) * Tightness; const core::vector3df t2 = ( p3 - p1 ) * Tightness; // interpolated point node->setPosition(p1 * h1 + p2 * h2 + t1 * h3 + t2 * h4); } //! Writes attributes of the scene node animator. void CSceneNodeAnimatorFollowSpline::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addFloat("Speed", Speed); out->addFloat("Tightness", Tightness); out->addBool("Loop", Loop); out->addBool("PingPong", PingPong); u32 count = Points.size(); if ( options && (options->Flags & io::EARWF_FOR_EDITOR)) { // add one point in addition when serializing for editors // to make it easier to add points quickly count += 1; } for (u32 i=0; iaddVector3d(tname.c_str(), igetAttributeAsFloat("Speed"); Tightness = in->getAttributeAsFloat("Tightness"); Loop = in->getAttributeAsBool("Loop"); PingPong = in->getAttributeAsBool("PingPong"); Points.clear(); for(u32 i=1; true; ++i) { core::stringc pname = "Point"; pname += i; if (in->existsAttribute(pname.c_str())) Points.push_back(in->getAttributeAsVector3d(pname.c_str())); else break; } // remove last point if double entry from editor if ( options && (options->Flags & io::EARWF_FOR_EDITOR) && Points.size() > 2 && Points.getLast() == core::vector3df(0,0,0)) { Points.erase(Points.size()-1); if (Points.size() > 2 && Points.getLast() == core::vector3df(0,0,0)) Points.erase(Points.size()-1); } } ISceneNodeAnimator* CSceneNodeAnimatorFollowSpline::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorFollowSpline * newAnimator = new CSceneNodeAnimatorFollowSpline(StartTime, Points, Speed, Tightness); return newAnimator; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorFlyStraight.h0000644000000000000000000000333112574354552023130 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_NODE_ANIMATOR_FLY_STRAIGHT_H_INCLUDED__ #define __C_SCENE_NODE_ANIMATOR_FLY_STRAIGHT_H_INCLUDED__ #include "ISceneNodeAnimatorFinishing.h" namespace irr { namespace scene { class CSceneNodeAnimatorFlyStraight : public ISceneNodeAnimatorFinishing { public: //! constructor CSceneNodeAnimatorFlyStraight(const core::vector3df& startPoint, const core::vector3df& endPoint, u32 timeForWay, bool loop, u32 now, bool pingpong); //! animates a scene node virtual void animateNode(ISceneNode* node, u32 timeMs); //! Writes attributes of the scene node animator. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node animator. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_FLY_STRAIGHT; } //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer after calling this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); private: void recalculateIntermediateValues(); core::vector3df Start; core::vector3df End; core::vector3df Vector; f32 TimeFactor; u32 StartTime; u32 TimeForWay; bool Loop; bool PingPong; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorFlyStraight.cpp0000644000000000000000000000537312574354552023473 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSceneNodeAnimatorFlyStraight.h" namespace irr { namespace scene { //! constructor CSceneNodeAnimatorFlyStraight::CSceneNodeAnimatorFlyStraight(const core::vector3df& startPoint, const core::vector3df& endPoint, u32 timeForWay, bool loop, u32 now, bool pingpong) : ISceneNodeAnimatorFinishing(now + timeForWay), Start(startPoint), End(endPoint), TimeFactor(0.0f), StartTime(now), TimeForWay(timeForWay), Loop(loop), PingPong(pingpong) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorFlyStraight"); #endif recalculateIntermediateValues(); } void CSceneNodeAnimatorFlyStraight::recalculateIntermediateValues() { Vector = End - Start; TimeFactor = (f32)Vector.getLength() / TimeForWay; Vector.normalize(); } //! animates a scene node void CSceneNodeAnimatorFlyStraight::animateNode(ISceneNode* node, u32 timeMs) { if (!node) return; u32 t = (timeMs-StartTime); core::vector3df pos; if (!Loop && !PingPong && t >= TimeForWay) { pos = End; HasFinished = true; } else if (!Loop && PingPong && t >= TimeForWay * 2.f ) { pos = Start; HasFinished = true; } else { f32 phase = fmodf( (f32) t, (f32) TimeForWay ); core::vector3df rel = Vector * phase * TimeFactor; const bool pong = PingPong && fmodf( (f32) t, (f32) TimeForWay*2.f ) >= TimeForWay; if ( !pong ) { pos += Start + rel; } else { pos = End - rel; } } node->setPosition(pos); } //! Writes attributes of the scene node animator. void CSceneNodeAnimatorFlyStraight::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addVector3d("Start", Start); out->addVector3d("End", End); out->addInt("TimeForWay", TimeForWay); out->addBool("Loop", Loop); out->addBool("PingPong", PingPong); } //! Reads attributes of the scene node animator. void CSceneNodeAnimatorFlyStraight::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Start = in->getAttributeAsVector3d("Start"); End = in->getAttributeAsVector3d("End"); TimeForWay = in->getAttributeAsInt("TimeForWay"); Loop = in->getAttributeAsBool("Loop"); PingPong = in->getAttributeAsBool("PingPong"); recalculateIntermediateValues(); } ISceneNodeAnimator* CSceneNodeAnimatorFlyStraight::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorFlyStraight * newAnimator = new CSceneNodeAnimatorFlyStraight(Start, End, TimeForWay, Loop, StartTime, PingPong); return newAnimator; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorFlyCircle.h0000644000000000000000000000344512574354552022552 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_NODE_ANIMATOR_FLY_CIRCLE_H_INCLUDED__ #define __C_SCENE_NODE_ANIMATOR_FLY_CIRCLE_H_INCLUDED__ #include "ISceneNode.h" namespace irr { namespace scene { class CSceneNodeAnimatorFlyCircle : public ISceneNodeAnimator { public: //! constructor CSceneNodeAnimatorFlyCircle(u32 time, const core::vector3df& center, f32 radius, f32 speed, const core::vector3df& direction, f32 radiusEllipsoid); //! animates a scene node virtual void animateNode(ISceneNode* node, u32 timeMs); //! Writes attributes of the scene node animator. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node animator. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_FLY_CIRCLE; } //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer after calling this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); private: // do some initial calculations void init(); // circle center core::vector3df Center; // up-vector, normal to the circle's plane core::vector3df Direction; // Two helper vectors core::vector3df VecU; core::vector3df VecV; f32 Radius; f32 RadiusEllipsoid; f32 Speed; u32 StartTime; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorFlyCircle.cpp0000644000000000000000000000551712574354552023107 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSceneNodeAnimatorFlyCircle.h" namespace irr { namespace scene { //! constructor CSceneNodeAnimatorFlyCircle::CSceneNodeAnimatorFlyCircle(u32 time, const core::vector3df& center, f32 radius, f32 speed, const core::vector3df& direction, f32 radiusEllipsoid) : Center(center), Direction(direction), Radius(radius), RadiusEllipsoid(radiusEllipsoid), Speed(speed), StartTime(time) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorFlyCircle"); #endif init(); } void CSceneNodeAnimatorFlyCircle::init() { Direction.normalize(); if (Direction.Y != 0) VecV = core::vector3df(50,0,0).crossProduct(Direction).normalize(); else VecV = core::vector3df(0,50,0).crossProduct(Direction).normalize(); VecU = VecV.crossProduct(Direction).normalize(); } //! animates a scene node void CSceneNodeAnimatorFlyCircle::animateNode(ISceneNode* node, u32 timeMs) { if ( 0 == node ) return; f32 time; // Check for the condition where the StartTime is in the future. if(StartTime > timeMs) time = ((s32)timeMs - (s32)StartTime) * Speed; else time = (timeMs-StartTime) * Speed; // node->setPosition(Center + Radius * ((VecU*cosf(time)) + (VecV*sinf(time)))); f32 r2 = RadiusEllipsoid == 0.f ? Radius : RadiusEllipsoid; node->setPosition(Center + (Radius*cosf(time)*VecU) + (r2*sinf(time)*VecV ) ); } //! Writes attributes of the scene node animator. void CSceneNodeAnimatorFlyCircle::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addVector3d("Center", Center); out->addFloat("Radius", Radius); out->addFloat("Speed", Speed); out->addVector3d("Direction", Direction); out->addFloat("RadiusEllipsoid", RadiusEllipsoid); } //! Reads attributes of the scene node animator. void CSceneNodeAnimatorFlyCircle::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Center = in->getAttributeAsVector3d("Center"); Radius = in->getAttributeAsFloat("Radius"); Speed = in->getAttributeAsFloat("Speed"); Direction = in->getAttributeAsVector3d("Direction"); StartTime = 0; if (Direction.equals(core::vector3df(0,0,0))) Direction.set(0,1,0); // irrlicht 1.1 backwards compatibility else Direction.normalize(); RadiusEllipsoid = in->getAttributeAsFloat("RadiusEllipsoid"); init(); } ISceneNodeAnimator* CSceneNodeAnimatorFlyCircle::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorFlyCircle * newAnimator = new CSceneNodeAnimatorFlyCircle(StartTime, Center, Radius, Speed, Direction, RadiusEllipsoid); return newAnimator; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorDelete.h0000644000000000000000000000216412574354552022075 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_NODE_ANIMATOR_DELETE_H_INCLUDED__ #define __C_SCENE_NODE_ANIMATOR_DELETE_H_INCLUDED__ #include "ISceneNodeAnimatorFinishing.h" namespace irr { namespace scene { class CSceneNodeAnimatorDelete : public ISceneNodeAnimatorFinishing { public: //! constructor CSceneNodeAnimatorDelete(ISceneManager* manager, u32 when); //! animates a scene node virtual void animateNode(ISceneNode* node, u32 timeMs); //! Returns type of the scene node animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_DELETION; } //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer after calling this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); private: ISceneManager* SceneManager; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorDelete.cpp0000644000000000000000000000231012574354552022421 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSceneNodeAnimatorDelete.h" #include "ISceneManager.h" namespace irr { namespace scene { //! constructor CSceneNodeAnimatorDelete::CSceneNodeAnimatorDelete(ISceneManager* manager, u32 time) : ISceneNodeAnimatorFinishing(time), SceneManager(manager) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorDelete"); #endif } //! animates a scene node void CSceneNodeAnimatorDelete::animateNode(ISceneNode* node, u32 timeMs) { if (timeMs > FinishTime) { HasFinished = true; if(node && SceneManager) { // don't delete if scene manager is attached to an editor if (!SceneManager->getParameters()->getAttributeAsBool(IRR_SCENE_MANAGER_IS_EDITOR)) SceneManager->addToDeletionQueue(node); } } } ISceneNodeAnimator* CSceneNodeAnimatorDelete::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorDelete * newAnimator = new CSceneNodeAnimatorDelete(SceneManager, FinishTime); return newAnimator; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.h0000644000000000000000000001346512574354552024353 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_NODE_ANIMATOR_COLLISION_RESPONSE_H_INCLUDED__ #define __C_SCENE_NODE_ANIMATOR_COLLISION_RESPONSE_H_INCLUDED__ #include "ISceneNodeAnimatorCollisionResponse.h" namespace irr { namespace scene { //! Special scene node animator for doing automatic collision detection and response. /** This scene node animator can be attached to any scene node modifying it in that way, that it cannot move through walls of the world, is influenced by gravity and acceleration. This animator is useful for example for first person shooter games. Attach it for example to a first person shooter camera, and the camera will behave as the player control in a first person shooter game: The camera stops and slides at walls, walks up stairs, falls down if there is no floor under it, and so on. */ class CSceneNodeAnimatorCollisionResponse : public ISceneNodeAnimatorCollisionResponse { public: //! constructor CSceneNodeAnimatorCollisionResponse(ISceneManager* scenemanager, ITriangleSelector* world, ISceneNode* object, const core::vector3df& ellipsoidRadius = core::vector3df(30,60,30), const core::vector3df& gravityPerSecond = core::vector3df(0,-100.0f,0), const core::vector3df& ellipsoidTranslation = core::vector3df(0,0,0), f32 slidingSpeed = 0.0005f); //! destructor virtual ~CSceneNodeAnimatorCollisionResponse(); //! Returns if the attached scene node is falling, which means that //! there is no blocking wall from the scene node in the direction of //! the gravity. virtual bool isFalling() const; //! Sets the radius of the ellipsoid with which collision detection and //! response is done. virtual void setEllipsoidRadius(const core::vector3df& radius); //! Returns the radius of the ellipsoid with which the collision detection and //! response is done. virtual core::vector3df getEllipsoidRadius() const; //! Sets the gravity of the environment. virtual void setGravity(const core::vector3df& gravity); //! 'Jump' the animator, by adding a jump speed opposite to its gravity virtual void jump(f32 jumpSpeed); //! Should the Target react on collision ( default = true ) virtual void setAnimateTarget ( bool enable ); virtual bool getAnimateTarget () const; //! Returns current vector of gravity. virtual core::vector3df getGravity() const; //! Sets the translation of the ellipsoid for collision detection. virtual void setEllipsoidTranslation(const core::vector3df &translation); //! Returns the translation of the ellipsoid for collision detection. virtual core::vector3df getEllipsoidTranslation() const; //! Sets a triangle selector holding all triangles of the world with which //! the scene node may collide. virtual void setWorld(ITriangleSelector* newWorld); //! Returns the current triangle selector containing all triangles for //! collision detection. virtual ITriangleSelector* getWorld() const; //! animates a scene node virtual void animateNode(ISceneNode* node, u32 timeMs); //! Writes attributes of the scene node animator. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node animator. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_COLLISION_RESPONSE; } //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer after calling this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); //! Set the single node that this animator will act on. virtual void setTargetNode(ISceneNode * node) { setNode(node); } //! Gets the single node that this animator is acting on. virtual ISceneNode* getTargetNode(void) const { return Object; } //! Returns true if a collision occurred during the last animateNode() virtual bool collisionOccurred() const { return CollisionOccurred; } //! Returns the last point of collision. virtual const core::vector3df & getCollisionPoint() const { return CollisionPoint; } //! Returns the last triangle that caused a collision. virtual const core::triangle3df & getCollisionTriangle() const { return CollisionTriangle; } virtual const core::vector3df & getCollisionResultPosition(void) const { return CollisionResultPosition; } virtual ISceneNode* getCollisionNode(void) const { return CollisionNode; } //! Sets a callback interface which will be called if a collision occurs. /** \param callback: collision callback handler that will be called when a collision occurs. Set this to 0 to disable the callback. */ virtual void setCollisionCallback(ICollisionCallback* callback); private: void setNode(ISceneNode* node); core::vector3df Radius; core::vector3df Gravity; core::vector3df Translation; core::vector3df FallingVelocity; // In the direction of Gravity. core::vector3df LastPosition; core::triangle3df RefTriangle; ITriangleSelector* World; ISceneNode* Object; ISceneManager* SceneManager; u32 LastTime; f32 SlidingSpeed; core::vector3df CollisionPoint; core::triangle3df CollisionTriangle; core::vector3df CollisionResultPosition; ISceneNode * CollisionNode; ICollisionCallback* CollisionCallback; bool Falling; bool IsCamera; bool AnimateCameraTarget; bool CollisionOccurred; bool FirstUpdate; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.cpp0000644000000000000000000001714112574354552024701 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSceneNodeAnimatorCollisionResponse.h" #include "ISceneCollisionManager.h" #include "ISceneManager.h" #include "ICameraSceneNode.h" #include "os.h" namespace irr { namespace scene { //! constructor CSceneNodeAnimatorCollisionResponse::CSceneNodeAnimatorCollisionResponse( ISceneManager* scenemanager, ITriangleSelector* world, ISceneNode* object, const core::vector3df& ellipsoidRadius, const core::vector3df& gravityPerSecond, const core::vector3df& ellipsoidTranslation, f32 slidingSpeed) : Radius(ellipsoidRadius), Gravity(gravityPerSecond), Translation(ellipsoidTranslation), World(world), Object(object), SceneManager(scenemanager), LastTime(0), SlidingSpeed(slidingSpeed), CollisionNode(0), CollisionCallback(0), Falling(false), IsCamera(false), AnimateCameraTarget(true), CollisionOccurred(false), FirstUpdate(true) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorCollisionResponse"); #endif if (World) World->grab(); setNode(Object); } //! destructor CSceneNodeAnimatorCollisionResponse::~CSceneNodeAnimatorCollisionResponse() { if (World) World->drop(); if (CollisionCallback) CollisionCallback->drop(); } //! Returns if the attached scene node is falling, which means that //! there is no blocking wall from the scene node in the direction of //! the gravity. bool CSceneNodeAnimatorCollisionResponse::isFalling() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Falling; } //! Sets the radius of the ellipsoid with which collision detection and //! response is done. void CSceneNodeAnimatorCollisionResponse::setEllipsoidRadius( const core::vector3df& radius) { Radius = radius; FirstUpdate = true; } //! Returns the radius of the ellipsoid with wich the collision detection and //! response is done. core::vector3df CSceneNodeAnimatorCollisionResponse::getEllipsoidRadius() const { return Radius; } //! Sets the gravity of the environment. void CSceneNodeAnimatorCollisionResponse::setGravity(const core::vector3df& gravity) { Gravity = gravity; FirstUpdate = true; } //! Returns current vector of gravity. core::vector3df CSceneNodeAnimatorCollisionResponse::getGravity() const { return Gravity; } //! 'Jump' the animator, by adding a jump speed opposite to its gravity void CSceneNodeAnimatorCollisionResponse::jump(f32 jumpSpeed) { FallingVelocity -= (core::vector3df(Gravity).normalize()) * jumpSpeed; Falling = true; } //! Sets the translation of the ellipsoid for collision detection. void CSceneNodeAnimatorCollisionResponse::setEllipsoidTranslation(const core::vector3df &translation) { Translation = translation; } //! Returns the translation of the ellipsoid for collision detection. core::vector3df CSceneNodeAnimatorCollisionResponse::getEllipsoidTranslation() const { return Translation; } //! Sets a triangle selector holding all triangles of the world with which //! the scene node may collide. void CSceneNodeAnimatorCollisionResponse::setWorld(ITriangleSelector* newWorld) { if (newWorld) newWorld->grab(); if (World) World->drop(); World = newWorld; FirstUpdate = true; } //! Returns the current triangle selector containing all triangles for //! collision detection. ITriangleSelector* CSceneNodeAnimatorCollisionResponse::getWorld() const { return World; } void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 timeMs) { CollisionOccurred = false; if (node != Object) setNode(node); if(!Object || !World) return; // trigger reset if ( timeMs == 0 ) { FirstUpdate = true; timeMs = LastTime; } if ( FirstUpdate ) { LastPosition = Object->getPosition(); Falling = false; LastTime = timeMs; FallingVelocity.set ( 0, 0, 0 ); FirstUpdate = false; } const u32 diff = timeMs - LastTime; LastTime = timeMs; CollisionResultPosition = Object->getPosition(); core::vector3df vel = CollisionResultPosition - LastPosition; FallingVelocity += Gravity * (f32)diff * 0.001f; CollisionTriangle = RefTriangle; CollisionPoint = core::vector3df(); CollisionResultPosition = core::vector3df(); CollisionNode = 0; // core::vector3df force = vel + FallingVelocity; if ( AnimateCameraTarget ) { // TODO: divide SlidingSpeed by frame time bool f = false; CollisionResultPosition = SceneManager->getSceneCollisionManager()->getCollisionResultPosition( World, LastPosition-Translation, Radius, vel, CollisionTriangle, CollisionPoint, f, CollisionNode, SlidingSpeed, FallingVelocity); CollisionOccurred = (CollisionTriangle != RefTriangle); CollisionResultPosition += Translation; if (f)//CollisionTriangle == RefTriangle) { Falling = true; } else { Falling = false; FallingVelocity.set(0, 0, 0); } bool collisionConsumed = false; if (CollisionOccurred && CollisionCallback) collisionConsumed = CollisionCallback->onCollision(*this); if(!collisionConsumed) Object->setPosition(CollisionResultPosition); } // move camera target if (AnimateCameraTarget && IsCamera) { const core::vector3df pdiff = Object->getPosition() - LastPosition - vel; ICameraSceneNode* cam = (ICameraSceneNode*)Object; cam->setTarget(cam->getTarget() + pdiff); } LastPosition = Object->getPosition(); } void CSceneNodeAnimatorCollisionResponse::setNode(ISceneNode* node) { Object = node; if (Object) { LastPosition = Object->getPosition(); IsCamera = (Object->getType() == ESNT_CAMERA); } LastTime = os::Timer::getTime(); } //! Writes attributes of the scene node animator. void CSceneNodeAnimatorCollisionResponse::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addVector3d("Radius", Radius); out->addVector3d("Gravity", Gravity); out->addVector3d("Translation", Translation); out->addBool("AnimateCameraTarget", AnimateCameraTarget); } //! Reads attributes of the scene node animator. void CSceneNodeAnimatorCollisionResponse::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Radius = in->getAttributeAsVector3d("Radius"); Gravity = in->getAttributeAsVector3d("Gravity"); Translation = in->getAttributeAsVector3d("Translation"); AnimateCameraTarget = in->getAttributeAsBool("AnimateCameraTarget"); } ISceneNodeAnimator* CSceneNodeAnimatorCollisionResponse::createClone(ISceneNode* node, ISceneManager* newManager) { if (!newManager) newManager = SceneManager; CSceneNodeAnimatorCollisionResponse * newAnimator = new CSceneNodeAnimatorCollisionResponse(newManager, World, Object, Radius, (Gravity * 1000.0f), Translation, SlidingSpeed); return newAnimator; } void CSceneNodeAnimatorCollisionResponse::setCollisionCallback(ICollisionCallback* callback) { if ( CollisionCallback == callback ) return; if (CollisionCallback) CollisionCallback->drop(); CollisionCallback = callback; if (CollisionCallback) CollisionCallback->grab(); } //! Should the Target react on collision ( default = true ) void CSceneNodeAnimatorCollisionResponse::setAnimateTarget ( bool enable ) { AnimateCameraTarget = enable; FirstUpdate = true; } //! Should the Target react on collision ( default = true ) bool CSceneNodeAnimatorCollisionResponse::getAnimateTarget () const { return AnimateCameraTarget; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorCameraMaya.h0000644000000000000000000000603212574354552022671 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_NODE_ANIMATOR_CAMERA_MAYA_H_INCLUDED__ #define __C_SCENE_NODE_ANIMATOR_CAMERA_MAYA_H_INCLUDED__ #include "ISceneNodeAnimatorCameraMaya.h" #include "ICameraSceneNode.h" #include "vector2d.h" namespace irr { namespace gui { class ICursorControl; } namespace scene { //! Special scene node animator for FPS cameras /** This scene node animator can be attached to a camera to make it act like a 3d modelling tool camera */ class CSceneNodeAnimatorCameraMaya : public ISceneNodeAnimatorCameraMaya { public: //! Constructor CSceneNodeAnimatorCameraMaya(gui::ICursorControl* cursor, f32 rotateSpeed = -1500.f, f32 zoomSpeed = 200.f, f32 translationSpeed = 1500.f, f32 distance=70.f); //! Destructor virtual ~CSceneNodeAnimatorCameraMaya(); //! Animates the scene node, currently only works on cameras virtual void animateNode(ISceneNode* node, u32 timeMs); //! Event receiver virtual bool OnEvent(const SEvent& event); //! Returns the speed of movement in units per millisecond virtual f32 getMoveSpeed() const; //! Sets the speed of movement in units per millisecond virtual void setMoveSpeed(f32 moveSpeed); //! Returns the rotation speed virtual f32 getRotateSpeed() const; //! Set the rotation speed virtual void setRotateSpeed(f32 rotateSpeed); //! Returns the zoom speed virtual f32 getZoomSpeed() const; //! Set the zoom speed virtual void setZoomSpeed(f32 zoomSpeed); //! Returns the current distance, i.e. orbit radius virtual f32 getDistance() const; //! Set the distance virtual void setDistance(f32 distance); //! This animator will receive events when attached to the active camera virtual bool isEventReceiverEnabled() const { return true; } //! Returns type of the scene node virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_CAMERA_MAYA; } //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer after calling this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); private: void allKeysUp(); void animate(); bool isMouseKeyDown(s32 key) const; bool MouseKeys[3]; gui::ICursorControl *CursorControl; scene::ICameraSceneNode* OldCamera; core::vector3df OldTarget; core::vector3df LastCameraTarget; // to find out if the camera target was moved outside this animator core::position2df RotateStart; core::position2df ZoomStart; core::position2df TranslateStart; core::position2df MousePos; f32 ZoomSpeed; f32 RotateSpeed; f32 TranslateSpeed; f32 CurrentZoom; f32 RotX, RotY; bool Zooming; bool Rotating; bool Moving; bool Translating; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorCameraMaya.cpp0000644000000000000000000001715612574354552023235 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSceneNodeAnimatorCameraMaya.h" #include "ICursorControl.h" #include "ICameraSceneNode.h" #include "SViewFrustum.h" #include "ISceneManager.h" namespace irr { namespace scene { //! constructor CSceneNodeAnimatorCameraMaya::CSceneNodeAnimatorCameraMaya(gui::ICursorControl* cursor, f32 rotateSpeed, f32 zoomSpeed, f32 translateSpeed, f32 distance) : CursorControl(cursor), OldCamera(0), MousePos(0.5f, 0.5f), ZoomSpeed(zoomSpeed), RotateSpeed(rotateSpeed), TranslateSpeed(translateSpeed), CurrentZoom(distance), RotX(0.0f), RotY(0.0f), Zooming(false), Rotating(false), Moving(false), Translating(false) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorCameraMaya"); #endif if (CursorControl) { CursorControl->grab(); MousePos = CursorControl->getRelativePosition(); } allKeysUp(); } //! destructor CSceneNodeAnimatorCameraMaya::~CSceneNodeAnimatorCameraMaya() { if (CursorControl) CursorControl->drop(); } //! It is possible to send mouse and key events to the camera. Most cameras //! may ignore this input, but camera scene nodes which are created for //! example with scene::ISceneManager::addMayaCameraSceneNode or //! scene::ISceneManager::addMeshViewerCameraSceneNode, may want to get this input //! for changing their position, look at target or whatever. bool CSceneNodeAnimatorCameraMaya::OnEvent(const SEvent& event) { if (event.EventType != EET_MOUSE_INPUT_EVENT) return false; switch(event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: MouseKeys[0] = true; break; case EMIE_RMOUSE_PRESSED_DOWN: MouseKeys[2] = true; break; case EMIE_MMOUSE_PRESSED_DOWN: MouseKeys[1] = true; break; case EMIE_LMOUSE_LEFT_UP: MouseKeys[0] = false; break; case EMIE_RMOUSE_LEFT_UP: MouseKeys[2] = false; break; case EMIE_MMOUSE_LEFT_UP: MouseKeys[1] = false; break; case EMIE_MOUSE_MOVED: MousePos = CursorControl->getRelativePosition(); break; case EMIE_MOUSE_WHEEL: case EMIE_LMOUSE_DOUBLE_CLICK: case EMIE_RMOUSE_DOUBLE_CLICK: case EMIE_MMOUSE_DOUBLE_CLICK: case EMIE_LMOUSE_TRIPLE_CLICK: case EMIE_RMOUSE_TRIPLE_CLICK: case EMIE_MMOUSE_TRIPLE_CLICK: case EMIE_COUNT: return false; } return true; } //! OnAnimate() is called just before rendering the whole scene. void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs) { //Alt + LM = Rotate around camera pivot //Alt + LM + MM = Dolly forth/back in view direction (speed % distance camera pivot - max distance to pivot) //Alt + MM = Move on camera plane (Screen center is about the mouse pointer, depending on move speed) if (!node || node->getType() != ESNT_CAMERA) return; ICameraSceneNode* camera = static_cast(node); // If the camera isn't the active camera, and receiving input, then don't process it. if (!camera->isInputReceiverEnabled()) return; scene::ISceneManager * smgr = camera->getSceneManager(); if (smgr && smgr->getActiveCamera() != camera) return; if (OldCamera != camera) { LastCameraTarget = OldTarget = camera->getTarget(); OldCamera = camera; } else { OldTarget += camera->getTarget() - LastCameraTarget; } f32 nRotX = RotX; f32 nRotY = RotY; f32 nZoom = CurrentZoom; if ( (isMouseKeyDown(0) && isMouseKeyDown(2)) || isMouseKeyDown(1) ) { if (!Zooming) { ZoomStart = MousePos; Zooming = true; } else { const f32 targetMinDistance = 0.1f; nZoom += (ZoomStart.X - MousePos.X) * ZoomSpeed; if (nZoom < targetMinDistance) // jox: fixed bug: bounce back when zooming to close nZoom = targetMinDistance; } } else if (Zooming) { const f32 old = CurrentZoom; CurrentZoom = CurrentZoom + (ZoomStart.X - MousePos.X ) * ZoomSpeed; nZoom = CurrentZoom; if (nZoom < 0) nZoom = CurrentZoom = old; Zooming = false; } // Translation --------------------------------- core::vector3df translate(OldTarget); const core::vector3df upVector(camera->getUpVector()); const core::vector3df target = camera->getTarget(); core::vector3df pos = camera->getPosition(); core::vector3df tvectX = pos - target; tvectX = tvectX.crossProduct(upVector); tvectX.normalize(); const SViewFrustum* const va = camera->getViewFrustum(); core::vector3df tvectY = (va->getFarLeftDown() - va->getFarRightDown()); tvectY = tvectY.crossProduct(upVector.Y > 0 ? pos - target : target - pos); tvectY.normalize(); if (isMouseKeyDown(2) && !Zooming) { if (!Translating) { TranslateStart = MousePos; Translating = true; } else { translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed + tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed; } } else if (Translating) { translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed + tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed; OldTarget = translate; Translating = false; } // Rotation ------------------------------------ if (isMouseKeyDown(0) && !Zooming) { if (!Rotating) { RotateStart = MousePos; Rotating = true; nRotX = RotX; nRotY = RotY; } else { nRotX += (RotateStart.X - MousePos.X) * RotateSpeed; nRotY += (RotateStart.Y - MousePos.Y) * RotateSpeed; } } else if (Rotating) { RotX += (RotateStart.X - MousePos.X) * RotateSpeed; RotY += (RotateStart.Y - MousePos.Y) * RotateSpeed; nRotX = RotX; nRotY = RotY; Rotating = false; } // Set pos ------------------------------------ pos = translate; pos.X += nZoom; pos.rotateXYBy(nRotY, translate); pos.rotateXZBy(-nRotX, translate); camera->setPosition(pos); camera->setTarget(translate); // Rotation Error ---------------------------- // jox: fixed bug: jitter when rotating to the top and bottom of y pos.set(0,1,0); pos.rotateXYBy(-nRotY); pos.rotateXZBy(-nRotX+180.f); camera->setUpVector(pos); LastCameraTarget = camera->getTarget(); } bool CSceneNodeAnimatorCameraMaya::isMouseKeyDown(s32 key) const { return MouseKeys[key]; } void CSceneNodeAnimatorCameraMaya::allKeysUp() { for (s32 i=0; i<3; ++i) MouseKeys[i] = false; } //! Sets the rotation speed void CSceneNodeAnimatorCameraMaya::setRotateSpeed(f32 speed) { RotateSpeed = speed; } //! Sets the movement speed void CSceneNodeAnimatorCameraMaya::setMoveSpeed(f32 speed) { TranslateSpeed = speed; } //! Sets the zoom speed void CSceneNodeAnimatorCameraMaya::setZoomSpeed(f32 speed) { ZoomSpeed = speed; } //! Set the distance void CSceneNodeAnimatorCameraMaya::setDistance(f32 distance) { CurrentZoom=distance; } //! Gets the rotation speed f32 CSceneNodeAnimatorCameraMaya::getRotateSpeed() const { return RotateSpeed; } // Gets the movement speed f32 CSceneNodeAnimatorCameraMaya::getMoveSpeed() const { return TranslateSpeed; } //! Gets the zoom speed f32 CSceneNodeAnimatorCameraMaya::getZoomSpeed() const { return ZoomSpeed; } //! Returns the current distance, i.e. orbit radius f32 CSceneNodeAnimatorCameraMaya::getDistance() const { return CurrentZoom; } ISceneNodeAnimator* CSceneNodeAnimatorCameraMaya::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorCameraMaya * newAnimator = new CSceneNodeAnimatorCameraMaya(CursorControl, RotateSpeed, ZoomSpeed, TranslateSpeed); return newAnimator; } } // end namespace } // end namespace irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h0000644000000000000000000000663212574354552022440 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ #define __C_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ #include "ISceneNodeAnimatorCameraFPS.h" #include "vector2d.h" #include "position2d.h" #include "SKeyMap.h" #include "irrArray.h" namespace irr { namespace gui { class ICursorControl; } namespace scene { //! Special scene node animator for FPS cameras class CSceneNodeAnimatorCameraFPS : public ISceneNodeAnimatorCameraFPS { public: //! Constructor CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cursorControl, f32 rotateSpeed = 100.0f, f32 moveSpeed = .5f, f32 jumpSpeed=0.f, SKeyMap* keyMapArray=0, u32 keyMapSize=0, bool noVerticalMovement=false, bool invertY=false); //! Destructor virtual ~CSceneNodeAnimatorCameraFPS(); //! Animates the scene node, currently only works on cameras virtual void animateNode(ISceneNode* node, u32 timeMs); //! Event receiver virtual bool OnEvent(const SEvent& event); //! Returns the speed of movement in units per second virtual f32 getMoveSpeed() const; //! Sets the speed of movement in units per second virtual void setMoveSpeed(f32 moveSpeed); //! Returns the rotation speed virtual f32 getRotateSpeed() const; //! Set the rotation speed virtual void setRotateSpeed(f32 rotateSpeed); //! Sets the keyboard mapping for this animator (old style) //! \param keymap: an array of keyboard mappings, see SKeyMap //! \param count: the size of the keyboard map array virtual void setKeyMap(SKeyMap *map, u32 count); //! Sets the keyboard mapping for this animator //! \param keymap The new keymap array virtual void setKeyMap(const core::array& keymap); //! Gets the keyboard mapping for this animator virtual const core::array& getKeyMap() const; //! Sets whether vertical movement should be allowed. virtual void setVerticalMovement(bool allow); //! Sets whether the Y axis of the mouse should be inverted. /** If enabled then moving the mouse down will cause the camera to look up. It is disabled by default. */ virtual void setInvertMouse(bool invert); //! This animator will receive events when attached to the active camera virtual bool isEventReceiverEnabled() const { return true; } //! Returns the type of this animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_CAMERA_FPS; } //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer once you're done with it. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0); private: void allKeysUp(); gui::ICursorControl *CursorControl; f32 MaxVerticalAngle; f32 MoveSpeed; f32 RotateSpeed; f32 JumpSpeed; // -1.0f for inverted mouse, defaults to 1.0f f32 MouseYDirection; s32 LastAnimationTime; core::array KeyMap; core::position2d CenterCursor, CursorPos; bool CursorKeys[EKA_COUNT]; bool firstUpdate; bool firstInput; bool NoVerticalMovement; }; } // end namespace scene } // end namespace irr #endif // __C_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp0000644000000000000000000002130112574354552022761 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSceneNodeAnimatorCameraFPS.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "Keycodes.h" #include "ICursorControl.h" #include "ICameraSceneNode.h" #include "ISceneNodeAnimatorCollisionResponse.h" namespace irr { namespace scene { //! constructor CSceneNodeAnimatorCameraFPS::CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cursorControl, f32 rotateSpeed, f32 moveSpeed, f32 jumpSpeed, SKeyMap* keyMapArray, u32 keyMapSize, bool noVerticalMovement, bool invertY) : CursorControl(cursorControl), MaxVerticalAngle(88.0f), MoveSpeed(moveSpeed), RotateSpeed(rotateSpeed), JumpSpeed(jumpSpeed), MouseYDirection(invertY ? -1.0f : 1.0f), LastAnimationTime(0), firstUpdate(true), firstInput(true), NoVerticalMovement(noVerticalMovement) { #ifdef _DEBUG setDebugName("CCameraSceneNodeAnimatorFPS"); #endif if (CursorControl) CursorControl->grab(); allKeysUp(); // create key map if (!keyMapArray || !keyMapSize) { // create default key map KeyMap.push_back(SKeyMap(EKA_MOVE_FORWARD, irr::KEY_UP)); KeyMap.push_back(SKeyMap(EKA_MOVE_BACKWARD, irr::KEY_DOWN)); KeyMap.push_back(SKeyMap(EKA_STRAFE_LEFT, irr::KEY_LEFT)); KeyMap.push_back(SKeyMap(EKA_STRAFE_RIGHT, irr::KEY_RIGHT)); KeyMap.push_back(SKeyMap(EKA_JUMP_UP, irr::KEY_KEY_J)); } else { // create custom key map setKeyMap(keyMapArray, keyMapSize); } } //! destructor CSceneNodeAnimatorCameraFPS::~CSceneNodeAnimatorCameraFPS() { if (CursorControl) CursorControl->drop(); } //! It is possible to send mouse and key events to the camera. Most cameras //! may ignore this input, but camera scene nodes which are created for //! example with scene::ISceneManager::addMayaCameraSceneNode or //! scene::ISceneManager::addFPSCameraSceneNode, may want to get this input //! for changing their position, look at target or whatever. bool CSceneNodeAnimatorCameraFPS::OnEvent(const SEvent& evt) { switch(evt.EventType) { case EET_KEY_INPUT_EVENT: for (u32 i=0; igetRelativePosition(); return true; } break; default: break; } return false; } void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) { if (!node || node->getType() != ESNT_CAMERA) return; ICameraSceneNode* camera = static_cast(node); if (firstUpdate) { camera->updateAbsolutePosition(); if (CursorControl ) { CursorControl->setPosition(0.5f, 0.5f); CursorPos = CenterCursor = CursorControl->getRelativePosition(); } LastAnimationTime = timeMs; firstUpdate = false; } // If the camera isn't the active camera, and receiving input, then don't process it. if(!camera->isInputReceiverEnabled()) { firstInput = true; return; } if ( firstInput ) { allKeysUp(); firstInput = false; } scene::ISceneManager * smgr = camera->getSceneManager(); if(smgr && smgr->getActiveCamera() != camera) return; // get time f32 timeDiff = (f32) ( timeMs - LastAnimationTime ); LastAnimationTime = timeMs; // update position core::vector3df pos = camera->getPosition(); // Update rotation core::vector3df target = (camera->getTarget() - camera->getAbsolutePosition()); core::vector3df relativeRotation = target.getHorizontalAngle(); if (CursorControl) { if (CursorPos != CenterCursor) { relativeRotation.Y -= (0.5f - CursorPos.X) * RotateSpeed; relativeRotation.X -= (0.5f - CursorPos.Y) * RotateSpeed * MouseYDirection; // X < MaxVerticalAngle or X > 360-MaxVerticalAngle if (relativeRotation.X > MaxVerticalAngle*2 && relativeRotation.X < 360.0f-MaxVerticalAngle) { relativeRotation.X = 360.0f-MaxVerticalAngle; } else if (relativeRotation.X > MaxVerticalAngle && relativeRotation.X < 360.0f-MaxVerticalAngle) { relativeRotation.X = MaxVerticalAngle; } // Do the fix as normal, special case below // reset cursor position to the centre of the window. CursorControl->setPosition(0.5f, 0.5f); CenterCursor = CursorControl->getRelativePosition(); // needed to avoid problems when the event receiver is disabled CursorPos = CenterCursor; } // Special case, mouse is whipped outside of window before it can update. video::IVideoDriver* driver = smgr->getVideoDriver(); core::vector2d mousepos(u32(CursorControl->getPosition().X), u32(CursorControl->getPosition().Y)); core::rect screenRect(0, 0, driver->getScreenSize().Width, driver->getScreenSize().Height); // Only if we are moving outside quickly. bool reset = !screenRect.isPointInside(mousepos); if(reset) { // Force a reset. CursorControl->setPosition(0.5f, 0.5f); CenterCursor = CursorControl->getRelativePosition(); CursorPos = CenterCursor; } } // set target target.set(0,0, core::max_(1.f, pos.getLength())); core::vector3df movedir = target; core::matrix4 mat; mat.setRotationDegrees(core::vector3df(relativeRotation.X, relativeRotation.Y, 0)); mat.transformVect(target); if (NoVerticalMovement) { mat.setRotationDegrees(core::vector3df(0, relativeRotation.Y, 0)); mat.transformVect(movedir); } else { movedir = target; } movedir.normalize(); if (CursorKeys[EKA_MOVE_FORWARD]) pos += movedir * timeDiff * MoveSpeed; if (CursorKeys[EKA_MOVE_BACKWARD]) pos -= movedir * timeDiff * MoveSpeed; // strafing core::vector3df strafevect = target; strafevect = strafevect.crossProduct(camera->getUpVector()); if (NoVerticalMovement) strafevect.Y = 0.0f; strafevect.normalize(); if (CursorKeys[EKA_STRAFE_LEFT]) pos += strafevect * timeDiff * MoveSpeed; if (CursorKeys[EKA_STRAFE_RIGHT]) pos -= strafevect * timeDiff * MoveSpeed; // For jumping, we find the collision response animator attached to our camera // and if it's not falling, we tell it to jump. if (CursorKeys[EKA_JUMP_UP]) { const ISceneNodeAnimatorList& animators = camera->getAnimators(); ISceneNodeAnimatorList::ConstIterator it = animators.begin(); while(it != animators.end()) { if(ESNAT_COLLISION_RESPONSE == (*it)->getType()) { ISceneNodeAnimatorCollisionResponse * collisionResponse = static_cast(*it); if(!collisionResponse->isFalling()) collisionResponse->jump(JumpSpeed); } it++; } } // write translation camera->setPosition(pos); // write right target target += pos; camera->setTarget(target); } void CSceneNodeAnimatorCameraFPS::allKeysUp() { for (u32 i=0; i& keymap) { KeyMap=keymap; } const core::array& CSceneNodeAnimatorCameraFPS::getKeyMap() const { return KeyMap; } //! Sets whether vertical movement should be allowed. void CSceneNodeAnimatorCameraFPS::setVerticalMovement(bool allow) { NoVerticalMovement = !allow; } //! Sets whether the Y axis of the mouse should be inverted. void CSceneNodeAnimatorCameraFPS::setInvertMouse(bool invert) { if (invert) MouseYDirection = -1.0f; else MouseYDirection = 1.0f; } ISceneNodeAnimator* CSceneNodeAnimatorCameraFPS::createClone(ISceneNode* node, ISceneManager* newManager) { CSceneNodeAnimatorCameraFPS * newAnimator = new CSceneNodeAnimatorCameraFPS(CursorControl, RotateSpeed, MoveSpeed, JumpSpeed, 0, 0, NoVerticalMovement); newAnimator->setKeyMap(KeyMap); return newAnimator; } } // namespace scene } // namespace irr irrlicht-1.8.3/source/Irrlicht/CSceneManager.h0000644000000000000000000007024312574354552017747 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_MANAGER_H_INCLUDED__ #define __C_SCENE_MANAGER_H_INCLUDED__ #include "ISceneManager.h" #include "ISceneNode.h" #include "ICursorControl.h" #include "irrString.h" #include "irrArray.h" #include "IMeshLoader.h" #include "CAttributes.h" #include "ILightManager.h" namespace irr { namespace io { class IXMLWriter; class IFileSystem; } namespace scene { class IMeshCache; class IGeometryCreator; /*! The Scene Manager manages scene nodes, mesh recources, cameras and all the other stuff. */ class CSceneManager : public ISceneManager, public ISceneNode { public: //! constructor CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, gui::ICursorControl* cursorControl, IMeshCache* cache = 0, gui::IGUIEnvironment *guiEnvironment = 0); //! destructor virtual ~CSceneManager(); //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. virtual IAnimatedMesh* getMesh(const io::path& filename); //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. virtual IAnimatedMesh* getMesh(io::IReadFile* file); //! Returns an interface to the mesh cache which is shared beween all existing scene managers. virtual IMeshCache* getMeshCache(); //! returns the video driver virtual video::IVideoDriver* getVideoDriver(); //! return the gui environment virtual gui::IGUIEnvironment* getGUIEnvironment(); //! return the filesystem virtual io::IFileSystem* getFileSystem(); //! adds Volume Lighting Scene Node. //! the returned pointer must not be dropped. virtual IVolumeLightSceneNode* addVolumeLightSceneNode(ISceneNode* parent=0, s32 id=-1, const u32 subdivU = 32, const u32 subdivV = 32, const video::SColor foot = video::SColor(51, 0, 230, 180), const video::SColor tail = video::SColor(0, 0, 0, 0), const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); //! adds a cube scene node to the scene. It is a simple cube of (1,1,1) size. //! the returned pointer must not be dropped. virtual IMeshSceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); //! Adds a sphere scene node to the scene. virtual IMeshSceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); //! adds a scene node for rendering an animated mesh model virtual IAnimatedMeshSceneNode* addAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f), bool alsoAddIfMeshPointerZero=false); //! adds a scene node for rendering a static mesh //! the returned pointer must not be dropped. virtual IMeshSceneNode* addMeshSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f), bool alsoAddIfMeshPointerZero=false); //! Adds a scene node for rendering a animated water surface mesh. virtual ISceneNode* addWaterSurfaceSceneNode(IMesh* mesh, f32 waveHeight, f32 waveSpeed, f32 wlenght, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); //! renders the node. virtual void render(); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! registers a node for rendering it at a specific time. virtual u32 registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS pass = ESNRP_AUTOMATIC); //! draws all scene nodes virtual void drawAll(); //! Adds a scene node for rendering using a octree to the scene graph. This a good method for rendering //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much //! faster then a bsp tree. virtual IMeshSceneNode* addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false); //! Adss a scene node for rendering using a octree. This a good method for rendering //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much //! faster then a bsp tree. virtual IMeshSceneNode* addOctreeSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=128, bool alsoAddIfMeshPointerZero=false); //! Adds a camera scene node to the tree and sets it as active camera. //! \param position: Position of the space relative to its parent where the camera will be placed. //! \param lookat: Position where the camera will look at. Also known as target. //! \param parent: Parent scene node of the camera. Can be null. If the parent moves, //! the camera will move too. //! \return Pointer to interface to camera virtual ICameraSceneNode* addCameraSceneNode(ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& lookat = core::vector3df(0,0,100), s32 id=-1, bool makeActive=true); //! Adds a camera scene node which is able to be controlle with the mouse similar //! like in the 3D Software Maya by Alias Wavefront. //! The returned pointer must not be dropped. virtual ICameraSceneNode* addCameraSceneNodeMaya(ISceneNode* parent=0, f32 rotateSpeed=-1500.f, f32 zoomSpeed=200.f, f32 translationSpeed=1500.f, s32 id=-1, f32 distance=70.f, bool makeActive=true); //! Adds a camera scene node which is able to be controled with the mouse and keys //! like in most first person shooters (FPS): virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, f32 rotateSpeed = 100.0f, f32 moveSpeed = .5f, s32 id=-1, SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, f32 jumpSpeed = 0.f, bool invertMouseY=false, bool makeActive=true); //! Adds a dynamic light scene node. The light will cast dynamic light on all //! other scene nodes in the scene, which have the material flag video::MTF_LIGHTING //! turned on. (This is the default setting in most scene nodes). virtual ILightSceneNode* addLightSceneNode(ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), video::SColorf color = video::SColorf(1.0f, 1.0f, 1.0f), f32 range=100.0f, s32 id=-1); //! Adds a billboard scene node to the scene. A billboard is like a 3d sprite: A 2d element, //! which always looks to the camera. It is usually used for things like explosions, fire, //! lensflares and things like that. virtual IBillboardSceneNode* addBillboardSceneNode(ISceneNode* parent = 0, const core::dimension2d& size = core::dimension2d(10.0f, 10.0f), const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1, video::SColor shadeTop = 0xFFFFFFFF, video::SColor shadeBottom = 0xFFFFFFFF); //! Adds a skybox scene node. A skybox is a big cube with 6 textures on it and //! is drawn around the camera position. virtual ISceneNode* addSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, video::ITexture* left, video::ITexture* right, video::ITexture* front, video::ITexture* back, ISceneNode* parent = 0, s32 id=-1); //! Adds a skydome scene node. A skydome is a large (half-) sphere with a //! panoramic texture on it and is drawn around the camera position. virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, u32 horiRes=16, u32 vertRes=8, f32 texturePercentage=0.9, f32 spherePercentage=2.0,f32 radius = 1000.f, ISceneNode* parent=0, s32 id=-1); //! Adds a text scene node, which is able to display //! 2d text at a position in three dimensional space virtual ITextSceneNode* addTextSceneNode(gui::IGUIFont* font, const wchar_t* text, video::SColor color=video::SColor(100,255,255,255), ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1); //! Adds a text scene node, which uses billboards virtual IBillboardTextSceneNode* addBillboardTextSceneNode(gui::IGUIFont* font, const wchar_t* text, ISceneNode* parent = 0, const core::dimension2d& size = core::dimension2d(10.0f, 10.0f), const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1, video::SColor colorTop = 0xFFFFFFFF, video::SColor colorBottom = 0xFFFFFFFF); //! Adds a scene node, which can render a quake3 shader virtual IMeshSceneNode* addQuake3SceneNode(const IMeshBuffer* meshBuffer, const quake3::IShader * shader, ISceneNode* parent=0, s32 id=-1 ); //! Adds a Hill Plane mesh to the mesh pool. The mesh is //! generated on the fly and looks like a plane with some hills //! on it. You can specify how many hills should be on the plane //! and how high they should be. Also you must specify a name //! for the mesh because the mesh is added to the mesh pool and //! can be retrieved back using ISceneManager::getMesh with the //! name as parameter. virtual IAnimatedMesh* addHillPlaneMesh(const io::path& name, const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material = 0, f32 hillHeight = 0.0f, const core::dimension2d& countHills = core::dimension2d(1.0f, 1.0f), const core::dimension2d& textureRepeatCount = core::dimension2d(1.0f, 1.0f)); //! Adds a terrain mesh to the mesh pool. virtual IAnimatedMesh* addTerrainMesh(const io::path& meshname, video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize = core::dimension2d(10.0f,10.0f), f32 maxHeight=200.0f, const core::dimension2d& defaultVertexBlockSize = core::dimension2d(64,64)); //! Add a arrow mesh to the mesh pool virtual IAnimatedMesh* addArrowMesh(const io::path& name, video::SColor vtxColor0, video::SColor vtxColor1, u32 tesselationCylinder, u32 tesselationCone, f32 height, f32 cylinderHeight, f32 width0, f32 width1); //! Adds a static sphere mesh to the mesh pool. IAnimatedMesh* addSphereMesh(const io::path& name, f32 radius=5.f, u32 polyCountX=16, u32 polyCountY=16); //! Adds a static volume light mesh to the mesh pool. IAnimatedMesh* addVolumeLightMesh(const io::path& name, const u32 SubdivideU = 32, const u32 SubdivideV = 32, const video::SColor FootColor = video::SColor(51, 0, 230, 180), const video::SColor TailColor = video::SColor(0, 0, 0, 0)); //! Adds a particle system scene node. virtual IParticleSystemSceneNode* addParticleSystemSceneNode( bool withDefaultEmitter=true, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); //! Adds a terrain scene node to the scene graph. virtual ITerrainSceneNode* addTerrainSceneNode( const io::path& heightMapFileName, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), video::SColor vertexColor = video::SColor(255,255,255,255), s32 maxLOD=4, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17,s32 smoothFactor=0, bool addAlsoIfHeightmapEmpty = false); //! Adds a terrain scene node to the scene graph. virtual ITerrainSceneNode* addTerrainSceneNode( io::IReadFile* heightMap, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), video::SColor vertexColor = video::SColor(255,255,255,255), s32 maxLOD=4, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17,s32 smoothFactor=0, bool addAlsoIfHeightmapEmpty=false); //! Adds a dummy transformation scene node to the scene graph. virtual IDummyTransformationSceneNode* addDummyTransformationSceneNode( ISceneNode* parent=0, s32 id=-1); //! Adds an empty scene node. virtual ISceneNode* addEmptySceneNode(ISceneNode* parent, s32 id=-1); //! Returns the root scene node. This is the scene node wich is parent //! of all scene nodes. The root scene node is a special scene node which //! only exists to manage all scene nodes. It is not rendered and cannot //! be removed from the scene. //! \return Pointer to the root scene node. virtual ISceneNode* getRootSceneNode(); //! Returns the current active camera. //! \return The active camera is returned. Note that this can be NULL, if there //! was no camera created yet. virtual ICameraSceneNode* getActiveCamera() const; //! Sets the active camera. The previous active camera will be deactivated. //! \param camera: The new camera which should be active. virtual void setActiveCamera(ICameraSceneNode* camera); //! creates a rotation animator, which rotates the attached scene node around itself. //! \param rotationPerSecond: Specifies the speed of the animation //! \return The animator. Attach it to a scene node with ISceneNode::addAnimator() //! and the animator will animate it. virtual ISceneNodeAnimator* createRotationAnimator(const core::vector3df& rotationPerSecond); //! creates a fly circle animator /** Lets the attached scene node fly around a center. \param center Center relative to node origin \param speed: The orbital speed, in radians per millisecond. \param direction: Specifies the upvector used for alignment of the mesh. \param startPosition: The position on the circle where the animator will begin. Value is in multiples of a circle, i.e. 0.5 is half way around. \return The animator. Attach it to a scene node with ISceneNode::addAnimator() */ virtual ISceneNodeAnimator* createFlyCircleAnimator( const core::vector3df& center=core::vector3df(0.f, 0.f, 0.f), f32 radius=100.f, f32 speed=0.001f, const core::vector3df& direction=core::vector3df(0.f, 1.f, 0.f), f32 startPosition = 0.f, f32 radiusEllipsoid = 0.f); //! Creates a fly straight animator, which lets the attached scene node //! fly or move along a line between two points. virtual ISceneNodeAnimator* createFlyStraightAnimator(const core::vector3df& startPoint, const core::vector3df& endPoint, u32 timeForWay, bool loop=false,bool pingpong = false); //! Creates a texture animator, which switches the textures of the target scene //! node based on a list of textures. virtual ISceneNodeAnimator* createTextureAnimator(const core::array& textures, s32 timePerFrame, bool loop); //! Creates a scene node animator, which deletes the scene node after //! some time automaticly. virtual ISceneNodeAnimator* createDeleteAnimator(u32 timeMS); //! Creates a special scene node animator for doing automatic collision detection //! and response. virtual ISceneNodeAnimatorCollisionResponse* createCollisionResponseAnimator( ITriangleSelector* world, ISceneNode* sceneNode, const core::vector3df& ellipsoidRadius = core::vector3df(30,60,30), const core::vector3df& gravityPerSecond = core::vector3df(0,-1.0f,0), const core::vector3df& ellipsoidTranslation = core::vector3df(0,0,0), f32 slidingValue = 0.0005f); //! Creates a follow spline animator. virtual ISceneNodeAnimator* createFollowSplineAnimator(s32 startTime, const core::array< core::vector3df >& points, f32 speed, f32 tightness, bool loop, bool pingpong); //! Creates a simple ITriangleSelector, based on a mesh. virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node); //! Creates a simple ITriangleSelector, based on an animated mesh scene node. //! Details of the mesh associated with the node will be extracted internally. //! Call ITriangleSelector::update() to have the triangle selector updated based //! on the current frame of the animated mesh scene node. //! \param: The animated mesh scene node from which to build the selector virtual ITriangleSelector* createTriangleSelector(IAnimatedMeshSceneNode* node); //! Creates a simple ITriangleSelector, based on a mesh. virtual ITriangleSelector* createOctreeTriangleSelector(IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode); //! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. virtual ITriangleSelector* createTriangleSelectorFromBoundingBox( ISceneNode* node); //! Creates a meta triangle selector. virtual IMetaTriangleSelector* createMetaTriangleSelector(); //! Creates a triangle selector which can select triangles from a terrain scene node //! \param: Pointer to the created terrain scene node //! \param: Level of detail, 0 for highest detail. virtual ITriangleSelector* createTerrainTriangleSelector( ITerrainSceneNode* node, s32 LOD=0); //! Adds an external mesh loader. virtual void addExternalMeshLoader(IMeshLoader* externalLoader); //! Returns the number of mesh loaders supported by Irrlicht at this time virtual u32 getMeshLoaderCount() const; //! Retrieve the given mesh loader virtual IMeshLoader* getMeshLoader(u32 index) const; //! Adds an external scene loader. virtual void addExternalSceneLoader(ISceneLoader* externalLoader); //! Returns the number of scene loaders supported by Irrlicht at this time virtual u32 getSceneLoaderCount() const; //! Retrieve the given scene loader virtual ISceneLoader* getSceneLoader(u32 index) const; //! Returns a pointer to the scene collision manager. virtual ISceneCollisionManager* getSceneCollisionManager(); //! Returns a pointer to the mesh manipulator. virtual IMeshManipulator* getMeshManipulator(); //! Sets the color of stencil buffers shadows drawn by the scene manager. virtual void setShadowColor(video::SColor color); //! Returns the current color of shadows. virtual video::SColor getShadowColor() const; //! Adds a scene node to the deletion queue. virtual void addToDeletionQueue(ISceneNode* node); //! Returns the first scene node with the specified id. virtual ISceneNode* getSceneNodeFromId(s32 id, ISceneNode* start=0); //! Returns the first scene node with the specified name. virtual ISceneNode* getSceneNodeFromName(const c8* name, ISceneNode* start=0); //! Returns the first scene node with the specified type. virtual ISceneNode* getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start=0); //! returns scene nodes by type. virtual void getSceneNodesFromType(ESCENE_NODE_TYPE type, core::array& outNodes, ISceneNode* start=0); //! Posts an input event to the environment. Usually you do not have to //! use this method, it is used by the internal engine. virtual bool postEventFromUser(const SEvent& event); //! Clears the whole scene. All scene nodes are removed. virtual void clear(); //! Removes all children of this scene node virtual void removeAll(); //! Returns interface to the parameters set in this scene. virtual io::IAttributes* getParameters(); //! Returns current render pass. virtual E_SCENE_NODE_RENDER_PASS getSceneNodeRenderPass() const; //! Creates a new scene manager. virtual ISceneManager* createNewSceneManager(bool cloneContent); //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_SCENE_MANAGER; } //! Returns the default scene node factory which can create all built in scene nodes virtual ISceneNodeFactory* getDefaultSceneNodeFactory(); //! Adds a scene node factory to the scene manager. /** Use this to extend the scene manager with new scene node types which it should be able to create automaticly, for example when loading data from xml files. */ virtual void registerSceneNodeFactory(ISceneNodeFactory* factoryToAdd); //! Returns amount of registered scene node factories. virtual u32 getRegisteredSceneNodeFactoryCount() const; //! Returns a scene node factory by index virtual ISceneNodeFactory* getSceneNodeFactory(u32 index); //! Returns a typename from a scene node type or null if not found virtual const c8* getSceneNodeTypeName(ESCENE_NODE_TYPE type); //! Returns a typename from a scene node animator type or null if not found virtual const c8* getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type); //! Adds a scene node to the scene by name virtual ISceneNode* addSceneNode(const char* sceneNodeTypeName, ISceneNode* parent=0); //! creates a scene node animator based on its type name virtual ISceneNodeAnimator* createSceneNodeAnimator(const char* typeName, ISceneNode* target=0); //! Returns the default scene node animator factory which can create all built-in scene node animators virtual ISceneNodeAnimatorFactory* getDefaultSceneNodeAnimatorFactory(); //! Adds a scene node animator factory to the scene manager. virtual void registerSceneNodeAnimatorFactory(ISceneNodeAnimatorFactory* factoryToAdd); //! Returns amount of registered scene node animator factories. virtual u32 getRegisteredSceneNodeAnimatorFactoryCount() const; //! Returns a scene node animator factory by index virtual ISceneNodeAnimatorFactory* getSceneNodeAnimatorFactory(u32 index); //! Saves the current scene into a file. virtual bool saveScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0); //! Saves the current scene into a file. virtual bool saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0); //! Saves the current scene into a file. virtual bool saveScene(io::IXMLWriter* writer, const io::path& currentPath, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0); //! Loads a scene. Note that the current scene is not cleared before. virtual bool loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* rootNode=0); //! Loads a scene. Note that the current scene is not cleared before. virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* rootNode=0); //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns a mesh writer implementation if available virtual IMeshWriter* createMeshWriter(EMESH_WRITER_TYPE type); //! Get a skinned mesh, which is not available as header-only code virtual ISkinnedMesh* createSkinnedMesh(); //! Sets ambient color of the scene virtual void setAmbientLight(const video::SColorf &ambientColor); //! Returns ambient color of the scene virtual const video::SColorf& getAmbientLight() const; //! Register a custom callbacks manager which gets callbacks during scene rendering. virtual void setLightManager(ILightManager* lightManager); //! Get current render time. virtual E_SCENE_NODE_RENDER_PASS getCurrentRendertime() const { return CurrentRendertime; } //! Set current render time. virtual void setCurrentRendertime(E_SCENE_NODE_RENDER_PASS currentRendertime) { CurrentRendertime = currentRendertime; } //! Get an instance of a geometry creator. virtual const IGeometryCreator* getGeometryCreator(void) const { return GeometryCreator; } //! returns if node is culled virtual bool isCulled(const ISceneNode* node) const; private: //! clears the deletion list void clearDeletionList(); //! writes a scene node void writeSceneNode(io::IXMLWriter* writer, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer, const fschar_t* currentPath=0, bool init=false); struct DefaultNodeEntry { DefaultNodeEntry(ISceneNode* n) : Node(n), TextureValue(0) { if (n->getMaterialCount()) TextureValue = (n->getMaterial(0).getTexture(0)); } bool operator < (const DefaultNodeEntry& other) const { return (TextureValue < other.TextureValue); } ISceneNode* Node; private: void* TextureValue; }; //! sort on distance (center) to camera struct TransparentNodeEntry { TransparentNodeEntry(ISceneNode* n, const core::vector3df& camera) : Node(n) { Distance = Node->getAbsoluteTransformation().getTranslation().getDistanceFromSQ(camera); } bool operator < (const TransparentNodeEntry& other) const { return Distance > other.Distance; } ISceneNode* Node; private: f64 Distance; }; //! sort on distance (sphere) to camera struct DistanceNodeEntry { DistanceNodeEntry(ISceneNode* n, const core::vector3df& cameraPos) : Node(n) { setNodeAndDistanceFromPosition(n, cameraPos); } bool operator < (const DistanceNodeEntry& other) const { return Distance < other.Distance; } void setNodeAndDistanceFromPosition(ISceneNode* n, const core::vector3df & fromPosition) { Node = n; Distance = Node->getAbsoluteTransformation().getTranslation().getDistanceFromSQ(fromPosition); Distance -= Node->getBoundingBox().getExtent().getLengthSQ() * 0.5; } ISceneNode* Node; private: f64 Distance; }; //! video driver video::IVideoDriver* Driver; //! file system io::IFileSystem* FileSystem; //! GUI Enviroment ( Debug Purpose ) gui::IGUIEnvironment* GUIEnvironment; //! cursor control gui::ICursorControl* CursorControl; //! collision manager ISceneCollisionManager* CollisionManager; //! render pass lists core::array CameraList; core::array LightList; core::array ShadowNodeList; core::array SkyBoxList; core::array SolidNodeList; core::array TransparentNodeList; core::array TransparentEffectNodeList; core::array MeshLoaderList; core::array SceneLoaderList; core::array DeletionList; core::array SceneNodeFactoryList; core::array SceneNodeAnimatorFactoryList; //! current active camera ICameraSceneNode* ActiveCamera; core::vector3df camWorldPos; // Position of camera for transparent nodes. video::SColor ShadowColor; video::SColorf AmbientLight; //! String parameters // NODE: Attributes are slow and should only be used for debug-info and not in release io::CAttributes Parameters; //! Mesh cache IMeshCache* MeshCache; E_SCENE_NODE_RENDER_PASS CurrentRendertime; //! An optional callbacks manager to allow the user app finer control //! over the scene lighting and rendering. ILightManager* LightManager; //! constants for reading and writing XML. //! Not made static due to portability problems. const core::stringw IRR_XML_FORMAT_SCENE; const core::stringw IRR_XML_FORMAT_NODE; const core::stringw IRR_XML_FORMAT_NODE_ATTR_TYPE; IGeometryCreator* GeometryCreator; }; } // end namespace video } // end namespace scene #endif irrlicht-1.8.3/source/Irrlicht/CSceneManager.cpp0000644000000000000000000020254312574354552020302 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CSceneManager.h" #include "IVideoDriver.h" #include "IFileSystem.h" #include "SAnimatedMesh.h" #include "CMeshCache.h" #include "IXMLWriter.h" #include "ISceneUserDataSerializer.h" #include "IGUIEnvironment.h" #include "IMaterialRenderer.h" #include "IReadFile.h" #include "IWriteFile.h" #include "ISceneLoader.h" #include "os.h" // We need this include for the case of skinned mesh support without // any such loader #ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ #include "CSkinnedMesh.h" #endif #ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ #include "CIrrMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ #include "CBSPMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_MD2_LOADER_ #include "CMD2MeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_ #include "CAnimatedMeshHalfLife.h" #endif #ifdef _IRR_COMPILE_WITH_MS3D_LOADER_ #include "CMS3DMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_3DS_LOADER_ #include "C3DSMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_X_LOADER_ #include "CXMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_OCT_LOADER_ #include "COCTLoader.h" #endif #ifdef _IRR_COMPILE_WITH_CSM_LOADER_ #include "CCSMLoader.h" #endif #ifdef _IRR_COMPILE_WITH_LMTS_LOADER_ #include "CLMTSMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_MY3D_LOADER_ #include "CMY3DMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_ #include "CColladaFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_DMF_LOADER_ #include "CDMFLoader.h" #endif #ifdef _IRR_COMPILE_WITH_OGRE_LOADER_ #include "COgreMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_OBJ_LOADER_ #include "COBJMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_MD3_LOADER_ #include "CMD3MeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_B3D_LOADER_ #include "CB3DMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_LWO_LOADER_ #include "CLWOMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_STL_LOADER_ #include "CSTLMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_PLY_LOADER_ #include "CPLYMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_SMF_LOADER_ #include "CSMFMeshFileLoader.h" #endif #ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_ #include "CSceneLoaderIrr.h" #endif #ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_ #include "CColladaMeshWriter.h" #endif #ifdef _IRR_COMPILE_WITH_IRR_WRITER_ #include "CIrrMeshWriter.h" #endif #ifdef _IRR_COMPILE_WITH_STL_WRITER_ #include "CSTLMeshWriter.h" #endif #ifdef _IRR_COMPILE_WITH_OBJ_WRITER_ #include "COBJMeshWriter.h" #endif #ifdef _IRR_COMPILE_WITH_PLY_WRITER_ #include "CPLYMeshWriter.h" #endif #include "CCubeSceneNode.h" #include "CSphereSceneNode.h" #include "CAnimatedMeshSceneNode.h" #include "COctreeSceneNode.h" #include "CCameraSceneNode.h" #include "CLightSceneNode.h" #include "CBillboardSceneNode.h" #include "CMeshSceneNode.h" #include "CSkyBoxSceneNode.h" #include "CSkyDomeSceneNode.h" #include "CParticleSystemSceneNode.h" #include "CDummyTransformationSceneNode.h" #include "CWaterSurfaceSceneNode.h" #include "CTerrainSceneNode.h" #include "CEmptySceneNode.h" #include "CTextSceneNode.h" #include "CQuake3ShaderSceneNode.h" #include "CVolumeLightSceneNode.h" #include "CDefaultSceneNodeFactory.h" #include "CSceneCollisionManager.h" #include "CTriangleSelector.h" #include "COctreeTriangleSelector.h" #include "CTriangleBBSelector.h" #include "CMetaTriangleSelector.h" #include "CTerrainTriangleSelector.h" #include "CSceneNodeAnimatorRotation.h" #include "CSceneNodeAnimatorFlyCircle.h" #include "CSceneNodeAnimatorFlyStraight.h" #include "CSceneNodeAnimatorTexture.h" #include "CSceneNodeAnimatorCollisionResponse.h" #include "CSceneNodeAnimatorDelete.h" #include "CSceneNodeAnimatorFollowSpline.h" #include "CSceneNodeAnimatorCameraFPS.h" #include "CSceneNodeAnimatorCameraMaya.h" #include "CDefaultSceneNodeAnimatorFactory.h" #include "CGeometryCreator.h" namespace irr { namespace scene { //! constructor CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, gui::ICursorControl* cursorControl, IMeshCache* cache, gui::IGUIEnvironment* gui) : ISceneNode(0, 0), Driver(driver), FileSystem(fs), GUIEnvironment(gui), CursorControl(cursorControl), CollisionManager(0), ActiveCamera(0), ShadowColor(150,0,0,0), AmbientLight(0,0,0,0), MeshCache(cache), CurrentRendertime(ESNRP_NONE), LightManager(0), IRR_XML_FORMAT_SCENE(L"irr_scene"), IRR_XML_FORMAT_NODE(L"node"), IRR_XML_FORMAT_NODE_ATTR_TYPE(L"type") { #ifdef _DEBUG ISceneManager::setDebugName("CSceneManager ISceneManager"); ISceneNode::setDebugName("CSceneManager ISceneNode"); #endif // root node's scene manager SceneManager = this; // set scene parameters Parameters.setAttribute( DEBUG_NORMAL_LENGTH, 1.f ); Parameters.setAttribute( DEBUG_NORMAL_COLOR, video::SColor(255, 34, 221, 221)); if (Driver) Driver->grab(); if (FileSystem) FileSystem->grab(); if (CursorControl) CursorControl->grab(); if (GUIEnvironment) GUIEnvironment->grab(); // create mesh cache if not there already if (!MeshCache) MeshCache = new CMeshCache(); else MeshCache->grab(); // create collision manager CollisionManager = new CSceneCollisionManager(this, Driver); // create geometry creator GeometryCreator = new CGeometryCreator(); // add file format loaders. add the least commonly used ones first, // as these are checked last // TODO: now that we have multiple scene managers, these should be // shallow copies from the previous manager if there is one. #ifdef _IRR_COMPILE_WITH_STL_LOADER_ MeshLoaderList.push_back(new CSTLMeshFileLoader()); #endif #ifdef _IRR_COMPILE_WITH_PLY_LOADER_ MeshLoaderList.push_back(new CPLYMeshFileLoader(this)); #endif #ifdef _IRR_COMPILE_WITH_SMF_LOADER_ MeshLoaderList.push_back(new CSMFMeshFileLoader(Driver)); #endif #ifdef _IRR_COMPILE_WITH_OCT_LOADER_ MeshLoaderList.push_back(new COCTLoader(this, FileSystem)); #endif #ifdef _IRR_COMPILE_WITH_CSM_LOADER_ MeshLoaderList.push_back(new CCSMLoader(this, FileSystem)); #endif #ifdef _IRR_COMPILE_WITH_LMTS_LOADER_ MeshLoaderList.push_back(new CLMTSMeshFileLoader(FileSystem, Driver, &Parameters)); #endif #ifdef _IRR_COMPILE_WITH_MY3D_LOADER_ MeshLoaderList.push_back(new CMY3DMeshFileLoader(this, FileSystem)); #endif #ifdef _IRR_COMPILE_WITH_DMF_LOADER_ MeshLoaderList.push_back(new CDMFLoader(this, FileSystem)); #endif #ifdef _IRR_COMPILE_WITH_OGRE_LOADER_ MeshLoaderList.push_back(new COgreMeshFileLoader(FileSystem, Driver)); #endif #ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_ MeshLoaderList.push_back(new CHalflifeMDLMeshFileLoader( this )); #endif #ifdef _IRR_COMPILE_WITH_MD3_LOADER_ MeshLoaderList.push_back(new CMD3MeshFileLoader( this)); #endif #ifdef _IRR_COMPILE_WITH_LWO_LOADER_ MeshLoaderList.push_back(new CLWOMeshFileLoader(this, FileSystem)); #endif #ifdef _IRR_COMPILE_WITH_MD2_LOADER_ MeshLoaderList.push_back(new CMD2MeshFileLoader()); #endif #ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ MeshLoaderList.push_back(new CIrrMeshFileLoader(this, FileSystem)); #endif #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ MeshLoaderList.push_back(new CBSPMeshFileLoader(this, FileSystem)); #endif #ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_ MeshLoaderList.push_back(new CColladaFileLoader(this, FileSystem)); #endif #ifdef _IRR_COMPILE_WITH_3DS_LOADER_ MeshLoaderList.push_back(new C3DSMeshFileLoader(this, FileSystem)); #endif #ifdef _IRR_COMPILE_WITH_X_LOADER_ MeshLoaderList.push_back(new CXMeshFileLoader(this, FileSystem)); #endif #ifdef _IRR_COMPILE_WITH_MS3D_LOADER_ MeshLoaderList.push_back(new CMS3DMeshFileLoader(Driver)); #endif #ifdef _IRR_COMPILE_WITH_OBJ_LOADER_ MeshLoaderList.push_back(new COBJMeshFileLoader(this, FileSystem)); #endif #ifdef _IRR_COMPILE_WITH_B3D_LOADER_ MeshLoaderList.push_back(new CB3DMeshFileLoader(this)); #endif // scene loaders #ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_ SceneLoaderList.push_back(new CSceneLoaderIrr(this, FileSystem)); #endif // factories ISceneNodeFactory* factory = new CDefaultSceneNodeFactory(this); registerSceneNodeFactory(factory); factory->drop(); ISceneNodeAnimatorFactory* animatorFactory = new CDefaultSceneNodeAnimatorFactory(this, CursorControl); registerSceneNodeAnimatorFactory(animatorFactory); animatorFactory->drop(); } //! destructor CSceneManager::~CSceneManager() { clearDeletionList(); //! force to remove hardwareTextures from the driver //! because Scenes may hold internally data bounded to sceneNodes //! which may be destroyed twice if (Driver) Driver->removeAllHardwareBuffers(); if (FileSystem) FileSystem->drop(); if (CursorControl) CursorControl->drop(); if (CollisionManager) CollisionManager->drop(); if (GeometryCreator) GeometryCreator->drop(); if (GUIEnvironment) GUIEnvironment->drop(); u32 i; for (i=0; idrop(); for (i=0; idrop(); if (ActiveCamera) ActiveCamera->drop(); ActiveCamera = 0; if (MeshCache) MeshCache->drop(); for (i=0; idrop(); for (i=0; idrop(); if (LightManager) LightManager->drop(); // remove all nodes and animators before dropping the driver // as render targets may be destroyed twice removeAll(); removeAnimators(); if (Driver) Driver->drop(); } //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. IAnimatedMesh* CSceneManager::getMesh(const io::path& filename) { IAnimatedMesh* msh = MeshCache->getMeshByName(filename); if (msh) return msh; io::IReadFile* file = FileSystem->createAndOpenFile(filename); if (!file) { os::Printer::log("Could not load mesh, because file could not be opened: ", filename, ELL_ERROR); return 0; } // iterate the list in reverse order so user-added loaders can override the built-in ones s32 count = MeshLoaderList.size(); for (s32 i=count-1; i>=0; --i) { if (MeshLoaderList[i]->isALoadableFileExtension(filename)) { // reset file to avoid side effects of previous calls to createMesh file->seek(0); msh = MeshLoaderList[i]->createMesh(file); if (msh) { MeshCache->addMesh(filename, msh); msh->drop(); break; } } } file->drop(); if (!msh) os::Printer::log("Could not load mesh, file format seems to be unsupported", filename, ELL_ERROR); else os::Printer::log("Loaded mesh", filename, ELL_INFORMATION); return msh; } //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. IAnimatedMesh* CSceneManager::getMesh(io::IReadFile* file) { if (!file) return 0; io::path name = file->getFileName(); IAnimatedMesh* msh = MeshCache->getMeshByName(file->getFileName()); if (msh) return msh; // iterate the list in reverse order so user-added loaders can override the built-in ones s32 count = MeshLoaderList.size(); for (s32 i=count-1; i>=0; --i) { if (MeshLoaderList[i]->isALoadableFileExtension(name)) { // reset file to avoid side effects of previous calls to createMesh file->seek(0); msh = MeshLoaderList[i]->createMesh(file); if (msh) { MeshCache->addMesh(file->getFileName(), msh); msh->drop(); break; } } } if (!msh) os::Printer::log("Could not load mesh, file format seems to be unsupported", file->getFileName(), ELL_ERROR); else os::Printer::log("Loaded mesh", file->getFileName(), ELL_INFORMATION); return msh; } //! returns the video driver video::IVideoDriver* CSceneManager::getVideoDriver() { return Driver; } //! returns the GUI Environment gui::IGUIEnvironment* CSceneManager::getGUIEnvironment() { return GUIEnvironment; } //! Get the active FileSystem /** \return Pointer to the FileSystem This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ io::IFileSystem* CSceneManager::getFileSystem() { return FileSystem; } //! Adds a text scene node, which is able to display //! 2d text at a position in three dimensional space ITextSceneNode* CSceneManager::addTextSceneNode(gui::IGUIFont* font, const wchar_t* text, video::SColor color, ISceneNode* parent, const core::vector3df& position, s32 id) { if (!font) return 0; if (!parent) parent = this; ITextSceneNode* t = new CTextSceneNode(parent, this, id, font, getSceneCollisionManager(), position, text, color); t->drop(); return t; } //! Adds a text scene node, which uses billboards IBillboardTextSceneNode* CSceneManager::addBillboardTextSceneNode(gui::IGUIFont* font, const wchar_t* text, ISceneNode* parent, const core::dimension2d& size, const core::vector3df& position, s32 id, video::SColor colorTop, video::SColor colorBottom) { if (!font && GUIEnvironment) font = GUIEnvironment->getBuiltInFont(); if (!font) return 0; if (!parent) parent = this; IBillboardTextSceneNode* node = new CBillboardTextSceneNode(parent, this, id, font, text, position, size, colorTop, colorBottom); node->drop(); return node; } //! Adds a scene node, which can render a quake3 shader IMeshSceneNode* CSceneManager::addQuake3SceneNode(const IMeshBuffer* meshBuffer, const quake3::IShader * shader, ISceneNode* parent, s32 id ) { #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ if (!shader) return 0; if (!parent) parent = this; CQuake3ShaderSceneNode* node = new CQuake3ShaderSceneNode( parent, this, id, FileSystem, meshBuffer, shader ); node->drop(); return node; #else return 0; #endif } //! adds Volume Lighting Scene Node. //! the returned pointer must not be dropped. IVolumeLightSceneNode* CSceneManager::addVolumeLightSceneNode( ISceneNode* parent, s32 id, const u32 subdivU, const u32 subdivV, const video::SColor foot, const video::SColor tail, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) { if (!parent) parent = this; IVolumeLightSceneNode* node = new CVolumeLightSceneNode(parent, this, id, subdivU, subdivV, foot, tail, position, rotation, scale); node->drop(); return node; } //! adds a test scene node for test purposes to the scene. It is a simple cube of (1,1,1) size. //! the returned pointer must not be dropped. IMeshSceneNode* CSceneManager::addCubeSceneNode(f32 size, ISceneNode* parent, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) { if (!parent) parent = this; IMeshSceneNode* node = new CCubeSceneNode(size, parent, this, id, position, rotation, scale); node->drop(); return node; } //! Adds a sphere scene node for test purposes to the scene. IMeshSceneNode* CSceneManager::addSphereSceneNode(f32 radius, s32 polyCount, ISceneNode* parent, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) { if (!parent) parent = this; IMeshSceneNode* node = new CSphereSceneNode(radius, polyCount, polyCount, parent, this, id, position, rotation, scale); node->drop(); return node; } //! adds a scene node for rendering a static mesh //! the returned pointer must not be dropped. IMeshSceneNode* CSceneManager::addMeshSceneNode(IMesh* mesh, ISceneNode* parent, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale, bool alsoAddIfMeshPointerZero) { if (!alsoAddIfMeshPointerZero && !mesh) return 0; if (!parent) parent = this; IMeshSceneNode* node = new CMeshSceneNode(mesh, parent, this, id, position, rotation, scale); node->drop(); return node; } //! Adds a scene node for rendering a animated water surface mesh. ISceneNode* CSceneManager::addWaterSurfaceSceneNode(IMesh* mesh, f32 waveHeight, f32 waveSpeed, f32 waveLength, ISceneNode* parent, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) { if (!parent) parent = this; ISceneNode* node = new CWaterSurfaceSceneNode(waveHeight, waveSpeed, waveLength, mesh, parent, this, id, position, rotation, scale); node->drop(); return node; } //! adds a scene node for rendering an animated mesh model IAnimatedMeshSceneNode* CSceneManager::addAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale, bool alsoAddIfMeshPointerZero) { if (!alsoAddIfMeshPointerZero && !mesh) return 0; if (!parent) parent = this; IAnimatedMeshSceneNode* node = new CAnimatedMeshSceneNode(mesh, parent, this, id, position, rotation, scale); node->drop(); return node; } //! Adds a scene node for rendering using a octree to the scene graph. This a good method for rendering //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much //! faster then a bsp tree. IMeshSceneNode* CSceneManager::addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero) { if (!alsoAddIfMeshPointerZero && (!mesh || !mesh->getFrameCount())) return 0; return addOctreeSceneNode(mesh ? mesh->getMesh(0) : 0, parent, id, minimalPolysPerNode, alsoAddIfMeshPointerZero); } //! Adds a scene node for rendering using a octree. This a good method for rendering //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much //! faster then a bsp tree. IMeshSceneNode* CSceneManager::addOctreeSceneNode(IMesh* mesh, ISceneNode* parent, s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero) { if (!alsoAddIfMeshPointerZero && !mesh) return 0; if (!parent) parent = this; COctreeSceneNode* node = new COctreeSceneNode(parent, this, id, minimalPolysPerNode); if (node) { node->setMesh(mesh); node->drop(); } return node; } //! Adds a camera scene node to the tree and sets it as active camera. //! \param position: Position of the space relative to its parent where the camera will be placed. //! \param lookat: Position where the camera will look at. Also known as target. //! \param parent: Parent scene node of the camera. Can be null. If the parent moves, //! the camera will move too. //! \return Returns pointer to interface to camera ICameraSceneNode* CSceneManager::addCameraSceneNode(ISceneNode* parent, const core::vector3df& position, const core::vector3df& lookat, s32 id, bool makeActive) { if (!parent) parent = this; ICameraSceneNode* node = new CCameraSceneNode(parent, this, id, position, lookat); if (makeActive) setActiveCamera(node); node->drop(); return node; } //! Adds a camera scene node which is able to be controlled with the mouse similar //! to in the 3D Software Maya by Alias Wavefront. //! The returned pointer must not be dropped. ICameraSceneNode* CSceneManager::addCameraSceneNodeMaya(ISceneNode* parent, f32 rotateSpeed, f32 zoomSpeed, f32 translationSpeed, s32 id, f32 distance, bool makeActive) { ICameraSceneNode* node = addCameraSceneNode(parent, core::vector3df(), core::vector3df(0,0,100), id, makeActive); if (node) { ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraMaya(CursorControl, rotateSpeed, zoomSpeed, translationSpeed, distance); node->addAnimator(anm); anm->drop(); } return node; } //! Adds a camera scene node which is able to be controlled with the mouse and keys //! like in most first person shooters (FPS): ICameraSceneNode* CSceneManager::addCameraSceneNodeFPS(ISceneNode* parent, f32 rotateSpeed, f32 moveSpeed, s32 id, SKeyMap* keyMapArray, s32 keyMapSize, bool noVerticalMovement, f32 jumpSpeed, bool invertMouseY, bool makeActive) { ICameraSceneNode* node = addCameraSceneNode(parent, core::vector3df(), core::vector3df(0,0,100), id, makeActive); if (node) { ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraFPS(CursorControl, rotateSpeed, moveSpeed, jumpSpeed, keyMapArray, keyMapSize, noVerticalMovement, invertMouseY); // Bind the node's rotation to its target. This is consistent with 1.4.2 and below. node->bindTargetAndRotation(true); node->addAnimator(anm); anm->drop(); } return node; } //! Adds a dynamic light scene node. The light will cast dynamic light on all //! other scene nodes in the scene, which have the material flag video::MTF_LIGHTING //! turned on. (This is the default setting in most scene nodes). ILightSceneNode* CSceneManager::addLightSceneNode(ISceneNode* parent, const core::vector3df& position, video::SColorf color, f32 range, s32 id) { if (!parent) parent = this; ILightSceneNode* node = new CLightSceneNode(parent, this, id, position, color, range); node->drop(); return node; } //! Adds a billboard scene node to the scene. A billboard is like a 3d sprite: A 2d element, //! which always looks to the camera. It is usually used for things like explosions, fire, //! lensflares and things like that. IBillboardSceneNode* CSceneManager::addBillboardSceneNode(ISceneNode* parent, const core::dimension2d& size, const core::vector3df& position, s32 id, video::SColor colorTop, video::SColor colorBottom ) { if (!parent) parent = this; IBillboardSceneNode* node = new CBillboardSceneNode(parent, this, id, position, size, colorTop, colorBottom); node->drop(); return node; } //! Adds a skybox scene node. A skybox is a big cube with 6 textures on it and //! is drawn around the camera position. ISceneNode* CSceneManager::addSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, video::ITexture* left, video::ITexture* right, video::ITexture* front, video::ITexture* back, ISceneNode* parent, s32 id) { if (!parent) parent = this; ISceneNode* node = new CSkyBoxSceneNode(top, bottom, left, right, front, back, parent, this, id); node->drop(); return node; } //! Adds a skydome scene node. A skydome is a large (half-) sphere with a //! panoramic texture on it and is drawn around the camera position. ISceneNode* CSceneManager::addSkyDomeSceneNode(video::ITexture* texture, u32 horiRes, u32 vertRes, f32 texturePercentage,f32 spherePercentage, f32 radius, ISceneNode* parent, s32 id) { if (!parent) parent = this; ISceneNode* node = new CSkyDomeSceneNode(texture, horiRes, vertRes, texturePercentage, spherePercentage, radius, parent, this, id); node->drop(); return node; } //! Adds a particle system scene node. IParticleSystemSceneNode* CSceneManager::addParticleSystemSceneNode( bool withDefaultEmitter, ISceneNode* parent, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) { if (!parent) parent = this; IParticleSystemSceneNode* node = new CParticleSystemSceneNode(withDefaultEmitter, parent, this, id, position, rotation, scale); node->drop(); return node; } //! Adds a terrain scene node to the scene graph. ITerrainSceneNode* CSceneManager::addTerrainSceneNode( const io::path& heightMapFileName, ISceneNode* parent, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale, video::SColor vertexColor, s32 maxLOD, E_TERRAIN_PATCH_SIZE patchSize, s32 smoothFactor, bool addAlsoIfHeightmapEmpty) { io::IReadFile* file = FileSystem->createAndOpenFile(heightMapFileName); if (!file && !addAlsoIfHeightmapEmpty) { os::Printer::log("Could not load terrain, because file could not be opened.", heightMapFileName, ELL_ERROR); return 0; } ITerrainSceneNode* terrain = addTerrainSceneNode(file, parent, id, position, rotation, scale, vertexColor, maxLOD, patchSize, smoothFactor, addAlsoIfHeightmapEmpty); if (file) file->drop(); return terrain; } //! Adds a terrain scene node to the scene graph. ITerrainSceneNode* CSceneManager::addTerrainSceneNode( io::IReadFile* heightMapFile, ISceneNode* parent, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale, video::SColor vertexColor, s32 maxLOD, E_TERRAIN_PATCH_SIZE patchSize, s32 smoothFactor, bool addAlsoIfHeightmapEmpty) { if (!parent) parent = this; if (!heightMapFile && !addAlsoIfHeightmapEmpty) { os::Printer::log("Could not load terrain, because file could not be opened.", ELL_ERROR); return 0; } CTerrainSceneNode* node = new CTerrainSceneNode(parent, this, FileSystem, id, maxLOD, patchSize, position, rotation, scale); if (!node->loadHeightMap(heightMapFile, vertexColor, smoothFactor)) { if (!addAlsoIfHeightmapEmpty) { node->remove(); node->drop(); return 0; } } node->drop(); return node; } //! Adds an empty scene node. ISceneNode* CSceneManager::addEmptySceneNode(ISceneNode* parent, s32 id) { if (!parent) parent = this; ISceneNode* node = new CEmptySceneNode(parent, this, id); node->drop(); return node; } //! Adds a dummy transformation scene node to the scene graph. IDummyTransformationSceneNode* CSceneManager::addDummyTransformationSceneNode( ISceneNode* parent, s32 id) { if (!parent) parent = this; IDummyTransformationSceneNode* node = new CDummyTransformationSceneNode( parent, this, id); node->drop(); return node; } //! Adds a Hill Plane mesh to the mesh pool. The mesh is generated on the fly //! and looks like a plane with some hills on it. You can specify how many hills //! there should be on the plane and how high they should be. Also you must //! specify a name for the mesh, because the mesh is added to the mesh pool, //! and can be retrieved again using ISceneManager::getMesh with the name as //! parameter. IAnimatedMesh* CSceneManager::addHillPlaneMesh(const io::path& name, const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material, f32 hillHeight, const core::dimension2d& countHills, const core::dimension2d& textureRepeatCount) { if (MeshCache->isMeshLoaded(name)) return MeshCache->getMeshByName(name); IMesh* mesh = GeometryCreator->createHillPlaneMesh(tileSize, tileCount, material, hillHeight, countHills, textureRepeatCount); if (!mesh) return 0; SAnimatedMesh* animatedMesh = new SAnimatedMesh(); if (!animatedMesh) { mesh->drop(); return 0; } animatedMesh->addMesh(mesh); mesh->drop(); animatedMesh->recalculateBoundingBox(); MeshCache->addMesh(name, animatedMesh); animatedMesh->drop(); return animatedMesh; } //! Adds a terrain mesh to the mesh pool. IAnimatedMesh* CSceneManager::addTerrainMesh(const io::path& name, video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize, f32 maxHeight, const core::dimension2d& defaultVertexBlockSize) { if (MeshCache->isMeshLoaded(name)) return MeshCache->getMeshByName(name); const bool debugBorders=false; IMesh* mesh = GeometryCreator->createTerrainMesh(texture, heightmap, stretchSize, maxHeight, Driver, defaultVertexBlockSize, debugBorders); if (!mesh) return 0; SAnimatedMesh* animatedMesh = new SAnimatedMesh(); if (!animatedMesh) { mesh->drop(); return 0; } animatedMesh->addMesh(mesh); mesh->drop(); animatedMesh->recalculateBoundingBox(); MeshCache->addMesh(name, animatedMesh); animatedMesh->drop(); return animatedMesh; } //! Adds an arrow mesh to the mesh pool. IAnimatedMesh* CSceneManager::addArrowMesh(const io::path& name, video::SColor vtxColor0, video::SColor vtxColor1, u32 tesselationCylinder, u32 tesselationCone, f32 height, f32 cylinderHeight, f32 width0,f32 width1) { if (MeshCache->isMeshLoaded(name)) return MeshCache->getMeshByName(name); IMesh* mesh = GeometryCreator->createArrowMesh( tesselationCylinder, tesselationCone, height, cylinderHeight, width0,width1, vtxColor0, vtxColor1); if (!mesh) return 0; SAnimatedMesh* animatedMesh = new SAnimatedMesh(); if (!animatedMesh) { mesh->drop(); return 0; } animatedMesh->addMesh(mesh); mesh->drop(); animatedMesh->recalculateBoundingBox(); MeshCache->addMesh(name, animatedMesh); animatedMesh->drop(); return animatedMesh; } //! Adds a static sphere mesh to the mesh pool. IAnimatedMesh* CSceneManager::addSphereMesh(const io::path& name, f32 radius, u32 polyCountX, u32 polyCountY) { if (MeshCache->isMeshLoaded(name)) return MeshCache->getMeshByName(name); IMesh* mesh = GeometryCreator->createSphereMesh(radius, polyCountX, polyCountY); if (!mesh) return 0; SAnimatedMesh* animatedMesh = new SAnimatedMesh(); if (!animatedMesh) { mesh->drop(); return 0; } animatedMesh->addMesh(mesh); mesh->drop(); animatedMesh->recalculateBoundingBox(); MeshCache->addMesh(name, animatedMesh); animatedMesh->drop(); return animatedMesh; } //! Adds a static volume light mesh to the mesh pool. IAnimatedMesh* CSceneManager::addVolumeLightMesh(const io::path& name, const u32 SubdivideU, const u32 SubdivideV, const video::SColor FootColor, const video::SColor TailColor) { if (MeshCache->isMeshLoaded(name)) return MeshCache->getMeshByName(name); IMesh* mesh = GeometryCreator->createVolumeLightMesh(SubdivideU, SubdivideV, FootColor, TailColor); if (!mesh) return 0; SAnimatedMesh* animatedMesh = new SAnimatedMesh(); if (!animatedMesh) { mesh->drop(); return 0; } animatedMesh->addMesh(mesh); mesh->drop(); animatedMesh->recalculateBoundingBox(); MeshCache->addMesh(name, animatedMesh); animatedMesh->drop(); return animatedMesh; } //! Returns the root scene node. This is the scene node wich is parent //! of all scene nodes. The root scene node is a special scene node which //! only exists to manage all scene nodes. It is not rendered and cannot //! be removed from the scene. //! \return Returns a pointer to the root scene node. ISceneNode* CSceneManager::getRootSceneNode() { return this; } //! Returns the current active camera. //! \return The active camera is returned. Note that this can be NULL, if there //! was no camera created yet. ICameraSceneNode* CSceneManager::getActiveCamera() const { return ActiveCamera; } //! Sets the active camera. The previous active camera will be deactivated. //! \param camera: The new camera which should be active. void CSceneManager::setActiveCamera(ICameraSceneNode* camera) { if (camera) camera->grab(); if (ActiveCamera) ActiveCamera->drop(); ActiveCamera = camera; } //! renders the node. void CSceneManager::render() { } //! returns the axis aligned bounding box of this node const core::aabbox3d& CSceneManager::getBoundingBox() const { _IRR_DEBUG_BREAK_IF(true) // Bounding Box of Scene Manager wanted. // should never be used. return *((core::aabbox3d*)0); } //! returns if node is culled bool CSceneManager::isCulled(const ISceneNode* node) const { const ICameraSceneNode* cam = getActiveCamera(); if (!cam) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } bool result = false; // has occlusion query information if (node->getAutomaticCulling() & scene::EAC_OCC_QUERY) { result = (Driver->getOcclusionQueryResult(const_cast(node))==0); } // can be seen by a bounding box ? if (!result && (node->getAutomaticCulling() & scene::EAC_BOX)) { core::aabbox3d tbox = node->getBoundingBox(); node->getAbsoluteTransformation().transformBoxEx(tbox); result = !(tbox.intersectsWithBox(cam->getViewFrustum()->getBoundingBox() )); } // can be seen by a bounding sphere if (!result && (node->getAutomaticCulling() & scene::EAC_FRUSTUM_SPHERE)) { // requires bbox diameter } // can be seen by cam pyramid planes ? if (!result && (node->getAutomaticCulling() & scene::EAC_FRUSTUM_BOX)) { SViewFrustum frust = *cam->getViewFrustum(); //transform the frustum to the node's current absolute transformation core::matrix4 invTrans(node->getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE); //invTrans.makeInverse(); frust.transform(invTrans); core::vector3df edges[8]; node->getBoundingBox().getEdges(edges); for (s32 i=0; igetMaterialCount(); taken = 0; for (u32 i=0; igetMaterialRenderer(node->getMaterial(i).MaterialType); if (rnd && rnd->isTransparent()) { // register as transparent node TransparentNodeEntry e(node, camWorldPos); TransparentNodeList.push_back(e); taken = 1; break; } } // not transparent, register as solid if (!taken) { SolidNodeList.push_back(node); taken = 1; } } break; case ESNRP_SHADOW: if (!isCulled(node)) { ShadowNodeList.push_back(node); taken = 1; } break; case ESNRP_NONE: // ignore this one break; } #ifdef _IRR_SCENEMANAGER_DEBUG s32 index = Parameters.findAttribute ( "calls" ); Parameters.setAttribute ( index, Parameters.getAttributeAsInt ( index ) + 1 ); if (!taken) { index = Parameters.findAttribute ( "culled" ); Parameters.setAttribute ( index, Parameters.getAttributeAsInt ( index ) + 1 ); } #endif return taken; } //! This method is called just before the rendering process of the whole scene. //! draws all scene nodes void CSceneManager::drawAll() { if (!Driver) return; #ifdef _IRR_SCENEMANAGER_DEBUG // reset attributes Parameters.setAttribute ( "culled", 0 ); Parameters.setAttribute ( "calls", 0 ); Parameters.setAttribute ( "drawn_solid", 0 ); Parameters.setAttribute ( "drawn_transparent", 0 ); Parameters.setAttribute ( "drawn_transparent_effect", 0 ); #endif u32 i; // new ISO for scoping problem in some compilers // reset all transforms Driver->setMaterial(video::SMaterial()); Driver->setTransform ( video::ETS_PROJECTION, core::IdentityMatrix ); Driver->setTransform ( video::ETS_VIEW, core::IdentityMatrix ); Driver->setTransform ( video::ETS_WORLD, core::IdentityMatrix ); for (i=video::ETS_COUNT-1; i>=video::ETS_TEXTURE_0; --i) Driver->setTransform ( (video::E_TRANSFORMATION_STATE)i, core::IdentityMatrix ); // TODO: This should not use an attribute here but a real parameter when necessary (too slow!) Driver->setAllowZWriteOnTransparent(Parameters.getAttributeAsBool( ALLOW_ZWRITE_ON_TRANSPARENT) ); // do animations and other stuff. OnAnimate(os::Timer::getTime()); /*! First Scene Node for prerendering should be the active camera consistent Camera is needed for culling */ camWorldPos.set(0,0,0); if (ActiveCamera) { ActiveCamera->render(); camWorldPos = ActiveCamera->getAbsolutePosition(); } // let all nodes register themselves OnRegisterSceneNode(); if (LightManager) LightManager->OnPreRender(LightList); //render camera scenes { CurrentRendertime = ESNRP_CAMERA; Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); if (LightManager) LightManager->OnRenderPassPreRender(CurrentRendertime); for (i=0; irender(); CameraList.set_used(0); if (LightManager) LightManager->OnRenderPassPostRender(CurrentRendertime); } //render lights scenes { CurrentRendertime = ESNRP_LIGHT; Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); if (LightManager) { LightManager->OnRenderPassPreRender(CurrentRendertime); } else { // Sort the lights by distance from the camera core::vector3df camWorldPos(0, 0, 0); if (ActiveCamera) camWorldPos = ActiveCamera->getAbsolutePosition(); core::array SortedLights; SortedLights.set_used(LightList.size()); for (s32 light = (s32)LightList.size() - 1; light >= 0; --light) SortedLights[light].setNodeAndDistanceFromPosition(LightList[light], camWorldPos); SortedLights.set_sorted(false); SortedLights.sort(); for(s32 light = (s32)LightList.size() - 1; light >= 0; --light) LightList[light] = SortedLights[light].Node; } Driver->deleteAllDynamicLights(); Driver->setAmbientLight(AmbientLight); u32 maxLights = LightList.size(); if (!LightManager) maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount(), maxLights); for (i=0; i< maxLights; ++i) LightList[i]->render(); if (LightManager) LightManager->OnRenderPassPostRender(CurrentRendertime); } // render skyboxes { CurrentRendertime = ESNRP_SKY_BOX; Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); if (LightManager) { LightManager->OnRenderPassPreRender(CurrentRendertime); for (i=0; iOnNodePreRender(node); node->render(); LightManager->OnNodePostRender(node); } } else { for (i=0; irender(); } SkyBoxList.set_used(0); if (LightManager) LightManager->OnRenderPassPostRender(CurrentRendertime); } // render default objects { CurrentRendertime = ESNRP_SOLID; Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); SolidNodeList.sort(); // sort by textures if (LightManager) { LightManager->OnRenderPassPreRender(CurrentRendertime); for (i=0; iOnNodePreRender(node); node->render(); LightManager->OnNodePostRender(node); } } else { for (i=0; irender(); } #ifdef _IRR_SCENEMANAGER_DEBUG Parameters.setAttribute("drawn_solid", (s32) SolidNodeList.size() ); #endif SolidNodeList.set_used(0); if (LightManager) LightManager->OnRenderPassPostRender(CurrentRendertime); } // render shadows { CurrentRendertime = ESNRP_SHADOW; Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); if (LightManager) { LightManager->OnRenderPassPreRender(CurrentRendertime); for (i=0; iOnNodePreRender(node); node->render(); LightManager->OnNodePostRender(node); } } else { for (i=0; irender(); } if (!ShadowNodeList.empty()) Driver->drawStencilShadow(true,ShadowColor, ShadowColor, ShadowColor, ShadowColor); ShadowNodeList.set_used(0); if (LightManager) LightManager->OnRenderPassPostRender(CurrentRendertime); } // render transparent objects. { CurrentRendertime = ESNRP_TRANSPARENT; Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); TransparentNodeList.sort(); // sort by distance from camera if (LightManager) { LightManager->OnRenderPassPreRender(CurrentRendertime); for (i=0; iOnNodePreRender(node); node->render(); LightManager->OnNodePostRender(node); } } else { for (i=0; irender(); } #ifdef _IRR_SCENEMANAGER_DEBUG Parameters.setAttribute ( "drawn_transparent", (s32) TransparentNodeList.size() ); #endif TransparentNodeList.set_used(0); if (LightManager) LightManager->OnRenderPassPostRender(CurrentRendertime); } // render transparent effect objects. { CurrentRendertime = ESNRP_TRANSPARENT_EFFECT; Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRendertime) != 0); TransparentEffectNodeList.sort(); // sort by distance from camera if (LightManager) { LightManager->OnRenderPassPreRender(CurrentRendertime); for (i=0; iOnNodePreRender(node); node->render(); LightManager->OnNodePostRender(node); } } else { for (i=0; irender(); } #ifdef _IRR_SCENEMANAGER_DEBUG Parameters.setAttribute ( "drawn_transparent_effect", (s32) TransparentEffectNodeList.size() ); #endif TransparentEffectNodeList.set_used(0); } if (LightManager) LightManager->OnPostRender(); LightList.set_used(0); clearDeletionList(); CurrentRendertime = ESNRP_NONE; } void CSceneManager::setLightManager(ILightManager* lightManager) { if (lightManager) lightManager->grab(); if (LightManager) LightManager->drop(); LightManager = lightManager; } //! Sets the color of stencil buffers shadows drawn by the scene manager. void CSceneManager::setShadowColor(video::SColor color) { ShadowColor = color; } //! Returns the current color of shadows. video::SColor CSceneManager::getShadowColor() const { return ShadowColor; } //! creates a rotation animator, which rotates the attached scene node around itself. ISceneNodeAnimator* CSceneManager::createRotationAnimator(const core::vector3df& rotationPerSecond) { ISceneNodeAnimator* anim = new CSceneNodeAnimatorRotation(os::Timer::getTime(), rotationPerSecond); return anim; } //! creates a fly circle animator, which lets the attached scene node fly around a center. ISceneNodeAnimator* CSceneManager::createFlyCircleAnimator( const core::vector3df& center, f32 radius, f32 speed, const core::vector3df& direction, f32 startPosition, f32 radiusEllipsoid) { const f32 orbitDurationMs = (core::DEGTORAD * 360.f) / speed; const u32 effectiveTime = os::Timer::getTime() + (u32)(orbitDurationMs * startPosition); ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyCircle( effectiveTime, center, radius, speed, direction,radiusEllipsoid); return anim; } //! Creates a fly straight animator, which lets the attached scene node //! fly or move along a line between two points. ISceneNodeAnimator* CSceneManager::createFlyStraightAnimator(const core::vector3df& startPoint, const core::vector3df& endPoint, u32 timeForWay, bool loop,bool pingpong) { ISceneNodeAnimator* anim = new CSceneNodeAnimatorFlyStraight(startPoint, endPoint, timeForWay, loop, os::Timer::getTime(), pingpong); return anim; } //! Creates a texture animator, which switches the textures of the target scene //! node based on a list of textures. ISceneNodeAnimator* CSceneManager::createTextureAnimator(const core::array& textures, s32 timePerFrame, bool loop) { ISceneNodeAnimator* anim = new CSceneNodeAnimatorTexture(textures, timePerFrame, loop, os::Timer::getTime()); return anim; } //! Creates a scene node animator, which deletes the scene node after //! some time automaticly. ISceneNodeAnimator* CSceneManager::createDeleteAnimator(u32 when) { return new CSceneNodeAnimatorDelete(this, os::Timer::getTime() + when); } //! Creates a special scene node animator for doing automatic collision detection //! and response. ISceneNodeAnimatorCollisionResponse* CSceneManager::createCollisionResponseAnimator( ITriangleSelector* world, ISceneNode* sceneNode, const core::vector3df& ellipsoidRadius, const core::vector3df& gravityPerSecond, const core::vector3df& ellipsoidTranslation, f32 slidingValue) { ISceneNodeAnimatorCollisionResponse* anim = new CSceneNodeAnimatorCollisionResponse(this, world, sceneNode, ellipsoidRadius, gravityPerSecond, ellipsoidTranslation, slidingValue); return anim; } //! Creates a follow spline animator. ISceneNodeAnimator* CSceneManager::createFollowSplineAnimator(s32 startTime, const core::array< core::vector3df >& points, f32 speed, f32 tightness, bool loop, bool pingpong) { ISceneNodeAnimator* a = new CSceneNodeAnimatorFollowSpline(startTime, points, speed, tightness, loop, pingpong); return a; } //! Adds an external mesh loader. void CSceneManager::addExternalMeshLoader(IMeshLoader* externalLoader) { if (!externalLoader) return; externalLoader->grab(); MeshLoaderList.push_back(externalLoader); } //! Returns the number of mesh loaders supported by Irrlicht at this time u32 CSceneManager::getMeshLoaderCount() const { return MeshLoaderList.size(); } //! Retrieve the given mesh loader IMeshLoader* CSceneManager::getMeshLoader(u32 index) const { if (index < MeshLoaderList.size()) return MeshLoaderList[index]; else return 0; } //! Adds an external scene loader. void CSceneManager::addExternalSceneLoader(ISceneLoader* externalLoader) { if (!externalLoader) return; externalLoader->grab(); SceneLoaderList.push_back(externalLoader); } //! Returns the number of scene loaders u32 CSceneManager::getSceneLoaderCount() const { return SceneLoaderList.size(); } //! Retrieve the given scene loader ISceneLoader* CSceneManager::getSceneLoader(u32 index) const { if (index < SceneLoaderList.size()) return SceneLoaderList[index]; else return 0; } //! Returns a pointer to the scene collision manager. ISceneCollisionManager* CSceneManager::getSceneCollisionManager() { return CollisionManager; } //! Returns a pointer to the mesh manipulator. IMeshManipulator* CSceneManager::getMeshManipulator() { return Driver->getMeshManipulator(); } //! Creates a simple ITriangleSelector, based on a mesh. ITriangleSelector* CSceneManager::createTriangleSelector(IMesh* mesh, ISceneNode* node) { if (!mesh) return 0; return new CTriangleSelector(mesh, node); } //! Creates a simple and updatable ITriangleSelector, based on a the mesh owned by an //! animated scene node ITriangleSelector* CSceneManager::createTriangleSelector(IAnimatedMeshSceneNode* node) { if (!node || !node->getMesh()) return 0; return new CTriangleSelector(node); } //! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. ITriangleSelector* CSceneManager::createTriangleSelectorFromBoundingBox(ISceneNode* node) { if (!node) return 0; return new CTriangleBBSelector(node); } //! Creates a simple ITriangleSelector, based on a mesh. ITriangleSelector* CSceneManager::createOctreeTriangleSelector(IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode) { if (!mesh) return 0; return new COctreeTriangleSelector(mesh, node, minimalPolysPerNode); } //! Creates a meta triangle selector. IMetaTriangleSelector* CSceneManager::createMetaTriangleSelector() { return new CMetaTriangleSelector(); } //! Creates a triangle selector which can select triangles from a terrain scene node ITriangleSelector* CSceneManager::createTerrainTriangleSelector( ITerrainSceneNode* node, s32 LOD) { return new CTerrainTriangleSelector(node, LOD); } //! Adds a scene node to the deletion queue. void CSceneManager::addToDeletionQueue(ISceneNode* node) { if (!node) return; node->grab(); DeletionList.push_back(node); } //! clears the deletion list void CSceneManager::clearDeletionList() { if (DeletionList.empty()) return; for (u32 i=0; iremove(); DeletionList[i]->drop(); } DeletionList.clear(); } //! Returns the first scene node with the specified name. ISceneNode* CSceneManager::getSceneNodeFromName(const char* name, ISceneNode* start) { if (start == 0) start = getRootSceneNode(); if (!strcmp(start->getName(),name)) return start; ISceneNode* node = 0; const ISceneNodeList& list = start->getChildren(); ISceneNodeList::ConstIterator it = list.begin(); for (; it!=list.end(); ++it) { node = getSceneNodeFromName(name, *it); if (node) return node; } return 0; } //! Returns the first scene node with the specified id. ISceneNode* CSceneManager::getSceneNodeFromId(s32 id, ISceneNode* start) { if (start == 0) start = getRootSceneNode(); if (start->getID() == id) return start; ISceneNode* node = 0; const ISceneNodeList& list = start->getChildren(); ISceneNodeList::ConstIterator it = list.begin(); for (; it!=list.end(); ++it) { node = getSceneNodeFromId(id, *it); if (node) return node; } return 0; } //! Returns the first scene node with the specified type. ISceneNode* CSceneManager::getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start) { if (start == 0) start = getRootSceneNode(); if (start->getType() == type || ESNT_ANY == type) return start; ISceneNode* node = 0; const ISceneNodeList& list = start->getChildren(); ISceneNodeList::ConstIterator it = list.begin(); for (; it!=list.end(); ++it) { node = getSceneNodeFromType(type, *it); if (node) return node; } return 0; } //! returns scene nodes by type. void CSceneManager::getSceneNodesFromType(ESCENE_NODE_TYPE type, core::array& outNodes, ISceneNode* start) { if (start == 0) start = getRootSceneNode(); if (start->getType() == type || ESNT_ANY == type) outNodes.push_back(start); const ISceneNodeList& list = start->getChildren(); ISceneNodeList::ConstIterator it = list.begin(); for (; it!=list.end(); ++it) { getSceneNodesFromType(type, outNodes, *it); } } //! Posts an input event to the environment. Usually you do not have to //! use this method, it is used by the internal engine. bool CSceneManager::postEventFromUser(const SEvent& event) { bool ret = false; ICameraSceneNode* cam = getActiveCamera(); if (cam) ret = cam->OnEvent(event); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! Removes all children of this scene node void CSceneManager::removeAll() { ISceneNode::removeAll(); setActiveCamera(0); // Make sure the driver is reset, might need a more complex method at some point if (Driver) Driver->setMaterial(video::SMaterial()); } //! Clears the whole scene. All scene nodes are removed. void CSceneManager::clear() { removeAll(); } //! Returns interface to the parameters set in this scene. io::IAttributes* CSceneManager::getParameters() { return &Parameters; } //! Returns current render pass. E_SCENE_NODE_RENDER_PASS CSceneManager::getSceneNodeRenderPass() const { return CurrentRendertime; } //! Returns an interface to the mesh cache which is shared beween all existing scene managers. IMeshCache* CSceneManager::getMeshCache() { return MeshCache; } //! Creates a new scene manager. ISceneManager* CSceneManager::createNewSceneManager(bool cloneContent) { CSceneManager* manager = new CSceneManager(Driver, FileSystem, CursorControl, MeshCache, GUIEnvironment); if (cloneContent) manager->cloneMembers(this, manager); return manager; } //! Returns the default scene node factory which can create all built in scene nodes ISceneNodeFactory* CSceneManager::getDefaultSceneNodeFactory() { return getSceneNodeFactory(0); } //! Adds a scene node factory to the scene manager. void CSceneManager::registerSceneNodeFactory(ISceneNodeFactory* factoryToAdd) { if (factoryToAdd) { factoryToAdd->grab(); SceneNodeFactoryList.push_back(factoryToAdd); } } //! Returns amount of registered scene node factories. u32 CSceneManager::getRegisteredSceneNodeFactoryCount() const { return SceneNodeFactoryList.size(); } //! Returns a scene node factory by index ISceneNodeFactory* CSceneManager::getSceneNodeFactory(u32 index) { if (index < SceneNodeFactoryList.size()) return SceneNodeFactoryList[index]; return 0; } //! Returns the default scene node animator factory which can create all built-in scene node animators ISceneNodeAnimatorFactory* CSceneManager::getDefaultSceneNodeAnimatorFactory() { return getSceneNodeAnimatorFactory(0); } //! Adds a scene node animator factory to the scene manager. void CSceneManager::registerSceneNodeAnimatorFactory(ISceneNodeAnimatorFactory* factoryToAdd) { if (factoryToAdd) { factoryToAdd->grab(); SceneNodeAnimatorFactoryList.push_back(factoryToAdd); } } //! Returns amount of registered scene node animator factories. u32 CSceneManager::getRegisteredSceneNodeAnimatorFactoryCount() const { return SceneNodeAnimatorFactoryList.size(); } //! Returns a scene node animator factory by index ISceneNodeAnimatorFactory* CSceneManager::getSceneNodeAnimatorFactory(u32 index) { if (index < SceneNodeAnimatorFactoryList.size()) return SceneNodeAnimatorFactoryList[index]; return 0; } //! Saves the current scene into a file. //! \param filename: Name of the file . bool CSceneManager::saveScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node) { bool ret = false; io::IWriteFile* file = FileSystem->createAndWriteFile(filename); if (file) { ret = saveScene(file, userDataSerializer, node); file->drop(); } else os::Printer::log("Unable to open file", filename, ELL_ERROR); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! Saves the current scene into a file. bool CSceneManager::saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node) { if (!file) { return false; } bool result=false; io::IXMLWriter* writer = FileSystem->createXMLWriter(file); if (!writer) { os::Printer::log("Unable to create XML writer", file->getFileName(), ELL_ERROR); } else { result = saveScene(writer, FileSystem->getFileDir(FileSystem->getAbsolutePath(file->getFileName())), userDataSerializer, node); writer->drop(); } return result; } //! Saves the current scene into a file. bool CSceneManager::saveScene(io::IXMLWriter* writer, const io::path& currentPath, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node) { if (!writer) return false; if (!node) node=this; writer->writeXMLHeader(); writeSceneNode(writer, node, userDataSerializer, currentPath.c_str(), true); return true; } //! Loads a scene. bool CSceneManager::loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer, ISceneNode* rootNode) { io::IReadFile* file = FileSystem->createAndOpenFile(filename); if (!file) { os::Printer::log("Unable to open scene file", filename.c_str(), ELL_ERROR); return false; } const bool ret = loadScene(file, userDataSerializer, rootNode); file->drop(); return ret; } //! Loads a scene. Note that the current scene is not cleared before. bool CSceneManager::loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer, ISceneNode* rootNode) { if (!file) { os::Printer::log("Unable to open scene file", ELL_ERROR); return false; } bool ret = false; // try scene loaders in reverse order s32 i = SceneLoaderList.size()-1; for (; i >= 0 && !ret; --i) if (SceneLoaderList[i]->isALoadableFileFormat(file)) ret = SceneLoaderList[i]->loadScene(file, userDataSerializer, rootNode); if (!ret) os::Printer::log("Could not load scene file, perhaps the format is unsupported: ", file->getFileName().c_str(), ELL_ERROR); return ret; } //! writes a scene node void CSceneManager::writeSceneNode(io::IXMLWriter* writer, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer, const fschar_t* currentPath, bool init) { if (!writer || !node || node->isDebugObject()) return; const wchar_t* name; ISceneNode* tmpNode=node; if (init) { name = IRR_XML_FORMAT_SCENE.c_str(); writer->writeElement(name, false); node=this; } else { name = IRR_XML_FORMAT_NODE.c_str(); writer->writeElement(name, false, IRR_XML_FORMAT_NODE_ATTR_TYPE.c_str(), core::stringw(getSceneNodeTypeName(node->getType())).c_str()); } writer->writeLineBreak(); // write properties io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); io::SAttributeReadWriteOptions options; if (currentPath) { options.Filename=currentPath; options.Flags|=io::EARWF_USE_RELATIVE_PATHS; } node->serializeAttributes(attr, &options); if (attr->getAttributeCount() != 0) { attr->write(writer); writer->writeLineBreak(); } // write materials if (node->getMaterialCount() && Driver) { const wchar_t* materialElement = L"materials"; writer->writeElement(materialElement); writer->writeLineBreak(); for (u32 i=0; i < node->getMaterialCount(); ++i) { io::IAttributes* tmp_attr = Driver->createAttributesFromMaterial(node->getMaterial(i), &options); tmp_attr->write(writer); tmp_attr->drop(); } writer->writeClosingTag(materialElement); writer->writeLineBreak(); } // write animators if (!node->getAnimators().empty()) { const wchar_t* animatorElement = L"animators"; writer->writeElement(animatorElement); writer->writeLineBreak(); ISceneNodeAnimatorList::ConstIterator it = node->getAnimators().begin(); for (; it != node->getAnimators().end(); ++it) { attr->clear(); attr->addString("Type", getAnimatorTypeName((*it)->getType())); (*it)->serializeAttributes(attr); attr->write(writer); } writer->writeClosingTag(animatorElement); writer->writeLineBreak(); } // write possible user data if (userDataSerializer) { io::IAttributes* userData = userDataSerializer->createUserData(node); if (userData) { const wchar_t* userDataElement = L"userData"; writer->writeLineBreak(); writer->writeElement(userDataElement); writer->writeLineBreak(); userData->write(writer); writer->writeClosingTag(userDataElement); writer->writeLineBreak(); writer->writeLineBreak(); userData->drop(); } } // reset to actual root node if (init) node=tmpNode; // write children once root node is written // if parent is not scene manager, we need to write out node first if (init && (node != this)) { writeSceneNode(writer, node, userDataSerializer, currentPath); } else { ISceneNodeList::ConstIterator it = node->getChildren().begin(); for (; it != node->getChildren().end(); ++it) writeSceneNode(writer, (*it), userDataSerializer, currentPath); } attr->drop(); writer->writeClosingTag(name); writer->writeLineBreak(); writer->writeLineBreak(); } //! Returns a typename from a scene node type or null if not found const c8* CSceneManager::getSceneNodeTypeName(ESCENE_NODE_TYPE type) { const char* name = 0; for (s32 i=(s32)SceneNodeFactoryList.size()-1; !name && i>=0; --i) name = SceneNodeFactoryList[i]->getCreateableSceneNodeTypeName(type); return name; } //! Adds a scene node to the scene by name ISceneNode* CSceneManager::addSceneNode(const char* sceneNodeTypeName, ISceneNode* parent) { ISceneNode* node = 0; for (s32 i=(s32)SceneNodeFactoryList.size()-1; i>=0 && !node; --i) node = SceneNodeFactoryList[i]->addSceneNode(sceneNodeTypeName, parent); return node; } ISceneNodeAnimator* CSceneManager::createSceneNodeAnimator(const char* typeName, ISceneNode* target) { ISceneNodeAnimator *animator = 0; for (s32 i=(s32)SceneNodeAnimatorFactoryList.size()-1; i>=0 && !animator; --i) animator = SceneNodeAnimatorFactoryList[i]->createSceneNodeAnimator(typeName, target); return animator; } //! Returns a typename from a scene node animator type or null if not found const c8* CSceneManager::getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) { const char* name = 0; for (s32 i=SceneNodeAnimatorFactoryList.size()-1; !name && i >= 0; --i) name = SceneNodeAnimatorFactoryList[i]->getCreateableSceneNodeAnimatorTypeName(type); return name; } //! Writes attributes of the scene node. void CSceneManager::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addString ("Name", Name.c_str()); out->addInt ("Id", ID ); out->addColorf ("AmbientLight", AmbientLight); // fog attributes from video driver video::SColor color; video::E_FOG_TYPE fogType; f32 start, end, density; bool pixelFog, rangeFog; Driver->getFog(color, fogType, start, end, density, pixelFog, rangeFog); out->addEnum("FogType", fogType, video::FogTypeNames); out->addColorf("FogColor", color); out->addFloat("FogStart", start); out->addFloat("FogEnd", end); out->addFloat("FogDensity", density); out->addBool("FogPixel", pixelFog); out->addBool("FogRange", rangeFog); } //! Reads attributes of the scene node. void CSceneManager::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Name = in->getAttributeAsString("Name"); ID = in->getAttributeAsInt("Id"); AmbientLight = in->getAttributeAsColorf("AmbientLight"); // fog attributes video::SColor color; video::E_FOG_TYPE fogType; f32 start, end, density; bool pixelFog, rangeFog; if (in->existsAttribute("FogType")) { fogType = (video::E_FOG_TYPE) in->getAttributeAsEnumeration("FogType", video::FogTypeNames); color = in->getAttributeAsColorf("FogColor").toSColor(); start = in->getAttributeAsFloat("FogStart"); end = in->getAttributeAsFloat("FogEnd"); density = in->getAttributeAsFloat("FogDensity"); pixelFog = in->getAttributeAsBool("FogPixel"); rangeFog = in->getAttributeAsBool("FogRange"); Driver->setFog(color, fogType, start, end, density, pixelFog, rangeFog); } RelativeTranslation.set(0,0,0); RelativeRotation.set(0,0,0); RelativeScale.set(1,1,1); IsVisible = true; AutomaticCullingState = scene::EAC_BOX; DebugDataVisible = scene::EDS_OFF; IsDebugObject = false; updateAbsolutePosition(); } //! Sets ambient color of the scene void CSceneManager::setAmbientLight(const video::SColorf &ambientColor) { AmbientLight = ambientColor; } //! Returns ambient color of the scene const video::SColorf& CSceneManager::getAmbientLight() const { return AmbientLight; } //! Get a skinned mesh, which is not available as header-only code ISkinnedMesh* CSceneManager::createSkinnedMesh() { #ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ return new CSkinnedMesh(); #else return 0; #endif } //! Returns a mesh writer implementation if available IMeshWriter* CSceneManager::createMeshWriter(EMESH_WRITER_TYPE type) { switch(type) { case EMWT_IRR_MESH: #ifdef _IRR_COMPILE_WITH_IRR_WRITER_ return new CIrrMeshWriter(Driver, FileSystem); #else return 0; #endif case EMWT_COLLADA: #ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_ return new CColladaMeshWriter(this, Driver, FileSystem); #else return 0; #endif case EMWT_STL: #ifdef _IRR_COMPILE_WITH_STL_WRITER_ return new CSTLMeshWriter(this); #else return 0; #endif case EMWT_OBJ: #ifdef _IRR_COMPILE_WITH_OBJ_WRITER_ return new COBJMeshWriter(this, FileSystem); #else return 0; #endif case EMWT_PLY: #ifdef _IRR_COMPILE_WITH_PLY_WRITER_ return new CPLYMeshWriter(); #else return 0; #endif } return 0; } // creates a scenemanager ISceneManager* createSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, gui::ICursorControl* cursorcontrol, gui::IGUIEnvironment *guiEnvironment) { return new CSceneManager(driver, fs, cursorcontrol, 0, guiEnvironment ); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CSceneLoaderIrr.h0000644000000000000000000000434312574354552020256 0ustar rootroot// Copyright (C) 2010-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_LOADER_IRR_H_INCLUDED__ #define __C_SCENE_LOADER_IRR_H_INCLUDED__ #include "ISceneLoader.h" #include "IXMLReader.h" namespace irr { namespace io { class IFileSystem; } namespace scene { class ISceneManager; //! Class which can load a scene into the scene manager. class CSceneLoaderIrr : public virtual ISceneLoader { public: //! Constructor CSceneLoaderIrr(ISceneManager *smgr, io::IFileSystem* fs); //! Destructor virtual ~CSceneLoaderIrr(); //! Returns true if the class might be able to load this file. virtual bool isALoadableFileExtension(const io::path& filename) const; //! Returns true if the class might be able to load this file. virtual bool isALoadableFileFormat(io::IReadFile *file) const; //! Loads the scene into the scene manager. virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* rootNode=0); private: //! Recursively reads nodes from the xml file void readSceneNode(io::IXMLReader* reader, ISceneNode* parent, ISceneUserDataSerializer* userDataSerializer); //! read a node's materials void readMaterials(io::IXMLReader* reader, ISceneNode* node); //! read a node's animators void readAnimators(io::IXMLReader* reader, ISceneNode* node); //! read any other data into the user serializer void readUserData(io::IXMLReader* reader, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer); ISceneManager *SceneManager; io::IFileSystem *FileSystem; //! constants for reading and writing XML. //! Not made static due to portability problems. // TODO: move to own header const core::stringw IRR_XML_FORMAT_SCENE; const core::stringw IRR_XML_FORMAT_NODE; const core::stringw IRR_XML_FORMAT_NODE_ATTR_TYPE; const core::stringw IRR_XML_FORMAT_ATTRIBUTES; const core::stringw IRR_XML_FORMAT_MATERIALS; const core::stringw IRR_XML_FORMAT_ANIMATORS; const core::stringw IRR_XML_FORMAT_USERDATA; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSceneLoaderIrr.cpp0000644000000000000000000001556112574354552020615 0ustar rootroot// Copyright (C) 2010-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSceneLoaderIrr.h" #include "ISceneNodeAnimatorFactory.h" #include "ISceneUserDataSerializer.h" #include "ISceneManager.h" #include "IVideoDriver.h" #include "IFileSystem.h" #include "os.h" namespace irr { namespace scene { //! Constructor CSceneLoaderIrr::CSceneLoaderIrr(ISceneManager *smgr, io::IFileSystem* fs) : SceneManager(smgr), FileSystem(fs), IRR_XML_FORMAT_SCENE(L"irr_scene"), IRR_XML_FORMAT_NODE(L"node"), IRR_XML_FORMAT_NODE_ATTR_TYPE(L"type"), IRR_XML_FORMAT_ATTRIBUTES(L"attributes"), IRR_XML_FORMAT_MATERIALS(L"materials"), IRR_XML_FORMAT_ANIMATORS(L"animators"), IRR_XML_FORMAT_USERDATA(L"userData") { } //! Destructor CSceneLoaderIrr::~CSceneLoaderIrr() { } //! Returns true if the class might be able to load this file. bool CSceneLoaderIrr::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension(filename, "irr"); } //! Returns true if the class might be able to load this file. bool CSceneLoaderIrr::isALoadableFileFormat(io::IReadFile *file) const { // todo: check inside the file return true; } //! Loads the scene into the scene manager. bool CSceneLoaderIrr::loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer, ISceneNode* rootNode) { if (!file) { os::Printer::log("Unable to open scene file", ELL_ERROR); return false; } io::IXMLReader* reader = FileSystem->createXMLReader(file); if (!reader) { os::Printer::log("Scene is not a valid XML file", file->getFileName().c_str(), ELL_ERROR); return false; } // TODO: COLLADA_CREATE_SCENE_INSTANCES can be removed when the COLLADA loader is a scene loader bool oldColladaSingleMesh = SceneManager->getParameters()->getAttributeAsBool(COLLADA_CREATE_SCENE_INSTANCES); SceneManager->getParameters()->setAttribute(COLLADA_CREATE_SCENE_INSTANCES, false); // read file while (reader->read()) { readSceneNode(reader, rootNode, userDataSerializer); } // restore old collada parameters SceneManager->getParameters()->setAttribute(COLLADA_CREATE_SCENE_INSTANCES, oldColladaSingleMesh); // clean up reader->drop(); return true; } //! Reads the next node void CSceneLoaderIrr::readSceneNode(io::IXMLReader* reader, ISceneNode* parent, ISceneUserDataSerializer* userDataSerializer) { if (!reader) return; scene::ISceneNode* node = 0; if (!parent && IRR_XML_FORMAT_SCENE==reader->getNodeName()) node = SceneManager->getRootSceneNode(); else if (parent && IRR_XML_FORMAT_NODE==reader->getNodeName()) { // find node type and create it core::stringc attrName = reader->getAttributeValue(IRR_XML_FORMAT_NODE_ATTR_TYPE.c_str()); node = SceneManager->addSceneNode(attrName.c_str(), parent); if (!node) os::Printer::log("Could not create scene node of unknown type", attrName.c_str()); } else node=parent; // read attributes while(reader->read()) { bool endreached = false; const wchar_t* name = reader->getNodeName(); switch (reader->getNodeType()) { case io::EXN_ELEMENT_END: if ((IRR_XML_FORMAT_NODE == name) || (IRR_XML_FORMAT_SCENE == name)) { endreached = true; } break; case io::EXN_ELEMENT: if (IRR_XML_FORMAT_ATTRIBUTES == name) { // read attributes io::IAttributes* attr = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver()); attr->read(reader, true); if (node) node->deserializeAttributes(attr); attr->drop(); } else if (IRR_XML_FORMAT_MATERIALS == name) readMaterials(reader, node); else if (IRR_XML_FORMAT_ANIMATORS == name) readAnimators(reader, node); else if (IRR_XML_FORMAT_USERDATA == name) readUserData(reader, node, userDataSerializer); else if ((IRR_XML_FORMAT_NODE == name) || (IRR_XML_FORMAT_SCENE == name)) { readSceneNode(reader, node, userDataSerializer); } else { os::Printer::log("Found unknown element in irrlicht scene file", core::stringc(name).c_str()); } break; default: break; } if (endreached) break; } if (node && userDataSerializer) userDataSerializer->OnCreateNode(node); } //! reads materials of a node void CSceneLoaderIrr::readMaterials(io::IXMLReader* reader, ISceneNode* node) { u32 nr = 0; while(reader->read()) { const wchar_t* name = reader->getNodeName(); switch(reader->getNodeType()) { case io::EXN_ELEMENT_END: if (IRR_XML_FORMAT_MATERIALS == name) return; break; case io::EXN_ELEMENT: if (IRR_XML_FORMAT_ATTRIBUTES == name) { // read materials from attribute list io::IAttributes* attr = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver()); attr->read(reader); if (node && node->getMaterialCount() > nr) { SceneManager->getVideoDriver()->fillMaterialStructureFromAttributes( node->getMaterial(nr), attr); } attr->drop(); ++nr; } break; default: break; } } } //! reads animators of a node void CSceneLoaderIrr::readAnimators(io::IXMLReader* reader, ISceneNode* node) { while(reader->read()) { const wchar_t* name = reader->getNodeName(); switch(reader->getNodeType()) { case io::EXN_ELEMENT_END: if (IRR_XML_FORMAT_ANIMATORS == name) return; break; case io::EXN_ELEMENT: if (IRR_XML_FORMAT_ATTRIBUTES == name) { // read animator data from attribute list io::IAttributes* attr = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver()); attr->read(reader); if (node) { core::stringc typeName = attr->getAttributeAsString("Type"); ISceneNodeAnimator* anim = SceneManager->createSceneNodeAnimator(typeName.c_str(), node); if (anim) { anim->deserializeAttributes(attr); anim->drop(); } } attr->drop(); } break; default: break; } } } //! reads user data of a node void CSceneLoaderIrr::readUserData(io::IXMLReader* reader, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer) { while(reader->read()) { const wchar_t* name = reader->getNodeName(); switch(reader->getNodeType()) { case io::EXN_ELEMENT_END: if (IRR_XML_FORMAT_USERDATA == name) return; break; case io::EXN_ELEMENT: if (IRR_XML_FORMAT_ATTRIBUTES == name) { // read user data from attribute list io::IAttributes* attr = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver()); attr->read(reader); if (node && userDataSerializer) { userDataSerializer->OnReadUserData(node, attr); } attr->drop(); } break; default: break; } } } } // scene } // irr irrlicht-1.8.3/source/Irrlicht/CSceneCollisionManager.h0000644000000000000000000001255212574354552021622 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_SCENE_COLLISION_MANAGER_H_INCLUDED__ #define __C_SCENE_COLLISION_MANAGER_H_INCLUDED__ #include "ISceneCollisionManager.h" #include "ISceneManager.h" #include "IVideoDriver.h" namespace irr { namespace scene { //! The Scene Collision Manager provides methods for performing collision tests and picking on scene nodes. class CSceneCollisionManager : public ISceneCollisionManager { public: //! constructor CSceneCollisionManager(ISceneManager* smanager, video::IVideoDriver* driver); //! destructor virtual ~CSceneCollisionManager(); //! Returns the scene node, which is currently visible at the given //! screen coordinates, viewed from the currently active camera. virtual ISceneNode* getSceneNodeFromScreenCoordinatesBB(const core::position2d& pos, s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0); //! Returns the nearest scene node which collides with a 3d ray and //! whose id matches a bitmask. virtual ISceneNode* getSceneNodeFromRayBB(const core::line3d& ray, s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0); //! Returns the scene node, at which the overgiven camera is looking at and //! which id matches the bitmask. virtual ISceneNode* getSceneNodeFromCameraBB(ICameraSceneNode* camera, s32 idBitMask=0, bool bNoDebugObjects = false); //! Finds the collision point of a line and lots of triangles, if there is one. virtual bool getCollisionPoint(const core::line3d& ray, ITriangleSelector* selector, core::vector3df& outCollisionPoint, core::triangle3df& outTriangle, ISceneNode* & outNode); //! Collides a moving ellipsoid with a 3d world with gravity and returns //! the resulting new position of the ellipsoid. virtual core::vector3df getCollisionResultPosition( ITriangleSelector* selector, const core::vector3df &ellipsoidPosition, const core::vector3df& ellipsoidRadius, const core::vector3df& ellipsoidDirectionAndSpeed, core::triangle3df& triout, core::vector3df& hitPosition, bool& outFalling, ISceneNode*& outNode, f32 slidingSpeed, const core::vector3df& gravityDirectionAndSpeed); //! Returns a 3d ray which would go through the 2d screen coodinates. virtual core::line3d getRayFromScreenCoordinates( const core::position2d & pos, ICameraSceneNode* camera = 0); //! Calculates 2d screen position from a 3d position. virtual core::position2d getScreenCoordinatesFrom3DPosition( const core::vector3df & pos, ICameraSceneNode* camera=0, bool useViewPort=false); //! Gets the scene node and nearest collision point for a ray based on //! the nodes' id bitmasks, bounding boxes and triangle selectors. virtual ISceneNode* getSceneNodeAndCollisionPointFromRay( core::line3df ray, core::vector3df & outCollisionPoint, core::triangle3df & outTriangle, s32 idBitMask = 0, ISceneNode * collisionRootNode = 0, bool noDebugObjects = false); private: //! recursive method for going through all scene nodes void getPickedNodeBB(ISceneNode* root, core::line3df& ray, s32 bits, bool bNoDebugObjects, f32& outbestdistance, ISceneNode*& outbestnode); //! recursive method for going through all scene nodes void getPickedNodeFromBBAndSelector(ISceneNode * root, core::line3df & ray, s32 bits, bool noDebugObjects, f32 & outBestDistanceSquared, ISceneNode * & outBestNode, core::vector3df & outBestCollisionPoint, core::triangle3df & outBestTriangle); struct SCollisionData { core::vector3df eRadius; core::vector3df R3Velocity; core::vector3df R3Position; core::vector3df velocity; core::vector3df normalizedVelocity; core::vector3df basePoint; bool foundCollision; f32 nearestDistance; core::vector3df intersectionPoint; core::triangle3df intersectionTriangle; s32 triangleIndex; s32 triangleHits; f32 slidingSpeed; ITriangleSelector* selector; }; //! Tests the current collision data against an individual triangle. /** \param colData: the collision data. \param triangle: the triangle to test against. \return true if the triangle is hit (and is the closest hit), false otherwise */ bool testTriangleIntersection(SCollisionData* colData, const core::triangle3df& triangle); //! recursive method for doing collision response core::vector3df collideEllipsoidWithWorld(ITriangleSelector* selector, const core::vector3df &position, const core::vector3df& radius, const core::vector3df& velocity, f32 slidingSpeed, const core::vector3df& gravity, core::triangle3df& triout, core::vector3df& hitPosition, bool& outFalling, ISceneNode*& outNode); core::vector3df collideWithWorld(s32 recursionDepth, SCollisionData &colData, core::vector3df pos, core::vector3df vel); inline bool getLowestRoot(f32 a, f32 b, f32 c, f32 maxR, f32* root); ISceneManager* SceneManager; video::IVideoDriver* Driver; core::array Triangles; // triangle buffer }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CSceneCollisionManager.cpp0000644000000000000000000007254412574354552022164 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CSceneCollisionManager.h" #include "ISceneNode.h" #include "ICameraSceneNode.h" #include "ITriangleSelector.h" #include "SViewFrustum.h" #include "os.h" #include "irrMath.h" namespace irr { namespace scene { //! constructor CSceneCollisionManager::CSceneCollisionManager(ISceneManager* smanager, video::IVideoDriver* driver) : SceneManager(smanager), Driver(driver) { #ifdef _DEBUG setDebugName("CSceneCollisionManager"); #endif if (Driver) Driver->grab(); } //! destructor CSceneCollisionManager::~CSceneCollisionManager() { if (Driver) Driver->drop(); } //! Returns the scene node, which is currently visible at the given //! screen coordinates, viewed from the currently active camera. ISceneNode* CSceneCollisionManager::getSceneNodeFromScreenCoordinatesBB( const core::position2d& pos, s32 idBitMask, bool noDebugObjects, scene::ISceneNode* root) { const core::line3d ln = getRayFromScreenCoordinates(pos, 0); if ( ln.start == ln.end ) return 0; return getSceneNodeFromRayBB(ln, idBitMask, noDebugObjects, root); } //! Returns the nearest scene node which collides with a 3d ray and //! which id matches a bitmask. ISceneNode* CSceneCollisionManager::getSceneNodeFromRayBB( const core::line3d& ray, s32 idBitMask, bool noDebugObjects, scene::ISceneNode* root) { ISceneNode* best = 0; f32 dist = FLT_MAX; core::line3d truncatableRay(ray); getPickedNodeBB((root==0)?SceneManager->getRootSceneNode():root, truncatableRay, idBitMask, noDebugObjects, dist, best); return best; } //! recursive method for going through all scene nodes void CSceneCollisionManager::getPickedNodeBB(ISceneNode* root, core::line3df& ray, s32 bits, bool noDebugObjects, f32& outbestdistance, ISceneNode*& outbestnode) { const ISceneNodeList& children = root->getChildren(); const core::vector3df rayVector = ray.getVector().normalize(); ISceneNodeList::ConstIterator it = children.begin(); for (; it != children.end(); ++it) { ISceneNode* current = *it; if (current->isVisible()) { if((noDebugObjects ? !current->isDebugObject() : true) && (bits==0 || (bits != 0 && (current->getID() & bits)))) { // get world to object space transform core::matrix4 worldToObject; if (!current->getAbsoluteTransformation().getInverse(worldToObject)) continue; // transform vector from world space to object space core::line3df objectRay(ray); worldToObject.transformVect(objectRay.start); worldToObject.transformVect(objectRay.end); const core::aabbox3df & objectBox = current->getBoundingBox(); // Do the initial intersection test in object space, since the // object space box test is more accurate. if(objectBox.isPointInside(objectRay.start)) { // use fast bbox intersection to find distance to hitpoint // algorithm from Kay et al., code from gamedev.net const core::vector3df dir = (objectRay.end-objectRay.start).normalize(); const core::vector3df minDist = (objectBox.MinEdge - objectRay.start)/dir; const core::vector3df maxDist = (objectBox.MaxEdge - objectRay.start)/dir; const core::vector3df realMin(core::min_(minDist.X, maxDist.X),core::min_(minDist.Y, maxDist.Y),core::min_(minDist.Z, maxDist.Z)); const core::vector3df realMax(core::max_(minDist.X, maxDist.X),core::max_(minDist.Y, maxDist.Y),core::max_(minDist.Z, maxDist.Z)); const f32 minmax = core::min_(realMax.X, realMax.Y, realMax.Z); // nearest distance to intersection const f32 maxmin = core::max_(realMin.X, realMin.Y, realMin.Z); const f32 toIntersectionSq = (maxmin>0?maxmin*maxmin:minmax*minmax); if (toIntersectionSq < outbestdistance) { outbestdistance = toIntersectionSq; outbestnode = current; // And we can truncate the ray to stop us hitting further nodes. ray.end = ray.start + (rayVector * sqrtf(toIntersectionSq)); } } else if (objectBox.intersectsWithLine(objectRay)) { // Now transform into world space, since we need to use world space // scales and distances. core::aabbox3df worldBox(objectBox); current->getAbsoluteTransformation().transformBox(worldBox); core::vector3df edges[8]; worldBox.getEdges(edges); /* We need to check against each of 6 faces, composed of these corners: /3--------/7 / | / | / | / | 1---------5 | | 2- - -| -6 | / | / |/ | / 0---------4/ Note that we define them as opposite pairs of faces. */ static const s32 faceEdges[6][3] = { { 0, 1, 5 }, // Front { 6, 7, 3 }, // Back { 2, 3, 1 }, // Left { 4, 5, 7 }, // Right { 1, 3, 7 }, // Top { 2, 0, 4 } // Bottom }; core::vector3df intersection; core::plane3df facePlane; f32 bestDistToBoxBorder = FLT_MAX; f32 bestToIntersectionSq = FLT_MAX; for(s32 face = 0; face < 6; ++face) { facePlane.setPlane(edges[faceEdges[face][0]], edges[faceEdges[face][1]], edges[faceEdges[face][2]]); // Only consider lines that might be entering through this face, since we // already know that the start point is outside the box. if(facePlane.classifyPointRelation(ray.start) != core::ISREL3D_FRONT) continue; // Don't bother using a limited ray, since we already know that it should be long // enough to intersect with the box. if(facePlane.getIntersectionWithLine(ray.start, rayVector, intersection)) { const f32 toIntersectionSq = ray.start.getDistanceFromSQ(intersection); if(toIntersectionSq < outbestdistance) { // We have to check that the intersection with this plane is actually // on the box, so need to go back to object space again. worldToObject.transformVect(intersection); // find the closest point on the box borders. Have to do this as exact checks will fail due to floating point problems. f32 distToBorder = core::max_ ( core::min_ (core::abs_(objectBox.MinEdge.X-intersection.X), core::abs_(objectBox.MaxEdge.X-intersection.X)), core::min_ (core::abs_(objectBox.MinEdge.Y-intersection.Y), core::abs_(objectBox.MaxEdge.Y-intersection.Y)), core::min_ (core::abs_(objectBox.MinEdge.Z-intersection.Z), core::abs_(objectBox.MaxEdge.Z-intersection.Z)) ); if ( distToBorder < bestDistToBoxBorder ) { bestDistToBoxBorder = distToBorder; bestToIntersectionSq = toIntersectionSq; } } } // If the ray could be entering through the first face of a pair, then it can't // also be entering through the opposite face, and so we can skip that face. if (!(face & 0x01)) ++face; } if ( bestDistToBoxBorder < FLT_MAX ) { outbestdistance = bestToIntersectionSq; outbestnode = current; // If we got a hit, we can now truncate the ray to stop us hitting further nodes. ray.end = ray.start + (rayVector * sqrtf(outbestdistance)); } } } // Only check the children if this node is visible. getPickedNodeBB(current, ray, bits, noDebugObjects, outbestdistance, outbestnode); } } } ISceneNode* CSceneCollisionManager::getSceneNodeAndCollisionPointFromRay( core::line3df ray, core::vector3df & outCollisionPoint, core::triangle3df & outTriangle, s32 idBitMask, ISceneNode * collisionRootNode, bool noDebugObjects) { ISceneNode* bestNode = 0; f32 bestDistanceSquared = FLT_MAX; if(0 == collisionRootNode) collisionRootNode = SceneManager->getRootSceneNode(); // We don't try to do anything too clever, like sorting the candidate // nodes by distance to bounding-box. In the example below, we could do the // triangle collision check with node A first, but we'd have to check node B // anyway, as the actual collision point could be (and is) closer than the // collision point in node A. // // ray end // | // AAAAAAAAAA // A | // A | B // A | B // A BBBBB // A | // A | // | // | // ray start // // We therefore have to do a full BB and triangle collision on every scene // node in order to find the nearest collision point, so sorting them by // bounding box would be pointless. getPickedNodeFromBBAndSelector(collisionRootNode, ray, idBitMask, noDebugObjects, bestDistanceSquared, bestNode, outCollisionPoint, outTriangle); return bestNode; } void CSceneCollisionManager::getPickedNodeFromBBAndSelector( ISceneNode * root, core::line3df & ray, s32 bits, bool noDebugObjects, f32 & outBestDistanceSquared, ISceneNode * & outBestNode, core::vector3df & outBestCollisionPoint, core::triangle3df & outBestTriangle) { const ISceneNodeList& children = root->getChildren(); ISceneNodeList::ConstIterator it = children.begin(); for (; it != children.end(); ++it) { ISceneNode* current = *it; ITriangleSelector * selector = current->getTriangleSelector(); if (selector && current->isVisible() && (noDebugObjects ? !current->isDebugObject() : true) && (bits==0 || (bits != 0 && (current->getID() & bits)))) { // get world to object space transform core::matrix4 mat; if (!current->getAbsoluteTransformation().getInverse(mat)) continue; // transform vector from world space to object space core::line3df line(ray); mat.transformVect(line.start); mat.transformVect(line.end); const core::aabbox3df& box = current->getBoundingBox(); core::vector3df candidateCollisionPoint; core::triangle3df candidateTriangle; // do intersection test in object space ISceneNode * hitNode = 0; if (box.intersectsWithLine(line) && getCollisionPoint(ray, selector, candidateCollisionPoint, candidateTriangle, hitNode)) { const f32 distanceSquared = (candidateCollisionPoint - ray.start).getLengthSQ(); if(distanceSquared < outBestDistanceSquared) { outBestDistanceSquared = distanceSquared; outBestNode = current; outBestCollisionPoint = candidateCollisionPoint; outBestTriangle = candidateTriangle; const core::vector3df rayVector = ray.getVector().normalize(); ray.end = ray.start + (rayVector * sqrtf(distanceSquared)); } } } getPickedNodeFromBBAndSelector(current, ray, bits, noDebugObjects, outBestDistanceSquared, outBestNode, outBestCollisionPoint, outBestTriangle); } } //! Returns the scene node, at which the overgiven camera is looking at and //! which id matches the bitmask. ISceneNode* CSceneCollisionManager::getSceneNodeFromCameraBB( ICameraSceneNode* camera, s32 idBitMask, bool noDebugObjects) { if (!camera) return 0; const core::vector3df start = camera->getAbsolutePosition(); core::vector3df end = camera->getTarget(); end = start + ((end - start).normalize() * camera->getFarValue()); return getSceneNodeFromRayBB(core::line3d(start, end), idBitMask, noDebugObjects); } //! Finds the collision point of a line and lots of triangles, if there is one. bool CSceneCollisionManager::getCollisionPoint(const core::line3d& ray, ITriangleSelector* selector, core::vector3df& outIntersection, core::triangle3df& outTriangle, ISceneNode*& outNode) { if (!selector) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } s32 totalcnt = selector->getTriangleCount(); if ( totalcnt <= 0 ) return false; Triangles.set_used(totalcnt); s32 cnt = 0; selector->getTriangles(Triangles.pointer(), totalcnt, cnt, ray); const core::vector3df linevect = ray.getVector().normalize(); core::vector3df intersection; f32 nearest = FLT_MAX; bool found = false; const f32 raylength = ray.getLengthSQ(); const f32 minX = core::min_(ray.start.X, ray.end.X); const f32 maxX = core::max_(ray.start.X, ray.end.X); const f32 minY = core::min_(ray.start.Y, ray.end.Y); const f32 maxY = core::max_(ray.start.Y, ray.end.Y); const f32 minZ = core::min_(ray.start.Z, ray.end.Z); const f32 maxZ = core::max_(ray.start.Z, ray.end.Z); for (s32 i=0; i triangle.pointA.X && minX > triangle.pointB.X && minX > triangle.pointC.X) continue; if(maxX < triangle.pointA.X && maxX < triangle.pointB.X && maxX < triangle.pointC.X) continue; if(minY > triangle.pointA.Y && minY > triangle.pointB.Y && minY > triangle.pointC.Y) continue; if(maxY < triangle.pointA.Y && maxY < triangle.pointB.Y && maxY < triangle.pointC.Y) continue; if(minZ > triangle.pointA.Z && minZ > triangle.pointB.Z && minZ > triangle.pointC.Z) continue; if(maxZ < triangle.pointA.Z && maxZ < triangle.pointB.Z && maxZ < triangle.pointC.Z) continue; if (triangle.getIntersectionWithLine(ray.start, linevect, intersection)) { const f32 tmp = intersection.getDistanceFromSQ(ray.start); const f32 tmp2 = intersection.getDistanceFromSQ(ray.end); if (tmp < raylength && tmp2 < raylength && tmp < nearest) { nearest = tmp; outTriangle = triangle; outIntersection = intersection; outNode = selector->getSceneNodeForTriangle(i); found = true; } } } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return found; } //! Collides a moving ellipsoid with a 3d world with gravity and returns //! the resulting new position of the ellipsoid. core::vector3df CSceneCollisionManager::getCollisionResultPosition( ITriangleSelector* selector, const core::vector3df &position, const core::vector3df& radius, const core::vector3df& direction, core::triangle3df& triout, core::vector3df& hitPosition, bool& outFalling, ISceneNode*& outNode, f32 slidingSpeed, const core::vector3df& gravity) { return collideEllipsoidWithWorld(selector, position, radius, direction, slidingSpeed, gravity, triout, hitPosition, outFalling, outNode); } bool CSceneCollisionManager::testTriangleIntersection(SCollisionData* colData, const core::triangle3df& triangle) { const core::plane3d trianglePlane = triangle.getPlane(); // only check front facing polygons if ( !trianglePlane.isFrontFacing(colData->normalizedVelocity) ) return false; // get interval of plane intersection f32 t1, t0; bool embeddedInPlane = false; // calculate signed distance from sphere position to triangle plane f32 signedDistToTrianglePlane = trianglePlane.getDistanceTo( colData->basePoint); f32 normalDotVelocity = trianglePlane.Normal.dotProduct(colData->velocity); if ( core::iszero ( normalDotVelocity ) ) { // sphere is traveling parallel to plane if (fabs(signedDistToTrianglePlane) >= 1.0f) return false; // no collision possible else { // sphere is embedded in plane embeddedInPlane = true; t0 = 0.0; t1 = 1.0; } } else { normalDotVelocity = core::reciprocal ( normalDotVelocity ); // N.D is not 0. Calculate intersection interval t0 = (-1.f - signedDistToTrianglePlane) * normalDotVelocity; t1 = (1.f - signedDistToTrianglePlane) * normalDotVelocity; // Swap so t0 < t1 if (t0 > t1) { f32 tmp = t1; t1 = t0; t0 = tmp; } // check if at least one value is within the range if (t0 > 1.0f || t1 < 0.0f) return false; // both t values are outside 1 and 0, no collision possible // clamp to 0 and 1 t0 = core::clamp ( t0, 0.f, 1.f ); t1 = core::clamp ( t1, 0.f, 1.f ); } // at this point we have t0 and t1, if there is any intersection, it // is between this interval core::vector3df collisionPoint; bool foundCollision = false; f32 t = 1.0f; // first check the easy case: Collision within the triangle; // if this happens, it must be at t0 and this is when the sphere // rests on the front side of the triangle plane. This can only happen // if the sphere is not embedded in the triangle plane. if (!embeddedInPlane) { core::vector3df planeIntersectionPoint = (colData->basePoint - trianglePlane.Normal) + (colData->velocity * t0); if (triangle.isPointInside(planeIntersectionPoint)) { foundCollision = true; t = t0; collisionPoint = planeIntersectionPoint; } } // if we havent found a collision already we will have to sweep // the sphere against points and edges of the triangle. Note: A // collision inside the triangle will always happen before a // vertex or edge collision. if (!foundCollision) { core::vector3df velocity = colData->velocity; core::vector3df base = colData->basePoint; f32 velocitySqaredLength = velocity.getLengthSQ(); f32 a,b,c; f32 newT; // for each edge or vertex a quadratic equation has to be solved: // a*t^2 + b*t + c = 0. We calculate a,b, and c for each test. // check against points a = velocitySqaredLength; // p1 b = 2.0f * (velocity.dotProduct(base - triangle.pointA)); c = (triangle.pointA-base).getLengthSQ() - 1.f; if (getLowestRoot(a,b,c,t, &newT)) { t = newT; foundCollision = true; collisionPoint = triangle.pointA; } // p2 if (!foundCollision) { b = 2.0f * (velocity.dotProduct(base - triangle.pointB)); c = (triangle.pointB-base).getLengthSQ() - 1.f; if (getLowestRoot(a,b,c,t, &newT)) { t = newT; foundCollision = true; collisionPoint = triangle.pointB; } } // p3 if (!foundCollision) { b = 2.0f * (velocity.dotProduct(base - triangle.pointC)); c = (triangle.pointC-base).getLengthSQ() - 1.f; if (getLowestRoot(a,b,c,t, &newT)) { t = newT; foundCollision = true; collisionPoint = triangle.pointC; } } // check against edges: // p1 --- p2 core::vector3df edge = triangle.pointB - triangle.pointA; core::vector3df baseToVertex = triangle.pointA - base; f32 edgeSqaredLength = edge.getLengthSQ(); f32 edgeDotVelocity = edge.dotProduct(velocity); f32 edgeDotBaseToVertex = edge.dotProduct(baseToVertex); // calculate parameters for equation a = edgeSqaredLength* -velocitySqaredLength + edgeDotVelocity*edgeDotVelocity; b = edgeSqaredLength* (2.f *velocity.dotProduct(baseToVertex)) - 2.0f*edgeDotVelocity*edgeDotBaseToVertex; c = edgeSqaredLength* (1.f -baseToVertex.getLengthSQ()) + edgeDotBaseToVertex*edgeDotBaseToVertex; // does the swept sphere collide against infinite edge? if (getLowestRoot(a,b,c,t,&newT)) { f32 f = (edgeDotVelocity*newT - edgeDotBaseToVertex) / edgeSqaredLength; if (f >=0.0f && f <= 1.0f) { // intersection took place within segment t = newT; foundCollision = true; collisionPoint = triangle.pointA + (edge*f); } } // p2 --- p3 edge = triangle.pointC-triangle.pointB; baseToVertex = triangle.pointB - base; edgeSqaredLength = edge.getLengthSQ(); edgeDotVelocity = edge.dotProduct(velocity); edgeDotBaseToVertex = edge.dotProduct(baseToVertex); // calculate parameters for equation a = edgeSqaredLength* -velocitySqaredLength + edgeDotVelocity*edgeDotVelocity; b = edgeSqaredLength* (2*velocity.dotProduct(baseToVertex)) - 2.0f*edgeDotVelocity*edgeDotBaseToVertex; c = edgeSqaredLength* (1-baseToVertex.getLengthSQ()) + edgeDotBaseToVertex*edgeDotBaseToVertex; // does the swept sphere collide against infinite edge? if (getLowestRoot(a,b,c,t,&newT)) { f32 f = (edgeDotVelocity*newT-edgeDotBaseToVertex) / edgeSqaredLength; if (f >=0.0f && f <= 1.0f) { // intersection took place within segment t = newT; foundCollision = true; collisionPoint = triangle.pointB + (edge*f); } } // p3 --- p1 edge = triangle.pointA-triangle.pointC; baseToVertex = triangle.pointC - base; edgeSqaredLength = edge.getLengthSQ(); edgeDotVelocity = edge.dotProduct(velocity); edgeDotBaseToVertex = edge.dotProduct(baseToVertex); // calculate parameters for equation a = edgeSqaredLength* -velocitySqaredLength + edgeDotVelocity*edgeDotVelocity; b = edgeSqaredLength* (2*velocity.dotProduct(baseToVertex)) - 2.0f*edgeDotVelocity*edgeDotBaseToVertex; c = edgeSqaredLength* (1-baseToVertex.getLengthSQ()) + edgeDotBaseToVertex*edgeDotBaseToVertex; // does the swept sphere collide against infinite edge? if (getLowestRoot(a,b,c,t,&newT)) { f32 f = (edgeDotVelocity*newT-edgeDotBaseToVertex) / edgeSqaredLength; if (f >=0.0f && f <= 1.0f) { // intersection took place within segment t = newT; foundCollision = true; collisionPoint = triangle.pointC + (edge*f); } } }// end no collision found // set result: if (foundCollision) { // distance to collision is t f32 distToCollision = t*colData->velocity.getLength(); // does this triangle qualify for closest hit? if (!colData->foundCollision || distToCollision < colData->nearestDistance) { colData->nearestDistance = distToCollision; colData->intersectionPoint = collisionPoint; colData->foundCollision = true; colData->intersectionTriangle = triangle; ++colData->triangleHits; return true; } }// end found collision return false; } //! Collides a moving ellipsoid with a 3d world with gravity and returns //! the resulting new position of the ellipsoid. core::vector3df CSceneCollisionManager::collideEllipsoidWithWorld( ITriangleSelector* selector, const core::vector3df &position, const core::vector3df& radius, const core::vector3df& velocity, f32 slidingSpeed, const core::vector3df& gravity, core::triangle3df& triout, core::vector3df& hitPosition, bool& outFalling, ISceneNode*& outNode) { if (!selector || radius.X == 0.0f || radius.Y == 0.0f || radius.Z == 0.0f) return position; // This code is based on the paper "Improved Collision detection and Response" // by Kasper Fauerby, but some parts are modified. SCollisionData colData; colData.R3Position = position; colData.R3Velocity = velocity; colData.eRadius = radius; colData.nearestDistance = FLT_MAX; colData.selector = selector; colData.slidingSpeed = slidingSpeed; colData.triangleHits = 0; colData.triangleIndex = -1; core::vector3df eSpacePosition = colData.R3Position / colData.eRadius; core::vector3df eSpaceVelocity = colData.R3Velocity / colData.eRadius; // iterate until we have our final position core::vector3df finalPos = collideWithWorld( 0, colData, eSpacePosition, eSpaceVelocity); outFalling = false; // add gravity if (gravity != core::vector3df(0,0,0)) { colData.R3Position = finalPos * colData.eRadius; colData.R3Velocity = gravity; colData.triangleHits = 0; eSpaceVelocity = gravity/colData.eRadius; finalPos = collideWithWorld(0, colData, finalPos, eSpaceVelocity); outFalling = (colData.triangleHits == 0); } if (colData.triangleHits) { triout = colData.intersectionTriangle; triout.pointA *= colData.eRadius; triout.pointB *= colData.eRadius; triout.pointC *= colData.eRadius; outNode = selector->getSceneNodeForTriangle(colData.triangleIndex); } finalPos *= colData.eRadius; hitPosition = colData.intersectionPoint * colData.eRadius; return finalPos; } core::vector3df CSceneCollisionManager::collideWithWorld(s32 recursionDepth, SCollisionData &colData, core::vector3df pos, core::vector3df vel) { f32 veryCloseDistance = colData.slidingSpeed; if (recursionDepth > 5) return pos; colData.velocity = vel; colData.normalizedVelocity = vel; colData.normalizedVelocity.normalize(); colData.basePoint = pos; colData.foundCollision = false; colData.nearestDistance = FLT_MAX; //------------------ collide with world // get all triangles with which we might collide core::aabbox3d box(colData.R3Position); box.addInternalPoint(colData.R3Position + colData.R3Velocity); box.MinEdge -= colData.eRadius; box.MaxEdge += colData.eRadius; s32 totalTriangleCnt = colData.selector->getTriangleCount(); Triangles.set_used(totalTriangleCnt); core::matrix4 scaleMatrix; scaleMatrix.setScale( core::vector3df(1.0f / colData.eRadius.X, 1.0f / colData.eRadius.Y, 1.0f / colData.eRadius.Z)); s32 triangleCnt = 0; colData.selector->getTriangles(Triangles.pointer(), totalTriangleCnt, triangleCnt, box, &scaleMatrix); for (s32 i=0; i= veryCloseDistance) { core::vector3df v = vel; v.setLength( colData.nearestDistance - veryCloseDistance ); newBasePoint = colData.basePoint + v; v.normalize(); colData.intersectionPoint -= (v * veryCloseDistance); } // calculate sliding plane const core::vector3df slidePlaneOrigin = colData.intersectionPoint; const core::vector3df slidePlaneNormal = (newBasePoint - colData.intersectionPoint).normalize(); core::plane3d slidingPlane(slidePlaneOrigin, slidePlaneNormal); core::vector3df newDestinationPoint = destinationPoint - (slidePlaneNormal * slidingPlane.getDistanceTo(destinationPoint)); // generate slide vector const core::vector3df newVelocityVector = newDestinationPoint - colData.intersectionPoint; if (newVelocityVector.getLength() < veryCloseDistance) return newBasePoint; return collideWithWorld(recursionDepth+1, colData, newBasePoint, newVelocityVector); } //! Returns a 3d ray which would go through the 2d screen coodinates. core::line3d CSceneCollisionManager::getRayFromScreenCoordinates( const core::position2d & pos, ICameraSceneNode* camera) { core::line3d ln(0,0,0,0,0,0); if (!SceneManager) return ln; if (!camera) camera = SceneManager->getActiveCamera(); if (!camera) return ln; const scene::SViewFrustum* f = camera->getViewFrustum(); core::vector3df farLeftUp = f->getFarLeftUp(); core::vector3df lefttoright = f->getFarRightUp() - farLeftUp; core::vector3df uptodown = f->getFarLeftDown() - farLeftUp; const core::rect& viewPort = Driver->getViewPort(); core::dimension2d screenSize(viewPort.getWidth(), viewPort.getHeight()); f32 dx = pos.X / (f32)screenSize.Width; f32 dy = pos.Y / (f32)screenSize.Height; if (camera->isOrthogonal()) ln.start = f->cameraPosition + (lefttoright * (dx-0.5f)) + (uptodown * (dy-0.5f)); else ln.start = f->cameraPosition; ln.end = farLeftUp + (lefttoright * dx) + (uptodown * dy); return ln; } //! Calculates 2d screen position from a 3d position. core::position2d CSceneCollisionManager::getScreenCoordinatesFrom3DPosition( const core::vector3df & pos3d, ICameraSceneNode* camera, bool useViewPort) { if (!SceneManager || !Driver) return core::position2d(-1000,-1000); if (!camera) camera = SceneManager->getActiveCamera(); if (!camera) return core::position2d(-1000,-1000); core::dimension2d dim; if (useViewPort) dim.set(Driver->getViewPort().getWidth(), Driver->getViewPort().getHeight()); else dim=(Driver->getCurrentRenderTargetSize()); dim.Width /= 2; dim.Height /= 2; core::matrix4 trans = camera->getProjectionMatrix(); trans *= camera->getViewMatrix(); f32 transformedPos[4] = { pos3d.X, pos3d.Y, pos3d.Z, 1.0f }; trans.multiplyWith1x4Matrix(transformedPos); if (transformedPos[3] < 0) return core::position2d(-10000,-10000); const f32 zDiv = transformedPos[3] == 0.0f ? 1.0f : core::reciprocal(transformedPos[3]); return core::position2d( dim.Width + core::round32(dim.Width * (transformedPos[0] * zDiv)), dim.Height - core::round32(dim.Height * (transformedPos[1] * zDiv))); } inline bool CSceneCollisionManager::getLowestRoot(f32 a, f32 b, f32 c, f32 maxR, f32* root) { // check if solution exists const f32 determinant = b*b - 4.0f*a*c; // if determinant is negative, no solution if (determinant < 0.0f || a == 0.f ) return false; // calculate two roots: (if det==0 then x1==x2 // but lets disregard that slight optimization) const f32 sqrtD = sqrtf(determinant); const f32 invDA = core::reciprocal(2*a); f32 r1 = (-b - sqrtD) * invDA; f32 r2 = (-b + sqrtD) * invDA; // sort so x1 <= x2 if (r1 > r2) core::swap(r1,r2); // get lowest root if (r1 > 0 && r1 < maxR) { *root = r1; return true; } // its possible that we want x2, this can happen if x1 < 0 if (r2 > 0 && r2 < maxR) { *root = r2; return true; } return false; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CReadFile.h0000644000000000000000000000233112574354552017063 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_READ_FILE_H_INCLUDED__ #define __C_READ_FILE_H_INCLUDED__ #include #include "IReadFile.h" #include "irrString.h" namespace irr { namespace io { /*! Class for reading a real file from disk. */ class CReadFile : public IReadFile { public: CReadFile(const io::path& fileName); virtual ~CReadFile(); //! returns how much was read virtual s32 read(void* buffer, u32 sizeToRead); //! changes position in file, returns true if successful virtual bool seek(long finalPos, bool relativeMovement = false); //! returns size of file virtual long getSize() const; //! returns if file is open virtual bool isOpen() const { return File != 0; } //! returns where in the file we are. virtual long getPos() const; //! returns name of file virtual const io::path& getFileName() const; private: //! opens the file void openFile(); FILE* File; long FileSize; io::path Filename; }; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CReadFile.cpp0000644000000000000000000000360712574354552017425 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CReadFile.h" namespace irr { namespace io { CReadFile::CReadFile(const io::path& fileName) : File(0), FileSize(0), Filename(fileName) { #ifdef _DEBUG setDebugName("CReadFile"); #endif openFile(); } CReadFile::~CReadFile() { if (File) fclose(File); } //! returns how much was read s32 CReadFile::read(void* buffer, u32 sizeToRead) { if (!isOpen()) return 0; return (s32)fread(buffer, 1, sizeToRead, File); } //! changes position in file, returns true if successful //! if relativeMovement==true, the pos is changed relative to current pos, //! otherwise from begin of file bool CReadFile::seek(long finalPos, bool relativeMovement) { if (!isOpen()) return false; return fseek(File, finalPos, relativeMovement ? SEEK_CUR : SEEK_SET) == 0; } //! returns size of file long CReadFile::getSize() const { return FileSize; } //! returns where in the file we are. long CReadFile::getPos() const { return ftell(File); } //! opens the file void CReadFile::openFile() { if (Filename.size() == 0) // bugfix posted by rt { File = 0; return; } #if defined ( _IRR_WCHAR_FILESYSTEM ) File = _wfopen(Filename.c_str(), L"rb"); #else File = fopen(Filename.c_str(), "rb"); #endif if (File) { // get FileSize fseek(File, 0, SEEK_END); FileSize = getPos(); fseek(File, 0, SEEK_SET); } } //! returns name of file const io::path& CReadFile::getFileName() const { return Filename; } IReadFile* createReadFile(const io::path& fileName) { CReadFile* file = new CReadFile(fileName); if (file->isOpen()) return file; file->drop(); return 0; } } // end namespace io } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CQuake3ShaderSceneNode.h0000644000000000000000000000713112574354552021457 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_QUAKE3_SCENE_NODE_H_INCLUDED__ #define __C_QUAKE3_SCENE_NODE_H_INCLUDED__ #include "IMeshSceneNode.h" #include "IQ3Shader.h" #include "IFileSystem.h" #include "SMeshBuffer.h" #include "SMeshBufferLightMap.h" #include "SMesh.h" #include "ISceneManager.h" namespace irr { namespace scene { //! Scene node which is a quake3 shader. class CQuake3ShaderSceneNode : public scene::IMeshSceneNode { public: CQuake3ShaderSceneNode( ISceneNode* parent, ISceneManager* mgr, s32 id, io::IFileSystem* fileSystem, const IMeshBuffer* original, const quake3::IShader* shader ); virtual ~CQuake3ShaderSceneNode(); virtual void OnRegisterSceneNode(); virtual void render(); virtual void OnAnimate(u32 timeMs); virtual const core::aabbox3d& getBoundingBox() const; virtual u32 getMaterialCount() const; virtual video::SMaterial& getMaterial(u32 i); //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_Q3SHADER_SCENE_NODE; } virtual void setMesh(IMesh* mesh){} virtual IMesh* getMesh() { return Mesh; } virtual void setReadOnlyMaterials(bool readonly) {} virtual bool isReadOnlyMaterials() const { return true; } //! Creates shadow volume scene node as child of this node //! and returns a pointer to it. virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh, s32 id, bool zfailmethod=true, f32 infinity=10000.0f); //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. virtual bool removeChild(ISceneNode* child); private: const quake3::IShader* Shader; SMesh *Mesh; IShadowVolumeSceneNode* Shadow; const SMeshBufferLightMap* Original; SMeshBuffer* MeshBuffer; core::vector3df MeshOffset; struct SQ3Texture { SQ3Texture () : TextureIndex ( 0 ), TextureFrequency(0.f), TextureAddressMode( video::ETC_REPEAT ) { Texture.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); } quake3::tTexArray Texture; u32 TextureIndex; f32 TextureFrequency; video::E_TEXTURE_CLAMP TextureAddressMode; // Wrapping/Clamping }; core::array< SQ3Texture > Q3Texture; void loadTextures ( io::IFileSystem * fileSystem ); void addBuffer ( scene::SMeshBufferLightMap * buffer ); void cloneBuffer ( scene::SMeshBuffer *dest, const scene::SMeshBufferLightMap * buffer, bool translateCenter ); void deformvertexes_wave ( f32 dt, quake3::SModifierFunction &function ); void deformvertexes_move ( f32 dt, quake3::SModifierFunction &function ); void deformvertexes_bulge( f32 dt, quake3::SModifierFunction &function ); void deformvertexes_autosprite( f32 dt, quake3::SModifierFunction &function ); void deformvertexes_autosprite2( f32 dt, quake3::SModifierFunction &function ); void deformvertexes_normal ( f32 dt, quake3::SModifierFunction &function ); void vertextransform_tcgen ( f32 dt, quake3::SModifierFunction &function ); void vertextransform_rgbgen ( f32 dt, quake3::SModifierFunction &function ); void vertextransform_alphagen ( f32 dt, quake3::SModifierFunction &function ); void transformtex ( const core::matrix4 &m, const u32 clamp ); f32 TimeAbs; void animate( u32 stage, core::matrix4 &texture ); E_SCENE_NODE_RENDER_PASS getRenderStage() const; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CQuake3ShaderSceneNode.cpp0000644000000000000000000011251612574354552022016 0ustar rootroot// Copyright (C) 2002-2012 Thomas Alten / Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ #include "CQuake3ShaderSceneNode.h" #include "ISceneManager.h" #include "IVideoDriver.h" #include "ICameraSceneNode.h" #include "SViewFrustum.h" #include "IMeshManipulator.h" #include "SMesh.h" #include "IMaterialRenderer.h" #include "CShadowVolumeSceneNode.h" namespace irr { namespace scene { // who, if not you.. using namespace quake3; /*! */ CQuake3ShaderSceneNode::CQuake3ShaderSceneNode( scene::ISceneNode* parent, scene::ISceneManager* mgr,s32 id, io::IFileSystem *fileSystem, const scene::IMeshBuffer *original, const IShader * shader) : scene::IMeshSceneNode(parent, mgr, id, core::vector3df(0.f, 0.f, 0.f), core::vector3df(0.f, 0.f, 0.f), core::vector3df(1.f, 1.f, 1.f)), Shader(shader), Mesh(0), Shadow(0), Original(0), MeshBuffer(0), TimeAbs(0.f) { #ifdef _DEBUG core::stringc dName = "CQuake3ShaderSceneNode "; dName += Shader->name; setDebugName( dName.c_str() ); #endif // name the Scene Node this->Name = Shader->name; // take lightmap vertex type MeshBuffer = new SMeshBuffer(); Mesh = new SMesh (); Mesh->addMeshBuffer ( MeshBuffer ); MeshBuffer->drop (); //Original = new SMeshBufferLightMap(); Original = (const scene::SMeshBufferLightMap*) original; Original->grab(); // clone meshbuffer to modifiable buffer cloneBuffer(MeshBuffer, Original, Original->getMaterial().ColorMask != 0); // load all Textures in all stages loadTextures( fileSystem ); setAutomaticCulling( scene::EAC_OFF ); } /*! */ CQuake3ShaderSceneNode::~CQuake3ShaderSceneNode() { if (Shadow) Shadow->drop(); if (Mesh) Mesh->drop(); if (Original) Original->drop(); } /* create single copies */ void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBuffer *dest, const scene::SMeshBufferLightMap * buffer, bool translateCenter ) { dest->Material = buffer->Material; dest->Indices = buffer->Indices; const u32 vsize = buffer->Vertices.size(); dest->Vertices.set_used( vsize ); for ( u32 i = 0; i!= vsize; ++i ) { const video::S3DVertex2TCoords& src = buffer->Vertices[i]; video::S3DVertex &dst = dest->Vertices[i]; dst.Pos = src.Pos; dst.Normal = src.Normal; dst.Color = 0xFFFFFFFF; dst.TCoords = src.TCoords; if ( i == 0 ) dest->BoundingBox.reset ( src.Pos ); else dest->BoundingBox.addInternalPoint ( src.Pos ); } // move the (temp) Mesh to a ScenePosititon // set Scene Node Position if ( translateCenter ) { MeshOffset = dest->BoundingBox.getCenter(); setPosition( MeshOffset ); core::matrix4 m; m.setTranslation( -MeshOffset ); SceneManager->getMeshManipulator()->transform( dest, m ); } // No Texture!. Use Shader-Pointer for sorting dest->Material.setTexture(0, (video::ITexture*) Shader); } /* load the textures for all stages */ void CQuake3ShaderSceneNode::loadTextures( io::IFileSystem * fileSystem ) { const SVarGroup *group; u32 i; video::IVideoDriver *driver = SceneManager->getVideoDriver(); // generic stage u32 mipmap = 0; group = Shader->getGroup( 1 ); if ( group->isDefined ( "nomipmaps" ) ) { mipmap = 2 | (driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS)? 1: 0 ); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); } // clear all stages and prefill empty Q3Texture.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); Q3Texture.clear(); for ( i = 0; i != Shader->VarGroup->VariableGroup.size(); ++i ) { Q3Texture.push_back( SQ3Texture() ); } u32 pos; // get texture map for ( i = 0; i < Shader->VarGroup->VariableGroup.size(); ++i ) { group = Shader->getGroup( i ); const core::stringc &mapname = group->get( "map" ); if ( 0 == mapname.size() ) continue; // our lightmap is passed in material.Texture[2] if ( mapname == "$lightmap" ) { Q3Texture [i].Texture.push_back( Original->getMaterial().getTexture(1) ); } else { pos = 0; getTextures( Q3Texture [i].Texture, mapname, pos, fileSystem, driver ); } } // get anim map for ( i = 0; i < Shader->VarGroup->VariableGroup.size(); ++i ) { if ( Q3Texture [i].Texture.size() ) continue; group = Shader->getGroup( i ); const core::stringc &animmap = group->get( "animmap" ); if ( 0 == animmap.size() ) continue; // first parameter is frequency pos = 0; Q3Texture [i].TextureFrequency = core::max_( 0.0001f, getAsFloat( animmap, pos ) ); getTextures( Q3Texture [i].Texture, animmap, pos,fileSystem, driver ); } // get clamp map for ( i = 0; i < Shader->VarGroup->VariableGroup.size(); ++i ) { if ( Q3Texture [i].Texture.size() ) continue; group = Shader->getGroup( i ); const core::stringc &clampmap = group->get( "clampmap" ); if ( 0 == clampmap.size() ) continue; Q3Texture [i].TextureAddressMode = video::ETC_CLAMP_TO_EDGE; pos = 0; getTextures( Q3Texture [i].Texture, clampmap, pos,fileSystem, driver ); } if ( mipmap & 2 ) driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap & 1); } /* Register each texture stage, if first is visible */ void CQuake3ShaderSceneNode::OnRegisterSceneNode() { if ( isVisible() ) { SceneManager->registerNodeForRendering(this, getRenderStage() ); } ISceneNode::OnRegisterSceneNode(); } /* is this a transparent node ? */ E_SCENE_NODE_RENDER_PASS CQuake3ShaderSceneNode::getRenderStage() const { E_SCENE_NODE_RENDER_PASS ret = ESNRP_SOLID; // generic stage const SVarGroup *group; group = Shader->getGroup( 1 ); /* else if ( group->getIndex( "portal" ) >= 0 ) { ret = ESNRP_TRANSPARENT_EFFECT; } else */ if ( group->isDefined( "sort", "opaque" ) ) { ret = ESNRP_SOLID; } else if ( group->isDefined( "sort", "additive" ) ) { ret = ESNRP_TRANSPARENT; } else if ( strstr ( Shader->name.c_str(), "flame" ) || group->isDefined( "surfaceparm", "water" ) || group->isDefined( "sort", "underwater" ) || group->isDefined( "sort", "underwater" ) ) { ret = ESNRP_TRANSPARENT_EFFECT; } else { // Look if first drawing stage needs graphical underlay for ( u32 stage = 2; stage < Shader->VarGroup->VariableGroup.size(); ++stage ) { if ( 0 == Q3Texture [ stage ].Texture.size() ) continue; group = Shader->getGroup( stage ); SBlendFunc blendfunc ( video::EMFN_MODULATE_1X ); getBlendFunc( group->get( "blendfunc" ), blendfunc ); getBlendFunc( group->get( "alphafunc" ), blendfunc ); //ret = blendfunc.isTransparent ? ESNRP_TRANSPARENT : ESNRP_SOLID; if ( blendfunc.isTransparent ) { ret = ESNRP_TRANSPARENT; } break; } } return ret; } /* render in multipass technique */ void CQuake3ShaderSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); E_SCENE_NODE_RENDER_PASS pass = SceneManager->getSceneNodeRenderPass(); video::SMaterial material; const SVarGroup *group; material.Lighting = false; material.setTexture(1, 0); material.NormalizeNormals = false; // generic stage group = Shader->getGroup( 1 ); material.BackfaceCulling = getCullingFunction( group->get( "cull" ) ); u32 pushProjection = 0; core::matrix4 projection ( core::matrix4::EM4CONST_NOTHING ); // decal ( solve z-fighting ) if ( group->isDefined( "polygonoffset" ) ) { projection = driver->getTransform( video::ETS_PROJECTION ); core::matrix4 decalProjection ( projection ); /* f32 n = SceneManager->getActiveCamera()->getNearValue(); f32 f = SceneManager->getActiveCamera()->getFarValue (); f32 delta = 0.01f; f32 pz = 0.2f; f32 epsilon = -2.f * f * n * delta / ( ( f + n ) * pz * ( pz + delta ) ); decalProjection[10] *= 1.f + epsilon; */ // TODO: involve camera decalProjection[10] -= 0.0002f; driver->setTransform( video::ETS_PROJECTION, decalProjection ); pushProjection |= 1; } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation ); if (Shadow) Shadow->updateShadowVolumes(); //! render all stages u32 drawCount = (pass == ESNRP_TRANSPARENT_EFFECT) ? 1 : 0; core::matrix4 textureMatrix ( core::matrix4::EM4CONST_NOTHING ); for ( u32 stage = 1; stage < Shader->VarGroup->VariableGroup.size(); ++stage ) { SQ3Texture &q = Q3Texture[stage]; // advance current stage textureMatrix.makeIdentity(); animate( stage, textureMatrix ); // stage finished, no drawing stage ( vertex transform only ) video::ITexture * tex = q.Texture.size() ? q.Texture [ q.TextureIndex ] : 0; if ( 0 == tex ) continue; // current stage group = Shader->getGroup( stage ); material.setTexture(0, tex ); material.ZBuffer = getDepthFunction( group->get( "depthfunc" ) ); if ( group->isDefined( "depthwrite" ) ) { material.ZWriteEnable = true; } else { material.ZWriteEnable = drawCount == 0; } //resolve quake3 blendfunction to irrlicht Material Type SBlendFunc blendfunc ( video::EMFN_MODULATE_1X ); getBlendFunc( group->get( "blendfunc" ), blendfunc ); getBlendFunc( group->get( "alphafunc" ), blendfunc ); material.MaterialType = blendfunc.type; material.MaterialTypeParam = blendfunc.param0; material.TextureLayer[0].TextureWrapU = q.TextureAddressMode; material.TextureLayer[0].TextureWrapV = q.TextureAddressMode; //material.TextureLayer[0].TrilinearFilter = 1; //material.TextureLayer[0].AnisotropicFilter = 0xFF; material.setTextureMatrix( 0, textureMatrix ); driver->setMaterial( material ); driver->drawMeshBuffer( MeshBuffer ); drawCount += 1; } if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY ) { video::SMaterial deb_m; deb_m.Wireframe = true; deb_m.Lighting = false; deb_m.BackfaceCulling = material.BackfaceCulling; driver->setMaterial( deb_m ); driver->drawMeshBuffer( MeshBuffer ); } // show normals if ( DebugDataVisible & scene::EDS_NORMALS ) { video::SMaterial deb_m; IAnimatedMesh * arrow = SceneManager->addArrowMesh ( "__debugnormalq3", 0xFFECEC00,0xFF999900, 4, 8, 8.f, 6.f, 0.5f,1.f ); if ( 0 == arrow ) { arrow = SceneManager->getMesh ( "__debugnormalq3" ); } const IMesh *mesh = arrow->getMesh ( 0 ); // find a good scaling factor core::matrix4 m2; // draw normals const scene::IMeshBuffer* mb = MeshBuffer; const u32 vSize = video::getVertexPitchFromType(mb->getVertexType()); const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices(); //f32 colCycle = 270.f / (f32) core::s32_max ( mb->getVertexCount() - 1, 1 ); for ( u32 i=0; i != mb->getVertexCount(); ++i ) { // Align to v->normal m2.buildRotateFromTo ( core::vector3df ( 0.f, 1.f, 0 ), v->Normal ); m2.setTranslation ( v->Pos + AbsoluteTransformation.getTranslation () ); /* core::quaternion quatRot( v->Normal.Z, 0.f, -v->Normal.X, 1 + v->Normal.Y ); quatRot.normalize(); quatRot.getMatrix ( m2, v->Pos ); m2 [ 12 ] += AbsoluteTransformation [ 12 ]; m2 [ 13 ] += AbsoluteTransformation [ 13 ]; m2 [ 14 ] += AbsoluteTransformation [ 14 ]; */ driver->setTransform(video::ETS_WORLD, m2 ); deb_m.Lighting = true; /* irr::video::SColorHSL color; irr::video::SColor rgb(0); color.Hue = i * colCycle * core::DEGTORAD; color.Saturation = 1.f; color.Luminance = 0.5f; color.toRGB( deb_m.EmissiveColor ); */ switch ( i ) { case 0: deb_m.EmissiveColor.set(0xFFFFFFFF); break; case 1: deb_m.EmissiveColor.set(0xFFFF0000); break; case 2: deb_m.EmissiveColor.set(0xFF00FF00); break; case 3: deb_m.EmissiveColor.set(0xFF0000FF); break; default: deb_m.EmissiveColor = v->Color; break; } driver->setMaterial( deb_m ); for ( u32 a = 0; a != mesh->getMeshBufferCount(); ++a ) driver->drawMeshBuffer ( mesh->getMeshBuffer ( a ) ); v = (const video::S3DVertex*) ( (u8*) v + vSize ); } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); } if ( pushProjection & 1 ) { driver->setTransform( video::ETS_PROJECTION, projection ); } if ( DebugDataVisible & scene::EDS_BBOX ) { video::SMaterial deb_m; deb_m.Lighting = false; driver->setMaterial(deb_m); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); driver->draw3DBox( getBoundingBox(), video::SColor(255,255,0,0)); } } //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. bool CQuake3ShaderSceneNode::removeChild(ISceneNode* child) { if (child && Shadow == child) { Shadow->drop(); Shadow = 0; } return ISceneNode::removeChild(child); } //! Creates shadow volume scene node as child of this node //! and returns a pointer to it. IShadowVolumeSceneNode* CQuake3ShaderSceneNode::addShadowVolumeSceneNode( const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity) { if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) return 0; if (!shadowMesh) shadowMesh = Mesh; // if null is given, use the mesh of node if (Shadow) Shadow->drop(); Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity); return Shadow; } /*! 3.3.1 deformVertexes wave
Designed for water surfaces, modifying the values differently at each point. It accepts the standard wave functions of the type sin, triangle, square, sawtooth or inversesawtooth. The "div" parameter is used to control the wave "spread" - a value equal to the tessSize of the surface is a good default value (tessSize is subdivision size, in game units, used for the shader when seen in the game world) . */ void CQuake3ShaderSceneNode::deformvertexes_wave( f32 dt, SModifierFunction &function ) { function.wave = core::reciprocal( function.wave ); const f32 phase = function.phase; const u32 vsize = Original->Vertices.size(); for ( u32 i = 0; i != vsize; ++i ) { const video::S3DVertex2TCoords &src = Original->Vertices[i]; video::S3DVertex &dst = MeshBuffer->Vertices[i]; if ( 0 == function.count ) dst.Pos = src.Pos - MeshOffset; const f32 wavephase = (dst.Pos.X + dst.Pos.Y + dst.Pos.Z) * function.wave; function.phase = phase + wavephase; const f32 f = function.evaluate( dt ); dst.Pos.X += f * src.Normal.X; dst.Pos.Y += f * src.Normal.Y; dst.Pos.Z += f * src.Normal.Z; if ( i == 0 ) MeshBuffer->BoundingBox.reset ( dst.Pos ); else MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos ); } function.count = 1; } /*! deformVertexes move x y z func base amplitude phase freq The move parameter is used to make a brush, curve patch or model appear to move together as a unit. The x y z values are the distance and direction in game units the object appears to move relative to it's point of origin in the map. The func base amplitude phase freq values are the same as found in other waveform manipulations. The product of the function modifies the values x, y, and z. Therefore, if you have an amplitude of 5 and an x value of 2, the object will travel 10 units from its point of origin along the x axis. This results in a total of 20 units of motion along the x axis, since the amplitude is the variation both above and below the base. It must be noted that an object made with this shader does not actually change position, it only appears to. Design Notes: If an object is made up of surfaces with different shaders, all must have matching deformVertexes move values or the object will appear to tear itself apart. */ void CQuake3ShaderSceneNode::deformvertexes_move( f32 dt, SModifierFunction &function ) { function.wave = core::reciprocal( function.wave ); const f32 f = function.evaluate( dt ); const u32 vsize = Original->Vertices.size(); for ( u32 i = 0; i != vsize; ++i ) { const video::S3DVertex2TCoords &src = Original->Vertices[i]; video::S3DVertex &dst = MeshBuffer->Vertices[i]; if ( 0 == function.count ) dst.Pos = src.Pos - MeshOffset; dst.Pos.X += f * function.x; dst.Pos.Y += f * function.y; dst.Pos.Z += f * function.z; if ( i == 0 ) MeshBuffer->BoundingBox.reset ( dst.Pos ); else MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos ); } function.count = 1; } /*! 3.3.2 deformVertexes normal
This deformation affects the normals of a vertex without actually moving it, which will effect later shader options like lighting and especially environment mapping. If the shader stages don't use normals in any of their calculations, there will be no visible effect. Design Notes: Putting values of 0.1 t o 0.5 in Amplitude and 1.0 to 4.0 in the Frequency can produce some satisfying results. Some things that have been done with it: A small fluttering bat, falling leaves, rain, flags. */ void CQuake3ShaderSceneNode::deformvertexes_normal( f32 dt, SModifierFunction &function ) { function.func = SINUS; const u32 vsize = Original->Vertices.size(); for ( u32 i = 0; i != vsize; ++i ) { const video::S3DVertex2TCoords &src = Original->Vertices[i]; video::S3DVertex &dst = MeshBuffer->Vertices[i]; function.base = atan2f ( src.Pos.X, src.Pos.Y ); function.phase = src.Pos.X + src.Pos.Z; const f32 lat = function.evaluate( dt ); function.base = src.Normal.Y; function.phase = src.Normal.Z + src.Normal.X; const f32 lng = function.evaluate( dt ); dst.Normal.X = cosf ( lat ) * sinf ( lng ); dst.Normal.Y = sinf ( lat ) * sinf ( lng ); dst.Normal.Z = cosf ( lng ); } } /*! 3.3.3 deformVertexes bulge This forces a bulge to move along the given s and t directions. Designed for use on curved pipes. Specific parameter definitions for deform keywords:
This is roughly defined as the size of the waves that occur. It is measured in game units. Smaller values create a greater density of smaller wave forms occurring in a given area. Larger values create a lesser density of waves, or otherwise put, the appearance of larger waves. To look correct this value should closely correspond to the value (in pixels) set for tessSize (tessellation size) of the texture. A value of 100.0 is a good default value (which means your tessSize should be close to that for things to look "wavelike"). This is the type of wave form being created. Sin stands for sine wave, a regular smoothly flowing wave. Triangle is a wave with a sharp ascent and a sharp decay. It will make a choppy looking wave forms. A square wave is simply on or off for the period of the frequency with no in between. The sawtooth wave has the ascent of a triangle wave, but has the decay cut off sharply like a square wave. An inversesawtooth wave reverses this. This is the distance, in game units that the apparent surface of the texture is displaced from the actual surface of the brush as placed in the editor. A positive value appears above the brush surface. A negative value appears below the brush surface. An example of this is the Quad effect, which essentially is a shell with a positive base value to stand it away from the model surface and a 0 (zero) value for amplitude. The distance that the deformation moves away from the base value. See Wave Forms in the introduction for a description of amplitude. See Wave Forms in the introduction for a description of phase) See Wave Forms in the introduction for a description of frequency) Design Note: The div and amplitude parameters, when used in conjunction with liquid volumes like water should take into consideration how much the water will be moving. A large ocean area would have have massive swells (big div values) that rose and fell dramatically (big amplitude values). While a small, quiet pool may move very little. */ void CQuake3ShaderSceneNode::deformvertexes_bulge( f32 dt, SModifierFunction &function ) { function.func = SINUS; function.wave = core::reciprocal( function.bulgewidth ); dt *= function.bulgespeed * 0.1f; const f32 phase = function.phase; const u32 vsize = Original->Vertices.size(); for ( u32 i = 0; i != vsize; ++i ) { const video::S3DVertex2TCoords &src = Original->Vertices[i]; video::S3DVertex &dst = MeshBuffer->Vertices[i]; const f32 wavephase = (Original->Vertices[i].TCoords.X ) * function.wave; function.phase = phase + wavephase; const f32 f = function.evaluate( dt ); if ( 0 == function.count ) dst.Pos = src.Pos - MeshOffset; dst.Pos.X += f * src.Normal.X; dst.Pos.Y += f * src.Normal.Y; dst.Pos.Z += f * src.Normal.Z; if ( i == 0 ) MeshBuffer->BoundingBox.reset ( dst.Pos ); else MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos ); } function.count = 1; } /*! deformVertexes autosprite This function can be used to make any given triangle quad (pair of triangles that form a square rectangle) automatically behave like a sprite without having to make it a separate entity. This means that the "sprite" on which the texture is placed will rotate to always appear at right angles to the player's view as a sprite would. Any four-sided brush side, flat patch, or pair of triangles in a model can have the autosprite effect on it. The brush face containing a texture with this shader keyword must be square. */ void CQuake3ShaderSceneNode::deformvertexes_autosprite( f32 dt, SModifierFunction &function ) { u32 vsize = Original->Vertices.size(); u32 g; u32 i; const core::vector3df& camPos = SceneManager->getActiveCamera()->getPosition(); video::S3DVertex * dv = MeshBuffer->Vertices.pointer(); const video::S3DVertex2TCoords * vin = Original->Vertices.const_pointer(); core::matrix4 lookat ( core::matrix4::EM4CONST_NOTHING ); core::quaternion q; for ( i = 0; i < vsize; i += 4 ) { // quad-plane core::vector3df center = 0.25f * ( vin[i+0].Pos + vin[i+1].Pos + vin[i+2].Pos + vin[i+3].Pos ); core::vector3df forward = camPos - center; q.rotationFromTo ( vin[i].Normal, forward ); q.getMatrixCenter ( lookat, center, MeshOffset ); for ( g = 0; g < 4; ++g ) { lookat.transformVect ( dv[i+g].Pos, vin[i+g].Pos ); lookat.rotateVect ( dv[i+g].Normal, vin[i+g].Normal ); } } function.count = 1; } /*! deformVertexes autosprite2 Is a slightly modified "sprite" that only rotates around the middle of its longest axis. This allows you to make a pillar of fire that you can walk around, or an energy beam stretched across the room. */ struct sortaxis { core::vector3df v; bool operator < ( const sortaxis &other ) const { return v.getLengthSQ () < other.v.getLengthSQ (); } }; /*! */ void CQuake3ShaderSceneNode::deformvertexes_autosprite2( f32 dt, SModifierFunction &function ) { u32 vsize = Original->Vertices.size(); u32 g; u32 i; const core::vector3df camPos = SceneManager->getActiveCamera()->getAbsolutePosition(); video::S3DVertex * dv = MeshBuffer->Vertices.pointer(); const video::S3DVertex2TCoords * vin = Original->Vertices.const_pointer(); core::matrix4 lookat ( core::matrix4::EM4CONST_NOTHING ); core::array < sortaxis > axis; axis.set_used ( 3 ); for ( i = 0; i < vsize; i += 4 ) { // quad-plane core::vector3df center = 0.25f * ( vin[i+0].Pos + vin[i+1].Pos + vin[i+2].Pos + vin[i+3].Pos ); // longes axe axis[0].v = vin[i+1].Pos - vin[i+0].Pos; axis[1].v = vin[i+2].Pos - vin[i+0].Pos; axis[2].v = vin[i+3].Pos - vin[i+0].Pos; axis.set_sorted ( false ); axis.sort (); lookat.buildAxisAlignedBillboard ( camPos, center, MeshOffset, axis[1].v, vin[i+0].Normal ); for ( g = 0; g < 4; ++g ) { lookat.transformVect ( dv[i+g].Pos, vin[i+g].Pos ); lookat.rotateVect ( dv[i+g].Normal, vin[i+g].Normal ); } } function.count = 1; } /* Generate Vertex Color */ void CQuake3ShaderSceneNode::vertextransform_rgbgen( f32 dt, SModifierFunction &function ) { u32 i; const u32 vsize = Original->Vertices.size(); switch ( function.rgbgen ) { case IDENTITY: //rgbgen identity for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].Color.set(0xFFFFFFFF); break; case IDENTITYLIGHTING: // rgbgen identitylighting TODO: overbright for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].Color.set(0xFF7F7F7F); break; case EXACTVERTEX: // alphagen exactvertex TODO lighting case VERTEX: // rgbgen vertex for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].Color=Original->Vertices[i].Color; break; case WAVE: { // rgbGen wave f32 f = function.evaluate( dt ) * 255.f; s32 value = core::clamp( core::floor32(f), 0, 255 ); value = 0xFF000000 | value << 16 | value << 8 | value; for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].Color.set(value); } break; case CONSTANT: { //rgbgen const ( x y z ) video::SColorf cf( function.x, function.y, function.z ); video::SColor col = cf.toSColor(); for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].Color=col; } break; default: break; } } /* Generate Vertex Color, Alpha */ void CQuake3ShaderSceneNode::vertextransform_alphagen( f32 dt, SModifierFunction &function ) { u32 i; const u32 vsize = Original->Vertices.size(); switch ( function.alphagen ) { case IDENTITY: //alphagen identity for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].Color.setAlpha ( 0xFF ); break; case EXACTVERTEX: // alphagen exactvertex TODO lighting case VERTEX: // alphagen vertex for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].Color.setAlpha ( Original->Vertices[i].Color.getAlpha() ); break; case CONSTANT: { // alphagen const u32 a = (u32) ( function.x * 255.f ); for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].Color.setAlpha ( a ); } break; case LIGHTINGSPECULAR: { // alphagen lightingspecular TODO!!! const SViewFrustum *frustum = SceneManager->getActiveCamera()->getViewFrustum(); const core::matrix4 &view = frustum->getTransform ( video::ETS_VIEW ); const f32 *m = view.pointer(); for ( i = 0; i != vsize; ++i ) { const core::vector3df &n = Original->Vertices[i].Normal; MeshBuffer->Vertices[i].Color.setAlpha ((u32)( 128.f *(1.f+(n.X*m[0]+n.Y*m[1]+n.Z*m[2])))); } } break; case WAVE: { // alphagen wave f32 f = function.evaluate( dt ) * 255.f; s32 value = core::clamp( core::floor32(f), 0, 255 ); for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].Color.setAlpha ( value ); } break; default: break; } } /* Generate Texture Coordinates */ void CQuake3ShaderSceneNode::vertextransform_tcgen( f32 dt, SModifierFunction &function ) { u32 i; const u32 vsize = Original->Vertices.size(); switch ( function.tcgen ) { case TURBULENCE: //tcgen turb { function.wave = core::reciprocal( function.phase ); const f32 phase = function.phase; for ( i = 0; i != vsize; ++i ) { const video::S3DVertex2TCoords &src = Original->Vertices[i]; video::S3DVertex &dst = MeshBuffer->Vertices[i]; const f32 wavephase = (src.Pos.X + src.Pos.Y + src.Pos.Z) * function.wave; function.phase = phase + wavephase; const f32 f = function.evaluate( dt ); dst.TCoords.X = src.TCoords.X + f * src.Normal.X; dst.TCoords.Y = src.TCoords.Y + f * src.Normal.Y; } } break; case TEXTURE: // tcgen texture for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].TCoords = Original->Vertices[i].TCoords; break; case LIGHTMAP: // tcgen lightmap for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].TCoords = Original->Vertices[i].TCoords2; break; case ENVIRONMENT: { // tcgen environment const SViewFrustum *frustum = SceneManager->getActiveCamera()->getViewFrustum(); const core::matrix4 &view = frustum->getTransform ( video::ETS_VIEW ); const f32 *m = view.pointer(); core::vector3df n; for ( i = 0; i != vsize; ++i ) { //const core::vector3df &n = Original->Vertices[i].Normal; n = frustum->cameraPosition - Original->Vertices[i].Pos; n.normalize(); n += Original->Vertices[i].Normal; n.normalize(); MeshBuffer->Vertices[i].TCoords.X = 0.5f*(1.f+(n.X*m[0]+n.Y*m[1]+n.Z*m[2])); MeshBuffer->Vertices[i].TCoords.Y = 0.5f*(1.f+(n.X*m[4]+n.Y*m[5]+n.Z*m[6])); } } break; default: break; } } #if 0 /* Transform Texture Coordinates */ void CQuake3ShaderSceneNode::transformtex( const core::matrix4 &m, const u32 addressMode ) { u32 i; const u32 vsize = MeshBuffer->Vertices.size(); f32 tx1; f32 ty1; if ( addressMode ) { for ( i = 0; i != vsize; ++i ) { core::vector2df &tx = MeshBuffer->Vertices[i].TCoords; tx1 = m[0] * tx.X + m[4] * tx.Y + m[8]; ty1 = m[1] * tx.X + m[5] * tx.Y + m[9]; tx.X = tx1; tx.Y = ty1; } } else { for ( i = 0; i != vsize; ++i ) { core::vector2df &tx = MeshBuffer->Vertices[i].TCoords; tx1 = m[0] * tx.X + m[4] * tx.Y + m[8]; ty1 = m[1] * tx.X + m[5] * tx.Y + m[9]; tx.X = tx1 <= 0.f ? 0.f : tx1 >= 1.f ? 1.f : tx1; tx.Y = ty1 <= 0.f ? 0.f : ty1 >= 1.f ? 1.f : ty1; //tx.X = core::clamp( tx1, 0.f, 1.f ); //tx.Y = core::clamp( ty1, 0.f, 1.f ); } } } #endif /* Texture & Vertex Transform Animator Return a Texture Transformation for this stage Vertex transformation are called if found */ void CQuake3ShaderSceneNode::animate( u32 stage,core::matrix4 &texture ) { const SVarGroup *group = Shader->getGroup( stage ); // select current texture SQ3Texture &q3Tex = Q3Texture [ stage ]; if ( q3Tex.TextureFrequency != 0.f ) { s32 v = core::floor32( TimeAbs * q3Tex.TextureFrequency ); q3Tex.TextureIndex = v % q3Tex.Texture.size(); } core::matrix4 m2; SModifierFunction function; f32 f[16]; // walk group for all modifiers for ( u32 g = 0; g != group->Variable.size(); ++g ) { const SVariable &v = group->Variable[g]; // get the modifier static const c8 * modifierList[] = { "tcmod","deformvertexes","rgbgen","tcgen","map","alphagen" }; u32 pos = 0; function.masterfunc0 = (eQ3ModifierFunction) isEqual( v.name, pos, modifierList, 6 ); if ( UNKNOWN == function.masterfunc0 ) continue; switch ( function.masterfunc0 ) { //tcmod case TCMOD: m2.makeIdentity(); break; default: break; } // get the modifier function static const c8 * funclist[] = { "scroll","scale","rotate","stretch","turb", "wave","identity","vertex", "texture","lightmap","environment","$lightmap", "bulge","autosprite","autosprite2","transform", "exactvertex","const","lightingspecular","move","normal", "identitylighting" }; static const c8 * groupToken[] = { "(", ")" }; pos = 0; function.masterfunc1 = (eQ3ModifierFunction) isEqual( v.content, pos, funclist, 22 ); if ( function.masterfunc1 != UNKNOWN ) function.masterfunc1 = (eQ3ModifierFunction) ((u32) function.masterfunc1 + FUNCTION2 + 1); switch ( function.masterfunc1 ) { case SCROLL: // tcMod scroll f[0] = getAsFloat( v.content, pos ) * TimeAbs; f[1] = getAsFloat( v.content, pos ) * TimeAbs; m2.setTextureTranslate( f[0], f[1] ); break; case SCALE: // tcmod scale f[0] = getAsFloat( v.content, pos ); f[1] = getAsFloat( v.content, pos ); m2.setTextureScale( f[0], f[1] ); break; case ROTATE: // tcmod rotate m2.setTextureRotationCenter( getAsFloat( v.content, pos ) * core::DEGTORAD * TimeAbs ); break; case TRANSFORM: // tcMod memset(f, 0, sizeof ( f )); f[10] = f[15] = 1.f; f[0] = getAsFloat( v.content, pos ); f[1] = getAsFloat( v.content, pos ); f[4] = getAsFloat( v.content, pos ); f[5] = getAsFloat( v.content, pos ); f[8] = getAsFloat( v.content, pos ); f[9] = getAsFloat( v.content, pos ); m2.setM ( f ); break; case STRETCH: // stretch case TURBULENCE: // turb case WAVE: // wave case IDENTITY: // identity case IDENTITYLIGHTING: case VERTEX: // vertex case MOVE: case CONSTANT: { // turb == sin, default == sin function.func = SINUS; if ( function.masterfunc0 == DEFORMVERTEXES ) { switch ( function.masterfunc1 ) { case WAVE: // deformvertexes wave function.wave = getAsFloat( v.content, pos ); break; case MOVE: //deformvertexes move function.x = getAsFloat( v.content, pos ); function.z = getAsFloat( v.content, pos ); function.y = getAsFloat( v.content, pos ); break; default: break; } } switch ( function.masterfunc1 ) { case STRETCH: case TURBULENCE: case WAVE: case MOVE: getModifierFunc( function, v.content, pos ); break; default: break; } switch ( function.masterfunc1 ) { case STRETCH: //tcMod stretch f[0] = core::reciprocal( function.evaluate(TimeAbs) ); m2.setTextureScaleCenter( f[0], f[0] ); break; case TURBULENCE: //tcMod turb //function.tcgen = TURBULENCE; m2.setTextureRotationCenter( function.frequency * core::DEGTORAD * TimeAbs ); break; case WAVE: case IDENTITY: case IDENTITYLIGHTING: case VERTEX: case EXACTVERTEX: case CONSTANT: case LIGHTINGSPECULAR: case MOVE: switch ( function.masterfunc0 ) { case DEFORMVERTEXES: switch ( function.masterfunc1 ) { case WAVE: deformvertexes_wave( TimeAbs, function ); break; case MOVE: deformvertexes_move( TimeAbs, function ); break; default: break; } break; case RGBGEN: function.rgbgen = function.masterfunc1; if ( function.rgbgen == CONSTANT ) { isEqual ( v.content, pos, groupToken, 2 ); function.x = getAsFloat( v.content, pos ); function.y = getAsFloat( v.content, pos ); function.z = getAsFloat( v.content, pos ); } //vertextransform_rgbgen( TimeAbs, function ); break; case ALPHAGEN: function.alphagen = function.masterfunc1; if ( function.alphagen == CONSTANT ) { function.x = getAsFloat( v.content, pos ); } //vertextransform_alphagen( TimeAbs, function ); break; default: break; } break; default: break; } } break; case TEXTURE: case LIGHTMAP: case ENVIRONMENT: // "texture","lightmap","environment" function.tcgen = function.masterfunc1; break; case DOLLAR_LIGHTMAP: // map == lightmap, tcgen == lightmap function.tcgen = LIGHTMAP; break; case BULGE: // deformvertexes bulge function.bulgewidth = getAsFloat( v.content, pos ); function.bulgeheight = getAsFloat( v.content, pos ); function.bulgespeed = getAsFloat( v.content, pos ); deformvertexes_bulge(TimeAbs, function); break; case NORMAL: // deformvertexes normal function.amp = getAsFloat( v.content, pos ); function.frequency = getAsFloat( v.content, pos ); deformvertexes_normal(TimeAbs, function); break; case AUTOSPRITE: // deformvertexes autosprite deformvertexes_autosprite(TimeAbs, function); break; case AUTOSPRITE2: // deformvertexes autosprite2 deformvertexes_autosprite2(TimeAbs, function); break; default: break; } // func switch ( function.masterfunc0 ) { case TCMOD: texture *= m2; break; default: break; } } // group vertextransform_rgbgen( TimeAbs, function ); vertextransform_alphagen( TimeAbs, function ); vertextransform_tcgen( TimeAbs, function ); } void CQuake3ShaderSceneNode::OnAnimate(u32 timeMs) { TimeAbs = f32( timeMs ) * (1.f/1000.f); ISceneNode::OnAnimate( timeMs ); } const core::aabbox3d& CQuake3ShaderSceneNode::getBoundingBox() const { return MeshBuffer->getBoundingBox(); } u32 CQuake3ShaderSceneNode::getMaterialCount() const { return Q3Texture.size(); } video::SMaterial& CQuake3ShaderSceneNode::getMaterial(u32 i) { video::SMaterial& m = MeshBuffer->Material; m.setTexture(0, 0); if ( Q3Texture [ i ].TextureIndex ) m.setTexture(0, Q3Texture [ i ].Texture [ Q3Texture [ i ].TextureIndex ]); return m; } } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CQ3LevelMesh.h0000644000000000000000000003642112574354552017507 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_Q3_LEVEL_MESH_H_INCLUDED__ #define __C_Q3_LEVEL_MESH_H_INCLUDED__ #include "IQ3LevelMesh.h" #include "IReadFile.h" #include "IFileSystem.h" #include "SMesh.h" #include "SMeshBufferLightMap.h" #include "IVideoDriver.h" #include "irrString.h" #include "ISceneManager.h" #include "os.h" namespace irr { namespace scene { class CQ3LevelMesh : public IQ3LevelMesh { public: //! constructor CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr, const quake3::Q3LevelLoadParameter &loadParam); //! destructor virtual ~CQ3LevelMesh(); //! loads a level from a .bsp-File. Also tries to load all //! needed textures. Returns true if successful. bool loadFile(io::IReadFile* file); //! returns the amount of frames in milliseconds. If the amount //! is 1, it is a static (=non animated) mesh. virtual u32 getFrameCount() const; //! Gets the default animation speed of the animated mesh. /** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */ virtual f32 getAnimationSpeed() const { return FramesPerSecond; } //! Gets the frame count of the animated mesh. /** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated. The actual speed is set in the scene node the mesh is instantiated in.*/ virtual void setAnimationSpeed(f32 fps) { FramesPerSecond=fps; } //! returns the animated mesh based on a detail level. 0 is the //! lowest, 255 the highest detail. Note, that some Meshes will //! ignore the detail level. virtual IMesh* getMesh(s32 frameInMs, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1); //! Returns an axis aligned bounding box of the mesh. //! \return A bounding box of this mesh is returned. virtual const core::aabbox3d& getBoundingBox() const; virtual void setBoundingBox( const core::aabbox3df& box); //! Returns the type of the animated mesh. virtual E_ANIMATED_MESH_TYPE getMeshType() const; //! loads the shader definition virtual void getShader( io::IReadFile* file ); //! loads the shader definition virtual const quake3::IShader * getShader( const c8 * filename, bool fileNameIsValid=true ); //! returns a already loaded Shader virtual const quake3::IShader * getShader( u32 index ) const; //! loads a configuration file virtual void getConfiguration( io::IReadFile* file ); //! get's an interface to the entities virtual quake3::tQ3EntityList & getEntityList(); //! returns the requested brush entity virtual IMesh* getBrushEntityMesh(s32 num) const; //! returns the requested brush entity virtual IMesh* getBrushEntityMesh(quake3::IEntity &ent) const; //Link to held meshes? ... //! returns amount of mesh buffers. virtual u32 getMeshBufferCount() const { return 0; } //! returns pointer to a mesh buffer virtual IMeshBuffer* getMeshBuffer(u32 nr) const { return 0; } //! Returns pointer to a mesh buffer which fits a material /** \param material: material to search for \return Pointer to the mesh buffer or 0 if there is no such mesh buffer. */ virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const { return 0; } virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) { return; } //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) { return; } //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) { return; } private: void constructMesh(); void solveTJunction(); void loadTextures(); scene::SMesh** buildMesh(s32 num); struct STexShader { video::ITexture* Texture; s32 ShaderID; }; core::array< STexShader > Tex; core::array Lightmap; enum eLumps { kEntities = 0, // Stores player/object positions, etc... kShaders = 1, // Stores texture information kPlanes = 2, // Stores the splitting planes kNodes = 3, // Stores the BSP nodes kLeafs = 4, // Stores the leafs of the nodes kLeafFaces = 5, // Stores the leaf's indices into the faces kLeafBrushes = 6, // Stores the leaf's indices into the brushes kModels = 7, // Stores the info of world models kBrushes = 8, // Stores the brushes info (for collision) kBrushSides = 9, // Stores the brush surfaces info kVertices = 10, // Stores the level vertices kMeshVerts = 11, // Stores the model vertices offsets kFogs = 12, // Stores the shader files (blending, anims..) kFaces = 13, // Stores the faces for the level kLightmaps = 14, // Stores the lightmaps for the level kLightGrid = 15, // Stores extra world lighting information kVisData = 16, // Stores PVS and cluster info (visibility) kLightArray = 17, // RBSP kMaxLumps // A constant to store the number of lumps }; enum eBspSurfaceType { BSP_MST_BAD, BSP_MST_PLANAR, BSP_MST_PATCH, BSP_MST_TRIANGLE_SOUP, BSP_MST_FLARE, BSP_MST_FOLIAGE }; struct tBSPHeader { s32 strID; // This should always be 'IBSP' s32 version; // This should be 0x2e for Quake 3 files }; tBSPHeader header; struct tBSPLump { s32 offset; s32 length; }; struct tBSPVertex { f32 vPosition[3]; // (x, y, z) position. f32 vTextureCoord[2]; // (u, v) texture coordinate f32 vLightmapCoord[2]; // (u, v) lightmap coordinate f32 vNormal[3]; // (x, y, z) normal vector u8 color[4]; // RGBA color for the vertex }; struct tBSPFace { s32 textureID; // The index into the texture array s32 fogNum; // The index for the effects (or -1 = n/a) s32 type; // 1=polygon, 2=patch, 3=mesh, 4=billboard s32 vertexIndex; // The index into this face's first vertex s32 numOfVerts; // The number of vertices for this face s32 meshVertIndex; // The index into the first meshvertex s32 numMeshVerts; // The number of mesh vertices s32 lightmapID; // The texture index for the lightmap s32 lMapCorner[2]; // The face's lightmap corner in the image s32 lMapSize[2]; // The size of the lightmap section f32 lMapPos[3]; // The 3D origin of lightmap. f32 lMapBitsets[2][3]; // The 3D space for s and t unit vectors. f32 vNormal[3]; // The face normal. s32 size[2]; // The bezier patch dimensions. }; struct tBSPTexture { c8 strName[64]; // The name of the texture w/o the extension u32 flags; // The surface flags (unknown) u32 contents; // The content flags (unknown) }; struct tBSPLightmap { u8 imageBits[128][128][3]; // The RGB data in a 128x128 image }; struct tBSPNode { s32 plane; // The index into the planes array s32 front; // The child index for the front node s32 back; // The child index for the back node s32 mins[3]; // The bounding box min position. s32 maxs[3]; // The bounding box max position. }; struct tBSPLeaf { s32 cluster; // The visibility cluster s32 area; // The area portal s32 mins[3]; // The bounding box min position s32 maxs[3]; // The bounding box max position s32 leafface; // The first index into the face array s32 numOfLeafFaces; // The number of faces for this leaf s32 leafBrush; // The first index for into the brushes s32 numOfLeafBrushes; // The number of brushes for this leaf }; struct tBSPPlane { f32 vNormal[3]; // Plane normal. f32 d; // The plane distance from origin }; struct tBSPVisData { s32 numOfClusters; // The number of clusters s32 bytesPerCluster; // Bytes (8 bits) in the cluster's bitset c8 *pBitsets; // Array of bytes holding the cluster vis. }; struct tBSPBrush { s32 brushSide; // The starting brush side for the brush s32 numOfBrushSides; // Number of brush sides for the brush s32 textureID; // The texture index for the brush }; struct tBSPBrushSide { s32 plane; // The plane index s32 textureID; // The texture index }; struct tBSPModel { f32 min[3]; // The min position for the bounding box f32 max[3]; // The max position for the bounding box. s32 faceIndex; // The first face index in the model s32 numOfFaces; // The number of faces in the model s32 brushIndex; // The first brush index in the model s32 numOfBrushes; // The number brushes for the model }; struct tBSPFog { c8 shader[64]; // The name of the shader file s32 brushIndex; // The brush index for this shader s32 visibleSide; // the brush side that ray tests need to clip against (-1 == none }; core::array < STexShader > FogMap; struct tBSPLights { u8 ambient[3]; // This is the ambient color in RGB u8 directional[3]; // This is the directional color in RGB u8 direction[2]; // The direction of the light: [phi,theta] }; void loadTextures (tBSPLump* l, io::IReadFile* file); // Load the textures void loadLightmaps (tBSPLump* l, io::IReadFile* file); // Load the lightmaps void loadVerts (tBSPLump* l, io::IReadFile* file); // Load the vertices void loadFaces (tBSPLump* l, io::IReadFile* file); // Load the faces void loadPlanes (tBSPLump* l, io::IReadFile* file); // Load the Planes of the BSP void loadNodes (tBSPLump* l, io::IReadFile* file); // load the Nodes of the BSP void loadLeafs (tBSPLump* l, io::IReadFile* file); // load the Leafs of the BSP void loadLeafFaces (tBSPLump* l, io::IReadFile* file); // load the Faces of the Leafs of the BSP void loadVisData (tBSPLump* l, io::IReadFile* file); // load the visibility data of the clusters void loadEntities (tBSPLump* l, io::IReadFile* file); // load the entities void loadModels (tBSPLump* l, io::IReadFile* file); // load the models void loadMeshVerts (tBSPLump* l, io::IReadFile* file); // load the mesh vertices void loadBrushes (tBSPLump* l, io::IReadFile* file); // load the brushes of the BSP void loadBrushSides (tBSPLump* l, io::IReadFile* file); // load the brushsides of the BSP void loadLeafBrushes(tBSPLump* l, io::IReadFile* file); // load the brushes of the leaf void loadFogs (tBSPLump* l, io::IReadFile* file); // load the shaders //bi-quadratic bezier patches void createCurvedSurface_bezier(SMeshBufferLightMap* meshBuffer, s32 faceIndex, s32 patchTesselation, s32 storevertexcolor); void createCurvedSurface_nosubdivision(SMeshBufferLightMap* meshBuffer, s32 faceIndex, s32 patchTesselation, s32 storevertexcolor); struct S3DVertex2TCoords_64 { core::vector3d Pos; core::vector3d Normal; video::SColorf Color; core::vector2d TCoords; core::vector2d TCoords2; void copy( video::S3DVertex2TCoords &dest ) const; S3DVertex2TCoords_64() {} S3DVertex2TCoords_64(const core::vector3d& pos, const core::vector3d& normal, const video::SColorf& color, const core::vector2d& tcoords, const core::vector2d& tcoords2) : Pos(pos), Normal(normal), Color(color), TCoords(tcoords), TCoords2(tcoords2) {} S3DVertex2TCoords_64 getInterpolated_quadratic(const S3DVertex2TCoords_64& v2, const S3DVertex2TCoords_64& v3, const f64 d) const { return S3DVertex2TCoords_64 ( Pos.getInterpolated_quadratic ( v2.Pos, v3.Pos, d ), Normal.getInterpolated_quadratic ( v2.Normal, v3.Normal, d ), Color.getInterpolated_quadratic ( v2.Color, v3.Color, (f32) d ), TCoords.getInterpolated_quadratic ( v2.TCoords, v3.TCoords, d ), TCoords2.getInterpolated_quadratic ( v2.TCoords2, v3.TCoords2, d )); } }; inline void copy( video::S3DVertex2TCoords * dest, const tBSPVertex * source, s32 vertexcolor ) const; void copy( S3DVertex2TCoords_64 * dest, const tBSPVertex * source, s32 vertexcolor ) const; struct SBezier { SMeshBufferLightMap *Patch; S3DVertex2TCoords_64 control[9]; void tesselate(s32 level); private: s32 Level; core::array column[3]; }; SBezier Bezier; quake3::Q3LevelLoadParameter LoadParam; tBSPLump Lumps[kMaxLumps]; tBSPTexture* Textures; s32 NumTextures; tBSPLightmap* LightMaps; s32 NumLightMaps; tBSPVertex* Vertices; s32 NumVertices; tBSPFace* Faces; s32 NumFaces; tBSPModel* Models; s32 NumModels; tBSPPlane* Planes; s32 NumPlanes; tBSPNode* Nodes; s32 NumNodes; tBSPLeaf* Leafs; s32 NumLeafs; s32 *LeafFaces; s32 NumLeafFaces; s32 *MeshVerts; // The vertex offsets for a mesh s32 NumMeshVerts; tBSPBrush* Brushes; s32 NumBrushes; scene::SMesh** BrushEntities; scene::SMesh* Mesh[quake3::E_Q3_MESH_SIZE]; video::IVideoDriver* Driver; core::stringc LevelName; io::IFileSystem* FileSystem; // needs because there are no file extenstions stored in .bsp files. // Additional content scene::ISceneManager* SceneManager; enum eToken { Q3_TOKEN_UNRESOLVED = 0, Q3_TOKEN_EOF = 1, Q3_TOKEN_START_LIST, Q3_TOKEN_END_LIST, Q3_TOKEN_ENTITY, Q3_TOKEN_TOKEN, Q3_TOKEN_EOL, Q3_TOKEN_COMMENT, Q3_TOKEN_MATH_DIVIDE, Q3_TOKEN_MATH_ADD, Q3_TOKEN_MATH_MULTIPY }; struct SQ3Parser { const c8 *source; u32 sourcesize; u32 index; core::stringc token; eToken tokenresult; }; SQ3Parser Parser; typedef void( CQ3LevelMesh::*tParserCallback ) ( quake3::SVarGroupList *& groupList, eToken token ); void parser_parse( const void * data, u32 size, tParserCallback callback ); void parser_nextToken(); void dumpVarGroup( const quake3::SVarGroup * group, s32 stack ) const; void scriptcallback_entity( quake3::SVarGroupList *& grouplist, eToken token ); void scriptcallback_shader( quake3::SVarGroupList *& grouplist, eToken token ); void scriptcallback_config( quake3::SVarGroupList *& grouplist, eToken token ); core::array < quake3::IShader > Shader; core::array < quake3::IShader > Entity; //quake3::tQ3EntityList Entity; quake3::tStringList ShaderFile; void InitShader(); void ReleaseShader(); void ReleaseEntity(); s32 setShaderMaterial( video::SMaterial & material, const tBSPFace * face ) const; s32 setShaderFogMaterial( video::SMaterial &material, const tBSPFace * face ) const; struct SToBuffer { s32 takeVertexColor; u32 index; }; void cleanMeshes(); void cleanMesh(SMesh *m, const bool texture0important = false); void cleanLoader (); void calcBoundingBoxes(); c8 buf[128]; f32 FramesPerSecond; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CQ3LevelMesh.cpp0000644000000000000000000014333012574354552020040 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ #include "CQ3LevelMesh.h" #include "ISceneManager.h" #include "os.h" #include "SMeshBufferLightMap.h" #include "irrString.h" #include "ILightSceneNode.h" #include "IQ3Shader.h" #include "IFileList.h" //#define TJUNCTION_SOLVER_ROUND //#define TJUNCTION_SOLVER_0125 namespace irr { namespace scene { using namespace quake3; //! constructor CQ3LevelMesh::CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr, const Q3LevelLoadParameter &loadParam) : LoadParam(loadParam), Textures(0), NumTextures(0), LightMaps(0), NumLightMaps(0), Vertices(0), NumVertices(0), Faces(0), NumFaces(0), Models(0), NumModels(0), Planes(0), NumPlanes(0), Nodes(0), NumNodes(0), Leafs(0), NumLeafs(0), LeafFaces(0), NumLeafFaces(0), MeshVerts(0), NumMeshVerts(0), Brushes(0), NumBrushes(0), BrushEntities(0), FileSystem(fs), SceneManager(smgr), FramesPerSecond(25.f) { #ifdef _DEBUG IReferenceCounted::setDebugName("CQ3LevelMesh"); #endif for ( s32 i = 0; i!= E_Q3_MESH_SIZE; ++i ) { Mesh[i] = 0; } Driver = smgr ? smgr->getVideoDriver() : 0; if (Driver) Driver->grab(); if (FileSystem) FileSystem->grab(); // load default shaders InitShader(); } //! destructor CQ3LevelMesh::~CQ3LevelMesh() { cleanLoader (); if (Driver) Driver->drop(); if (FileSystem) FileSystem->drop(); s32 i; for ( i = 0; i!= E_Q3_MESH_SIZE; ++i ) { if ( Mesh[i] ) { Mesh[i]->drop(); Mesh[i] = 0; } } for ( i = 1; i < NumModels; i++ ) { BrushEntities[i]->drop(); } delete [] BrushEntities; BrushEntities = 0; ReleaseShader(); ReleaseEntity(); } //! loads a level from a .bsp-File. Also tries to load all needed textures. Returns true if successful. bool CQ3LevelMesh::loadFile(io::IReadFile* file) { if (!file) return false; LevelName = file->getFileName(); file->read(&header, sizeof(tBSPHeader)); #ifdef __BIG_ENDIAN__ header.strID = os::Byteswap::byteswap(header.strID); header.version = os::Byteswap::byteswap(header.version); #endif if ( (header.strID != 0x50534249 || // IBSP ( header.version != 0x2e // quake3 && header.version != 0x2f // rtcw ) ) && ( header.strID != 0x50534252 || header.version != 1 ) // RBSP, starwars jedi, sof ) { os::Printer::log("Could not load .bsp file, unknown header.", file->getFileName(), ELL_ERROR); return false; } #if 0 if ( header.strID == 0x50534252 ) // RBSP Raven { LoadParam.swapHeader = 1; } #endif // now read lumps file->read(&Lumps[0], sizeof(tBSPLump)*kMaxLumps); s32 i; if ( LoadParam.swapHeader ) { for ( i=0; i< kMaxLumps;++i) { Lumps[i].offset = os::Byteswap::byteswap(Lumps[i].offset); Lumps[i].length = os::Byteswap::byteswap(Lumps[i].length); } } ReleaseEntity(); // load everything loadEntities(&Lumps[kEntities], file); // load the entities loadTextures(&Lumps[kShaders], file); // Load the textures loadLightmaps(&Lumps[kLightmaps], file); // Load the lightmaps loadVerts(&Lumps[kVertices], file); // Load the vertices loadFaces(&Lumps[kFaces], file); // Load the faces loadPlanes(&Lumps[kPlanes], file); // Load the Planes of the BSP loadNodes(&Lumps[kNodes], file); // load the Nodes of the BSP loadLeafs(&Lumps[kLeafs], file); // load the Leafs of the BSP loadLeafFaces(&Lumps[kLeafFaces], file); // load the Faces of the Leafs of the BSP loadVisData(&Lumps[kVisData], file); // load the visibility data of the clusters loadModels(&Lumps[kModels], file); // load the models loadMeshVerts(&Lumps[kMeshVerts], file); // load the mesh vertices loadBrushes(&Lumps[kBrushes], file); // load the brushes of the BSP loadBrushSides(&Lumps[kBrushSides], file); // load the brushsides of the BSP loadLeafBrushes(&Lumps[kLeafBrushes], file); // load the brushes of the leaf loadFogs(&Lumps[kFogs], file ); // load the fogs loadTextures(); constructMesh(); solveTJunction(); cleanMeshes(); calcBoundingBoxes(); cleanLoader(); return true; } /*! */ void CQ3LevelMesh::cleanLoader () { delete [] Textures; Textures = 0; delete [] LightMaps; LightMaps = 0; delete [] Vertices; Vertices = 0; delete [] Faces; Faces = 0; delete [] Models; Models = 0; delete [] Planes; Planes = 0; delete [] Nodes; Nodes = 0; delete [] Leafs; Leafs = 0; delete [] LeafFaces; LeafFaces = 0; delete [] MeshVerts; MeshVerts = 0; delete [] Brushes; Brushes = 0; Lightmap.clear(); Tex.clear(); } //! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. u32 CQ3LevelMesh::getFrameCount() const { return 1; } //! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level. IMesh* CQ3LevelMesh::getMesh(s32 frameInMs, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) { return Mesh[frameInMs]; } void CQ3LevelMesh::loadTextures(tBSPLump* l, io::IReadFile* file) { NumTextures = l->length / sizeof(tBSPTexture); if ( !NumTextures ) return; Textures = new tBSPTexture[NumTextures]; file->seek(l->offset); file->read(Textures, l->length); if ( LoadParam.swapHeader ) { for (s32 i=0;ilength / sizeof(tBSPLightmap); if ( !NumLightMaps ) return; LightMaps = new tBSPLightmap[NumLightMaps]; file->seek(l->offset); file->read(LightMaps, l->length); } /*! */ void CQ3LevelMesh::loadVerts(tBSPLump* l, io::IReadFile* file) { NumVertices = l->length / sizeof(tBSPVertex); if ( !NumVertices ) return; Vertices = new tBSPVertex[NumVertices]; file->seek(l->offset); file->read(Vertices, l->length); if ( LoadParam.swapHeader ) for (s32 i=0;ilength / sizeof(tBSPFace); if (!NumFaces) return; Faces = new tBSPFace[NumFaces]; file->seek(l->offset); file->read(Faces, l->length); if ( LoadParam.swapHeader ) { for ( s32 i=0;i entity; entity.set_used( l->length + 2 ); entity[l->length + 1 ] = 0; file->seek(l->offset); file->read( entity.pointer(), l->length); parser_parse( entity.pointer(), l->length, &CQ3LevelMesh::scriptcallback_entity ); } /*! load fog brushes */ void CQ3LevelMesh::loadFogs(tBSPLump* l, io::IReadFile* file) { u32 files = l->length / sizeof(tBSPFog); file->seek( l->offset ); tBSPFog fog; const IShader *shader; STexShader t; for ( u32 i = 0; i!= files; ++i ) { file->read( &fog, sizeof( fog ) ); shader = getShader( fog.shader ); t.Texture = 0; t.ShaderID = shader ? shader->ID : -1; FogMap.push_back ( t ); } } /*! load models named in bsp */ void CQ3LevelMesh::loadModels(tBSPLump* l, io::IReadFile* file) { NumModels = l->length / sizeof(tBSPModel); Models = new tBSPModel[NumModels]; file->seek( l->offset ); file->read(Models, l->length); if ( LoadParam.swapHeader ) { for ( s32 i = 0; i < NumModels; i++) { Models[i].min[0] = os::Byteswap::byteswap(Models[i].min[0]); Models[i].min[1] = os::Byteswap::byteswap(Models[i].min[1]); Models[i].min[2] = os::Byteswap::byteswap(Models[i].min[2]); Models[i].max[0] = os::Byteswap::byteswap(Models[i].max[0]); Models[i].max[1] = os::Byteswap::byteswap(Models[i].max[1]); Models[i].max[2] = os::Byteswap::byteswap(Models[i].max[2]); Models[i].faceIndex = os::Byteswap::byteswap(Models[i].faceIndex); Models[i].numOfFaces = os::Byteswap::byteswap(Models[i].numOfFaces); Models[i].brushIndex = os::Byteswap::byteswap(Models[i].brushIndex); Models[i].numOfBrushes = os::Byteswap::byteswap(Models[i].numOfBrushes); } } BrushEntities = new SMesh*[NumModels]; } /*! */ void CQ3LevelMesh::loadMeshVerts(tBSPLump* l, io::IReadFile* file) { NumMeshVerts = l->length / sizeof(s32); if (!NumMeshVerts) return; MeshVerts = new s32[NumMeshVerts]; file->seek(l->offset); file->read(MeshVerts, l->length); if ( LoadParam.swapHeader ) { for (int i=0;i= 'a' && symbol <= 'z' ) || (symbol >= 'A' && symbol <= 'Z' ) || (symbol >= '0' && symbol <= '9' ) || (symbol == '/' || symbol == '_' || symbol == '.' ); } /*! */ void CQ3LevelMesh::parser_nextToken() { u8 symbol; Parser.token = ""; Parser.tokenresult = Q3_TOKEN_UNRESOLVED; // skip white space do { if ( Parser.index >= Parser.sourcesize ) { Parser.tokenresult = Q3_TOKEN_EOF; return; } symbol = Parser.source [ Parser.index ]; Parser.index += 1; } while ( isQ3WhiteSpace( symbol ) ); // first symbol, one symbol switch ( symbol ) { case 0: Parser.tokenresult = Q3_TOKEN_EOF; return; case '/': // comment or divide if ( Parser.index >= Parser.sourcesize ) { Parser.tokenresult = Q3_TOKEN_EOF; return; } symbol = Parser.source [ Parser.index ]; Parser.index += 1; if ( isQ3WhiteSpace( symbol ) ) { Parser.tokenresult = Q3_TOKEN_MATH_DIVIDE; return; } else if ( symbol == '*' ) { // C-style comment in quake? } else if ( symbol == '/' ) { // skip to eol do { if ( Parser.index >= Parser.sourcesize ) { Parser.tokenresult = Q3_TOKEN_EOF; return; } symbol = Parser.source [ Parser.index ]; Parser.index += 1; } while ( symbol != '\n' ); Parser.tokenresult = Q3_TOKEN_COMMENT; return; } // take /[name] as valid token..?!?!?. mhmm, maybe break; case '\n': Parser.tokenresult = Q3_TOKEN_EOL; return; case '{': Parser.tokenresult = Q3_TOKEN_START_LIST; return; case '}': Parser.tokenresult = Q3_TOKEN_END_LIST; return; case '"': // string literal do { if ( Parser.index >= Parser.sourcesize ) { Parser.tokenresult = Q3_TOKEN_EOF; return; } symbol = Parser.source [ Parser.index ]; Parser.index += 1; if ( symbol != '"' ) Parser.token.append( symbol ); } while ( symbol != '"' ); Parser.tokenresult = Q3_TOKEN_ENTITY; return; } // user identity Parser.token.append( symbol ); // continue till whitespace bool validName = true; do { if ( Parser.index >= Parser.sourcesize ) { Parser.tokenresult = Q3_TOKEN_EOF; return; } symbol = Parser.source [ Parser.index ]; validName = isQ3ValidName( symbol ); if ( validName ) { Parser.token.append( symbol ); Parser.index += 1; } } while ( validName ); Parser.tokenresult = Q3_TOKEN_TOKEN; return; } /* parse entity & shader calls callback on content in {} */ void CQ3LevelMesh::parser_parse( const void * data, const u32 size, CQ3LevelMesh::tParserCallback callback ) { Parser.source = static_cast(data); Parser.sourcesize = size; Parser.index = 0; SVarGroupList *groupList; s32 active; s32 last; SVariable entity ( "" ); groupList = new SVarGroupList(); groupList->VariableGroup.push_back( SVarGroup() ); active = last = 0; do { parser_nextToken(); switch ( Parser.tokenresult ) { case Q3_TOKEN_START_LIST: { //stack = core::min_( stack + 1, 7 ); groupList->VariableGroup.push_back( SVarGroup() ); last = active; active = groupList->VariableGroup.size() - 1; entity.clear(); } break; // a unregisterd variable is finished case Q3_TOKEN_EOL: { if ( entity.isValid() ) { groupList->VariableGroup[active].Variable.push_back( entity ); entity.clear(); } } break; case Q3_TOKEN_TOKEN: case Q3_TOKEN_ENTITY: { Parser.token.make_lower(); // store content based on line-delemiter if ( 0 == entity.isValid() ) { entity.name = Parser.token; entity.content = ""; } else { if ( entity.content.size() ) { entity.content += " "; } entity.content += Parser.token; } } break; case Q3_TOKEN_END_LIST: { //stack = core::max_( stack - 1, 0 ); // close tag for first if ( active == 1 ) { (this->*callback)( groupList, Q3_TOKEN_END_LIST ); // new group groupList->drop(); groupList = new SVarGroupList(); groupList->VariableGroup.push_back( SVarGroup() ); last = 0; } active = last; entity.clear(); } break; default: break; } } while ( Parser.tokenresult != Q3_TOKEN_EOF ); (this->*callback)( groupList, Q3_TOKEN_EOF ); groupList->drop(); } /* this loader applies only textures for stage 1 & 2 */ s32 CQ3LevelMesh::setShaderFogMaterial( video::SMaterial &material, const tBSPFace * face ) const { material.MaterialType = video::EMT_SOLID; material.Wireframe = false; material.Lighting = false; material.BackfaceCulling = false; material.setTexture(0, 0); material.setTexture(1, 0); material.setTexture(2, 0); material.setTexture(3, 0); material.ZBuffer = video::ECFN_LESSEQUAL; material.ZWriteEnable = false; material.MaterialTypeParam = 0.f; s32 shaderState = -1; if ( (u32) face->fogNum < FogMap.size() ) { material.setTexture(0, FogMap [ face->fogNum ].Texture); shaderState = FogMap [ face->fogNum ].ShaderID; } return shaderState; } /* this loader applies only textures for stage 1 & 2 */ s32 CQ3LevelMesh::setShaderMaterial( video::SMaterial &material, const tBSPFace * face ) const { material.MaterialType = video::EMT_SOLID; material.Wireframe = false; material.Lighting = false; material.BackfaceCulling = true; material.setTexture(0, 0); material.setTexture(1, 0); material.setTexture(2, 0); material.setTexture(3, 0); material.ZBuffer = video::ECFN_LESSEQUAL; material.ZWriteEnable = true; material.MaterialTypeParam = 0.f; s32 shaderState = -1; if ( face->textureID >= 0 && face->textureID < (s32)Tex.size() ) { material.setTexture(0, Tex [ face->textureID ].Texture); shaderState = Tex [ face->textureID ].ShaderID; } if ( face->lightmapID >= 0 && face->lightmapID < (s32)Lightmap.size() ) { material.setTexture(1, Lightmap [ face->lightmapID ]); material.MaterialType = LoadParam.defaultLightMapMaterial; } // store shader ID material.MaterialTypeParam2 = (f32) shaderState; const IShader *shader = getShader(shaderState); if ( 0 == shader ) return shaderState; return shaderState; #if 0 const SVarGroup *group; // generic group = shader->getGroup( 1 ); if ( group ) { material.BackfaceCulling = getCullingFunction( group->get( "cull" ) ); if ( group->isDefined( "surfaceparm", "nolightmap" ) ) { material.MaterialType = video::EMT_SOLID; material.setTexture(1, 0); } } // try to get the best of the 8 texture stages.. // texture 1, texture 2 u32 startPos; for ( s32 g = 2; g <= 3; ++g ) { group = shader->getGroup( g ); if ( 0 == group ) continue; startPos = 0; if ( group->isDefined( "depthwrite" ) ) { material.ZWriteEnable = true; } SBlendFunc blendfunc ( LoadParam.defaultModulate ); getBlendFunc( group->get( "blendfunc" ), blendfunc ); getBlendFunc( group->get( "alphafunc" ), blendfunc ); if ( 0 == LoadParam.alpharef && ( blendfunc.type == video::EMT_TRANSPARENT_ALPHA_CHANNEL || blendfunc.type == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF ) ) { blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; blendfunc.param0 = 0.f; } material.MaterialType = blendfunc.type; material.MaterialTypeParam = blendfunc.param0; // try if we can match better shaderState |= (material.MaterialType == video::EMT_SOLID ) ? 0x00020000 : 0; } //material.BackfaceCulling = false; if ( shader->VarGroup->VariableGroup.size() <= 4 ) { shaderState |= 0x00010000; } material.MaterialTypeParam2 = (f32) shaderState; return shaderState; #endif } /*! Internal function to build a mesh. */ scene::SMesh** CQ3LevelMesh::buildMesh(s32 num) { scene::SMesh** newmesh = new SMesh *[quake3::E_Q3_MESH_SIZE]; s32 i, j, k,s; for (i = 0; i < E_Q3_MESH_SIZE; i++) { newmesh[i] = new SMesh(); } s32 *index; video::S3DVertex2TCoords temp[3]; video::SMaterial material; video::SMaterial material2; SToBuffer item [ E_Q3_MESH_SIZE ]; u32 itemSize; for (i = Models[num].faceIndex; i < Models[num].numOfFaces + Models[num].faceIndex; ++i) { const tBSPFace * face = Faces + i; s32 shaderState = setShaderMaterial( material, face ); itemSize = 0; const IShader *shader = getShader(shaderState); if ( face->fogNum >= 0 ) { setShaderFogMaterial ( material2, face ); item[itemSize].index = E_Q3_MESH_FOG; item[itemSize].takeVertexColor = 1; itemSize += 1; } switch( face->type ) { case 1: // normal polygons case 2: // patches case 3: // meshes if ( 0 == shader ) { if ( LoadParam.cleanUnResolvedMeshes || material.getTexture(0) ) { item[itemSize].takeVertexColor = 1; item[itemSize].index = E_Q3_MESH_GEOMETRY; itemSize += 1; } else { item[itemSize].takeVertexColor = 1; item[itemSize].index = E_Q3_MESH_UNRESOLVED; itemSize += 1; } } else { item[itemSize].takeVertexColor = 1; item[itemSize].index = E_Q3_MESH_ITEMS; itemSize += 1; } break; case 4: // billboards //item[itemSize].takeVertexColor = 1; //item[itemSize].index = E_Q3_MESH_ITEMS; //itemSize += 1; break; } for ( u32 g = 0; g != itemSize; ++g ) { scene::SMeshBufferLightMap* buffer = 0; if ( item[g].index == E_Q3_MESH_GEOMETRY ) { if ( 0 == item[g].takeVertexColor ) { item[g].takeVertexColor = material.getTexture(0) == 0 || material.getTexture(1) == 0; } if (Faces[i].lightmapID < -1 || Faces[i].lightmapID > NumLightMaps-1) { Faces[i].lightmapID = -1; } #if 0 // there are lightmapsids and textureid with -1 const s32 tmp_index = ((Faces[i].lightmapID+1) * (NumTextures+1)) + (Faces[i].textureID+1); buffer = (SMeshBufferLightMap*) newmesh[E_Q3_MESH_GEOMETRY]->getMeshBuffer(tmp_index); buffer->setHardwareMappingHint ( EHM_STATIC ); buffer->getMaterial() = material; #endif } // Construct a unique mesh for each shader or combine meshbuffers for same shader if ( 0 == buffer ) { if ( LoadParam.mergeShaderBuffer == 1 ) { // combine buffer = (SMeshBufferLightMap*) newmesh[ item[g].index ]->getMeshBuffer( item[g].index != E_Q3_MESH_FOG ? material : material2 ); } // create a seperate mesh buffer if ( 0 == buffer ) { buffer = new scene::SMeshBufferLightMap(); newmesh[ item[g].index ]->addMeshBuffer( buffer ); buffer->drop(); buffer->getMaterial() = item[g].index != E_Q3_MESH_FOG ? material : material2; if ( item[g].index == E_Q3_MESH_GEOMETRY ) buffer->setHardwareMappingHint ( EHM_STATIC ); } } switch(Faces[i].type) { case 4: // billboards break; case 2: // patches createCurvedSurface_bezier( buffer, i, LoadParam.patchTesselation, item[g].takeVertexColor ); break; case 1: // normal polygons case 3: // mesh vertices index = MeshVerts + face->meshVertIndex; k = buffer->getVertexCount(); // reallocate better if many small meshes are used s = buffer->getIndexCount()+face->numMeshVerts; if ( buffer->Indices.allocated_size () < (u32) s ) { if ( buffer->Indices.allocated_size () > 0 && face->numMeshVerts < 20 && NumFaces > 1000 ) { s = buffer->getIndexCount() + (NumFaces >> 3 * face->numMeshVerts ); } buffer->Indices.reallocate( s); } for ( j = 0; j < face->numMeshVerts; ++j ) { buffer->Indices.push_back( k + index [j] ); } s = k+face->numOfVerts; if ( buffer->Vertices.allocated_size () < (u32) s ) { if ( buffer->Indices.allocated_size () > 0 && face->numOfVerts < 20 && NumFaces > 1000 ) { s = buffer->getIndexCount() + (NumFaces >> 3 * face->numOfVerts ); } buffer->Vertices.reallocate( s); } for ( j = 0; j != face->numOfVerts; ++j ) { copy( &temp[0], &Vertices[ j + face->vertexIndex ], item[g].takeVertexColor ); buffer->Vertices.push_back( temp[0] ); } break; } // end switch } } return newmesh; } /*! */ void CQ3LevelMesh::solveTJunction() { } /*! constructs a mesh from the quake 3 level file. */ void CQ3LevelMesh::constructMesh() { if ( LoadParam.verbose > 0 ) { LoadParam.startTime = os::Timer::getRealTime(); if ( LoadParam.verbose > 1 ) { snprintf( buf, sizeof ( buf ), "quake3::constructMesh start to create %d faces, %d vertices,%d mesh vertices", NumFaces, NumVertices, NumMeshVerts ); os::Printer::log(buf, ELL_INFORMATION); } } s32 i, j; // First the main level SMesh **tmp = buildMesh(0); for (i = 0; i < E_Q3_MESH_SIZE; i++) { Mesh[i] = tmp[i]; } delete [] tmp; // Then the brush entities for (i = 1; i < NumModels; i++) { tmp = buildMesh(i); BrushEntities[i] = tmp[0]; // We only care about the main geometry here for (j = 1; j < E_Q3_MESH_SIZE; j++) { tmp[j]->drop(); } delete [] tmp; } if ( LoadParam.verbose > 0 ) { LoadParam.endTime = os::Timer::getRealTime(); snprintf( buf, sizeof ( buf ), "quake3::constructMesh needed %04d ms to create %d faces, %d vertices,%d mesh vertices", LoadParam.endTime - LoadParam.startTime, NumFaces, NumVertices, NumMeshVerts ); os::Printer::log(buf, ELL_INFORMATION); } } void CQ3LevelMesh::S3DVertex2TCoords_64::copy( video::S3DVertex2TCoords &dest ) const { #if defined (TJUNCTION_SOLVER_ROUND) dest.Pos.X = core::round_( (f32) Pos.X ); dest.Pos.Y = core::round_( (f32) Pos.Y ); dest.Pos.Z = core::round_( (f32) Pos.Z ); #elif defined (TJUNCTION_SOLVER_0125) dest.Pos.X = (f32) ( floor ( Pos.X * 8.f + 0.5 ) * 0.125 ); dest.Pos.Y = (f32) ( floor ( Pos.Y * 8.f + 0.5 ) * 0.125 ); dest.Pos.Z = (f32) ( floor ( Pos.Z * 8.f + 0.5 ) * 0.125 ); #else dest.Pos.X = (f32) Pos.X; dest.Pos.Y = (f32) Pos.Y; dest.Pos.Z = (f32) Pos.Z; #endif dest.Normal.X = (f32) Normal.X; dest.Normal.Y = (f32) Normal.Y; dest.Normal.Z = (f32) Normal.Z; dest.Normal.normalize(); dest.Color = Color.toSColor(); dest.TCoords.X = (f32) TCoords.X; dest.TCoords.Y = (f32) TCoords.Y; dest.TCoords2.X = (f32) TCoords2.X; dest.TCoords2.Y = (f32) TCoords2.Y; } void CQ3LevelMesh::copy( S3DVertex2TCoords_64 * dest, const tBSPVertex * source, s32 vertexcolor ) const { #if defined (TJUNCTION_SOLVER_ROUND) dest->Pos.X = core::round_( source->vPosition[0] ); dest->Pos.Y = core::round_( source->vPosition[2] ); dest->Pos.Z = core::round_( source->vPosition[1] ); #elif defined (TJUNCTION_SOLVER_0125) dest->Pos.X = (f32) ( floor ( source->vPosition[0] * 8.f + 0.5 ) * 0.125 ); dest->Pos.Y = (f32) ( floor ( source->vPosition[2] * 8.f + 0.5 ) * 0.125 ); dest->Pos.Z = (f32) ( floor ( source->vPosition[1] * 8.f + 0.5 ) * 0.125 ); #else dest->Pos.X = source->vPosition[0]; dest->Pos.Y = source->vPosition[2]; dest->Pos.Z = source->vPosition[1]; #endif dest->Normal.X = source->vNormal[0]; dest->Normal.Y = source->vNormal[2]; dest->Normal.Z = source->vNormal[1]; dest->Normal.normalize(); dest->TCoords.X = source->vTextureCoord[0]; dest->TCoords.Y = source->vTextureCoord[1]; dest->TCoords2.X = source->vLightmapCoord[0]; dest->TCoords2.Y = source->vLightmapCoord[1]; if ( vertexcolor ) { //u32 a = core::s32_min( source->color[3] * LoadParam.defaultModulate, 255 ); u32 a = source->color[3]; u32 r = core::s32_min( source->color[0] * LoadParam.defaultModulate, 255 ); u32 g = core::s32_min( source->color[1] * LoadParam.defaultModulate, 255 ); u32 b = core::s32_min( source->color[2] * LoadParam.defaultModulate, 255 ); dest->Color.set(a * 1.f/255.f, r * 1.f/255.f, g * 1.f/255.f, b * 1.f/255.f); } else { dest->Color.set( 1.f, 1.f, 1.f, 1.f ); } } inline void CQ3LevelMesh::copy( video::S3DVertex2TCoords * dest, const tBSPVertex * source, s32 vertexcolor ) const { #if defined (TJUNCTION_SOLVER_ROUND) dest->Pos.X = core::round_( source->vPosition[0] ); dest->Pos.Y = core::round_( source->vPosition[2] ); dest->Pos.Z = core::round_( source->vPosition[1] ); #elif defined (TJUNCTION_SOLVER_0125) dest->Pos.X = (f32) ( floor ( source->vPosition[0] * 8.f + 0.5 ) * 0.125 ); dest->Pos.Y = (f32) ( floor ( source->vPosition[2] * 8.f + 0.5 ) * 0.125 ); dest->Pos.Z = (f32) ( floor ( source->vPosition[1] * 8.f + 0.5 ) * 0.125 ); #else dest->Pos.X = source->vPosition[0]; dest->Pos.Y = source->vPosition[2]; dest->Pos.Z = source->vPosition[1]; #endif dest->Normal.X = source->vNormal[0]; dest->Normal.Y = source->vNormal[2]; dest->Normal.Z = source->vNormal[1]; dest->Normal.normalize(); dest->TCoords.X = source->vTextureCoord[0]; dest->TCoords.Y = source->vTextureCoord[1]; dest->TCoords2.X = source->vLightmapCoord[0]; dest->TCoords2.Y = source->vLightmapCoord[1]; if ( vertexcolor ) { //u32 a = core::s32_min( source->color[3] * LoadParam.defaultModulate, 255 ); u32 a = source->color[3]; u32 r = core::s32_min( source->color[0] * LoadParam.defaultModulate, 255 ); u32 g = core::s32_min( source->color[1] * LoadParam.defaultModulate, 255 ); u32 b = core::s32_min( source->color[2] * LoadParam.defaultModulate, 255 ); dest->Color.set(a << 24 | r << 16 | g << 8 | b); } else { dest->Color.set(0xFFFFFFFF); } } void CQ3LevelMesh::SBezier::tesselate( s32 level ) { //Calculate how many vertices across/down there are s32 j, k; column[0].set_used( level + 1 ); column[1].set_used( level + 1 ); column[2].set_used( level + 1 ); const f64 w = 0.0 + (1.0 / (f64) level ); //Tesselate along the columns for( j = 0; j <= level; ++j) { const f64 f = w * (f64) j; column[0][j] = control[0].getInterpolated_quadratic(control[3], control[6], f ); column[1][j] = control[1].getInterpolated_quadratic(control[4], control[7], f ); column[2][j] = control[2].getInterpolated_quadratic(control[5], control[8], f ); } const u32 idx = Patch->Vertices.size(); Patch->Vertices.reallocate(idx+level*level); //Tesselate across the rows to get final vertices video::S3DVertex2TCoords v; S3DVertex2TCoords_64 f; for( j = 0; j <= level; ++j) { for( k = 0; k <= level; ++k) { f = column[0][j].getInterpolated_quadratic(column[1][j], column[2][j], w * (f64) k); f.copy( v ); Patch->Vertices.push_back( v ); } } Patch->Indices.reallocate(Patch->Indices.size()+6*level*level); // connect for( j = 0; j < level; ++j) { for( k = 0; k < level; ++k) { const s32 inx = idx + ( k * ( level + 1 ) ) + j; Patch->Indices.push_back( inx + 0 ); Patch->Indices.push_back( inx + (level + 1 ) + 0 ); Patch->Indices.push_back( inx + (level + 1 ) + 1 ); Patch->Indices.push_back( inx + 0 ); Patch->Indices.push_back( inx + (level + 1 ) + 1 ); Patch->Indices.push_back( inx + 1 ); } } } /*! no subdivision */ void CQ3LevelMesh::createCurvedSurface_nosubdivision(SMeshBufferLightMap* meshBuffer, s32 faceIndex, s32 patchTesselation, s32 storevertexcolor) { tBSPFace * face = &Faces[faceIndex]; u32 j,k,m; // number of control points across & up const u32 controlWidth = face->size[0]; const u32 controlHeight = face->size[1]; if ( 0 == controlWidth || 0 == controlHeight ) return; video::S3DVertex2TCoords v; m = meshBuffer->Vertices.size(); meshBuffer->Vertices.reallocate(m+controlHeight * controlWidth); for ( j = 0; j!= controlHeight * controlWidth; ++j ) { copy( &v, &Vertices [ face->vertexIndex + j ], storevertexcolor ); meshBuffer->Vertices.push_back( v ); } meshBuffer->Indices.reallocate(meshBuffer->Indices.size()+6*(controlHeight-1) * (controlWidth-1)); for ( j = 0; j!= controlHeight - 1; ++j ) { for ( k = 0; k!= controlWidth - 1; ++k ) { meshBuffer->Indices.push_back( m + k + 0 ); meshBuffer->Indices.push_back( m + k + controlWidth + 0 ); meshBuffer->Indices.push_back( m + k + controlWidth + 1 ); meshBuffer->Indices.push_back( m + k + 0 ); meshBuffer->Indices.push_back( m + k + controlWidth + 1 ); meshBuffer->Indices.push_back( m + k + 1 ); } m += controlWidth; } } /*! */ void CQ3LevelMesh::createCurvedSurface_bezier(SMeshBufferLightMap* meshBuffer, s32 faceIndex, s32 patchTesselation, s32 storevertexcolor) { tBSPFace * face = &Faces[faceIndex]; u32 j,k; // number of control points across & up const u32 controlWidth = face->size[0]; const u32 controlHeight = face->size[1]; if ( 0 == controlWidth || 0 == controlHeight ) return; // number of biquadratic patches const u32 biquadWidth = (controlWidth - 1)/2; const u32 biquadHeight = (controlHeight -1)/2; if ( LoadParam.verbose > 1 ) { LoadParam.startTime = os::Timer::getRealTime(); } // Create space for a temporary array of the patch's control points core::array controlPoint; controlPoint.set_used( controlWidth * controlHeight ); for( j = 0; j < controlPoint.size(); ++j) { copy( &controlPoint[j], &Vertices [ face->vertexIndex + j ], storevertexcolor ); } // create a temporary patch Bezier.Patch = new scene::SMeshBufferLightMap(); //Loop through the biquadratic patches for( j = 0; j < biquadHeight; ++j) { for( k = 0; k < biquadWidth; ++k) { // set up this patch const s32 inx = j*controlWidth*2 + k*2; // setup bezier control points for this patch Bezier.control[0] = controlPoint[ inx + 0]; Bezier.control[1] = controlPoint[ inx + 1]; Bezier.control[2] = controlPoint[ inx + 2]; Bezier.control[3] = controlPoint[ inx + controlWidth + 0 ]; Bezier.control[4] = controlPoint[ inx + controlWidth + 1 ]; Bezier.control[5] = controlPoint[ inx + controlWidth + 2 ]; Bezier.control[6] = controlPoint[ inx + controlWidth * 2 + 0]; Bezier.control[7] = controlPoint[ inx + controlWidth * 2 + 1]; Bezier.control[8] = controlPoint[ inx + controlWidth * 2 + 2]; Bezier.tesselate( patchTesselation ); } } // stitch together with existing geometry // TODO: only border needs to be checked const u32 bsize = Bezier.Patch->getVertexCount(); const u32 msize = meshBuffer->getVertexCount(); /* for ( j = 0; j!= bsize; ++j ) { const core::vector3df &v = Bezier.Patch->Vertices[j].Pos; for ( k = 0; k!= msize; ++k ) { const core::vector3df &m = meshBuffer->Vertices[k].Pos; if ( !v.equals( m, tolerance ) ) continue; meshBuffer->Vertices[k].Pos = v; //Bezier.Patch->Vertices[j].Pos = m; } } */ // add Patch to meshbuffer meshBuffer->Vertices.reallocate(msize+bsize); for ( j = 0; j!= bsize; ++j ) { meshBuffer->Vertices.push_back( Bezier.Patch->Vertices[j] ); } // add indices to meshbuffer meshBuffer->Indices.reallocate(meshBuffer->getIndexCount()+Bezier.Patch->getIndexCount()); for ( j = 0; j!= Bezier.Patch->getIndexCount(); ++j ) { meshBuffer->Indices.push_back( msize + Bezier.Patch->Indices[j] ); } delete Bezier.Patch; if ( LoadParam.verbose > 1 ) { LoadParam.endTime = os::Timer::getRealTime(); snprintf( buf, sizeof ( buf ), "quake3::createCurvedSurface_bezier needed %04d ms to create bezier patch.(%dx%d)", LoadParam.endTime - LoadParam.startTime, biquadWidth, biquadHeight ); os::Printer::log(buf, ELL_INFORMATION); } } /*! Loads entities from file */ void CQ3LevelMesh::getConfiguration( io::IReadFile* file ) { tBSPLump l; l.offset = file->getPos(); l.length = file->getSize (); core::array entity; entity.set_used( l.length + 2 ); entity[l.length + 1 ] = 0; file->seek(l.offset); file->read( entity.pointer(), l.length); parser_parse( entity.pointer(), l.length, &CQ3LevelMesh::scriptcallback_config ); if ( Entity.size () ) Entity.getLast().name = file->getFileName(); } //! get's an interface to the entities tQ3EntityList & CQ3LevelMesh::getEntityList() { // Entity.sort(); return Entity; } //! returns the requested brush entity IMesh* CQ3LevelMesh::getBrushEntityMesh(s32 num) const { if (num < 1 || num >= NumModels) return 0; return BrushEntities[num]; } //! returns the requested brush entity IMesh* CQ3LevelMesh::getBrushEntityMesh(quake3::IEntity &ent) const { // This is a helper function to parse the entity, // so you don't have to. s32 num; const quake3::SVarGroup* group = ent.getGroup(1); const core::stringc& modnum = group->get("model"); if (!group->isDefined("model")) return 0; const char *temp = modnum.c_str() + 1; // We skip the first character. num = core::strtol10(temp); return getBrushEntityMesh(num); } /*! */ const IShader * CQ3LevelMesh::getShader(u32 index) const { index &= 0xFFFF; if ( index < Shader.size() ) { return &Shader[index]; } return 0; } /*! loads the shader definition */ const IShader* CQ3LevelMesh::getShader( const c8 * filename, bool fileNameIsValid ) { core::stringc searchName ( filename ); IShader search; search.name = searchName; search.name.replace( '\\', '/' ); search.name.make_lower(); core::stringc message; s32 index; //! is Shader already in cache? index = Shader.linear_search( search ); if ( index >= 0 ) { if ( LoadParam.verbose > 1 ) { message = searchName + " found " + Shader[index].name; os::Printer::log("quake3:getShader", message.c_str(), ELL_INFORMATION); } return &Shader[index]; } io::path loadFile; if ( !fileNameIsValid ) { // extract the shader name from the last path component in filename // "scripts/[name].shader" core::stringc cut( search.name ); s32 end = cut.findLast( '/' ); s32 start = cut.findLast( '/', end - 1 ); loadFile = LoadParam.scriptDir; loadFile.append( cut.subString( start, end - start ) ); loadFile.append( ".shader" ); } else { loadFile = search.name; } // already loaded the file ? index = ShaderFile.binary_search( loadFile ); if ( index >= 0 ) return 0; // add file to loaded files ShaderFile.push_back( loadFile ); if ( !FileSystem->existFile( loadFile.c_str() ) ) { if ( LoadParam.verbose > 1 ) { message = loadFile + " for " + searchName + " failed "; os::Printer::log("quake3:getShader", message.c_str(), ELL_INFORMATION); } return 0; } if ( LoadParam.verbose ) { message = loadFile + " for " + searchName; os::Printer::log("quake3:getShader Load shader", message.c_str(), ELL_INFORMATION); } io::IReadFile *file = FileSystem->createAndOpenFile( loadFile.c_str() ); if ( file ) { getShader ( file ); file->drop (); } // search again index = Shader.linear_search( search ); return index >= 0 ? &Shader[index] : 0; } /*! loads the shader definition */ void CQ3LevelMesh::getShader( io::IReadFile* file ) { if ( 0 == file ) return; // load script core::array script; const long len = file->getSize(); script.set_used( len + 2 ); file->seek( 0 ); file->read( script.pointer(), len ); script[ len + 1 ] = 0; // start a parser instance parser_parse( script.pointer(), len, &CQ3LevelMesh::scriptcallback_shader ); } //! adding default shaders void CQ3LevelMesh::InitShader() { ReleaseShader(); IShader element; SVarGroup group; SVariable variable ( "noshader" ); group.Variable.push_back( variable ); element.VarGroup = new SVarGroupList(); element.VarGroup->VariableGroup.push_back( group ); element.VarGroup->VariableGroup.push_back( SVarGroup() ); element.name = element.VarGroup->VariableGroup[0].Variable[0].name; element.ID = Shader.size(); Shader.push_back( element ); if ( LoadParam.loadAllShaders ) { io::EFileSystemType current = FileSystem->setFileListSystem ( io::FILESYSTEM_VIRTUAL ); io::path save = FileSystem->getWorkingDirectory(); io::path newDir; newDir = "/"; newDir += LoadParam.scriptDir; newDir += "/"; FileSystem->changeWorkingDirectoryTo ( newDir.c_str() ); core::stringc s; io::IFileList *fileList = FileSystem->createFileList (); for (u32 i=0; i< fileList->getFileCount(); ++i) { s = fileList->getFullFileName(i); if ( s.find ( ".shader" ) >= 0 ) { if ( 0 == LoadParam.loadSkyShader && s.find ( "sky.shader" ) >= 0 ) { } else { getShader ( s.c_str () ); } } } fileList->drop (); FileSystem->changeWorkingDirectoryTo ( save ); FileSystem->setFileListSystem ( current ); } } //! script callback for shaders //! i'm having troubles with the reference counting, during callback.. resorting.. void CQ3LevelMesh::ReleaseShader() { for ( u32 i = 0; i!= Shader.size(); ++i ) { Shader[i].VarGroup->drop(); } Shader.clear(); ShaderFile.clear(); } /*! */ void CQ3LevelMesh::ReleaseEntity() { for ( u32 i = 0; i!= Entity.size(); ++i ) { Entity[i].VarGroup->drop(); } Entity.clear(); } // config in simple (quake3) and advanced style void CQ3LevelMesh::scriptcallback_config( SVarGroupList *& grouplist, eToken token ) { IShader element; if ( token == Q3_TOKEN_END_LIST ) { if ( 0 == grouplist->VariableGroup[0].Variable.size() ) return; element.name = grouplist->VariableGroup[0].Variable[0].name; } else { if ( grouplist->VariableGroup.size() != 2 ) return; element.name = "configuration"; } grouplist->grab(); element.VarGroup = grouplist; element.ID = Entity.size(); Entity.push_back( element ); } // entity only has only one valid level.. and no assoziative name.. void CQ3LevelMesh::scriptcallback_entity( SVarGroupList *& grouplist, eToken token ) { if ( token != Q3_TOKEN_END_LIST || grouplist->VariableGroup.size() != 2 ) return; grouplist->grab(); IEntity element; element.VarGroup = grouplist; element.ID = Entity.size(); element.name = grouplist->VariableGroup[1].get( "classname" ); Entity.push_back( element ); } //!. script callback for shaders void CQ3LevelMesh::scriptcallback_shader( SVarGroupList *& grouplist,eToken token ) { if ( token != Q3_TOKEN_END_LIST || grouplist->VariableGroup[0].Variable.size()==0) return; IShader element; grouplist->grab(); element.VarGroup = grouplist; element.name = element.VarGroup->VariableGroup[0].Variable[0].name; element.ID = Shader.size(); /* core::stringc s; dumpShader ( s, &element ); printf ( s.c_str () ); */ Shader.push_back( element ); } /*! delete all buffers without geometry in it. */ void CQ3LevelMesh::cleanMeshes() { if ( 0 == LoadParam.cleanUnResolvedMeshes ) return; s32 i; // First the main level for (i = 0; i < E_Q3_MESH_SIZE; i++) { bool texture0important = ( i == 0 ); cleanMesh(Mesh[i], texture0important); } // Then the brush entities for (i = 1; i < NumModels; i++) { cleanMesh(BrushEntities[i], true); } } void CQ3LevelMesh::cleanMesh(SMesh *m, const bool texture0important) { // delete all buffers without geometry in it. u32 run = 0; u32 remove = 0; IMeshBuffer *b; run = 0; remove = 0; if ( LoadParam.verbose > 0 ) { LoadParam.startTime = os::Timer::getRealTime(); if ( LoadParam.verbose > 1 ) { snprintf( buf, sizeof ( buf ), "quake3::cleanMeshes start for %d meshes", m->MeshBuffers.size() ); os::Printer::log(buf, ELL_INFORMATION); } } u32 i = 0; s32 blockstart = -1; s32 blockcount = 0; while( i < m->MeshBuffers.size()) { run += 1; b = m->MeshBuffers[i]; if ( b->getVertexCount() == 0 || b->getIndexCount() == 0 || ( texture0important && b->getMaterial().getTexture(0) == 0 ) ) { if ( blockstart < 0 ) { blockstart = i; blockcount = 0; } blockcount += 1; i += 1; // delete Meshbuffer i -= 1; remove += 1; b->drop(); m->MeshBuffers.erase(i); } else { // clean blockwise if ( blockstart >= 0 ) { if ( LoadParam.verbose > 1 ) { snprintf( buf, sizeof ( buf ), "quake3::cleanMeshes cleaning mesh %d %d size", blockstart, blockcount ); os::Printer::log(buf, ELL_INFORMATION); } blockstart = -1; } i += 1; } } if ( LoadParam.verbose > 0 ) { LoadParam.endTime = os::Timer::getRealTime(); snprintf( buf, sizeof ( buf ), "quake3::cleanMeshes needed %04d ms to clean %d of %d meshes", LoadParam.endTime - LoadParam.startTime, remove, run ); os::Printer::log(buf, ELL_INFORMATION); } } // recalculate bounding boxes void CQ3LevelMesh::calcBoundingBoxes() { if ( LoadParam.verbose > 0 ) { LoadParam.startTime = os::Timer::getRealTime(); if ( LoadParam.verbose > 1 ) { snprintf( buf, sizeof ( buf ), "quake3::calcBoundingBoxes start create %d textures and %d lightmaps", NumTextures, NumLightMaps ); os::Printer::log(buf, ELL_INFORMATION); } } s32 g; // create bounding box for ( g = 0; g != E_Q3_MESH_SIZE; ++g ) { for ( u32 j=0; j < Mesh[g]->MeshBuffers.size(); ++j) { ((SMeshBufferLightMap*)Mesh[g]->MeshBuffers[j])->recalculateBoundingBox(); } Mesh[g]->recalculateBoundingBox(); // Mesh[0] is the main bbox if (g!=0) Mesh[0]->BoundingBox.addInternalBox(Mesh[g]->getBoundingBox()); } for (g = 1; g < NumModels; g++) { for ( u32 j=0; j < BrushEntities[g]->MeshBuffers.size(); ++j) { ((SMeshBufferLightMap*)BrushEntities[g]->MeshBuffers[j])-> recalculateBoundingBox(); } BrushEntities[g]->recalculateBoundingBox(); } if ( LoadParam.verbose > 0 ) { LoadParam.endTime = os::Timer::getRealTime(); snprintf( buf, sizeof ( buf ), "quake3::calcBoundingBoxes needed %04d ms to create %d textures and %d lightmaps", LoadParam.endTime - LoadParam.startTime, NumTextures, NumLightMaps ); os::Printer::log( buf, ELL_INFORMATION); } } //! loads the textures void CQ3LevelMesh::loadTextures() { if (!Driver) return; if ( LoadParam.verbose > 0 ) { LoadParam.startTime = os::Timer::getRealTime(); if ( LoadParam.verbose > 1 ) { snprintf( buf, sizeof ( buf ), "quake3::loadTextures start create %d textures and %d lightmaps", NumTextures, NumLightMaps ); os::Printer::log( buf, ELL_INFORMATION); } } c8 lightmapname[255]; s32 t; // load lightmaps. Lightmap.set_used(NumLightMaps); /* bool oldMipMapState = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); */ core::dimension2d lmapsize(128,128); video::IImage* lmapImg; for ( t = 0; t < NumLightMaps ; ++t) { sprintf(lightmapname, "%s.lightmap.%d", LevelName.c_str(), t); // lightmap is a CTexture::R8G8B8 format lmapImg = Driver->createImageFromData( video::ECF_R8G8B8, lmapsize, LightMaps[t].imageBits, false, true ); Lightmap[t] = Driver->addTexture( lightmapname, lmapImg ); lmapImg->drop(); } // Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); // load textures Tex.set_used( NumTextures ); const IShader* shader; core::stringc list; io::path check; tTexArray textureArray; // pre-load shaders for ( t=0; t< NumTextures; ++t) { shader = getShader(Textures[t].strName, false); } for ( t=0; t< NumTextures; ++t) { Tex[t].ShaderID = -1; Tex[t].Texture = 0; list = ""; // get a shader ( if one exists ) shader = getShader( Textures[t].strName, false); if ( shader ) { Tex[t].ShaderID = shader->ID; // if texture name == stage1 Texture map const SVarGroup * group; group = shader->getGroup( 2 ); if ( group ) { if ( core::cutFilenameExtension( check, group->get( "map" ) ) == Textures[t].strName ) { list += check; } else if ( check == "$lightmap" ) { // we check if lightmap is in stage 1 and texture in stage 2 group = shader->getGroup( 3 ); if ( group ) list += group->get( "map" ); } } } else { // no shader, take it list += Textures[t].strName; } u32 pos = 0; getTextures( textureArray, list, pos, FileSystem, Driver ); Tex[t].Texture = textureArray[0]; } if ( LoadParam.verbose > 0 ) { LoadParam.endTime = os::Timer::getRealTime(); snprintf( buf, sizeof ( buf ), "quake3::loadTextures needed %04d ms to create %d textures and %d lightmaps", LoadParam.endTime - LoadParam.startTime, NumTextures, NumLightMaps ); os::Printer::log( buf, ELL_INFORMATION); } } //! Returns an axis aligned bounding box of the mesh. const core::aabbox3d& CQ3LevelMesh::getBoundingBox() const { return Mesh[0]->getBoundingBox(); } void CQ3LevelMesh::setBoundingBox(const core::aabbox3df& box) { Mesh[0]->setBoundingBox(box); } //! Returns the type of the animated mesh. E_ANIMATED_MESH_TYPE CQ3LevelMesh::getMeshType() const { return scene::EAMT_BSP; } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_BSP_LOADER_ irrlicht-1.8.3/source/Irrlicht/CPLYMeshWriter.cpp0000644000000000000000000001046112574354552020424 0ustar rootroot// Copyright (C) 2008-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_PLY_WRITER_ #include "CPLYMeshWriter.h" #include "os.h" #include "IMesh.h" #include "IMeshBuffer.h" #include "IWriteFile.h" namespace irr { namespace scene { CPLYMeshWriter::CPLYMeshWriter() { #ifdef _DEBUG setDebugName("CPLYMeshWriter"); #endif } //! Returns the type of the mesh writer EMESH_WRITER_TYPE CPLYMeshWriter::getType() const { return EMWT_PLY; } //! writes a mesh bool CPLYMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { if (!file || !mesh) return false; os::Printer::log("Writing mesh", file->getFileName()); // write PLY header core::stringc header = "ply\n" "format ascii 1.0\n" "comment Irrlicht Engine "; header += IRRLICHT_SDK_VERSION; // get vertex and triangle counts u32 VertexCount = 0; u32 TriangleCount = 0; for (u32 i=0; i < mesh->getMeshBufferCount(); ++i) { VertexCount += mesh->getMeshBuffer(i)->getVertexCount(); TriangleCount += mesh->getMeshBuffer(i)->getIndexCount() / 3; } // vertex definition header += "\nelement vertex "; header += VertexCount; header += "\n" "property float x\n" "property float y\n" "property float z\n" "property float nx\n" "property float ny\n" "property float nz\n"; // todo: writer flags for extended (r,g,b,u,v) and non-standard (alpha,u1,uv,tx,ty,tz) properties // "property uchar red\n" // "property uchar green\n" // "property uchar blue\n" // "property uchar alpha\n" // "property float u\n" // "property float v\n"; // "property float u1\n // "property float v1\n" // "property float tx\n" // "property float ty\n" // "property float tz\n" // face definition header += "element face "; header += TriangleCount; header += "\n" "property list uchar int vertex_indices\n" "end_header\n"; // write header file->write(header.c_str(), header.size()); // write vertices c8 outLine[1024]; for (u32 i=0; i < mesh->getMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = mesh->getMeshBuffer(i); for (u32 j=0; j < mb->getVertexCount(); ++j) { const core::vector3df& pos = mb->getPosition(j); const core::vector3df& n = mb->getNormal(j); // const core::vector2df& tc = mb->getTCoords(j); u8 *buf = (u8*)mb->getVertices(); switch(mb->getVertexType()) { case video::EVT_STANDARD: buf += sizeof(video::S3DVertex)*j; break; case video::EVT_2TCOORDS: buf += sizeof(video::S3DVertex2TCoords)*j; break; case video::EVT_TANGENTS: buf += sizeof(video::S3DVertexTangents)*j; break; } // video::SColor &col = ( (video::S3DVertex*)buf )->Color; // x y z nx ny nz red green blue alpha u v [u1 v1 | tx ty tz]\n snprintf(outLine, 1024, "%f %f %f %f %f %f\n",// %u %u %u %u %f %f\n", pos.X, pos.Z, pos.Y, // Y and Z are flipped n.X, n.Z, n.Y); /*col.getRed(), col.getGreen(), col.getBlue(), col.getAlpha(), tc.X, tc.Y);*/ // write the line file->write(outLine, strlen(outLine)); } } // index of the first vertex in the current mesh buffer u32 StartOffset = 0; // write triangles for (u32 i=0; i < mesh->getMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = mesh->getMeshBuffer(i); for (u32 j=0; j < mb->getIndexCount(); j+=3) { // y and z are flipped so triangles are reversed u32 a=StartOffset, b=StartOffset, c=StartOffset; switch(mb->getIndexType()) { case video::EIT_16BIT: a += mb->getIndices()[j+0]; c += mb->getIndices()[j+1]; b += mb->getIndices()[j+2]; break; case video::EIT_32BIT: a += ((u32*)mb->getIndices()) [j+0]; c += ((u32*)mb->getIndices()) [j+0]; b += ((u32*)mb->getIndices()) [j+0]; break; } // count a b c\n snprintf(outLine, 1024, "3 %u %u %u\n", a, b, c); // write the line file->write(outLine, strlen(outLine)); } // increment offset StartOffset += mb->getVertexCount(); } // all done! return true; } } // end namespace } // end namespace #endif // _IRR_COMPILE_WITH_PLY_WRITER_ irrlicht-1.8.3/source/Irrlicht/CPLYMeshFileLoader.h0000644000000000000000000000631412574354552020625 0ustar rootroot// Copyright (C) 2009-2012 Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PLY_MESH_FILE_LOADER_H_INCLUDED__ #define __C_PLY_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "ISceneManager.h" #include "CDynamicMeshBuffer.h" namespace irr { namespace scene { enum E_PLY_PROPERTY_TYPE { EPLYPT_INT8 = 0, EPLYPT_INT16, EPLYPT_INT32, EPLYPT_FLOAT32, EPLYPT_FLOAT64, EPLYPT_LIST, EPLYPT_UNKNOWN }; //! Meshloader capable of loading obj meshes. class CPLYMeshFileLoader : public IMeshLoader { public: //! Constructor CPLYMeshFileLoader(scene::ISceneManager* smgr); //! Destructor virtual ~CPLYMeshFileLoader(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".ply") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: struct SPLYProperty { core::stringc Name; E_PLY_PROPERTY_TYPE Type; union { u8 Int8; u16 Int16; u32 Int32; f32 Float32; f64 Double; struct SPLYListProperty { E_PLY_PROPERTY_TYPE CountType; E_PLY_PROPERTY_TYPE ItemType; } List; } Data; inline u32 size() const { switch(Type) { case EPLYPT_INT8: return 1; case EPLYPT_INT16: return 2; case EPLYPT_INT32: case EPLYPT_FLOAT32: return 4; case EPLYPT_FLOAT64: return 8; case EPLYPT_LIST: case EPLYPT_UNKNOWN: default: return 0; } } inline bool isFloat() const { switch(Type) { case EPLYPT_FLOAT32: case EPLYPT_FLOAT64: return true; case EPLYPT_INT8: case EPLYPT_INT16: case EPLYPT_INT32: case EPLYPT_LIST: case EPLYPT_UNKNOWN: default: return false; } } }; struct SPLYElement { // name of the element. We only want "vertex" and "face" elements // but we have to parse the others anyway. core::stringc Name; // The number of elements in the file u32 Count; // Properties of this element core::array Properties; // in binary files, true if this is a fixed size bool IsFixedWidth; // known size in bytes, 0 if unknown u32 KnownSize; }; bool allocateBuffer(); c8* getNextLine(); c8* getNextWord(); void fillBuffer(); E_PLY_PROPERTY_TYPE getPropertyType(const c8* typeString) const; bool readVertex(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb); bool readFace(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb); void skipElement(const SPLYElement &Element); void skipProperty(const SPLYProperty &Property); f32 getFloat(E_PLY_PROPERTY_TYPE t); u32 getInt(E_PLY_PROPERTY_TYPE t); void moveForward(u32 bytes); core::array ElementList; scene::ISceneManager* SceneManager; io::IReadFile *File; c8 *Buffer; bool IsBinaryFile, IsWrongEndian, EndOfFile; s32 LineLength, WordLength; c8 *StartPointer, *EndPointer, *LineEndPointer; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CPLYMeshFileLoader.cpp0000644000000000000000000004607512574354552021170 0ustar rootroot// Copyright (C) 2009-2012 Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_PLY_LOADER_ #include "CPLYMeshFileLoader.h" #include "IMeshManipulator.h" #include "SMesh.h" #include "CDynamicMeshBuffer.h" #include "SAnimatedMesh.h" #include "IReadFile.h" #include "fast_atof.h" #include "os.h" namespace irr { namespace scene { // input buffer must be at least twice as long as the longest line in the file #define PLY_INPUT_BUFFER_SIZE 51200 // file is loaded in 50k chunks // constructor CPLYMeshFileLoader::CPLYMeshFileLoader(scene::ISceneManager* smgr) : SceneManager(smgr), File(0), Buffer(0) { } CPLYMeshFileLoader::~CPLYMeshFileLoader() { // delete the buffer in case we didn't earlier // (we do, but this could be disabled to increase the speed of loading hundreds of meshes) if (Buffer) { delete [] Buffer; Buffer = 0; } // Destroy the element list if it exists for (u32 i=0; igrab(); // attempt to allocate the buffer and fill with data if (!allocateBuffer()) { File->drop(); File = 0; return 0; } // start with empty mesh SAnimatedMesh* animMesh = 0; u32 vertCount=0; // Currently only supports ASCII meshes if (strcmp(getNextLine(), "ply")) { os::Printer::log("Not a valid PLY file", file->getFileName().c_str(), ELL_ERROR); } else { // cut the next line out getNextLine(); // grab the word from this line c8 *word = getNextWord(); // ignore comments while (strcmp(word, "comment") == 0) { getNextLine(); word = getNextWord(); } bool readingHeader = true; bool continueReading = true; IsBinaryFile = false; IsWrongEndian= false; do { if (strcmp(word, "format") == 0) { word = getNextWord(); if (strcmp(word, "binary_little_endian") == 0) { IsBinaryFile = true; #ifdef __BIG_ENDIAN__ IsWrongEndian = true; #endif } else if (strcmp(word, "binary_big_endian") == 0) { IsBinaryFile = true; #ifndef __BIG_ENDIAN__ IsWrongEndian = true; #endif } else if (strcmp(word, "ascii")) { // abort if this isn't an ascii or a binary mesh os::Printer::log("Unsupported PLY mesh format", word, ELL_ERROR); continueReading = false; } if (continueReading) { word = getNextWord(); if (strcmp(word, "1.0")) { os::Printer::log("Unsupported PLY mesh version", word, ELL_WARNING); } } } else if (strcmp(word, "property") == 0) { word = getNextWord(); if (!ElementList.size()) { os::Printer::log("PLY property found before element", word, ELL_WARNING); } else { // get element SPLYElement* el = ElementList[ElementList.size()-1]; // fill property struct SPLYProperty prop; prop.Type = getPropertyType(word); el->KnownSize += prop.size(); if (prop.Type == EPLYPT_LIST) { el->IsFixedWidth = false; word = getNextWord(); prop.Data.List.CountType = getPropertyType(word); if (IsBinaryFile && prop.Data.List.CountType == EPLYPT_UNKNOWN) { os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR); continueReading = false; } else { word = getNextWord(); prop.Data.List.ItemType = getPropertyType(word); if (IsBinaryFile && prop.Data.List.ItemType == EPLYPT_UNKNOWN) { os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR); continueReading = false; } } } else if (IsBinaryFile && prop.Type == EPLYPT_UNKNOWN) { os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR); continueReading = false; } prop.Name = getNextWord(); // add property to element el->Properties.push_back(prop); } } else if (strcmp(word, "element") == 0) { SPLYElement* el = new SPLYElement; el->Name = getNextWord(); el->Count = atoi(getNextWord()); el->IsFixedWidth = true; el->KnownSize = 0; ElementList.push_back(el); if (el->Name == "vertex") vertCount = el->Count; } else if (strcmp(word, "end_header") == 0) { readingHeader = false; if (IsBinaryFile) { StartPointer = LineEndPointer + 1; } } else if (strcmp(word, "comment") == 0) { // ignore line } else { os::Printer::log("Unknown item in PLY file", word, ELL_WARNING); } if (readingHeader && continueReading) { getNextLine(); word = getNextWord(); } } while (readingHeader && continueReading); // now to read the actual data from the file if (continueReading) { // create a mesh buffer CDynamicMeshBuffer *mb = new CDynamicMeshBuffer(video::EVT_STANDARD, vertCount > 65565 ? video::EIT_32BIT : video::EIT_16BIT); mb->getVertexBuffer().reallocate(vertCount); mb->getIndexBuffer().reallocate(vertCount); mb->setHardwareMappingHint(EHM_STATIC); bool hasNormals=true; // loop through each of the elements for (u32 i=0; iName == "vertex") { // loop through vertex properties for (u32 j=0; j < ElementList[i]->Count; ++j) hasNormals &= readVertex(*ElementList[i], mb); } else if (ElementList[i]->Name == "face") { // read faces for (u32 j=0; j < ElementList[i]->Count; ++j) readFace(*ElementList[i], mb); } else { // skip these elements for (u32 j=0; j < ElementList[i]->Count; ++j) skipElement(*ElementList[i]); } } mb->recalculateBoundingBox(); if (!hasNormals) SceneManager->getMeshManipulator()->recalculateNormals(mb); SMesh* m = new SMesh(); m->addMeshBuffer(mb); m->recalculateBoundingBox(); mb->drop(); animMesh = new SAnimatedMesh(); animMesh->addMesh(m); animMesh->recalculateBoundingBox(); m->drop(); } } // free the buffer delete [] Buffer; Buffer = 0; File->drop(); File = 0; // if we managed to create a mesh, return it return animMesh; } bool CPLYMeshFileLoader::readVertex(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb) { if (!IsBinaryFile) getNextLine(); video::S3DVertex vert; vert.Color.set(255,255,255,255); vert.TCoords.X = 0.0f; vert.TCoords.Y = 0.0f; vert.Normal.X = 0.0f; vert.Normal.Y = 1.0f; vert.Normal.Z = 0.0f; bool result=false; for (u32 i=0; i < Element.Properties.size(); ++i) { E_PLY_PROPERTY_TYPE t = Element.Properties[i].Type; if (Element.Properties[i].Name == "x") vert.Pos.X = getFloat(t); else if (Element.Properties[i].Name == "y") vert.Pos.Z = getFloat(t); else if (Element.Properties[i].Name == "z") vert.Pos.Y = getFloat(t); else if (Element.Properties[i].Name == "nx") { vert.Normal.X = getFloat(t); result=true; } else if (Element.Properties[i].Name == "ny") { vert.Normal.Z = getFloat(t); result=true; } else if (Element.Properties[i].Name == "nz") { vert.Normal.Y = getFloat(t); result=true; } else if (Element.Properties[i].Name == "u") vert.TCoords.X = getFloat(t); else if (Element.Properties[i].Name == "v") vert.TCoords.Y = getFloat(t); else if (Element.Properties[i].Name == "red") { u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); vert.Color.setRed(value); } else if (Element.Properties[i].Name == "green") { u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); vert.Color.setGreen(value); } else if (Element.Properties[i].Name == "blue") { u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); vert.Color.setBlue(value); } else if (Element.Properties[i].Name == "alpha") { u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); vert.Color.setAlpha(value); } else skipProperty(Element.Properties[i]); } mb->getVertexBuffer().push_back(vert); return result; } bool CPLYMeshFileLoader::readFace(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb) { if (!IsBinaryFile) getNextLine(); for (u32 i=0; i < Element.Properties.size(); ++i) { if ( (Element.Properties[i].Name == "vertex_indices" || Element.Properties[i].Name == "vertex_index") && Element.Properties[i].Type == EPLYPT_LIST) { // get count s32 count = getInt(Element.Properties[i].Data.List.CountType); u32 a = getInt(Element.Properties[i].Data.List.ItemType), b = getInt(Element.Properties[i].Data.List.ItemType), c = getInt(Element.Properties[i].Data.List.ItemType); s32 j = 3; mb->getIndexBuffer().push_back(a); mb->getIndexBuffer().push_back(c); mb->getIndexBuffer().push_back(b); for (; j < count; ++j) { b = c; c = getInt(Element.Properties[i].Data.List.ItemType); mb->getIndexBuffer().push_back(a); mb->getIndexBuffer().push_back(c); mb->getIndexBuffer().push_back(b); } } else if (Element.Properties[i].Name == "intensity") { // todo: face intensity skipProperty(Element.Properties[i]); } else skipProperty(Element.Properties[i]); } return true; } // skips an element and all properties. return false on EOF void CPLYMeshFileLoader::skipElement(const SPLYElement &Element) { if (IsBinaryFile) if (Element.IsFixedWidth) moveForward(Element.KnownSize); else for (u32 i=0; i < Element.Properties.size(); ++i) skipProperty(Element.Properties[i]); else getNextLine(); } void CPLYMeshFileLoader::skipProperty(const SPLYProperty &Property) { if (Property.Type == EPLYPT_LIST) { s32 count = getInt(Property.Data.List.CountType); for (s32 i=0; i < count; ++i) getInt(Property.Data.List.CountType); } else { if (IsBinaryFile) moveForward(Property.size()); else getNextWord(); } } bool CPLYMeshFileLoader::allocateBuffer() { // Destroy the element list if it exists for (u32 i=0; igetPos() == File->getSize()) { EndOfFile = true; } else { // read data from the file u32 count = File->read(EndPointer, PLY_INPUT_BUFFER_SIZE - length); // increment the end pointer by the number of bytes read EndPointer = EndPointer + count; // if we didn't completely fill the buffer if (count != PLY_INPUT_BUFFER_SIZE - length) { // blank the rest of the memory memset(EndPointer, 0, Buffer + PLY_INPUT_BUFFER_SIZE - EndPointer); // end of file EndOfFile = true; } } } // skips x bytes in the file, getting more data if required void CPLYMeshFileLoader::moveForward(u32 bytes) { if (StartPointer + bytes >= EndPointer) fillBuffer(); if (StartPointer + bytes < EndPointer) StartPointer += bytes; else StartPointer = EndPointer; } E_PLY_PROPERTY_TYPE CPLYMeshFileLoader::getPropertyType(const c8* typeString) const { if (strcmp(typeString, "char") == 0 || strcmp(typeString, "uchar") == 0 || strcmp(typeString, "int8") == 0 || strcmp(typeString, "uint8") == 0) { return EPLYPT_INT8; } else if (strcmp(typeString, "uint") == 0 || strcmp(typeString, "int16") == 0 || strcmp(typeString, "uint16") == 0 || strcmp(typeString, "short") == 0 || strcmp(typeString, "ushort") == 0) { return EPLYPT_INT16; } else if (strcmp(typeString, "int") == 0 || strcmp(typeString, "long") == 0 || strcmp(typeString, "ulong") == 0 || strcmp(typeString, "int32") == 0 || strcmp(typeString, "uint32") == 0) { return EPLYPT_INT32; } else if (strcmp(typeString, "float") == 0 || strcmp(typeString, "float32") == 0) { return EPLYPT_FLOAT32; } else if (strcmp(typeString, "float64") == 0 || strcmp(typeString, "double") == 0) { return EPLYPT_FLOAT64; } else if ( strcmp(typeString, "list") == 0 ) { return EPLYPT_LIST; } else { // unsupported type. // cannot be loaded in binary mode return EPLYPT_UNKNOWN; } } // Split the string data into a line in place by terminating it instead of copying. c8* CPLYMeshFileLoader::getNextLine() { // move the start pointer along StartPointer = LineEndPointer + 1; // crlf split across buffer move if (*StartPointer == '\n') { *StartPointer = '\0'; ++StartPointer; } // begin at the start of the next line c8* pos = StartPointer; while (pos < EndPointer && *pos && *pos != '\r' && *pos != '\n') ++pos; if ( pos < EndPointer && ( *(pos+1) == '\r' || *(pos+1) == '\n') ) { *pos = '\0'; ++pos; } // we have reached the end of the buffer if (pos >= EndPointer) { // get data from the file if (!EndOfFile) { fillBuffer(); // reset line end pointer LineEndPointer = StartPointer - 1; if (StartPointer != EndPointer) return getNextLine(); else return Buffer; } else { // EOF StartPointer = EndPointer-1; *StartPointer = '\0'; return StartPointer; } } else { // null terminate the string in place *pos = '\0'; LineEndPointer = pos; WordLength = -1; // return pointer to the start of the line return StartPointer; } } // null terminate the next word on the previous line and move the next word pointer along // since we already have a full line in the buffer, we never need to retrieve more data c8* CPLYMeshFileLoader::getNextWord() { // move the start pointer along StartPointer += WordLength + 1; if (StartPointer == LineEndPointer) { WordLength = -1; // return LineEndPointer; } // begin at the start of the next word c8* pos = StartPointer; while (*pos && pos < LineEndPointer && pos < EndPointer && *pos != ' ' && *pos != '\t') ++pos; while(*pos && pos < LineEndPointer && pos < EndPointer && (*pos == ' ' || *pos == '\t') ) { // null terminate the string in place *pos = '\0'; ++pos; } --pos; WordLength = (s32)(pos-StartPointer); // return pointer to the start of the word return StartPointer; } // read the next float from the file and move the start pointer along f32 CPLYMeshFileLoader::getFloat(E_PLY_PROPERTY_TYPE t) { f32 retVal = 0.0f; if (IsBinaryFile) { if (EndPointer - StartPointer < 8) fillBuffer(); if (EndPointer - StartPointer > 0) { switch (t) { case EPLYPT_INT8: retVal = *StartPointer; StartPointer++; break; case EPLYPT_INT16: if (IsWrongEndian) retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); else retVal = *(reinterpret_cast(StartPointer)); StartPointer += 2; break; case EPLYPT_INT32: if (IsWrongEndian) retVal = f32(os::Byteswap::byteswap(*(reinterpret_cast(StartPointer)))); else retVal = f32(*(reinterpret_cast(StartPointer))); StartPointer += 4; break; case EPLYPT_FLOAT32: if (IsWrongEndian) retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); else retVal = *(reinterpret_cast(StartPointer)); StartPointer += 4; break; case EPLYPT_FLOAT64: // todo: byteswap 64-bit retVal = f32(*(reinterpret_cast(StartPointer))); StartPointer += 8; break; case EPLYPT_LIST: case EPLYPT_UNKNOWN: default: retVal = 0.0f; StartPointer++; // ouch! } } else retVal = 0.0f; } else { c8* word = getNextWord(); switch (t) { case EPLYPT_INT8: case EPLYPT_INT16: case EPLYPT_INT32: retVal = f32(atoi(word)); break; case EPLYPT_FLOAT32: case EPLYPT_FLOAT64: retVal = f32(atof(word)); break; case EPLYPT_LIST: case EPLYPT_UNKNOWN: default: retVal = 0.0f; } } return retVal; } // read the next int from the file and move the start pointer along u32 CPLYMeshFileLoader::getInt(E_PLY_PROPERTY_TYPE t) { u32 retVal = 0; if (IsBinaryFile) { if (!EndOfFile && EndPointer - StartPointer < 8) fillBuffer(); if (EndPointer - StartPointer) { switch (t) { case EPLYPT_INT8: retVal = *StartPointer; StartPointer++; break; case EPLYPT_INT16: if (IsWrongEndian) retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); else retVal = *(reinterpret_cast(StartPointer)); StartPointer += 2; break; case EPLYPT_INT32: if (IsWrongEndian) retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); else retVal = *(reinterpret_cast(StartPointer)); StartPointer += 4; break; case EPLYPT_FLOAT32: if (IsWrongEndian) retVal = (u32)os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); else retVal = (u32)(*(reinterpret_cast(StartPointer))); StartPointer += 4; break; case EPLYPT_FLOAT64: // todo: byteswap 64-bit retVal = (u32)(*(reinterpret_cast(StartPointer))); StartPointer += 8; break; case EPLYPT_LIST: case EPLYPT_UNKNOWN: default: retVal = 0; StartPointer++; // ouch! } } else retVal = 0; } else { c8* word = getNextWord(); switch (t) { case EPLYPT_INT8: case EPLYPT_INT16: case EPLYPT_INT32: retVal = atoi(word); break; case EPLYPT_FLOAT32: case EPLYPT_FLOAT64: retVal = u32(atof(word)); break; case EPLYPT_LIST: case EPLYPT_UNKNOWN: default: retVal = 0; } } return retVal; } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_PLY_LOADER_ irrlicht-1.8.3/source/Irrlicht/CParticleSystemSceneNode.h0000644000000000000000000002314312574354552022150 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PARTICLE_SYSTEM_SCENE_NODE_H_INCLUDED__ #define __C_PARTICLE_SYSTEM_SCENE_NODE_H_INCLUDED__ #include "IParticleSystemSceneNode.h" #include "irrArray.h" #include "irrList.h" #include "SMeshBuffer.h" namespace irr { namespace scene { //! A particle system scene node. /** A scene node controlling a particle system. The behavior of the particles can be controlled by setting the right particle emitters and affectors. */ class CParticleSystemSceneNode : public IParticleSystemSceneNode { public: //! constructor CParticleSystemSceneNode(bool createDefaultEmitter, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale); //! destructor virtual ~CParticleSystemSceneNode(); //! Gets the particle emitter, which creates the particles. virtual IParticleEmitter* getEmitter(); //! Sets the particle emitter, which creates the particles. virtual void setEmitter(IParticleEmitter* emitter); //! Adds new particle affector to the particle system. virtual void addAffector(IParticleAffector* affector); //! Get a list of all particle affectors. virtual const core::list& getAffectors() const; //! Removes all particle affectors in the particle system. virtual void removeAllAffectors(); //! Returns the material based on the zero based index i. virtual video::SMaterial& getMaterial(u32 i); //! Returns amount of materials used by this scene node. virtual u32 getMaterialCount() const; //! pre render event virtual void OnRegisterSceneNode(); //! render virtual void render(); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! Creates a particle emitter for an animated mesh scene node virtual IParticleAnimatedMeshSceneNodeEmitter* createAnimatedMeshSceneNodeEmitter( scene::IAnimatedMeshSceneNode* node, bool useNormalDirection = true, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), f32 normalDirectionModifier = 100.0f, s32 mbNumber = -1, bool everyMeshVertex = false, u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin = 2000, u32 lifeTimeMax = 4000, s32 maxAngleDegrees = 0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Creates a box particle emitter. virtual IParticleBoxEmitter* createBoxEmitter( const core::aabbox3df& box = core::aabbox3d(-10,0,-10,5,30,10), const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Creates a particle emitter for emitting from a cylinder virtual IParticleCylinderEmitter* createCylinderEmitter( const core::vector3df& center, f32 radius, const core::vector3df& normal, f32 length, bool outlineOnly = false, const core::vector3df& direction = core::vector3df(0.0f,0.5f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPersSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin = 2000, u32 lifeTimeMax = 4000, s32 maxAngleDegrees = 0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Creates a mesh particle emitter. virtual IParticleMeshEmitter* createMeshEmitter( scene::IMesh* mesh, bool useNormalDirection = true, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), f32 normalDirectionModifier = 100.0f, s32 mbNumber = -1, bool everyMeshVertex = false, u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin = 2000, u32 lifeTimeMax = 4000, s32 maxAngleDegrees = 0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Creates a point particle emitter. virtual IParticlePointEmitter* createPointEmitter( const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Creates a ring particle emitter. virtual IParticleRingEmitter* createRingEmitter( const core::vector3df& center, f32 radius, f32 ringThickness, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Creates a sphere particle emitter. virtual IParticleSphereEmitter* createSphereEmitter( const core::vector3df& center, f32 radius, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Creates a point attraction affector. This affector modifies the positions of the //! particles and attracts them to a specified point at a specified speed per second. virtual IParticleAttractionAffector* createAttractionAffector( const core::vector3df& point, f32 speed = 1.0f, bool attract = true, bool affectX = true, bool affectY = true, bool affectZ = true); //! Creates a scale particle affector. virtual IParticleAffector* createScaleParticleAffector(const core::dimension2df& scaleTo = core::dimension2df(1.0f, 1.0f)); //! Creates a fade out particle affector. virtual IParticleFadeOutAffector* createFadeOutParticleAffector( const video::SColor& targetColor = video::SColor(0,0,0,0), u32 timeNeededToFadeOut = 1000); //! Creates a gravity affector. virtual IParticleGravityAffector* createGravityAffector( const core::vector3df& gravity = core::vector3df(0.0f,-0.03f,0.0f), u32 timeForceLost = 1000); //! Creates a rotation affector. This affector rotates the particles //! around a specified pivot point. The speed is in Degrees per second. virtual IParticleRotationAffector* createRotationAffector( const core::vector3df& speed = core::vector3df(5.0f,5.0f,5.0f), const core::vector3df& pivotPoint = core::vector3df(0.0f,0.0f,0.0f) ); //! Sets the size of all particles. virtual void setParticleSize( const core::dimension2d &size = core::dimension2d(5.0f, 5.0f)); //! Sets if the particles should be global. If they are, the particles are affected by //! the movement of the particle system scene node too, otherwise they completely //! ignore it. Default is true. virtual void setParticlesAreGlobal(bool global=true); //! Remove all currently visible particles virtual void clearParticles(); //! Do manually update the particles. //! This should only be called when you want to render the node outside the scenegraph, //! as the node will care about this otherwise automatically. virtual void doParticleSystem(u32 time); //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_PARTICLE_SYSTEM; } private: void reallocateBuffers(); core::list AffectorList; IParticleEmitter* Emitter; core::array Particles; core::dimension2d ParticleSize; u32 LastEmitTime; s32 MaxParticles; SMeshBuffer* Buffer; enum E_PARTICLES_PRIMITIVE { EPP_POINT=0, EPP_BILLBOARD, EPP_POINTSPRITE }; E_PARTICLES_PRIMITIVE ParticlePrimitive; bool ParticlesAreGlobal; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CParticleSystemSceneNode.cpp0000644000000000000000000005161412574354552022507 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleSystemSceneNode.h" #include "os.h" #include "ISceneManager.h" #include "ICameraSceneNode.h" #include "IVideoDriver.h" #include "CParticleAnimatedMeshSceneNodeEmitter.h" #include "CParticleBoxEmitter.h" #include "CParticleCylinderEmitter.h" #include "CParticleMeshEmitter.h" #include "CParticlePointEmitter.h" #include "CParticleRingEmitter.h" #include "CParticleSphereEmitter.h" #include "CParticleAttractionAffector.h" #include "CParticleFadeOutAffector.h" #include "CParticleGravityAffector.h" #include "CParticleRotationAffector.h" #include "CParticleScaleAffector.h" #include "SViewFrustum.h" namespace irr { namespace scene { //! constructor CParticleSystemSceneNode::CParticleSystemSceneNode(bool createDefaultEmitter, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) : IParticleSystemSceneNode(parent, mgr, id, position, rotation, scale), Emitter(0), ParticleSize(core::dimension2d(5.0f, 5.0f)), LastEmitTime(0), MaxParticles(0xffff), Buffer(0), ParticlesAreGlobal(true) { #ifdef _DEBUG setDebugName("CParticleSystemSceneNode"); #endif Buffer = new SMeshBuffer(); if (createDefaultEmitter) { IParticleEmitter* e = createBoxEmitter(); setEmitter(e); e->drop(); } } //! destructor CParticleSystemSceneNode::~CParticleSystemSceneNode() { if (Emitter) Emitter->drop(); if (Buffer) Buffer->drop(); removeAllAffectors(); } //! Gets the particle emitter, which creates the particles. IParticleEmitter* CParticleSystemSceneNode::getEmitter() { return Emitter; } //! Sets the particle emitter, which creates the particles. void CParticleSystemSceneNode::setEmitter(IParticleEmitter* emitter) { if (emitter == Emitter) return; if (Emitter) Emitter->drop(); Emitter = emitter; if (Emitter) Emitter->grab(); } //! Adds new particle effector to the particle system. void CParticleSystemSceneNode::addAffector(IParticleAffector* affector) { affector->grab(); AffectorList.push_back(affector); } //! Get a list of all particle affectors. const core::list& CParticleSystemSceneNode::getAffectors() const { return AffectorList; } //! Removes all particle affectors in the particle system. void CParticleSystemSceneNode::removeAllAffectors() { core::list::Iterator it = AffectorList.begin(); while (it != AffectorList.end()) { (*it)->drop(); it = AffectorList.erase(it); } } //! Returns the material based on the zero based index i. video::SMaterial& CParticleSystemSceneNode::getMaterial(u32 i) { return Buffer->Material; } //! Returns amount of materials used by this scene node. u32 CParticleSystemSceneNode::getMaterialCount() const { return 1; } //! Creates a particle emitter for an animated mesh scene node IParticleAnimatedMeshSceneNodeEmitter* CParticleSystemSceneNode::createAnimatedMeshSceneNodeEmitter( scene::IAnimatedMeshSceneNode* node, bool useNormalDirection, const core::vector3df& direction, f32 normalDirectionModifier, s32 mbNumber, bool everyMeshVertex, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize ) { return new CParticleAnimatedMeshSceneNodeEmitter( node, useNormalDirection, direction, normalDirectionModifier, mbNumber, everyMeshVertex, minParticlesPerSecond, maxParticlesPerSecond, minStartColor, maxStartColor, lifeTimeMin, lifeTimeMax, maxAngleDegrees, minStartSize, maxStartSize ); } //! Creates a box particle emitter. IParticleBoxEmitter* CParticleSystemSceneNode::createBoxEmitter( const core::aabbox3df& box, const core::vector3df& direction, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize ) { return new CParticleBoxEmitter(box, direction, minParticlesPerSecond, maxParticlesPerSecond, minStartColor, maxStartColor, lifeTimeMin, lifeTimeMax, maxAngleDegrees, minStartSize, maxStartSize ); } //! Creates a particle emitter for emitting from a cylinder IParticleCylinderEmitter* CParticleSystemSceneNode::createCylinderEmitter( const core::vector3df& center, f32 radius, const core::vector3df& normal, f32 length, bool outlineOnly, const core::vector3df& direction, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize ) { return new CParticleCylinderEmitter( center, radius, normal, length, outlineOnly, direction, minParticlesPerSecond, maxParticlesPerSecond, minStartColor, maxStartColor, lifeTimeMin, lifeTimeMax, maxAngleDegrees, minStartSize, maxStartSize ); } //! Creates a mesh particle emitter. IParticleMeshEmitter* CParticleSystemSceneNode::createMeshEmitter( scene::IMesh* mesh, bool useNormalDirection, const core::vector3df& direction, f32 normalDirectionModifier, s32 mbNumber, bool everyMeshVertex, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize) { return new CParticleMeshEmitter( mesh, useNormalDirection, direction, normalDirectionModifier, mbNumber, everyMeshVertex, minParticlesPerSecond, maxParticlesPerSecond, minStartColor, maxStartColor, lifeTimeMin, lifeTimeMax, maxAngleDegrees, minStartSize, maxStartSize ); } //! Creates a point particle emitter. IParticlePointEmitter* CParticleSystemSceneNode::createPointEmitter( const core::vector3df& direction, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize ) { return new CParticlePointEmitter(direction, minParticlesPerSecond, maxParticlesPerSecond, minStartColor, maxStartColor, lifeTimeMin, lifeTimeMax, maxAngleDegrees, minStartSize, maxStartSize ); } //! Creates a ring particle emitter. IParticleRingEmitter* CParticleSystemSceneNode::createRingEmitter( const core::vector3df& center, f32 radius, f32 ringThickness, const core::vector3df& direction, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize ) { return new CParticleRingEmitter( center, radius, ringThickness, direction, minParticlesPerSecond, maxParticlesPerSecond, minStartColor, maxStartColor, lifeTimeMin, lifeTimeMax, maxAngleDegrees, minStartSize, maxStartSize ); } //! Creates a sphere particle emitter. IParticleSphereEmitter* CParticleSystemSceneNode::createSphereEmitter( const core::vector3df& center, f32 radius, const core::vector3df& direction, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize ) { return new CParticleSphereEmitter(center, radius, direction, minParticlesPerSecond, maxParticlesPerSecond, minStartColor, maxStartColor, lifeTimeMin, lifeTimeMax, maxAngleDegrees, minStartSize, maxStartSize ); } //! Creates a point attraction affector. This affector modifies the positions of the //! particles and attracts them to a specified point at a specified speed per second. IParticleAttractionAffector* CParticleSystemSceneNode::createAttractionAffector( const core::vector3df& point, f32 speed, bool attract, bool affectX, bool affectY, bool affectZ ) { return new CParticleAttractionAffector( point, speed, attract, affectX, affectY, affectZ ); } //! Creates a scale particle affector. IParticleAffector* CParticleSystemSceneNode::createScaleParticleAffector(const core::dimension2df& scaleTo) { return new CParticleScaleAffector(scaleTo); } //! Creates a fade out particle affector. IParticleFadeOutAffector* CParticleSystemSceneNode::createFadeOutParticleAffector( const video::SColor& targetColor, u32 timeNeededToFadeOut) { return new CParticleFadeOutAffector(targetColor, timeNeededToFadeOut); } //! Creates a gravity affector. IParticleGravityAffector* CParticleSystemSceneNode::createGravityAffector( const core::vector3df& gravity, u32 timeForceLost) { return new CParticleGravityAffector(gravity, timeForceLost); } //! Creates a rotation affector. This affector rotates the particles around a specified pivot //! point. The speed represents Degrees of rotation per second. IParticleRotationAffector* CParticleSystemSceneNode::createRotationAffector( const core::vector3df& speed, const core::vector3df& pivotPoint ) { return new CParticleRotationAffector( speed, pivotPoint ); } //! pre render event void CParticleSystemSceneNode::OnRegisterSceneNode() { doParticleSystem(os::Timer::getTime()); if (IsVisible && (Particles.size() != 0)) { SceneManager->registerNodeForRendering(this); ISceneNode::OnRegisterSceneNode(); } } //! render void CParticleSystemSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); ICameraSceneNode* camera = SceneManager->getActiveCamera(); if (!camera || !driver) return; #if 0 // calculate vectors for letting particles look to camera core::vector3df view(camera->getTarget() - camera->getAbsolutePosition()); view.normalize(); view *= -1.0f; #else const core::matrix4 &m = camera->getViewFrustum()->getTransform( video::ETS_VIEW ); const core::vector3df view ( -m[2], -m[6] , -m[10] ); #endif // reallocate arrays, if they are too small reallocateBuffers(); // create particle vertex data s32 idx = 0; for (u32 i=0; igetUpVector().crossProduct(view); horizontal.normalize(); horizontal *= 0.5f * particle.size.Width; core::vector3df vertical = horizontal.crossProduct(view); vertical.normalize(); vertical *= 0.5f * particle.size.Height; #else f32 f; f = 0.5f * particle.size.Width; const core::vector3df horizontal ( m[0] * f, m[4] * f, m[8] * f ); f = -0.5f * particle.size.Height; const core::vector3df vertical ( m[1] * f, m[5] * f, m[9] * f ); #endif Buffer->Vertices[0+idx].Pos = particle.pos + horizontal + vertical; Buffer->Vertices[0+idx].Color = particle.color; Buffer->Vertices[0+idx].Normal = view; Buffer->Vertices[1+idx].Pos = particle.pos + horizontal - vertical; Buffer->Vertices[1+idx].Color = particle.color; Buffer->Vertices[1+idx].Normal = view; Buffer->Vertices[2+idx].Pos = particle.pos - horizontal - vertical; Buffer->Vertices[2+idx].Color = particle.color; Buffer->Vertices[2+idx].Normal = view; Buffer->Vertices[3+idx].Pos = particle.pos - horizontal + vertical; Buffer->Vertices[3+idx].Color = particle.color; Buffer->Vertices[3+idx].Normal = view; idx +=4; } // render all core::matrix4 mat; if (!ParticlesAreGlobal) mat.setTranslation(AbsoluteTransformation.getTranslation()); driver->setTransform(video::ETS_WORLD, mat); driver->setMaterial(Buffer->Material); driver->drawVertexPrimitiveList(Buffer->getVertices(), Particles.size()*4, Buffer->getIndices(), Particles.size()*2, video::EVT_STANDARD, EPT_TRIANGLES,Buffer->getIndexType()); // for debug purposes only: if ( DebugDataVisible & scene::EDS_BBOX ) { driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); video::SMaterial deb_m; deb_m.Lighting = false; driver->setMaterial(deb_m); driver->draw3DBox(Buffer->BoundingBox, video::SColor(0,255,255,255)); } } //! returns the axis aligned bounding box of this node const core::aabbox3d& CParticleSystemSceneNode::getBoundingBox() const { return Buffer->getBoundingBox(); } void CParticleSystemSceneNode::doParticleSystem(u32 time) { if (LastEmitTime==0) { LastEmitTime = time; return; } u32 now = time; u32 timediff = time - LastEmitTime; LastEmitTime = time; // run emitter if (Emitter && IsVisible) { SParticle* array = 0; s32 newParticles = Emitter->emitt(now, timediff, array); if (newParticles && array) { s32 j=Particles.size(); if (newParticles > 16250-j) newParticles=16250-j; Particles.set_used(j+newParticles); for (s32 i=j; i::Iterator ait = AffectorList.begin(); for (; ait != AffectorList.end(); ++ait) (*ait)->affect(now, Particles.pointer(), Particles.size()); if (ParticlesAreGlobal) Buffer->BoundingBox.reset(AbsoluteTransformation.getTranslation()); else Buffer->BoundingBox.reset(core::vector3df(0,0,0)); // animate all particles f32 scale = (f32)timediff; for (u32 i=0; i Particles[i].endTime) { // Particle order does not seem to matter. // So we can delete by switching with last particle and deleting that one. // This is a lot faster and speed is very important here as the erase otherwise // can cause noticable freezes. Particles[i] = Particles[Particles.size()-1]; Particles.erase( Particles.size()-1 ); } else { Particles[i].pos += (Particles[i].vector * scale); Buffer->BoundingBox.addInternalPoint(Particles[i].pos); ++i; } } const f32 m = (ParticleSize.Width > ParticleSize.Height ? ParticleSize.Width : ParticleSize.Height) * 0.5f; Buffer->BoundingBox.MaxEdge.X += m; Buffer->BoundingBox.MaxEdge.Y += m; Buffer->BoundingBox.MaxEdge.Z += m; Buffer->BoundingBox.MinEdge.X -= m; Buffer->BoundingBox.MinEdge.Y -= m; Buffer->BoundingBox.MinEdge.Z -= m; if (ParticlesAreGlobal) { core::matrix4 absinv( AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE ); absinv.transformBoxEx(Buffer->BoundingBox); } } //! Sets if the particles should be global. If it is, the particles are affected by //! the movement of the particle system scene node too, otherwise they completely //! ignore it. Default is true. void CParticleSystemSceneNode::setParticlesAreGlobal(bool global) { ParticlesAreGlobal = global; } //! Remove all currently visible particles void CParticleSystemSceneNode::clearParticles() { Particles.set_used(0); } //! Sets the size of all particles. void CParticleSystemSceneNode::setParticleSize(const core::dimension2d &size) { os::Printer::log("setParticleSize is deprecated, use setMinStartSize/setMaxStartSize in emitter.", irr::ELL_WARNING); //A bit of a hack, but better here than in the particle code if (Emitter) { Emitter->setMinStartSize(size); Emitter->setMaxStartSize(size); } ParticleSize = size; } void CParticleSystemSceneNode::reallocateBuffers() { if (Particles.size() * 4 > Buffer->getVertexCount() || Particles.size() * 6 > Buffer->getIndexCount()) { u32 oldSize = Buffer->getVertexCount(); Buffer->Vertices.set_used(Particles.size() * 4); u32 i; // fill remaining vertices for (i=oldSize; iVertices.size(); i+=4) { Buffer->Vertices[0+i].TCoords.set(0.0f, 0.0f); Buffer->Vertices[1+i].TCoords.set(0.0f, 1.0f); Buffer->Vertices[2+i].TCoords.set(1.0f, 1.0f); Buffer->Vertices[3+i].TCoords.set(1.0f, 0.0f); } // fill remaining indices u32 oldIdxSize = Buffer->getIndexCount(); u32 oldvertices = oldSize; Buffer->Indices.set_used(Particles.size() * 6); for (i=oldIdxSize; iIndices.size(); i+=6) { Buffer->Indices[0+i] = (u16)0+oldvertices; Buffer->Indices[1+i] = (u16)2+oldvertices; Buffer->Indices[2+i] = (u16)1+oldvertices; Buffer->Indices[3+i] = (u16)0+oldvertices; Buffer->Indices[4+i] = (u16)3+oldvertices; Buffer->Indices[5+i] = (u16)2+oldvertices; oldvertices += 4; } } } //! Writes attributes of the scene node. void CParticleSystemSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { IParticleSystemSceneNode::serializeAttributes(out, options); out->addBool("GlobalParticles", ParticlesAreGlobal); out->addFloat("ParticleWidth", ParticleSize.Width); out->addFloat("ParticleHeight", ParticleSize.Height); // write emitter E_PARTICLE_EMITTER_TYPE type = EPET_COUNT; if (Emitter) type = Emitter->getType(); out->addEnum("Emitter", (s32)type, ParticleEmitterTypeNames); if (Emitter) Emitter->serializeAttributes(out, options); // write affectors E_PARTICLE_AFFECTOR_TYPE atype = EPAT_NONE; for (core::list::ConstIterator it = AffectorList.begin(); it != AffectorList.end(); ++it) { atype = (*it)->getType(); out->addEnum("Affector", (s32)atype, ParticleAffectorTypeNames); (*it)->serializeAttributes(out); } // add empty affector to make it possible to add further affectors if (options && options->Flags & io::EARWF_FOR_EDITOR) out->addEnum("Affector", EPAT_NONE, ParticleAffectorTypeNames); } //! Reads attributes of the scene node. void CParticleSystemSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { IParticleSystemSceneNode::deserializeAttributes(in, options); ParticlesAreGlobal = in->getAttributeAsBool("GlobalParticles"); ParticleSize.Width = in->getAttributeAsFloat("ParticleWidth"); ParticleSize.Height = in->getAttributeAsFloat("ParticleHeight"); // read emitter int emitterIdx = in->findAttribute("Emitter"); if (emitterIdx == -1) return; if (Emitter) Emitter->drop(); Emitter = 0; E_PARTICLE_EMITTER_TYPE type = (E_PARTICLE_EMITTER_TYPE) in->getAttributeAsEnumeration("Emitter", ParticleEmitterTypeNames); switch(type) { case EPET_POINT: Emitter = createPointEmitter(); break; case EPET_ANIMATED_MESH: Emitter = createAnimatedMeshSceneNodeEmitter(NULL); // we can't set the node - the user will have to do this break; case EPET_BOX: Emitter = createBoxEmitter(); break; case EPET_CYLINDER: Emitter = createCylinderEmitter(core::vector3df(0,0,0), 10.f, core::vector3df(0,1,0), 10.f); // (values here don't matter) break; case EPET_MESH: Emitter = createMeshEmitter(NULL); // we can't set the mesh - the user will have to do this break; case EPET_RING: Emitter = createRingEmitter(core::vector3df(0,0,0), 10.f, 10.f); // (values here don't matter) break; case EPET_SPHERE: Emitter = createSphereEmitter(core::vector3df(0,0,0), 10.f); // (values here don't matter) break; default: break; } u32 idx = 0; #if 0 if (Emitter) idx = Emitter->deserializeAttributes(idx, in); ++idx; #else if (Emitter) Emitter->deserializeAttributes(in); #endif // read affectors removeAllAffectors(); u32 cnt = in->getAttributeCount(); while(idx < cnt) { const char* name = in->getAttributeName(idx); if (!name || strcmp("Affector", name)) return; E_PARTICLE_AFFECTOR_TYPE atype = (E_PARTICLE_AFFECTOR_TYPE)in->getAttributeAsEnumeration(idx, ParticleAffectorTypeNames); IParticleAffector* aff = 0; switch(atype) { case EPAT_ATTRACT: aff = createAttractionAffector(core::vector3df(0,0,0)); break; case EPAT_FADE_OUT: aff = createFadeOutParticleAffector(); break; case EPAT_GRAVITY: aff = createGravityAffector(); break; case EPAT_ROTATE: aff = createRotationAffector(); break; case EPAT_SCALE: aff = createScaleParticleAffector(); break; case EPAT_NONE: default: break; } ++idx; if (aff) { #if 0 idx = aff->deserializeAttributes(idx, in, options); ++idx; #else aff->deserializeAttributes(in, options); #endif addAffector(aff); aff->drop(); } } } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CParticleSphereEmitter.h0000644000000000000000000001205112574354552021654 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PARTICLE_SPHERE_EMITTER_H_INCLUDED__ #define __C_PARTICLE_SPHERE_EMITTER_H_INCLUDED__ #include "IParticleSphereEmitter.h" #include "irrArray.h" #include "aabbox3d.h" namespace irr { namespace scene { //! A default box emitter class CParticleSphereEmitter : public IParticleSphereEmitter { public: //! constructor CParticleSphereEmitter( const core::vector3df& center, f32 radius, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 20, u32 maxParticlesPerSecond = 40, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. virtual s32 emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray); //! Set direction the emitter emits particles virtual void setDirection( const core::vector3df& newDirection ) { Direction = newDirection; } //! Set minimum number of particles per second. virtual void setMinParticlesPerSecond( u32 minPPS ) { MinParticlesPerSecond = minPPS; } //! Set maximum number of particles per second. virtual void setMaxParticlesPerSecond( u32 maxPPS ) { MaxParticlesPerSecond = maxPPS; } //! Set minimum start color virtual void setMinStartColor( const video::SColor& color ) { MinStartColor = color; } //! Set maximum start color virtual void setMaxStartColor( const video::SColor& color ) { MaxStartColor = color; } //! Set the maximum starting size for particles virtual void setMaxStartSize( const core::dimension2df& size ) { MaxStartSize = size; } //! Set the minimum starting size for particles virtual void setMinStartSize( const core::dimension2df& size ) { MinStartSize = size; } //! Set the minimum particle life-time in milliseconds virtual void setMinLifeTime( u32 lifeTimeMin ) { MinLifeTime = lifeTimeMin; } //! Set the maximum particle life-time in milliseconds virtual void setMaxLifeTime( u32 lifeTimeMax ) { MaxLifeTime = lifeTimeMax; } //! Set maximal random derivation from the direction virtual void setMaxAngleDegrees( s32 maxAngleDegrees ) { MaxAngleDegrees = maxAngleDegrees; } //! Set the center of the sphere for particle emissions virtual void setCenter( const core::vector3df& center ) { Center = center; } //! Set the radius of the sphere for particle emissions virtual void setRadius( f32 radius ) { Radius = radius; } //! Gets direction the emitter emits particles virtual const core::vector3df& getDirection() const { return Direction; } //! Get minimum number of particles per second. virtual u32 getMinParticlesPerSecond() const { return MinParticlesPerSecond; } //! Get maximum number of particles per second. virtual u32 getMaxParticlesPerSecond() const { return MaxParticlesPerSecond; } //! Get minimum start color virtual const video::SColor& getMinStartColor() const { return MinStartColor; } //! Get maximum start color virtual const video::SColor& getMaxStartColor() const { return MaxStartColor; } //! Gets the maximum starting size for particles virtual const core::dimension2df& getMaxStartSize() const { return MaxStartSize; } //! Gets the minimum starting size for particles virtual const core::dimension2df& getMinStartSize() const { return MinStartSize; } //! Get the minimum particle life-time in milliseconds virtual u32 getMinLifeTime() const { return MinLifeTime; } //! Get the maximum particle life-time in milliseconds virtual u32 getMaxLifeTime() const { return MaxLifeTime; } //! Get maximal random derivation from the direction virtual s32 getMaxAngleDegrees() const { return MaxAngleDegrees; } //! Get the center of the sphere for particle emissions virtual const core::vector3df& getCenter() const { return Center; } //! Get the radius of the sphere for particle emissions virtual f32 getRadius() const { return Radius; } //! Writes attributes of the object. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: core::array Particles; core::vector3df Center; f32 Radius; core::vector3df Direction; core::dimension2df MinStartSize, MaxStartSize; u32 MinParticlesPerSecond, MaxParticlesPerSecond; video::SColor MinStartColor, MaxStartColor; u32 MinLifeTime, MaxLifeTime; u32 Time; u32 Emitted; s32 MaxAngleDegrees; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CParticleSphereEmitter.cpp0000644000000000000000000001363312574354552022216 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CParticleSphereEmitter.h" #include "os.h" #include "IAttributes.h" namespace irr { namespace scene { //! constructor CParticleSphereEmitter::CParticleSphereEmitter( const core::vector3df& center, f32 radius, const core::vector3df& direction, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize ) : Center(center), Radius(radius), Direction(direction), MinStartSize(minStartSize), MaxStartSize(maxStartSize), MinParticlesPerSecond(minParticlesPerSecond), MaxParticlesPerSecond(maxParticlesPerSecond), MinStartColor(minStartColor), MaxStartColor(maxStartColor), MinLifeTime(lifeTimeMin), MaxLifeTime(lifeTimeMax), Time(0), Emitted(0), MaxAngleDegrees(maxAngleDegrees) { #ifdef _DEBUG setDebugName("CParticleSphereEmitter"); #endif } //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. s32 CParticleSphereEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray) { Time += timeSinceLastCall; const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond; const f32 everyWhatMillisecond = 1000.0f / perSecond; if(Time > everyWhatMillisecond) { Particles.set_used(0); u32 amount = (u32)((Time / everyWhatMillisecond) + 0.5f); Time = 0; SParticle p; if(amount > MaxParticlesPerSecond*2) amount = MaxParticlesPerSecond * 2; for(u32 i=0; iaddVector3d("Center", Direction); out->addFloat("Radius", Radius); out->addVector3d("Direction", Direction); out->addFloat("MinStartSizeWidth", MinStartSize.Width); out->addFloat("MinStartSizeHeight", MinStartSize.Height); out->addFloat("MaxStartSizeWidth", MaxStartSize.Width); out->addFloat("MaxStartSizeHeight", MaxStartSize.Height); out->addInt("MinParticlesPerSecond", MinParticlesPerSecond); out->addInt("MaxParticlesPerSecond", MaxParticlesPerSecond); out->addColor("MinStartColor", MinStartColor); out->addColor("MaxStartColor", MaxStartColor); out->addInt("MinLifeTime", MinLifeTime); out->addInt("MaxLifeTime", MaxLifeTime); out->addInt("MaxAngleDegrees", MaxAngleDegrees); } //! Reads attributes of the object. void CParticleSphereEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Center = in->getAttributeAsVector3d("Center"); Radius = in->getAttributeAsFloat("Radius"); Direction = in->getAttributeAsVector3d("Direction"); if (Direction.getLength() == 0) Direction.set(0,0.01f,0); int idx = -1; idx = in->findAttribute("MinStartSizeWidth"); if ( idx >= 0 ) MinStartSize.Width = in->getAttributeAsFloat(idx); idx = in->findAttribute("MinStartSizeHeight"); if ( idx >= 0 ) MinStartSize.Height = in->getAttributeAsFloat(idx); idx = in->findAttribute("MaxStartSizeWidth"); if ( idx >= 0 ) MaxStartSize.Width = in->getAttributeAsFloat(idx); idx = in->findAttribute("MaxStartSizeHeight"); if ( idx >= 0 ) MaxStartSize.Height = in->getAttributeAsFloat(idx); MinParticlesPerSecond = in->getAttributeAsInt("MinParticlesPerSecond"); MaxParticlesPerSecond = in->getAttributeAsInt("MaxParticlesPerSecond"); MinParticlesPerSecond = core::max_(1u, MinParticlesPerSecond); MaxParticlesPerSecond = core::max_(MaxParticlesPerSecond, 1u); MaxParticlesPerSecond = core::min_(MaxParticlesPerSecond, 200u); MinParticlesPerSecond = core::min_(MinParticlesPerSecond, MaxParticlesPerSecond); MinStartColor = in->getAttributeAsColor("MinStartColor"); MaxStartColor = in->getAttributeAsColor("MaxStartColor"); MinLifeTime = in->getAttributeAsInt("MinLifeTime"); MaxLifeTime = in->getAttributeAsInt("MaxLifeTime"); MinLifeTime = core::max_(0u, MinLifeTime); MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime); MinLifeTime = core::min_(MinLifeTime, MaxLifeTime); MaxAngleDegrees = in->getAttributeAsInt("MaxAngleDegrees"); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CParticleScaleAffector.h0000644000000000000000000000275312574354552021605 0ustar rootroot// Copyright (C) 2010-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef C_PARTICLE_SCALE_AFFECTOR_H #define C_PARTICLE_SCALE_AFFECTOR_H #include namespace irr { namespace scene { class CParticleScaleAffector : public IParticleAffector { public: CParticleScaleAffector(const core::dimension2df& scaleTo = core::dimension2df(1.0f, 1.0f)); virtual void affect(u32 now, SParticle *particlearray, u32 count); //! Writes attributes of the object. //! Implement this to expose the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml serialization purposes. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. //! Implement this to set the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml deserialization purposes. //! \param startIndex: start index where to start reading attributes. //! \return: returns last index of an attribute read by this affector virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); //! Get emitter type virtual E_PARTICLE_AFFECTOR_TYPE getType() const; protected: core::dimension2df ScaleTo; }; } } #endif // C_PARTICLE_SCALE_AFFECTOR_H irrlicht-1.8.3/source/Irrlicht/CParticleScaleAffector.cpp0000644000000000000000000000271512574354552022136 0ustar rootroot// Copyright (C) 2010-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleScaleAffector.h" #include "IAttributes.h" namespace irr { namespace scene { CParticleScaleAffector::CParticleScaleAffector(const core::dimension2df& scaleTo) : ScaleTo(scaleTo) { #ifdef _DEBUG setDebugName("CParticleScaleAffector"); #endif } void CParticleScaleAffector::affect (u32 now, SParticle *particlearray, u32 count) { for(u32 i=0;iaddFloat("ScaleToWidth", ScaleTo.Width); out->addFloat("ScaleToHeight", ScaleTo.Height); } void CParticleScaleAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { ScaleTo.Width = in->getAttributeAsFloat("ScaleToWidth"); ScaleTo.Height = in->getAttributeAsFloat("ScaleToHeight"); } E_PARTICLE_AFFECTOR_TYPE CParticleScaleAffector::getType() const { return scene::EPAT_SCALE; } } } irrlicht-1.8.3/source/Irrlicht/CParticleRotationAffector.h0000644000000000000000000000331712574354552022352 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PARTICLE_ROTATION_AFFECTOR_H_INCLUDED__ #define __C_PARTICLE_ROTATION_AFFECTOR_H_INCLUDED__ #include "IParticleRotationAffector.h" namespace irr { namespace scene { //! Particle Affector for rotating particles about a point class CParticleRotationAffector : public IParticleRotationAffector { public: CParticleRotationAffector( const core::vector3df& speed = core::vector3df(5.0f, 5.0f, 5.0f), const core::vector3df& point = core::vector3df() ); //! Affects a particle. virtual void affect(u32 now, SParticle* particlearray, u32 count); //! Set the point that particles will attract to virtual void setPivotPoint( const core::vector3df& point ) { PivotPoint = point; } //! Set the speed in degrees per second virtual void setSpeed( const core::vector3df& speed ) { Speed = speed; } //! Get the point that particles are attracted to virtual const core::vector3df& getPivotPoint() const { return PivotPoint; } //! Get the speed in degrees per second virtual const core::vector3df& getSpeed() const { return Speed; } //! Writes attributes of the object. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: core::vector3df PivotPoint; core::vector3df Speed; u32 LastTime; }; } // end namespace scene } // end namespace irr #endif // __C_PARTICLE_ROTATION_AFFECTOR_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CParticleRotationAffector.cpp0000644000000000000000000000332212574354552022701 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleRotationAffector.h" #include "IAttributes.h" namespace irr { namespace scene { //! constructor CParticleRotationAffector::CParticleRotationAffector( const core::vector3df& speed, const core::vector3df& pivotPoint ) : PivotPoint(pivotPoint), Speed(speed), LastTime(0) { #ifdef _DEBUG setDebugName("CParticleRotationAffector"); #endif } //! Affects an array of particles. void CParticleRotationAffector::affect(u32 now, SParticle* particlearray, u32 count) { if( LastTime == 0 ) { LastTime = now; return; } f32 timeDelta = ( now - LastTime ) / 1000.0f; LastTime = now; if( !Enabled ) return; for(u32 i=0; iaddVector3d("PivotPoint", PivotPoint); out->addVector3d("Speed", Speed); } //! Reads attributes of the object. void CParticleRotationAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { PivotPoint = in->getAttributeAsVector3d("PivotPoint"); Speed = in->getAttributeAsVector3d("Speed"); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CPLYMeshWriter.h0000644000000000000000000000133412574354552020070 0ustar rootroot// Copyright (C) 2009-2012 Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_PLY_MESH_WRITER_H_INCLUDED__ #define __IRR_PLY_MESH_WRITER_H_INCLUDED__ #include "IMeshWriter.h" namespace irr { namespace scene { class IMeshBuffer; //! class to write PLY mesh files class CPLYMeshWriter : public IMeshWriter { public: CPLYMeshWriter(); //! Returns the type of the mesh writer virtual EMESH_WRITER_TYPE getType() const; //! writes a mesh virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE); }; } // end namespace } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/CParticleRingEmitter.h0000644000000000000000000001250712574354552021333 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PARTICLE_RING_EMITTER_H_INCLUDED__ #define __C_PARTICLE_RING_EMITTER_H_INCLUDED__ #include "IParticleRingEmitter.h" #include "irrArray.h" namespace irr { namespace scene { //! A ring emitter class CParticleRingEmitter : public IParticleRingEmitter { public: //! constructor CParticleRingEmitter( const core::vector3df& center, f32 radius, f32 ringThickness, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 20, u32 maxParticlesPerSecond = 40, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. virtual s32 emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray); //! Set direction the emitter emits particles virtual void setDirection( const core::vector3df& newDirection ) { Direction = newDirection; } //! Set minimum number of particles the emitter emits per second virtual void setMinParticlesPerSecond( u32 minPPS ) { MinParticlesPerSecond = minPPS; } //! Set maximum number of particles the emitter emits per second virtual void setMaxParticlesPerSecond( u32 maxPPS ) { MaxParticlesPerSecond = maxPPS; } //! Set minimum starting color for particles virtual void setMinStartColor( const video::SColor& color ) { MinStartColor = color; } //! Set maximum starting color for particles virtual void setMaxStartColor( const video::SColor& color ) { MaxStartColor = color; } //! Set the maximum starting size for particles virtual void setMaxStartSize( const core::dimension2df& size ) { MaxStartSize = size; } //! Set the minimum starting size for particles virtual void setMinStartSize( const core::dimension2df& size ) { MinStartSize = size; } //! Set the minimum particle life-time in milliseconds virtual void setMinLifeTime( u32 lifeTimeMin ) { MinLifeTime = lifeTimeMin; } //! Set the maximum particle life-time in milliseconds virtual void setMaxLifeTime( u32 lifeTimeMax ) { MaxLifeTime = lifeTimeMax; } //! Set maximal random derivation from the direction virtual void setMaxAngleDegrees( s32 maxAngleDegrees ) { MaxAngleDegrees = maxAngleDegrees; } //! Set the center of the ring virtual void setCenter( const core::vector3df& center ) { Center = center; } //! Set the radius of the ring virtual void setRadius( f32 radius ) { Radius = radius; } //! Set the thickness of the ring virtual void setRingThickness( f32 ringThickness ) { RingThickness = ringThickness; } //! Gets direction the emitter emits particles virtual const core::vector3df& getDirection() const { return Direction; } //! Gets the minimum number of particles the emitter emits per second virtual u32 getMinParticlesPerSecond() const { return MinParticlesPerSecond; } //! Gets the maximum number of particles the emitter emits per second virtual u32 getMaxParticlesPerSecond() const { return MaxParticlesPerSecond; } //! Gets the minimum starting color for particles virtual const video::SColor& getMinStartColor() const { return MinStartColor; } //! Gets the maximum starting color for particles virtual const video::SColor& getMaxStartColor() const { return MaxStartColor; } //! Gets the maximum starting size for particles virtual const core::dimension2df& getMaxStartSize() const { return MaxStartSize; } //! Gets the minimum starting size for particles virtual const core::dimension2df& getMinStartSize() const { return MinStartSize; } //! Get the minimum particle life-time in milliseconds virtual u32 getMinLifeTime() const { return MinLifeTime; } //! Get the maximum particle life-time in milliseconds virtual u32 getMaxLifeTime() const { return MaxLifeTime; } //! Get maximal random derivation from the direction virtual s32 getMaxAngleDegrees() const { return MaxAngleDegrees; } //! Get the center of the ring virtual const core::vector3df& getCenter() const { return Center; } //! Get the radius of the ring virtual f32 getRadius() const { return Radius; } //! Get the thickness of the ring virtual f32 getRingThickness() const { return RingThickness; } //! Writes attributes of the object. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: core::array Particles; core::vector3df Center; f32 Radius; f32 RingThickness; core::vector3df Direction; core::dimension2df MaxStartSize, MinStartSize; u32 MinParticlesPerSecond, MaxParticlesPerSecond; video::SColor MinStartColor, MaxStartColor; u32 MinLifeTime, MaxLifeTime; u32 Time; u32 Emitted; s32 MaxAngleDegrees; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CParticleRingEmitter.cpp0000644000000000000000000001373312574354552021670 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleRingEmitter.h" #include "os.h" #include "IAttributes.h" namespace irr { namespace scene { //! constructor CParticleRingEmitter::CParticleRingEmitter( const core::vector3df& center, f32 radius, f32 ringThickness, const core::vector3df& direction, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize ) : Center(center), Radius(radius), RingThickness(ringThickness), Direction(direction), MaxStartSize(maxStartSize), MinStartSize(minStartSize), MinParticlesPerSecond(minParticlesPerSecond), MaxParticlesPerSecond(maxParticlesPerSecond), MinStartColor(minStartColor), MaxStartColor(maxStartColor), MinLifeTime(lifeTimeMin), MaxLifeTime(lifeTimeMax), Time(0), Emitted(0), MaxAngleDegrees(maxAngleDegrees) { #ifdef _DEBUG setDebugName("CParticleRingEmitter"); #endif } //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. s32 CParticleRingEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray) { Time += timeSinceLastCall; u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond; f32 everyWhatMillisecond = 1000.0f / perSecond; if(Time > everyWhatMillisecond) { Particles.set_used(0); u32 amount = (u32)((Time / everyWhatMillisecond) + 0.5f); Time = 0; SParticle p; if(amount > MaxParticlesPerSecond*2) amount = MaxParticlesPerSecond * 2; for(u32 i=0; iaddVector3d("Center", Center); out->addFloat("Radius", Radius); out->addFloat("RingThickness", RingThickness); out->addVector3d("Direction", Direction); out->addFloat("MinStartSizeWidth", MinStartSize.Width); out->addFloat("MinStartSizeHeight", MinStartSize.Height); out->addFloat("MaxStartSizeWidth", MaxStartSize.Width); out->addFloat("MaxStartSizeHeight", MaxStartSize.Height); out->addInt("MinParticlesPerSecond", MinParticlesPerSecond); out->addInt("MaxParticlesPerSecond", MaxParticlesPerSecond); out->addColor("MinStartColor", MinStartColor); out->addColor("MaxStartColor", MaxStartColor); out->addInt("MinLifeTime", MinLifeTime); out->addInt("MaxLifeTime", MaxLifeTime); out->addInt("MaxAngleDegrees", MaxAngleDegrees); } //! Reads attributes of the object. void CParticleRingEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Center = in->getAttributeAsVector3d("Center"); Radius = in->getAttributeAsFloat("Radius"); RingThickness = in->getAttributeAsFloat("RingThickness"); Direction = in->getAttributeAsVector3d("Direction"); if (Direction.getLength() == 0) Direction.set(0,0.01f,0); int idx = -1; idx = in->findAttribute("MinStartSizeWidth"); if ( idx >= 0 ) MinStartSize.Width = in->getAttributeAsFloat(idx); idx = in->findAttribute("MinStartSizeHeight"); if ( idx >= 0 ) MinStartSize.Height = in->getAttributeAsFloat(idx); idx = in->findAttribute("MaxStartSizeWidth"); if ( idx >= 0 ) MaxStartSize.Width = in->getAttributeAsFloat(idx); idx = in->findAttribute("MaxStartSizeHeight"); if ( idx >= 0 ) MaxStartSize.Height = in->getAttributeAsFloat(idx); MinParticlesPerSecond = in->getAttributeAsInt("MinParticlesPerSecond"); MaxParticlesPerSecond = in->getAttributeAsInt("MaxParticlesPerSecond"); MinParticlesPerSecond = core::max_(1u, MinParticlesPerSecond); MaxParticlesPerSecond = core::max_(MaxParticlesPerSecond, 1u); MaxParticlesPerSecond = core::min_(MaxParticlesPerSecond, 200u); MinParticlesPerSecond = core::min_(MinParticlesPerSecond, MaxParticlesPerSecond); MinStartColor = in->getAttributeAsColor("MinStartColor"); MaxStartColor = in->getAttributeAsColor("MaxStartColor"); MinLifeTime = in->getAttributeAsInt("MinLifeTime"); MaxLifeTime = in->getAttributeAsInt("MaxLifeTime"); MinLifeTime = core::max_(0u, MinLifeTime); MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime); MinLifeTime = core::min_(MinLifeTime, MaxLifeTime); MaxAngleDegrees = in->getAttributeAsInt("MaxAngleDegrees"); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CParticlePointEmitter.h0000644000000000000000000001071012574354552021517 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PARTICLE_POINT_EMITTER_H_INCLUDED__ #define __C_PARTICLE_POINT_EMITTER_H_INCLUDED__ #include "IParticleEmitter.h" #include "irrArray.h" namespace irr { namespace scene { //! A default point emitter class CParticlePointEmitter : public IParticlePointEmitter { public: //! constructor CParticlePointEmitter( const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, video::SColor minStartColor = video::SColor(255,0,0,0), video::SColor maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. virtual s32 emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray); //! Set direction the emitter emits particles. virtual void setDirection( const core::vector3df& newDirection ) { Direction = newDirection; } //! Set minimum number of particles emitted per second. virtual void setMinParticlesPerSecond( u32 minPPS ) { MinParticlesPerSecond = minPPS; } //! Set maximum number of particles emitted per second. virtual void setMaxParticlesPerSecond( u32 maxPPS ) { MaxParticlesPerSecond = maxPPS; } //! Set minimum start color. virtual void setMinStartColor( const video::SColor& color ) { MinStartColor = color; } //! Set maximum start color. virtual void setMaxStartColor( const video::SColor& color ) { MaxStartColor = color; } //! Set the maximum starting size for particles virtual void setMaxStartSize( const core::dimension2df& size ) { MaxStartSize = size; } //! Set the minimum starting size for particles virtual void setMinStartSize( const core::dimension2df& size ) { MinStartSize = size; } //! Set the minimum particle life-time in milliseconds virtual void setMinLifeTime( u32 lifeTimeMin ) { MinLifeTime = lifeTimeMin; } //! Set the maximum particle life-time in milliseconds virtual void setMaxLifeTime( u32 lifeTimeMax ) { MaxLifeTime = lifeTimeMax; } //! Set maximal random derivation from the direction virtual void setMaxAngleDegrees( s32 maxAngleDegrees ) { MaxAngleDegrees = maxAngleDegrees; } //! Gets direction the emitter emits particles. virtual const core::vector3df& getDirection() const { return Direction; } //! Gets minimum number of particles emitted per second. virtual u32 getMinParticlesPerSecond() const { return MinParticlesPerSecond; } //! Gets maximum number of particles emitted per second. virtual u32 getMaxParticlesPerSecond() const { return MaxParticlesPerSecond; } //! Gets minimum start color. virtual const video::SColor& getMinStartColor() const { return MinStartColor; } //! Gets maximum start color. virtual const video::SColor& getMaxStartColor() const { return MaxStartColor; } //! Gets the maximum starting size for particles virtual const core::dimension2df& getMaxStartSize() const { return MaxStartSize; } //! Gets the minimum starting size for particles virtual const core::dimension2df& getMinStartSize() const { return MinStartSize; } //! Get the minimum particle life-time in milliseconds virtual u32 getMinLifeTime() const { return MinLifeTime; } //! Get the maximum particle life-time in milliseconds virtual u32 getMaxLifeTime() const { return MaxLifeTime; } //! Get maximal random derivation from the direction virtual s32 getMaxAngleDegrees() const { return MaxAngleDegrees; } //! Writes attributes of the object. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: SParticle Particle; core::vector3df Direction; core::dimension2df MinStartSize, MaxStartSize; u32 MinParticlesPerSecond, MaxParticlesPerSecond; video::SColor MinStartColor, MaxStartColor; u32 MinLifeTime, MaxLifeTime; s32 MaxAngleDegrees; u32 Time; u32 Emitted; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CParticlePointEmitter.cpp0000644000000000000000000001207312574354552022056 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticlePointEmitter.h" #include "os.h" #include "IAttributes.h" namespace irr { namespace scene { //! constructor CParticlePointEmitter::CParticlePointEmitter( const core::vector3df& direction, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, video::SColor minStartColor, video::SColor maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize) : Direction(direction), MinStartSize(minStartSize), MaxStartSize(maxStartSize), MinParticlesPerSecond(minParticlesPerSecond), MaxParticlesPerSecond(maxParticlesPerSecond), MinStartColor(minStartColor), MaxStartColor(maxStartColor), MinLifeTime(lifeTimeMin), MaxLifeTime(lifeTimeMax), MaxAngleDegrees(maxAngleDegrees), Time(0), Emitted(0) { #ifdef _DEBUG setDebugName("CParticlePointEmitter"); #endif } //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. s32 CParticlePointEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray) { Time += timeSinceLastCall; const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond; const f32 everyWhatMillisecond = 1000.0f / perSecond; if (Time > everyWhatMillisecond) { Time = 0; Particle.startTime = now; Particle.vector = Direction; if (MaxAngleDegrees) { core::vector3df tgt = Direction; tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees); Particle.vector = tgt; } Particle.endTime = now + MinLifeTime; if (MaxLifeTime != MinLifeTime) Particle.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime); if (MinStartColor==MaxStartColor) Particle.color=MinStartColor; else Particle.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand()); Particle.startColor = Particle.color; Particle.startVector = Particle.vector; if (MinStartSize==MaxStartSize) Particle.startSize = MinStartSize; else Particle.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand()); Particle.size = Particle.startSize; outArray = &Particle; return 1; } return 0; } //! Writes attributes of the object. void CParticlePointEmitter::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addVector3d("Direction", Direction); out->addFloat("MinStartSizeWidth", MinStartSize.Width); out->addFloat("MinStartSizeHeight", MinStartSize.Height); out->addFloat("MaxStartSizeWidth", MaxStartSize.Width); out->addFloat("MaxStartSizeHeight", MaxStartSize.Height); out->addInt("MinParticlesPerSecond", MinParticlesPerSecond); out->addInt("MaxParticlesPerSecond", MaxParticlesPerSecond); out->addColor("MinStartColor", MinStartColor); out->addColor("MaxStartColor", MaxStartColor); out->addInt("MinLifeTime", MinLifeTime); out->addInt("MaxLifeTime", MaxLifeTime); out->addInt("MaxAngleDegrees", MaxAngleDegrees); } //! Reads attributes of the object. void CParticlePointEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Direction = in->getAttributeAsVector3d("Direction"); if (Direction.getLength() == 0) Direction.set(0,0.01f,0); int idx = -1; idx = in->findAttribute("MinStartSizeWidth"); if ( idx >= 0 ) MinStartSize.Width = in->getAttributeAsFloat(idx); idx = in->findAttribute("MinStartSizeHeight"); if ( idx >= 0 ) MinStartSize.Height = in->getAttributeAsFloat(idx); idx = in->findAttribute("MaxStartSizeWidth"); if ( idx >= 0 ) MaxStartSize.Width = in->getAttributeAsFloat(idx); idx = in->findAttribute("MaxStartSizeHeight"); if ( idx >= 0 ) MaxStartSize.Height = in->getAttributeAsFloat(idx); MinParticlesPerSecond = in->getAttributeAsInt("MinParticlesPerSecond"); MaxParticlesPerSecond = in->getAttributeAsInt("MaxParticlesPerSecond"); MinParticlesPerSecond = core::max_(1u, MinParticlesPerSecond); MaxParticlesPerSecond = core::max_(MaxParticlesPerSecond, 1u); MaxParticlesPerSecond = core::min_(MaxParticlesPerSecond, 200u); MinParticlesPerSecond = core::min_(MinParticlesPerSecond, MaxParticlesPerSecond); MinStartColor = in->getAttributeAsColor("MinStartColor"); MaxStartColor = in->getAttributeAsColor("MaxStartColor"); MinLifeTime = in->getAttributeAsInt("MinLifeTime"); MaxLifeTime = in->getAttributeAsInt("MaxLifeTime"); MaxAngleDegrees = in->getAttributeAsInt("MaxAngleDegrees"); MinLifeTime = core::max_(0u, MinLifeTime); MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime); MinLifeTime = core::min_(MinLifeTime, MaxLifeTime); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CParticleMeshEmitter.h0000644000000000000000000001404412574354552021326 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PARTICLE_MESH_EMITTER_H_INCLUDED__ #define __C_PARTICLE_MESH_EMITTER_H_INCLUDED__ #include "IParticleMeshEmitter.h" #include "irrArray.h" #include "aabbox3d.h" #include "IMeshBuffer.h" namespace irr { namespace scene { //! A default box emitter class CParticleMeshEmitter : public IParticleMeshEmitter { public: //! constructor CParticleMeshEmitter( IMesh* mesh, bool useNormalDirection = true, const core::vector3df& direction = core::vector3df(0.0f,0.0f,0.0f), f32 normalDirectionModifier = 100.0f, s32 mbNumber = -1, bool everyMeshVertex = false, u32 minParticlesPerSecond = 20, u32 maxParticlesPerSecond = 40, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin = 2000, u32 lifeTimeMax = 4000, s32 maxAngleDegrees = 0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. virtual s32 emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray); //! Set Mesh to emit particles from virtual void setMesh( IMesh* mesh ); //! Set whether to use vertex normal for direction, or direction specified virtual void setUseNormalDirection( bool useNormalDirection ) { UseNormalDirection = useNormalDirection; } //! Set direction the emitter emits particles virtual void setDirection( const core::vector3df& newDirection ) { Direction = newDirection; } //! Set the amount that the normal is divided by for getting a particles direction virtual void setNormalDirectionModifier( f32 normalDirectionModifier ) { NormalDirectionModifier = normalDirectionModifier; } //! Sets whether to emit min<->max particles for every vertex per second, or to pick //! min<->max vertices every second virtual void setEveryMeshVertex( bool everyMeshVertex ) { EveryMeshVertex = everyMeshVertex; } //! Set minimum number of particles the emitter emits per second virtual void setMinParticlesPerSecond( u32 minPPS ) { MinParticlesPerSecond = minPPS; } //! Set maximum number of particles the emitter emits per second virtual void setMaxParticlesPerSecond( u32 maxPPS ) { MaxParticlesPerSecond = maxPPS; } //! Set minimum starting color for particles virtual void setMinStartColor( const video::SColor& color ) { MinStartColor = color; } //! Set maximum starting color for particles virtual void setMaxStartColor( const video::SColor& color ) { MaxStartColor = color; } //! Set the maximum starting size for particles virtual void setMaxStartSize( const core::dimension2df& size ) { MaxStartSize = size; } //! Set the minimum starting size for particles virtual void setMinStartSize( const core::dimension2df& size ) { MinStartSize = size; } //! Set the minimum particle life-time in milliseconds virtual void setMinLifeTime( u32 lifeTimeMin ) { MinLifeTime = lifeTimeMin; } //! Set the maximum particle life-time in milliseconds virtual void setMaxLifeTime( u32 lifeTimeMax ) { MaxLifeTime = lifeTimeMax; } //! Set maximal random derivation from the direction virtual void setMaxAngleDegrees( s32 maxAngleDegrees ) { MaxAngleDegrees = maxAngleDegrees; } //! Get Mesh we're emitting particles from virtual const IMesh* getMesh() const { return Mesh; } //! Get whether to use vertex normal for direciton, or direction specified virtual bool isUsingNormalDirection() const { return UseNormalDirection; } //! Get direction the emitter emits particles virtual const core::vector3df& getDirection() const { return Direction; } //! Get the amount that the normal is divided by for getting a particles direction virtual f32 getNormalDirectionModifier() const { return NormalDirectionModifier; } //! Gets whether to emit min<->max particles for every vertex per second, or to pick //! min<->max vertices every second virtual bool getEveryMeshVertex() const { return EveryMeshVertex; } //! Get the minimum number of particles the emitter emits per second virtual u32 getMinParticlesPerSecond() const { return MinParticlesPerSecond; } //! Get the maximum number of particles the emitter emits per second virtual u32 getMaxParticlesPerSecond() const { return MaxParticlesPerSecond; } //! Get the minimum starting color for particles virtual const video::SColor& getMinStartColor() const { return MinStartColor; } //! Get the maximum starting color for particles virtual const video::SColor& getMaxStartColor() const { return MaxStartColor; } //! Gets the maximum starting size for particles virtual const core::dimension2df& getMaxStartSize() const { return MaxStartSize; } //! Gets the minimum starting size for particles virtual const core::dimension2df& getMinStartSize() const { return MinStartSize; } //! Get the minimum particle life-time in milliseconds virtual u32 getMinLifeTime() const { return MinLifeTime; } //! Get the maximum particle life-time in milliseconds virtual u32 getMaxLifeTime() const { return MaxLifeTime; } //! Get maximal random derivation from the direction virtual s32 getMaxAngleDegrees() const { return MaxAngleDegrees; } private: const IMesh* Mesh; core::array VertexPerMeshBufferList; s32 TotalVertices; u32 MBCount; s32 MBNumber; f32 NormalDirectionModifier; core::array Particles; core::vector3df Direction; core::dimension2df MaxStartSize, MinStartSize; u32 MinParticlesPerSecond, MaxParticlesPerSecond; video::SColor MinStartColor, MaxStartColor; u32 MinLifeTime, MaxLifeTime; u32 Time; u32 Emitted; s32 MaxAngleDegrees; bool EveryMeshVertex; bool UseNormalDirection; }; } // end namespace scene } // end namespace irr #endif // __C_PARTICLE_MESH_EMITTER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CParticleMeshEmitter.cpp0000644000000000000000000001303312574354552021656 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CParticleMeshEmitter.h" #include "os.h" namespace irr { namespace scene { //! constructor CParticleMeshEmitter::CParticleMeshEmitter( IMesh* mesh, bool useNormalDirection, const core::vector3df& direction, f32 normalDirectionModifier, s32 mbNumber, bool everyMeshVertex, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize ) : Mesh(0), TotalVertices(0), MBCount(0), MBNumber(mbNumber), NormalDirectionModifier(normalDirectionModifier), Direction(direction), MaxStartSize(maxStartSize), MinStartSize(minStartSize), MinParticlesPerSecond(minParticlesPerSecond), MaxParticlesPerSecond(maxParticlesPerSecond), MinStartColor(minStartColor), MaxStartColor(maxStartColor), MinLifeTime(lifeTimeMin), MaxLifeTime(lifeTimeMax), Time(0), Emitted(0), MaxAngleDegrees(maxAngleDegrees), EveryMeshVertex(everyMeshVertex), UseNormalDirection(useNormalDirection) { #ifdef _DEBUG setDebugName("CParticleMeshEmitter"); #endif setMesh(mesh); } //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray) { Time += timeSinceLastCall; const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond; const f32 everyWhatMillisecond = 1000.0f / perSecond; if(Time > everyWhatMillisecond) { Particles.set_used(0); u32 amount = (u32)((Time / everyWhatMillisecond) + 0.5f); Time = 0; SParticle p; if(amount > MaxParticlesPerSecond * 2) amount = MaxParticlesPerSecond * 2; for(u32 i=0; igetMeshBufferCount(); ++j ) { for( u32 k=0; kgetMeshBuffer(j)->getVertexCount(); ++k ) { p.pos = Mesh->getMeshBuffer(j)->getPosition(k); if( UseNormalDirection ) p.vector = Mesh->getMeshBuffer(j)->getNormal(k) / NormalDirectionModifier; else p.vector = Direction; p.startTime = now; if( MaxAngleDegrees ) { core::vector3df tgt = p.vector; tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees); p.vector = tgt; } p.endTime = now + MinLifeTime; if (MaxLifeTime != MinLifeTime) p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime); if (MinStartColor==MaxStartColor) p.color=MinStartColor; else p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand()); p.startColor = p.color; p.startVector = p.vector; if (MinStartSize==MaxStartSize) p.startSize = MinStartSize; else p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand()); p.size = p.startSize; Particles.push_back(p); } } } else { const s32 randomMB = (MBNumber < 0) ? (os::Randomizer::rand() % MBCount) : MBNumber; u32 vertexNumber = Mesh->getMeshBuffer(randomMB)->getVertexCount(); if (!vertexNumber) continue; vertexNumber = os::Randomizer::rand() % vertexNumber; p.pos = Mesh->getMeshBuffer(randomMB)->getPosition(vertexNumber); if( UseNormalDirection ) p.vector = Mesh->getMeshBuffer(randomMB)->getNormal(vertexNumber) / NormalDirectionModifier; else p.vector = Direction; p.startTime = now; if( MaxAngleDegrees ) { core::vector3df tgt = Direction; tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees); p.vector = tgt; } p.endTime = now + MinLifeTime; if (MaxLifeTime != MinLifeTime) p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime); if (MinStartColor==MaxStartColor) p.color=MinStartColor; else p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand()); p.startColor = p.color; p.startVector = p.vector; if (MinStartSize==MaxStartSize) p.startSize = MinStartSize; else p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand()); p.size = p.startSize; Particles.push_back(p); } } outArray = Particles.pointer(); return Particles.size(); } return 0; } //! Set Mesh to emit particles from void CParticleMeshEmitter::setMesh(IMesh* mesh) { Mesh = mesh; TotalVertices = 0; MBCount = 0; VertexPerMeshBufferList.clear(); if ( !Mesh ) return; MBCount = Mesh->getMeshBufferCount(); VertexPerMeshBufferList.reallocate(MBCount); for( u32 i = 0; i < MBCount; ++i ) { VertexPerMeshBufferList.push_back( Mesh->getMeshBuffer(i)->getVertexCount() ); TotalVertices += Mesh->getMeshBuffer(i)->getVertexCount(); } } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CParticleGravityAffector.h0000644000000000000000000000433312574354552022177 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PARTICLE_GRAVITY_AFFECTOR_H_INCLUDED__ #define __C_PARTICLE_GRAVITY_AFFECTOR_H_INCLUDED__ #include "IParticleGravityAffector.h" #include "SColor.h" namespace irr { namespace scene { //! Particle Affector for affecting direction of particle class CParticleGravityAffector : public IParticleGravityAffector { public: CParticleGravityAffector( const core::vector3df& gravity = core::vector3df(0.0f,-0.03f,0.0f), u32 timeForceLost = 1000); //! Affects a particle. virtual void affect(u32 now, SParticle* particlearray, u32 count); //! Set the time in milliseconds when the gravity force is totally //! lost and the particle does not move any more. virtual void setTimeForceLost( f32 timeForceLost ) { TimeForceLost = timeForceLost; } //! Set the direction and force of gravity. virtual void setGravity( const core::vector3df& gravity ) { Gravity = gravity; } //! Set the time in milliseconds when the gravity force is totally //! lost and the particle does not move any more. virtual f32 getTimeForceLost() const { return TimeForceLost; } //! Set the direction and force of gravity. virtual const core::vector3df& getGravity() const { return Gravity; } //! Writes attributes of the object. //! Implement this to expose the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml serialization purposes. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. //! Implement this to set the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml deserialization purposes. //! \param startIndex: start index where to start reading attributes. //! \return: returns last index of an attribute read by this affector virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: f32 TimeForceLost; core::vector3df Gravity; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CParticleGravityAffector.cpp0000644000000000000000000000312012574354552022523 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleGravityAffector.h" #include "os.h" #include "IAttributes.h" namespace irr { namespace scene { //! constructor CParticleGravityAffector::CParticleGravityAffector( const core::vector3df& gravity, u32 timeForceLost) : IParticleGravityAffector(), TimeForceLost(static_cast(timeForceLost)), Gravity(gravity) { #ifdef _DEBUG setDebugName("CParticleGravityAffector"); #endif } //! Affects an array of particles. void CParticleGravityAffector::affect(u32 now, SParticle* particlearray, u32 count) { if (!Enabled) return; f32 d; for (u32 i=0; i 1.0f) d = 1.0f; if (d < 0.0f) d = 0.0f; d = 1.0f - d; particlearray[i].vector = particlearray[i].startVector.getInterpolated(Gravity, d); } } //! Writes attributes of the object. void CParticleGravityAffector::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addVector3d("Gravity", Gravity); out->addFloat("TimeForceLost", TimeForceLost); } //! Reads attributes of the object. void CParticleGravityAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Gravity = in->getAttributeAsVector3d("Gravity"); TimeForceLost = in->getAttributeAsFloat("TimeForceLost"); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CParticleFadeOutAffector.h0000644000000000000000000000433312574354552022101 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PARTICLE_FADE_OUT_AFFECTOR_H_INCLUDED__ #define __C_PARTICLE_FADE_OUT_AFFECTOR_H_INCLUDED__ #include "IParticleFadeOutAffector.h" #include "SColor.h" namespace irr { namespace scene { //! Particle Affector for fading out a color class CParticleFadeOutAffector : public IParticleFadeOutAffector { public: CParticleFadeOutAffector(const video::SColor& targetColor, u32 fadeOutTime); //! Affects a particle. virtual void affect(u32 now, SParticle* particlearray, u32 count); //! Sets the targetColor, i.e. the color the particles will interpolate //! to over time. virtual void setTargetColor( const video::SColor& targetColor ) { TargetColor = targetColor; } //! Sets the amount of time it takes for each particle to fade out. virtual void setFadeOutTime( u32 fadeOutTime ) { FadeOutTime = fadeOutTime ? static_cast(fadeOutTime) : 1.0f; } //! Sets the targetColor, i.e. the color the particles will interpolate //! to over time. virtual const video::SColor& getTargetColor() const { return TargetColor; } //! Sets the amount of time it takes for each particle to fade out. virtual u32 getFadeOutTime() const { return static_cast(FadeOutTime); } //! Writes attributes of the object. //! Implement this to expose the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml serialization purposes. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. //! Implement this to set the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml deserialization purposes. //! \param startIndex: start index where to start reading attributes. //! \return: returns last index of an attribute read by this affector virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: video::SColor TargetColor; f32 FadeOutTime; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CParticleFadeOutAffector.cpp0000644000000000000000000000414212574354552022432 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleFadeOutAffector.h" #include "IAttributes.h" #include "os.h" namespace irr { namespace scene { //! constructor CParticleFadeOutAffector::CParticleFadeOutAffector( const video::SColor& targetColor, u32 fadeOutTime) : IParticleFadeOutAffector(), TargetColor(targetColor) { #ifdef _DEBUG setDebugName("CParticleFadeOutAffector"); #endif FadeOutTime = fadeOutTime ? static_cast(fadeOutTime) : 1.0f; } //! Affects an array of particles. void CParticleFadeOutAffector::affect(u32 now, SParticle* particlearray, u32 count) { if (!Enabled) return; f32 d; for (u32 i=0; iaddColor("TargetColor", TargetColor); out->addFloat("FadeOutTime", FadeOutTime); } //! Reads attributes of the object. //! Implement this to set the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml deserialization purposes. //! \param startIndex: start index where to start reading attributes. //! \return: returns last index of an attribute read by this affector void CParticleFadeOutAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { TargetColor = in->getAttributeAsColor("TargetColor"); FadeOutTime = in->getAttributeAsFloat("FadeOutTime"); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CParticleCylinderEmitter.h0000644000000000000000000001354512574354552022210 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PARTICLE_CYLINDER_EMITTER_H_INCLUDED__ #define __C_PARTICLE_CYLINDER_EMITTER_H_INCLUDED__ #include "IParticleCylinderEmitter.h" #include "irrArray.h" namespace irr { namespace scene { //! A default box emitter class CParticleCylinderEmitter : public IParticleCylinderEmitter { public: //! constructor CParticleCylinderEmitter( const core::vector3df& center, f32 radius, const core::vector3df& normal, f32 length, bool outlineOnly = false, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 20, u32 maxParticlesPerSecond = 40, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. virtual s32 emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray); //! Set the center of the radius for the cylinder, at one end of the cylinder virtual void setCenter( const core::vector3df& center ) { Center = center; } //! Set the normal of the cylinder virtual void setNormal( const core::vector3df& normal ) { Normal = normal; } //! Set the radius of the cylinder virtual void setRadius( f32 radius ) { Radius = radius; } //! Set the length of the cylinder virtual void setLength( f32 length ) { Length = length; } //! Set whether or not to draw points inside the cylinder virtual void setOutlineOnly( bool outlineOnly ) { OutlineOnly = outlineOnly; } //! Set direction the emitter emits particles virtual void setDirection( const core::vector3df& newDirection ) { Direction = newDirection; } //! Set direction the emitter emits particles virtual void setMinParticlesPerSecond( u32 minPPS ) { MinParticlesPerSecond = minPPS; } //! Set direction the emitter emits particles virtual void setMaxParticlesPerSecond( u32 maxPPS ) { MaxParticlesPerSecond = maxPPS; } //! Set direction the emitter emits particles virtual void setMinStartColor( const video::SColor& color ) { MinStartColor = color; } //! Set direction the emitter emits particles virtual void setMaxStartColor( const video::SColor& color ) { MaxStartColor = color; } //! Set the maximum starting size for particles virtual void setMaxStartSize( const core::dimension2df& size ) { MaxStartSize = size; } //! Set the minimum starting size for particles virtual void setMinStartSize( const core::dimension2df& size ) { MinStartSize = size; } //! Set the minimum particle life-time in milliseconds virtual void setMinLifeTime( u32 lifeTimeMin ) { MinLifeTime = lifeTimeMin; } //! Set the maximum particle life-time in milliseconds virtual void setMaxLifeTime( u32 lifeTimeMax ) { MaxLifeTime = lifeTimeMax; } //! Maximal random derivation from the direction virtual void setMaxAngleDegrees( s32 maxAngleDegrees ) { MaxAngleDegrees = maxAngleDegrees; } //! Get the center of the cylinder virtual const core::vector3df& getCenter() const { return Center; } //! Get the normal of the cylinder virtual const core::vector3df& getNormal() const { return Normal; } //! Get the radius of the cylinder virtual f32 getRadius() const { return Radius; } //! Get the center of the cylinder virtual f32 getLength() const { return Length; } //! Get whether or not to draw points inside the cylinder virtual bool getOutlineOnly() const { return OutlineOnly; } //! Gets direction the emitter emits particles virtual const core::vector3df& getDirection() const { return Direction; } //! Gets direction the emitter emits particles virtual u32 getMinParticlesPerSecond() const { return MinParticlesPerSecond; } //! Gets direction the emitter emits particles virtual u32 getMaxParticlesPerSecond() const { return MaxParticlesPerSecond; } //! Gets direction the emitter emits particles virtual const video::SColor& getMinStartColor() const { return MinStartColor; } //! Gets direction the emitter emits particles virtual const video::SColor& getMaxStartColor() const { return MaxStartColor; } //! Gets the maximum starting size for particles virtual const core::dimension2df& getMaxStartSize() const { return MaxStartSize; } //! Gets the minimum starting size for particles virtual const core::dimension2df& getMinStartSize() const { return MinStartSize; } //! Get the minimum particle life-time in milliseconds virtual u32 getMinLifeTime() const { return MinLifeTime; } //! Get the maximum particle life-time in milliseconds virtual u32 getMaxLifeTime() const { return MaxLifeTime; } //! Maximal random derivation from the direction virtual s32 getMaxAngleDegrees() const { return MaxAngleDegrees; } //! Writes attributes of the object. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: core::array Particles; core::vector3df Center; core::vector3df Normal; core::vector3df Direction; core::dimension2df MaxStartSize, MinStartSize; u32 MinParticlesPerSecond, MaxParticlesPerSecond; video::SColor MinStartColor, MaxStartColor; u32 MinLifeTime, MaxLifeTime; f32 Radius; f32 Length; u32 Time; u32 Emitted; s32 MaxAngleDegrees; bool OutlineOnly; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CParticleCylinderEmitter.cpp0000644000000000000000000001467512574354552022550 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleCylinderEmitter.h" #include "os.h" #include "IAttributes.h" namespace irr { namespace scene { //! constructor CParticleCylinderEmitter::CParticleCylinderEmitter( const core::vector3df& center, f32 radius, const core::vector3df& normal, f32 length, bool outlineOnly, const core::vector3df& direction, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize ) : Center(center), Normal(normal), Direction(direction), MaxStartSize(maxStartSize), MinStartSize(minStartSize), MinParticlesPerSecond(minParticlesPerSecond), MaxParticlesPerSecond(maxParticlesPerSecond), MinStartColor(minStartColor), MaxStartColor(maxStartColor), MinLifeTime(lifeTimeMin), MaxLifeTime(lifeTimeMax), Radius(radius), Length(length), Time(0), Emitted(0), MaxAngleDegrees(maxAngleDegrees), OutlineOnly(outlineOnly) { #ifdef _DEBUG setDebugName("CParticleCylinderEmitter"); #endif } //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. s32 CParticleCylinderEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray) { Time += timeSinceLastCall; const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond; const f32 everyWhatMillisecond = 1000.0f / perSecond; if(Time > everyWhatMillisecond) { Particles.set_used(0); u32 amount = (u32)((Time / everyWhatMillisecond) + 0.5f); Time = 0; SParticle p; if(amount > MaxParticlesPerSecond*2) amount = MaxParticlesPerSecond * 2; for(u32 i=0; iaddVector3d("Center", Center); out->addVector3d("Normal", Normal); out->addVector3d("Direction", Direction); out->addFloat("MinStartSizeWidth", MinStartSize.Width); out->addFloat("MinStartSizeHeight", MinStartSize.Height); out->addFloat("MaxStartSizeWidth", MaxStartSize.Width); out->addFloat("MaxStartSizeHeight", MaxStartSize.Height); out->addInt("MinParticlesPerSecond", MinParticlesPerSecond); out->addInt("MaxParticlesPerSecond", MaxParticlesPerSecond); out->addColor("MinStartColor", MinStartColor); out->addColor("MaxStartColor", MaxStartColor); out->addInt("MinLifeTime", MinLifeTime); out->addInt("MaxLifeTime", MaxLifeTime); out->addFloat("Radius", Radius); out->addFloat("Length", Length); out->addInt("MaxAngleDegrees", MaxAngleDegrees); out->addBool("OutlineOnly", OutlineOnly); } //! Reads attributes of the object. void CParticleCylinderEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Center = in->getAttributeAsVector3d("Center"); Normal = in->getAttributeAsVector3d("Normal"); if (Normal.getLength() == 0) Normal.set(0,1.f,0); Direction = in->getAttributeAsVector3d("Direction"); if (Direction.getLength() == 0) Direction.set(0,0.01f,0); int idx = -1; idx = in->findAttribute("MinStartSizeWidth"); if ( idx >= 0 ) MinStartSize.Width = in->getAttributeAsFloat(idx); idx = in->findAttribute("MinStartSizeHeight"); if ( idx >= 0 ) MinStartSize.Height = in->getAttributeAsFloat(idx); idx = in->findAttribute("MaxStartSizeWidth"); if ( idx >= 0 ) MaxStartSize.Width = in->getAttributeAsFloat(idx); idx = in->findAttribute("MaxStartSizeHeight"); if ( idx >= 0 ) MaxStartSize.Height = in->getAttributeAsFloat(idx); MinParticlesPerSecond = in->getAttributeAsInt("MinParticlesPerSecond"); MaxParticlesPerSecond = in->getAttributeAsInt("MaxParticlesPerSecond"); MinParticlesPerSecond = core::max_(1u, MinParticlesPerSecond); MaxParticlesPerSecond = core::max_(MaxParticlesPerSecond, 1u); MaxParticlesPerSecond = core::min_(MaxParticlesPerSecond, 200u); MinParticlesPerSecond = core::min_(MinParticlesPerSecond, MaxParticlesPerSecond); MinStartColor = in->getAttributeAsColor("MinStartColor"); MaxStartColor = in->getAttributeAsColor("MaxStartColor"); MinLifeTime = in->getAttributeAsInt("MinLifeTime"); MaxLifeTime = in->getAttributeAsInt("MaxLifeTime"); MinLifeTime = core::max_(0u, MinLifeTime); MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime); MinLifeTime = core::min_(MinLifeTime, MaxLifeTime); Radius = in->getAttributeAsFloat("Radius"); Length = in->getAttributeAsFloat("Length"); MaxAngleDegrees = in->getAttributeAsInt("MaxAngleDegrees"); OutlineOnly = in->getAttributeAsBool("OutlineOnly"); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CParticleBoxEmitter.h0000644000000000000000000001140712574354552021162 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PARTICLE_BOX_EMITTER_H_INCLUDED__ #define __C_PARTICLE_BOX_EMITTER_H_INCLUDED__ #include "IParticleBoxEmitter.h" #include "irrArray.h" #include "aabbox3d.h" namespace irr { namespace scene { //! A default box emitter class CParticleBoxEmitter : public IParticleBoxEmitter { public: //! constructor CParticleBoxEmitter( const core::aabbox3df& box, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 20, u32 maxParticlesPerSecond = 40, video::SColor minStartColor = video::SColor(255,0,0,0), video::SColor maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. virtual s32 emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray); //! Set direction the emitter emits particles. virtual void setDirection( const core::vector3df& newDirection ) { Direction = newDirection; } //! Set minimum number of particles emitted per second. virtual void setMinParticlesPerSecond( u32 minPPS ) { MinParticlesPerSecond = minPPS; } //! Set maximum number of particles emitted per second. virtual void setMaxParticlesPerSecond( u32 maxPPS ) { MaxParticlesPerSecond = maxPPS; } //! Set minimum start color. virtual void setMinStartColor( const video::SColor& color ) { MinStartColor = color; } //! Set maximum start color. virtual void setMaxStartColor( const video::SColor& color ) { MaxStartColor = color; } //! Set the maximum starting size for particles virtual void setMaxStartSize( const core::dimension2df& size ) { MaxStartSize = size; }; //! Set the minimum starting size for particles virtual void setMinStartSize( const core::dimension2df& size ) { MinStartSize = size; }; //! Set the minimum particle life-time in milliseconds virtual void setMinLifeTime( u32 lifeTimeMin ) { MinLifeTime = lifeTimeMin; } //! Set the maximum particle life-time in milliseconds virtual void setMaxLifeTime( u32 lifeTimeMax ) { MaxLifeTime = lifeTimeMax; } //! Maximal random derivation from the direction virtual void setMaxAngleDegrees( s32 maxAngleDegrees ) { MaxAngleDegrees = maxAngleDegrees; } //! Set box from which the particles are emitted. virtual void setBox( const core::aabbox3df& box ) { Box = box; } //! Gets direction the emitter emits particles. virtual const core::vector3df& getDirection() const { return Direction; } //! Gets minimum number of particles emitted per second. virtual u32 getMinParticlesPerSecond() const { return MinParticlesPerSecond; } //! Gets maximum number of particles emitted per second. virtual u32 getMaxParticlesPerSecond() const { return MaxParticlesPerSecond; } //! Gets minimum start color. virtual const video::SColor& getMinStartColor() const { return MinStartColor; } //! Gets maximum start color. virtual const video::SColor& getMaxStartColor() const { return MaxStartColor; } //! Gets the maximum starting size for particles virtual const core::dimension2df& getMaxStartSize() const { return MaxStartSize; } //! Gets the minimum starting size for particles virtual const core::dimension2df& getMinStartSize() const { return MinStartSize; } //! Get the minimum particle life-time in milliseconds virtual u32 getMinLifeTime() const { return MinLifeTime; } //! Get the maximum particle life-time in milliseconds virtual u32 getMaxLifeTime() const { return MaxLifeTime; } //! Maximal random derivation from the direction virtual s32 getMaxAngleDegrees() const { return MaxAngleDegrees; } //! Get box from which the particles are emitted. virtual const core::aabbox3df& getBox() const { return Box; } //! Writes attributes of the object. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: core::array Particles; core::aabbox3df Box; core::vector3df Direction; core::dimension2df MaxStartSize, MinStartSize; u32 MinParticlesPerSecond, MaxParticlesPerSecond; video::SColor MinStartColor, MaxStartColor; u32 MinLifeTime, MaxLifeTime; u32 Time; u32 Emitted; s32 MaxAngleDegrees; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CParticleBoxEmitter.cpp0000644000000000000000000001374012574354552021517 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleBoxEmitter.h" #include "os.h" #include "IAttributes.h" #include "irrMath.h" namespace irr { namespace scene { //! constructor CParticleBoxEmitter::CParticleBoxEmitter( const core::aabbox3df& box, const core::vector3df& direction, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, video::SColor minStartColor, video::SColor maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize) : Box(box), Direction(direction), MaxStartSize(maxStartSize), MinStartSize(minStartSize), MinParticlesPerSecond(minParticlesPerSecond), MaxParticlesPerSecond(maxParticlesPerSecond), MinStartColor(minStartColor), MaxStartColor(maxStartColor), MinLifeTime(lifeTimeMin), MaxLifeTime(lifeTimeMax), Time(0), Emitted(0), MaxAngleDegrees(maxAngleDegrees) { #ifdef _DEBUG setDebugName("CParticleBoxEmitter"); #endif } //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. s32 CParticleBoxEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray) { Time += timeSinceLastCall; const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond; const f32 everyWhatMillisecond = 1000.0f / perSecond; if (Time > everyWhatMillisecond) { Particles.set_used(0); u32 amount = (u32)((Time / everyWhatMillisecond) + 0.5f); Time = 0; SParticle p; const core::vector3df& extent = Box.getExtent(); if (amount > MaxParticlesPerSecond*2) amount = MaxParticlesPerSecond * 2; for (u32 i=0; iaddVector3d("Box", b); out->addVector3d("Direction", Direction); out->addFloat("MinStartSizeWidth", MinStartSize.Width); out->addFloat("MinStartSizeHeight", MinStartSize.Height); out->addFloat("MaxStartSizeWidth", MaxStartSize.Width); out->addFloat("MaxStartSizeHeight", MaxStartSize.Height); out->addInt("MinParticlesPerSecond", MinParticlesPerSecond); out->addInt("MaxParticlesPerSecond", MaxParticlesPerSecond); out->addColor("MinStartColor", MinStartColor); out->addColor("MaxStartColor", MaxStartColor); out->addInt("MinLifeTime", MinLifeTime); out->addInt("MaxLifeTime", MaxLifeTime); out->addInt("MaxAngleDegrees", MaxAngleDegrees); } //! Reads attributes of the object. void CParticleBoxEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { // read data and correct input values here core::vector3df b = in->getAttributeAsVector3d("Box"); if (b.X <= 0) b.X = 1.0f; if (b.Y <= 0) b.Y = 1.0f; if (b.Z <= 0) b.Z = 1.0f; Box.MinEdge.X = -b.X; Box.MinEdge.Y = -b.Y; Box.MinEdge.Z = -b.Z; Box.MaxEdge.X = b.X; Box.MaxEdge.Y = b.Y; Box.MaxEdge.Z = b.Z; Direction = in->getAttributeAsVector3d("Direction"); if (Direction.getLength() == 0) Direction.set(0,0.01f,0); int idx = -1; idx = in->findAttribute("MinStartSizeWidth"); if ( idx >= 0 ) MinStartSize.Width = in->getAttributeAsFloat(idx); idx = in->findAttribute("MinStartSizeHeight"); if ( idx >= 0 ) MinStartSize.Height = in->getAttributeAsFloat(idx); idx = in->findAttribute("MaxStartSizeWidth"); if ( idx >= 0 ) MaxStartSize.Width = in->getAttributeAsFloat(idx); idx = in->findAttribute("MaxStartSizeHeight"); if ( idx >= 0 ) MaxStartSize.Height = in->getAttributeAsFloat(idx); MinParticlesPerSecond = in->getAttributeAsInt("MinParticlesPerSecond"); MaxParticlesPerSecond = in->getAttributeAsInt("MaxParticlesPerSecond"); MinParticlesPerSecond = core::max_(1u, MinParticlesPerSecond); MaxParticlesPerSecond = core::max_(MaxParticlesPerSecond, 1u); MaxParticlesPerSecond = core::min_(MaxParticlesPerSecond, 200u); MinParticlesPerSecond = core::min_(MinParticlesPerSecond, MaxParticlesPerSecond); MinStartColor = in->getAttributeAsColor("MinStartColor"); MaxStartColor = in->getAttributeAsColor("MaxStartColor"); MinLifeTime = in->getAttributeAsInt("MinLifeTime"); MaxLifeTime = in->getAttributeAsInt("MaxLifeTime"); MaxAngleDegrees = in->getAttributeAsInt("MaxAngleDegrees"); MinLifeTime = core::max_(0u, MinLifeTime); MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime); MinLifeTime = core::min_(MinLifeTime, MaxLifeTime); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CParticleAttractionAffector.h0000644000000000000000000000552112574354552022662 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PARTICLE_ATTRACTION_AFFECTOR_H_INCLUDED__ #define __C_PARTICLE_ATTRACTION_AFFECTOR_H_INCLUDED__ #include "IParticleAttractionAffector.h" namespace irr { namespace scene { //! Particle Affector for attracting particles to a point class CParticleAttractionAffector : public IParticleAttractionAffector { public: CParticleAttractionAffector( const core::vector3df& point = core::vector3df(), f32 speed = 1.0f, bool attract = true, bool affectX = true, bool affectY = true, bool affectZ = true ); //! Affects a particle. virtual void affect(u32 now, SParticle* particlearray, u32 count); //! Set the point that particles will attract to virtual void setPoint( const core::vector3df& point ) { Point = point; } //! Set the speed, in game units per second that the particles will attract to //! the specified point virtual void setSpeed( f32 speed ) { Speed = speed; } //! Set whether or not the particles are attracting or detracting virtual void setAttract( bool attract ) { Attract = attract; } //! Set whether or not this will affect particles in the X direction virtual void setAffectX( bool affect ) { AffectX = affect; } //! Set whether or not this will affect particles in the Y direction virtual void setAffectY( bool affect ) { AffectY = affect; } //! Set whether or not this will affect particles in the Z direction virtual void setAffectZ( bool affect ) { AffectZ = affect; } //! Get the point that particles are attracted to virtual const core::vector3df& getPoint() const { return Point; } //! Get the speed that points attract to the specified point virtual f32 getSpeed() const { return Speed; } //! Get whether or not the particles are attracting or detracting virtual bool getAttract() const { return Attract; } //! Get whether or not the particles X position are affected virtual bool getAffectX() const { return AffectX; } //! Get whether or not the particles Y position are affected virtual bool getAffectY() const { return AffectY; } //! Get whether or not the particles Z position are affected virtual bool getAffectZ() const { return AffectZ; } //! Writes attributes of the object. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: core::vector3df Point; f32 Speed; bool AffectX; bool AffectY; bool AffectZ; bool Attract; u32 LastTime; }; } // end namespace scene } // end namespace irr #endif // __C_PARTICLE_ATTRACTION_AFFECTOR_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CParticleAttractionAffector.cpp0000644000000000000000000000424512574354552023217 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleAttractionAffector.h" #include "IAttributes.h" namespace irr { namespace scene { //! constructor CParticleAttractionAffector::CParticleAttractionAffector( const core::vector3df& point, f32 speed, bool attract, bool affectX, bool affectY, bool affectZ ) : Point(point), Speed(speed), AffectX(affectX), AffectY(affectY), AffectZ(affectZ), Attract(attract), LastTime(0) { #ifdef _DEBUG setDebugName("CParticleAttractionAffector"); #endif } //! Affects an array of particles. void CParticleAttractionAffector::affect(u32 now, SParticle* particlearray, u32 count) { if( LastTime == 0 ) { LastTime = now; return; } f32 timeDelta = ( now - LastTime ) / 1000.0f; LastTime = now; if( !Enabled ) return; for(u32 i=0; iaddVector3d("Point", Point); out->addFloat("Speed", Speed); out->addBool("AffectX", AffectX); out->addBool("AffectY", AffectY); out->addBool("AffectZ", AffectZ); out->addBool("Attract", Attract); } //! Reads attributes of the object. void CParticleAttractionAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Point = in->getAttributeAsVector3d("Point"); Speed = in->getAttributeAsFloat("Speed"); AffectX = in->getAttributeAsBool("AffectX"); AffectY = in->getAttributeAsBool("AffectY"); AffectZ = in->getAttributeAsBool("AffectZ"); Attract = in->getAttributeAsBool("Attract"); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CParticleAnimatedMeshSceneNodeEmitter.h0000644000000000000000000001442012574354552024553 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PARTICLE_ANIMATED_MESH_SCENE_NODE_EMITTER_H_INCLUDED__ #define __C_PARTICLE_ANIMATED_MESH_SCENE_NODE_EMITTER_H_INCLUDED__ #include "IParticleAnimatedMeshSceneNodeEmitter.h" #include "irrArray.h" namespace irr { namespace scene { //! An animated mesh emitter class CParticleAnimatedMeshSceneNodeEmitter : public IParticleAnimatedMeshSceneNodeEmitter { public: //! constructor CParticleAnimatedMeshSceneNodeEmitter( IAnimatedMeshSceneNode* node, bool useNormalDirection = true, const core::vector3df& direction = core::vector3df(0.0f,0.0f,-1.0f), f32 normalDirectionModifier = 100.0f, s32 mbNumber = -1, bool everyMeshVertex = false, u32 minParticlesPerSecond = 20, u32 maxParticlesPerSecond = 40, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin = 2000, u32 lifeTimeMax = 4000, s32 maxAngleDegrees = 0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ); //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. virtual s32 emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray); //! Set Mesh to emit particles from virtual void setAnimatedMeshSceneNode( IAnimatedMeshSceneNode* node ); //! Set whether to use vertex normal for direction, or direction specified virtual void setUseNormalDirection( bool useNormalDirection ) { UseNormalDirection = useNormalDirection; } //! Set direction the emitter emits particles virtual void setDirection( const core::vector3df& newDirection ) { Direction = newDirection; } //! Set the amount that the normal is divided by for getting a particles direction virtual void setNormalDirectionModifier( f32 normalDirectionModifier ) { NormalDirectionModifier = normalDirectionModifier; } //! Sets whether to emit min<->max particles for every vertex per second, or to pick //! min<->max vertices every second virtual void setEveryMeshVertex( bool everyMeshVertex ) { EveryMeshVertex = everyMeshVertex; } //! Set minimum number of particles the emitter emits per second virtual void setMinParticlesPerSecond( u32 minPPS ) { MinParticlesPerSecond = minPPS; } //! Set maximum number of particles the emitter emits per second virtual void setMaxParticlesPerSecond( u32 maxPPS ) { MaxParticlesPerSecond = maxPPS; } //! Set minimum starting color for particles virtual void setMinStartColor( const video::SColor& color ) { MinStartColor = color; } //! Set maximum starting color for particles virtual void setMaxStartColor( const video::SColor& color ) { MaxStartColor = color; } //! Set the maximum starting size for particles virtual void setMaxStartSize( const core::dimension2df& size ) { MaxStartSize = size; } //! Set the minimum starting size for particles virtual void setMinStartSize( const core::dimension2df& size ) { MinStartSize = size; } //! Set the minimum particle life-time in milliseconds virtual void setMinLifeTime( u32 lifeTimeMin ) { MinLifeTime = lifeTimeMin; } //! Set the maximum particle life-time in milliseconds virtual void setMaxLifeTime( u32 lifeTimeMax ) { MaxLifeTime = lifeTimeMax; } //! Maximal random derivation from the direction virtual void setMaxAngleDegrees( s32 maxAngleDegrees ) { MaxAngleDegrees = maxAngleDegrees; } //! Get Mesh we're emitting particles from virtual const IAnimatedMeshSceneNode* getAnimatedMeshSceneNode() const { return Node; } //! Get whether to use vertex normal for direciton, or direction specified virtual bool isUsingNormalDirection() const { return UseNormalDirection; } //! Get direction the emitter emits particles virtual const core::vector3df& getDirection() const { return Direction; } //! Get the amount that the normal is divided by for getting a particles direction virtual f32 getNormalDirectionModifier() const { return NormalDirectionModifier; } //! Gets whether to emit min<->max particles for every vertex per second, or to pick //! min<->max vertices every second virtual bool getEveryMeshVertex() const { return EveryMeshVertex; } //! Get the minimum number of particles the emitter emits per second virtual u32 getMinParticlesPerSecond() const { return MinParticlesPerSecond; } //! Get the maximum number of particles the emitter emits per second virtual u32 getMaxParticlesPerSecond() const { return MaxParticlesPerSecond; } //! Get the minimum starting color for particles virtual const video::SColor& getMinStartColor() const { return MinStartColor; } //! Get the maximum starting color for particles virtual const video::SColor& getMaxStartColor() const { return MaxStartColor; } //! Get the maximum starting size for particles virtual const core::dimension2df& getMaxStartSize() const { return MaxStartSize; } //! Get the minimum starting size for particles virtual const core::dimension2df& getMinStartSize() const { return MinStartSize; } //! Get the minimum particle life-time in milliseconds virtual u32 getMinLifeTime() const { return MinLifeTime; } //! Get the maximum particle life-time in milliseconds virtual u32 getMaxLifeTime() const { return MaxLifeTime; } //! Maximal random derivation from the direction virtual s32 getMaxAngleDegrees() const { return MaxAngleDegrees; } private: IAnimatedMeshSceneNode* Node; IAnimatedMesh* AnimatedMesh; const IMesh* BaseMesh; s32 TotalVertices; u32 MBCount; s32 MBNumber; core::array VertexPerMeshBufferList; core::array Particles; core::vector3df Direction; f32 NormalDirectionModifier; u32 MinParticlesPerSecond, MaxParticlesPerSecond; video::SColor MinStartColor, MaxStartColor; u32 MinLifeTime, MaxLifeTime; core::dimension2df MaxStartSize, MinStartSize; u32 Time; u32 Emitted; s32 MaxAngleDegrees; bool EveryMeshVertex; bool UseNormalDirection; }; } // end namespace scene } // end namespace irr #endif // __C_PARTICLE_ANIMATED_MESH_SCENE_NODE_EMITTER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CParticleAnimatedMeshSceneNodeEmitter.cpp0000644000000000000000000001414712574354552025114 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CParticleAnimatedMeshSceneNodeEmitter.h" #include "IAnimatedMeshSceneNode.h" #include "IMesh.h" #include "os.h" namespace irr { namespace scene { //! constructor CParticleAnimatedMeshSceneNodeEmitter::CParticleAnimatedMeshSceneNodeEmitter( IAnimatedMeshSceneNode* node, bool useNormalDirection, const core::vector3df& direction, f32 normalDirectionModifier, s32 mbNumber, bool everyMeshVertex, u32 minParticlesPerSecond, u32 maxParticlesPerSecond, const video::SColor& minStartColor, const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees, const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize ) : Node(0), AnimatedMesh(0), BaseMesh(0), TotalVertices(0), MBCount(0), MBNumber(mbNumber), Direction(direction), NormalDirectionModifier(normalDirectionModifier), MinParticlesPerSecond(minParticlesPerSecond), MaxParticlesPerSecond(maxParticlesPerSecond), MinStartColor(minStartColor), MaxStartColor(maxStartColor), MinLifeTime(lifeTimeMin), MaxLifeTime(lifeTimeMax), MaxStartSize(maxStartSize), MinStartSize(minStartSize), Time(0), Emitted(0), MaxAngleDegrees(maxAngleDegrees), EveryMeshVertex(everyMeshVertex), UseNormalDirection(useNormalDirection) { #ifdef _DEBUG setDebugName("CParticleAnimatedMeshSceneNodeEmitter"); #endif setAnimatedMeshSceneNode(node); } //! Prepares an array with new particles to emitt into the system //! and returns how much new particles there are. s32 CParticleAnimatedMeshSceneNodeEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray) { Time += timeSinceLastCall; const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond; const f32 everyWhatMillisecond = 1000.0f / perSecond; if(Time > everyWhatMillisecond) { Particles.set_used(0); u32 amount = (u32)((Time / everyWhatMillisecond) + 0.5f); Time = 0; SParticle p; if(amount > MaxParticlesPerSecond * 2) amount = MaxParticlesPerSecond * 2; // Get Mesh for this frame IMesh* frameMesh = AnimatedMesh->getMesh( core::floor32(Node->getFrameNr()), 255, Node->getStartFrame(), Node->getEndFrame() ); for(u32 i=0; igetMeshBufferCount(); ++j ) { for( u32 k=0; kgetMeshBuffer(j)->getVertexCount(); ++k ) { p.pos = frameMesh->getMeshBuffer(j)->getPosition(k); if( UseNormalDirection ) p.vector = frameMesh->getMeshBuffer(j)->getNormal(k) / NormalDirectionModifier; else p.vector = Direction; p.startTime = now; if( MaxAngleDegrees ) { core::vector3df tgt = p.vector; tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees); p.vector = tgt; } p.endTime = now + MinLifeTime; if (MaxLifeTime != MinLifeTime) p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime); if (MinStartColor==MaxStartColor) p.color=MinStartColor; else p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand()); p.startColor = p.color; p.startVector = p.vector; if (MinStartSize==MaxStartSize) p.startSize = MinStartSize; else p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand()); p.size = p.startSize; Particles.push_back(p); } } } else { s32 randomMB = 0; if( MBNumber < 0 ) randomMB = os::Randomizer::rand() % MBCount; else randomMB = MBNumber; u32 vertexNumber = frameMesh->getMeshBuffer(randomMB)->getVertexCount(); if (!vertexNumber) continue; vertexNumber = os::Randomizer::rand() % vertexNumber; p.pos = frameMesh->getMeshBuffer(randomMB)->getPosition(vertexNumber); if( UseNormalDirection ) p.vector = frameMesh->getMeshBuffer(randomMB)->getNormal(vertexNumber) / NormalDirectionModifier; else p.vector = Direction; p.startTime = now; if( MaxAngleDegrees ) { core::vector3df tgt = Direction; tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees); p.vector = tgt; } p.endTime = now + MinLifeTime; if (MaxLifeTime != MinLifeTime) p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime); if (MinStartColor==MaxStartColor) p.color=MinStartColor; else p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand()); p.startColor = p.color; p.startVector = p.vector; if (MinStartSize==MaxStartSize) p.startSize = MinStartSize; else p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand()); p.size = p.startSize; Particles.push_back(p); } } outArray = Particles.pointer(); return Particles.size(); } return 0; } //! Set Mesh to emit particles from void CParticleAnimatedMeshSceneNodeEmitter::setAnimatedMeshSceneNode( IAnimatedMeshSceneNode* node ) { Node = node; AnimatedMesh = 0; BaseMesh = 0; TotalVertices = 0; VertexPerMeshBufferList.clear(); if ( !node ) { return; } AnimatedMesh = node->getMesh(); BaseMesh = AnimatedMesh->getMesh(0); MBCount = BaseMesh->getMeshBufferCount(); VertexPerMeshBufferList.reallocate(MBCount); for( u32 i = 0; i < MBCount; ++i ) { VertexPerMeshBufferList.push_back( BaseMesh->getMeshBuffer(i)->getVertexCount() ); TotalVertices += BaseMesh->getMeshBuffer(i)->getVertexCount(); } } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CPakReader.h0000644000000000000000000000701612574354552017253 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_PAK_READER_H_INCLUDED__ #define __C_PAK_READER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ #include "IReferenceCounted.h" #include "IReadFile.h" #include "irrArray.h" #include "irrString.h" #include "IFileSystem.h" #include "CFileList.h" namespace irr { namespace io { //! File header containing location and size of the table of contents struct SPAKFileHeader { // Don't change the order of these fields! They must match the order stored on disk. c8 tag[4]; u32 offset; u32 length; }; //! An entry in the PAK file's table of contents. struct SPAKFileEntry { // Don't change the order of these fields! They must match the order stored on disk. c8 name[56]; u32 offset; u32 length; }; //! Archiveloader capable of loading PAK Archives class CArchiveLoaderPAK : public IArchiveLoader { public: //! Constructor CArchiveLoaderPAK(io::IFileSystem* fs); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".zip") virtual bool isALoadableFileFormat(const io::path& filename) const; //! Check if the file might be loaded by this class /** Check might look into the file. \param file File handle to check. \return True if file seems to be loadable. */ virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! Check to see if the loader can create archives of this type. /** Check based on the archive type. \param fileType The archive type to check. \return True if the archile loader supports this type, false if not */ virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const; //! Creates an archive from the filename /** \param file File handle to check. \return Pointer to newly created archive, or 0 upon error. */ virtual IFileArchive* createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const; //! creates/loads an archive from the file. //! \return Pointer to the created archive. Returns 0 if loading failed. virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; //! Returns the type of archive created by this loader virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_PAK; } private: io::IFileSystem* FileSystem; }; //! reads from pak class CPakReader : public virtual IFileArchive, virtual CFileList { public: CPakReader(IReadFile* file, bool ignoreCase, bool ignorePaths); virtual ~CPakReader(); // file archive methods //! return the id of the file Archive virtual const io::path& getArchiveName() const { return File->getFileName(); } //! opens a file by file name virtual IReadFile* createAndOpenFile(const io::path& filename); //! opens a file by index virtual IReadFile* createAndOpenFile(u32 index); //! returns the list of files virtual const IFileList* getFileList() const; //! get the class Type virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_PAK; } private: //! scans for a local header, returns false if the header is invalid bool scanLocalHeader(); IReadFile* File; }; } // end namespace io } // end namespace irr #endif // __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ #endif // __C_PAK_READER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CPakReader.cpp0000644000000000000000000001042412574354552017603 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // Code contributed by skreamz #include "CPakReader.h" #ifdef __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ #include "os.h" #include "coreutil.h" namespace irr { namespace io { namespace { inline bool isHeaderValid(const SPAKFileHeader& header) { const c8* tag = header.tag; return tag[0] == 'P' && tag[1] == 'A' && tag[2] == 'C' && tag[3] == 'K'; } } // end namespace //! Constructor CArchiveLoaderPAK::CArchiveLoaderPAK( io::IFileSystem* fs) : FileSystem(fs) { #ifdef _DEBUG setDebugName("CArchiveLoaderPAK"); #endif } //! returns true if the file maybe is able to be loaded by this class bool CArchiveLoaderPAK::isALoadableFileFormat(const io::path& filename) const { return core::hasFileExtension(filename, "pak"); } //! Check to see if the loader can create archives of this type. bool CArchiveLoaderPAK::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const { return fileType == EFAT_PAK; } //! Creates an archive from the filename /** \param file File handle to check. \return Pointer to newly created archive, or 0 upon error. */ IFileArchive* CArchiveLoaderPAK::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const { IFileArchive *archive = 0; io::IReadFile* file = FileSystem->createAndOpenFile(filename); if (file) { archive = createArchive(file, ignoreCase, ignorePaths); file->drop (); } return archive; } //! creates/loads an archive from the file. //! \return Pointer to the created archive. Returns 0 if loading failed. IFileArchive* CArchiveLoaderPAK::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const { IFileArchive *archive = 0; if ( file ) { file->seek ( 0 ); archive = new CPakReader(file, ignoreCase, ignorePaths); } return archive; } //! Check if the file might be loaded by this class /** Check might look into the file. \param file File handle to check. \return True if file seems to be loadable. */ bool CArchiveLoaderPAK::isALoadableFileFormat(io::IReadFile* file) const { SPAKFileHeader header; file->read(&header, sizeof(header)); return isHeaderValid(header); } /*! PAK Reader */ CPakReader::CPakReader(IReadFile* file, bool ignoreCase, bool ignorePaths) : CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file) { #ifdef _DEBUG setDebugName("CPakReader"); #endif if (File) { File->grab(); scanLocalHeader(); sort(); } } CPakReader::~CPakReader() { if (File) File->drop(); } const IFileList* CPakReader::getFileList() const { return this; } bool CPakReader::scanLocalHeader() { SPAKFileHeader header; // Read and validate the header File->read(&header, sizeof(header)); if (!isHeaderValid(header)) return false; // Seek to the table of contents #ifdef __BIG_ENDIAN__ header.offset = os::Byteswap::byteswap(header.offset); header.length = os::Byteswap::byteswap(header.length); #endif File->seek(header.offset); const int numberOfFiles = header.length / sizeof(SPAKFileEntry); // Loop through each entry in the table of contents for(int i = 0; i < numberOfFiles; i++) { // read an entry SPAKFileEntry entry; File->read(&entry, sizeof(entry)); #ifdef _DEBUG os::Printer::log(entry.name); #endif #ifdef __BIG_ENDIAN__ entry.offset = os::Byteswap::byteswap(entry.offset); entry.length = os::Byteswap::byteswap(entry.length); #endif addItem(io::path(entry.name), entry.offset, entry.length, false ); } return true; } //! opens a file by file name IReadFile* CPakReader::createAndOpenFile(const io::path& filename) { s32 index = findFile(filename, false); if (index != -1) return createAndOpenFile(index); return 0; } //! opens a file by index IReadFile* CPakReader::createAndOpenFile(u32 index) { if (index >= Files.size() ) return 0; const SFileListEntry &entry = Files[index]; return createLimitReadFile( entry.FullName, File, entry.Offset, entry.Size ); } } // end namespace io } // end namespace irr #endif // __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ irrlicht-1.8.3/source/Irrlicht/COSOperator.h0000644000000000000000000000317212574354552017451 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_OS_OPERATOR_H_INCLUDED__ #define __C_OS_OPERATOR_H_INCLUDED__ #include "IOSOperator.h" namespace irr { class CIrrDeviceLinux; //! The Operating system operator provides operation system specific methods and informations. class COSOperator : public IOSOperator { public: // constructor #if defined(_IRR_COMPILE_WITH_X11_DEVICE_) COSOperator(const core::stringc& osversion, CIrrDeviceLinux* device); #endif COSOperator(const core::stringc& osversion); //! returns the current operation system version as string. virtual const core::stringc& getOperatingSystemVersion() const; //! copies text to the clipboard virtual void copyToClipboard(const c8* text) const; //! gets text from the clipboard //! \return Returns 0 if no string is in there. virtual const c8* getTextFromClipboard() const; //! gets the processor speed in megahertz //! \param Mhz: //! \return Returns true if successful, false if not virtual bool getProcessorSpeedMHz(u32* MHz) const; //! gets the total and available system RAM in kB //! \param Total: will contain the total system memory //! \param Avail: will contain the available memory //! \return Returns true if successful, false if not virtual bool getSystemMemory(u32* Total, u32* Avail) const; private: core::stringc OperatingSystem; #if defined(_IRR_COMPILE_WITH_X11_DEVICE_) CIrrDeviceLinux * IrrDeviceLinux; #endif }; } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/COSOperator.cpp0000644000000000000000000001121112574354552017775 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "COSOperator.h" #ifdef _IRR_WINDOWS_API_ #ifndef _IRR_XBOX_PLATFORM_ #include #endif #else #include #include #ifndef _IRR_SOLARIS_PLATFORM_ #include #include #endif #endif #if defined(_IRR_COMPILE_WITH_X11_DEVICE_) #include "CIrrDeviceLinux.h" #endif #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ #include "MacOSX/OSXClipboard.h" #endif namespace irr { #if defined(_IRR_COMPILE_WITH_X11_DEVICE_) // constructor linux COSOperator::COSOperator(const core::stringc& osVersion, CIrrDeviceLinux* device) : OperatingSystem(osVersion), IrrDeviceLinux(device) { } #endif // constructor COSOperator::COSOperator(const core::stringc& osVersion) : OperatingSystem(osVersion) { #ifdef _DEBUG setDebugName("COSOperator"); #endif } //! returns the current operating system version as string. const core::stringc& COSOperator::getOperatingSystemVersion() const { return OperatingSystem; } //! copies text to the clipboard void COSOperator::copyToClipboard(const c8* text) const { if (strlen(text)==0) return; // Windows version #if defined(_IRR_XBOX_PLATFORM_) #elif defined(_IRR_WINDOWS_API_) if (!OpenClipboard(NULL) || text == 0) return; EmptyClipboard(); HGLOBAL clipbuffer; char * buffer; clipbuffer = GlobalAlloc(GMEM_DDESHARE, strlen(text)+1); buffer = (char*)GlobalLock(clipbuffer); strcpy(buffer, text); GlobalUnlock(clipbuffer); SetClipboardData(CF_TEXT, clipbuffer); CloseClipboard(); // MacOSX version #elif defined(_IRR_COMPILE_WITH_OSX_DEVICE_) OSXCopyToClipboard(text); #elif defined(_IRR_COMPILE_WITH_X11_DEVICE_) if ( IrrDeviceLinux ) IrrDeviceLinux->copyToClipboard(text); #else #endif } //! gets text from the clipboard //! \return Returns 0 if no string is in there. const c8* COSOperator::getTextFromClipboard() const { #if defined(_IRR_XBOX_PLATFORM_) return 0; #elif defined(_IRR_WINDOWS_API_) if (!OpenClipboard(NULL)) return 0; char * buffer = 0; HANDLE hData = GetClipboardData( CF_TEXT ); buffer = (char*)GlobalLock( hData ); GlobalUnlock( hData ); CloseClipboard(); return buffer; #elif defined(_IRR_COMPILE_WITH_OSX_DEVICE_) return (OSXCopyFromClipboard()); #elif defined(_IRR_COMPILE_WITH_X11_DEVICE_) if ( IrrDeviceLinux ) return IrrDeviceLinux->getTextFromClipboard(); return 0; #else return 0; #endif } bool COSOperator::getProcessorSpeedMHz(u32* MHz) const { #if defined(_IRR_WINDOWS_API_) && !defined(_WIN32_WCE ) && !defined (_IRR_XBOX_PLATFORM_) LONG Error; HKEY Key; Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, __TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0, KEY_READ, &Key); if(Error != ERROR_SUCCESS) return false; DWORD Speed = 0; DWORD Size = sizeof(Speed); Error = RegQueryValueEx(Key, __TEXT("~MHz"), NULL, NULL, (LPBYTE)&Speed, &Size); RegCloseKey(Key); if (Error != ERROR_SUCCESS) return false; else if (MHz) *MHz = Speed; _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return true; #elif defined(_IRR_OSX_PLATFORM_) struct clockinfo CpuClock; size_t Size = sizeof(clockinfo); if (!sysctlbyname("kern.clockrate", &CpuClock, &Size, NULL, 0)) return false; else if (MHz) *MHz = CpuClock.hz; return true; #else // could probably be read from "/proc/cpuinfo" or "/proc/cpufreq" return false; #endif } bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const { #if defined(_IRR_WINDOWS_API_) && !defined (_IRR_XBOX_PLATFORM_) MEMORYSTATUS MemoryStatus; MemoryStatus.dwLength = sizeof(MEMORYSTATUS); // cannot fail GlobalMemoryStatus(&MemoryStatus); if (Total) *Total = (u32)(MemoryStatus.dwTotalPhys>>10); if (Avail) *Avail = (u32)(MemoryStatus.dwAvailPhys>>10); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return true; #elif defined(_IRR_POSIX_API_) && !defined(__FreeBSD__) #if defined(_SC_PHYS_PAGES) && defined(_SC_AVPHYS_PAGES) long ps = sysconf(_SC_PAGESIZE); long pp = sysconf(_SC_PHYS_PAGES); long ap = sysconf(_SC_AVPHYS_PAGES); if ((ps==-1)||(pp==-1)||(ap==-1)) return false; if (Total) *Total = (u32)((ps*(long long)pp)>>10); if (Avail) *Avail = (u32)((ps*(long long)ap)>>10); return true; #else // TODO: implement for non-availablity of symbols/features return false; #endif #else // TODO: implement for OSX return false; #endif } } // end namespace irrlicht-1.8.3/source/Irrlicht/COpenGLTexture.h0000644000000000000000000001311312574354552020115 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_OPEN_GL_TEXTURE_H_INCLUDED__ #define __C_OPEN_GL_TEXTURE_H_INCLUDED__ #include "ITexture.h" #include "IImage.h" #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #define GL_GLEXT_LEGACY 1 #else #define GL_GLEXT_PROTOTYPES 1 #endif #ifdef _IRR_WINDOWS_API_ // include windows headers for HWND #define WIN32_LEAN_AND_MEAN #include #include #ifdef _MSC_VER #pragma comment(lib, "OpenGL32.lib") #endif #elif defined(_IRR_OSX_PLATFORM_) #include #elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_) #define NO_SDL_GLEXT #include #include #else #if defined(_IRR_OSX_PLATFORM_) #include #else #include #endif #endif namespace irr { namespace video { class COpenGLDriver; //! OpenGL texture. class COpenGLTexture : public ITexture { public: //! constructor COpenGLTexture(IImage* surface, const io::path& name, void* mipmapData=0, COpenGLDriver* driver=0); //! destructor virtual ~COpenGLTexture(); //! lock function virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0); //! unlock function virtual void unlock(); //! Returns original size of the texture (image). virtual const core::dimension2d& getOriginalSize() const; //! Returns size of the texture. virtual const core::dimension2d& getSize() const; //! returns driver type of texture (=the driver, that created it) virtual E_DRIVER_TYPE getDriverType() const; //! returns color format of texture virtual ECOLOR_FORMAT getColorFormat() const; //! returns pitch of texture (in bytes) virtual u32 getPitch() const; //! return open gl texture name GLuint getOpenGLTextureName() const; //! return whether this texture has mipmaps virtual bool hasMipMaps() const; //! Regenerates the mip map levels of the texture. /** Useful after locking and modifying the texture \param mipmapData Pointer to raw mipmap data, including all necessary mip levels, in the same format as the main texture image. If not set the mipmaps are derived from the main image. */ virtual void regenerateMipMapLevels(void* mipmapData=0); //! Is it a render target? virtual bool isRenderTarget() const; //! Is it a FrameBufferObject? virtual bool isFrameBufferObject() const; //! Bind RenderTargetTexture virtual void bindRTT(); //! Unbind RenderTargetTexture virtual void unbindRTT(); //! sets whether this texture is intended to be used as a render target. void setIsRenderTarget(bool isTarget); protected: //! protected constructor with basic setup, no GL texture name created, for derived classes COpenGLTexture(const io::path& name, COpenGLDriver* driver); //! get the desired color format based on texture creation flags and the input format. ECOLOR_FORMAT getBestColorFormat(ECOLOR_FORMAT format); //! Get the OpenGL color format parameters based on the given Irrlicht color format GLint getOpenGLFormatAndParametersFromColorFormat( ECOLOR_FORMAT format, GLint& filtering, GLenum& colorformat, GLenum& type); //! get important numbers of the image and hw texture void getImageValues(IImage* image); //! copies the texture into an OpenGL texture. /** \param newTexture True if method is called for a newly created texture for the first time. Otherwise call with false to improve memory handling. \param mipmapData Pointer to raw mipmap data, including all necessary mip levels, in the same format as the main texture image. \param mipLevel If set to non-zero, only that specific miplevel is updated, using the MipImage member. */ void uploadTexture(bool newTexture=false, void* mipmapData=0, u32 mipLevel=0); core::dimension2d ImageSize; core::dimension2d TextureSize; ECOLOR_FORMAT ColorFormat; COpenGLDriver* Driver; IImage* Image; IImage* MipImage; GLuint TextureName; GLint InternalFormat; GLenum PixelFormat; GLenum PixelType; u8 MipLevelStored; bool HasMipMaps; bool MipmapLegacyMode; bool IsRenderTarget; bool AutomaticMipmapUpdate; bool ReadOnlyLock; bool KeepImage; }; //! OpenGL FBO texture. class COpenGLFBOTexture : public COpenGLTexture { public: //! FrameBufferObject constructor COpenGLFBOTexture(const core::dimension2d& size, const io::path& name, COpenGLDriver* driver = 0, ECOLOR_FORMAT format = ECF_UNKNOWN); //! destructor virtual ~COpenGLFBOTexture(); //! Is it a FrameBufferObject? virtual bool isFrameBufferObject() const; //! Bind RenderTargetTexture virtual void bindRTT(); //! Unbind RenderTargetTexture virtual void unbindRTT(); ITexture* DepthTexture; protected: GLuint ColorFrameBuffer; }; //! OpenGL FBO depth texture. class COpenGLFBODepthTexture : public COpenGLTexture { public: //! FrameBufferObject depth constructor COpenGLFBODepthTexture(const core::dimension2d& size, const io::path& name, COpenGLDriver* driver=0, bool useStencil=false); //! destructor virtual ~COpenGLFBODepthTexture(); //! Bind RenderTargetTexture virtual void bindRTT(); //! Unbind RenderTargetTexture virtual void unbindRTT(); bool attach(ITexture*); protected: GLuint DepthRenderBuffer; GLuint StencilRenderBuffer; bool UseStencil; }; } // end namespace video } // end namespace irr #endif #endif // _IRR_COMPILE_WITH_OPENGL_ irrlicht-1.8.3/source/Irrlicht/COpenGLTexture.cpp0000644000000000000000000006060512574354552020460 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "irrTypes.h" #include "COpenGLTexture.h" #include "COpenGLDriver.h" #include "os.h" #include "CColorConverter.h" #include "irrString.h" namespace irr { namespace video { //! constructor for usual textures COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mipmapData, COpenGLDriver* driver) : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0), TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), MipmapLegacyMode(true), IsRenderTarget(false), AutomaticMipmapUpdate(false), ReadOnlyLock(false), KeepImage(true) { #ifdef _DEBUG setDebugName("COpenGLTexture"); #endif HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); getImageValues(origImage); glGenTextures(1, &TextureName); if (ImageSize==TextureSize) { Image = Driver->createImage(ColorFormat, ImageSize); origImage->copyTo(Image); } else { Image = Driver->createImage(ColorFormat, TextureSize); // scale texture origImage->copyToScaling(Image); } uploadTexture(true, mipmapData); if (!KeepImage) { Image->drop(); Image=0; } } //! constructor for basic setup (only for derived classes) COpenGLTexture::COpenGLTexture(const io::path& name, COpenGLDriver* driver) : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0), TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), HasMipMaps(true), MipmapLegacyMode(true), IsRenderTarget(false), AutomaticMipmapUpdate(false), ReadOnlyLock(false), KeepImage(true) { #ifdef _DEBUG setDebugName("COpenGLTexture"); #endif } //! destructor COpenGLTexture::~COpenGLTexture() { if (TextureName) glDeleteTextures(1, &TextureName); if (Image) Image->drop(); } //! Choose best matching color format, based on texture creation flags ECOLOR_FORMAT COpenGLTexture::getBestColorFormat(ECOLOR_FORMAT format) { ECOLOR_FORMAT destFormat = ECF_A8R8G8B8; switch (format) { case ECF_A1R5G5B5: if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT)) destFormat = ECF_A1R5G5B5; break; case ECF_R5G6B5: if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT)) destFormat = ECF_A1R5G5B5; break; case ECF_A8R8G8B8: if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) destFormat = ECF_A1R5G5B5; break; case ECF_R8G8B8: if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) destFormat = ECF_A1R5G5B5; default: break; } if (Driver->getTextureCreationFlag(ETCF_NO_ALPHA_CHANNEL)) { switch (destFormat) { case ECF_A1R5G5B5: destFormat = ECF_R5G6B5; break; case ECF_A8R8G8B8: destFormat = ECF_R8G8B8; break; default: break; } } return destFormat; } //! Get opengl values for the GPU texture storage GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT format, GLint& filtering, GLenum& colorformat, GLenum& type) { // default filtering = GL_LINEAR; colorformat = GL_RGBA; type = GL_UNSIGNED_BYTE; GLenum internalformat = GL_RGBA; switch(format) { case ECF_A1R5G5B5: colorformat=GL_BGRA_EXT; type=GL_UNSIGNED_SHORT_1_5_5_5_REV; internalformat = GL_RGBA; break; case ECF_R5G6B5: colorformat=GL_RGB; type=GL_UNSIGNED_SHORT_5_6_5; internalformat = GL_RGB; break; case ECF_R8G8B8: colorformat=GL_BGR; type=GL_UNSIGNED_BYTE; internalformat = GL_RGB; break; case ECF_A8R8G8B8: colorformat=GL_BGRA_EXT; if (Driver->Version > 101) type=GL_UNSIGNED_INT_8_8_8_8_REV; internalformat = GL_RGBA; break; // Floating Point texture formats. Thanks to Patryk "Nadro" Nadrowski. case ECF_R16F: { #ifdef GL_ARB_texture_rg filtering = GL_NEAREST; colorformat = GL_RED; type = GL_FLOAT; internalformat = GL_R16F; #else ColorFormat = ECF_A8R8G8B8; internalformat = GL_RGB8; #endif } break; case ECF_G16R16F: { #ifdef GL_ARB_texture_rg filtering = GL_NEAREST; colorformat = GL_RG; type = GL_FLOAT; internalformat = GL_RG16F; #else ColorFormat = ECF_A8R8G8B8; internalformat = GL_RGB8; #endif } break; case ECF_A16B16G16R16F: { #ifdef GL_ARB_texture_rg filtering = GL_NEAREST; colorformat = GL_RGBA; type = GL_FLOAT; internalformat = GL_RGBA16F_ARB; #else ColorFormat = ECF_A8R8G8B8; internalformat = GL_RGBA8; #endif } break; case ECF_R32F: { #ifdef GL_ARB_texture_rg filtering = GL_NEAREST; colorformat = GL_RED; type = GL_FLOAT; internalformat = GL_R32F; #else ColorFormat = ECF_A8R8G8B8; internalformat = GL_RGB8; #endif } break; case ECF_G32R32F: { #ifdef GL_ARB_texture_rg filtering = GL_NEAREST; colorformat = GL_RG; type = GL_FLOAT; internalformat = GL_RG32F; #else ColorFormat = ECF_A8R8G8B8; internalformat = GL_RGB8; #endif } break; case ECF_A32B32G32R32F: { #ifdef GL_ARB_texture_float filtering = GL_NEAREST; colorformat = GL_RGBA; type = GL_FLOAT; internalformat = GL_RGBA32F_ARB; #else ColorFormat = ECF_A8R8G8B8; internalformat = GL_RGBA8; #endif } break; default: { os::Printer::log("Unsupported texture format", ELL_ERROR); internalformat = GL_RGBA8; } } #if defined(GL_ARB_framebuffer_sRGB) || defined(GL_EXT_framebuffer_sRGB) if (Driver->Params.HandleSRGB) { if (internalformat==GL_RGBA) internalformat=GL_SRGB_ALPHA_EXT; else if (internalformat==GL_RGB) internalformat=GL_SRGB_EXT; } #endif return internalformat; } // prepare values ImageSize, TextureSize, and ColorFormat based on image void COpenGLTexture::getImageValues(IImage* image) { if (!image) { os::Printer::log("No image for OpenGL texture.", ELL_ERROR); return; } ImageSize = image->getDimension(); if ( !ImageSize.Width || !ImageSize.Height) { os::Printer::log("Invalid size of image for OpenGL Texture.", ELL_ERROR); return; } const f32 ratio = (f32)ImageSize.Width/(f32)ImageSize.Height; if ((ImageSize.Width>Driver->MaxTextureSize) && (ratio >= 1.0f)) { ImageSize.Width = Driver->MaxTextureSize; ImageSize.Height = (u32)(Driver->MaxTextureSize/ratio); } else if (ImageSize.Height>Driver->MaxTextureSize) { ImageSize.Height = Driver->MaxTextureSize; ImageSize.Width = (u32)(Driver->MaxTextureSize*ratio); } TextureSize=ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT)); ColorFormat = getBestColorFormat(image->getColorFormat()); } //! copies the the texture into an open gl texture. void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level) { // check which image needs to be uploaded IImage* image = level?MipImage:Image; if (!image) { os::Printer::log("No image for OpenGL texture to upload", ELL_ERROR); return; } // get correct opengl color data values GLenum oldInternalFormat = InternalFormat; GLint filtering; InternalFormat = getOpenGLFormatAndParametersFromColorFormat(ColorFormat, filtering, PixelFormat, PixelType); // make sure we don't change the internal format of existing images if (!newTexture) InternalFormat=oldInternalFormat; Driver->setActiveTexture(0, this); if (Driver->testGLError()) os::Printer::log("Could not bind Texture", ELL_ERROR); // mipmap handling for main texture if (!level && newTexture) { #ifndef DISABLE_MIPMAPPING #ifdef GL_SGIS_generate_mipmap // auto generate if possible and no mipmap data is given if (HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) { if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST); else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); else glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_DONT_CARE); AutomaticMipmapUpdate=true; if (!Driver->queryFeature(EVDF_FRAMEBUFFER_OBJECT)) { glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE ); MipmapLegacyMode=true; } else MipmapLegacyMode=false; } else #endif { // Either generate manually due to missing capability // or use predefined mipmap data AutomaticMipmapUpdate=false; regenerateMipMapLevels(mipmapData); } if (HasMipMaps) // might have changed in regenerateMipMapLevels { // enable bilinear mipmap filter glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else #else HasMipMaps=false; os::Printer::log("Did not create OpenGL texture mip maps.", ELL_INFORMATION); #endif { // enable bilinear filter without mipmaps glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } } // now get image data and upload to GPU void* source = image->lock(); if (newTexture) glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width, image->getDimension().Height, 0, PixelFormat, PixelType, source); else glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, image->getDimension().Height, PixelFormat, PixelType, source); image->unlock(); if (!MipmapLegacyMode && AutomaticMipmapUpdate) { glEnable(GL_TEXTURE_2D); Driver->extGlGenerateMipmap(GL_TEXTURE_2D); } if (Driver->testGLError()) os::Printer::log("Could not glTexImage2D", ELL_ERROR); } //! lock function void* COpenGLTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) { // store info about which image is locked IImage* image = (mipmapLevel==0)?Image:MipImage; ReadOnlyLock |= (mode==ETLM_READ_ONLY); MipLevelStored = mipmapLevel; if (!ReadOnlyLock && mipmapLevel) { #ifdef GL_SGIS_generate_mipmap if (Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) { // do not automatically generate and update mipmaps glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); } #endif AutomaticMipmapUpdate=false; } // if data not available or might have changed on GPU download it if (!image || IsRenderTarget) { // prepare the data storage if necessary if (!image) { if (mipmapLevel) { u32 i=0; u32 width = TextureSize.Width; u32 height = TextureSize.Height; do { if (width>1) width>>=1; if (height>1) height>>=1; ++i; } while (i != mipmapLevel); MipImage = image = Driver->createImage(ECF_A8R8G8B8, core::dimension2du(width,height)); } else Image = image = Driver->createImage(ECF_A8R8G8B8, ImageSize); ColorFormat = ECF_A8R8G8B8; } if (!image) return 0; if (mode != ETLM_WRITE_ONLY) { u8* pixels = static_cast(image->lock()); if (!pixels) return 0; // we need to keep the correct texture bound later on GLint tmpTexture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmpTexture); glBindTexture(GL_TEXTURE_2D, TextureName); // we need to flip textures vertical // however, it seems that this does not hold for mipmap // textures, for unknown reasons. // allows to read pixels in top-to-bottom order #ifdef GL_MESA_pack_invert if (!mipmapLevel && Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert)) glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); #endif // download GPU data as ARGB8 to pixels; glGetTexImage(GL_TEXTURE_2D, mipmapLevel, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels); if (!mipmapLevel) { #ifdef GL_MESA_pack_invert if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert)) glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE); else #endif { // opengl images are horizontally flipped, so we have to fix that here. const s32 pitch=image->getPitch(); u8* p2 = pixels + (image->getDimension().Height - 1) * pitch; u8* tmpBuffer = new u8[pitch]; for (u32 i=0; i < image->getDimension().Height; i += 2) { memcpy(tmpBuffer, pixels, pitch); memcpy(pixels, p2, pitch); memcpy(p2, tmpBuffer, pitch); pixels += pitch; p2 -= pitch; } delete [] tmpBuffer; } } image->unlock(); //reset old bound texture glBindTexture(GL_TEXTURE_2D, tmpTexture); } } return image->lock(); } //! unlock function void COpenGLTexture::unlock() { // test if miplevel or main texture was locked IImage* image = MipImage?MipImage:Image; if (!image) return; // unlock image to see changes image->unlock(); // copy texture data to GPU if (!ReadOnlyLock) uploadTexture(false, 0, MipLevelStored); ReadOnlyLock = false; // cleanup local image if (MipImage) { MipImage->drop(); MipImage=0; } else if (!KeepImage) { Image->drop(); Image=0; } // update information if (Image) ColorFormat=Image->getColorFormat(); else ColorFormat=ECF_A8R8G8B8; } //! Returns size of the original image. const core::dimension2d& COpenGLTexture::getOriginalSize() const { return ImageSize; } //! Returns size of the texture. const core::dimension2d& COpenGLTexture::getSize() const { return TextureSize; } //! returns driver type of texture, i.e. the driver, which created the texture E_DRIVER_TYPE COpenGLTexture::getDriverType() const { return EDT_OPENGL; } //! returns color format of texture ECOLOR_FORMAT COpenGLTexture::getColorFormat() const { return ColorFormat; } //! returns pitch of texture (in bytes) u32 COpenGLTexture::getPitch() const { if (Image) return Image->getPitch(); else return 0; } //! return open gl texture name GLuint COpenGLTexture::getOpenGLTextureName() const { return TextureName; } //! Returns whether this texture has mipmaps bool COpenGLTexture::hasMipMaps() const { return HasMipMaps; } //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture void COpenGLTexture::regenerateMipMapLevels(void* mipmapData) { if (AutomaticMipmapUpdate || !HasMipMaps || !Image) return; if ((Image->getDimension().Width==1) && (Image->getDimension().Height==1)) return; // Manually create mipmaps or use prepared version u32 width=Image->getDimension().Width; u32 height=Image->getDimension().Height; u32 i=0; u8* target = static_cast(mipmapData); do { if (width>1) width>>=1; if (height>1) height>>=1; ++i; if (!target) target = new u8[width*height*Image->getBytesPerPixel()]; // create scaled version if no mipdata available if (!mipmapData) Image->copyToScaling(target, width, height, Image->getColorFormat()); glTexImage2D(GL_TEXTURE_2D, i, InternalFormat, width, height, 0, PixelFormat, PixelType, target); // get next prepared mipmap data if available if (mipmapData) { mipmapData = static_cast(mipmapData)+width*height*Image->getBytesPerPixel(); target = static_cast(mipmapData); } } while (width!=1 || height!=1); // cleanup if (!mipmapData) delete [] target; } bool COpenGLTexture::isRenderTarget() const { return IsRenderTarget; } void COpenGLTexture::setIsRenderTarget(bool isTarget) { IsRenderTarget = isTarget; } bool COpenGLTexture::isFrameBufferObject() const { return false; } //! Bind Render Target Texture void COpenGLTexture::bindRTT() { } //! Unbind Render Target Texture void COpenGLTexture::unbindRTT() { Driver->setActiveTexture(0, this); // Copy Our ViewPort To The Texture glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, getSize().Width, getSize().Height); } /* FBO Textures */ // helper function for render to texture static bool checkFBOStatus(COpenGLDriver* Driver); //! RTT ColorFrameBuffer constructor COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d& size, const io::path& name, COpenGLDriver* driver, ECOLOR_FORMAT format) : COpenGLTexture(name, driver), DepthTexture(0), ColorFrameBuffer(0) { #ifdef _DEBUG setDebugName("COpenGLTexture_FBO"); #endif ImageSize = size; TextureSize = size; if (ECF_UNKNOWN == format) format = getBestColorFormat(driver->getColorFormat()); ColorFormat = format; GLint FilteringType; InternalFormat = getOpenGLFormatAndParametersFromColorFormat(format, FilteringType, PixelFormat, PixelType); HasMipMaps = false; IsRenderTarget = true; #ifdef GL_EXT_framebuffer_object // generate frame buffer Driver->extGlGenFramebuffers(1, &ColorFrameBuffer); bindRTT(); // generate color texture glGenTextures(1, &TextureName); Driver->setActiveTexture(0, this); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, FilteringType); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, ImageSize.Width, ImageSize.Height, 0, PixelFormat, PixelType, 0); #ifdef _DEBUG driver->testGLError(); #endif // attach color texture to frame buffer Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, TextureName, 0); #ifdef _DEBUG checkFBOStatus(Driver); #endif #endif unbindRTT(); } //! destructor COpenGLFBOTexture::~COpenGLFBOTexture() { if (DepthTexture) if (DepthTexture->drop()) Driver->removeDepthTexture(DepthTexture); if (ColorFrameBuffer) Driver->extGlDeleteFramebuffers(1, &ColorFrameBuffer); } bool COpenGLFBOTexture::isFrameBufferObject() const { return true; } //! Bind Render Target Texture void COpenGLFBOTexture::bindRTT() { #ifdef GL_EXT_framebuffer_object if (ColorFrameBuffer != 0) Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, ColorFrameBuffer); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); #endif } //! Unbind Render Target Texture void COpenGLFBOTexture::unbindRTT() { #ifdef GL_EXT_framebuffer_object if (ColorFrameBuffer != 0) Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); #endif } /* FBO Depth Textures */ //! RTT DepthBuffer constructor COpenGLFBODepthTexture::COpenGLFBODepthTexture( const core::dimension2d& size, const io::path& name, COpenGLDriver* driver, bool useStencil) : COpenGLTexture(name, driver), DepthRenderBuffer(0), StencilRenderBuffer(0), UseStencil(useStencil) { #ifdef _DEBUG setDebugName("COpenGLTextureFBO_Depth"); #endif ImageSize = size; TextureSize = size; InternalFormat = GL_RGBA; PixelFormat = GL_RGBA; PixelType = GL_UNSIGNED_BYTE; HasMipMaps = false; if (useStencil) { glGenTextures(1, &DepthRenderBuffer); glBindTexture(GL_TEXTURE_2D, DepthRenderBuffer); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); #ifdef GL_EXT_packed_depth_stencil if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_EXT_packed_depth_stencil)) { // generate packed depth stencil texture glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_EXT, ImageSize.Width, ImageSize.Height, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0); StencilRenderBuffer = DepthRenderBuffer; // stencil is packed with depth } else // generate separate stencil and depth textures #endif { // generate depth texture glTexImage2D(GL_TEXTURE_2D, 0, Driver->getZBufferBits(), ImageSize.Width, ImageSize.Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); // generate stencil texture glGenTextures(1, &StencilRenderBuffer); glBindTexture(GL_TEXTURE_2D, StencilRenderBuffer); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_STENCIL_INDEX, ImageSize.Width, ImageSize.Height, 0, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 0); } } #ifdef GL_EXT_framebuffer_object else { // generate depth buffer Driver->extGlGenRenderbuffers(1, &DepthRenderBuffer); Driver->extGlBindRenderbuffer(GL_RENDERBUFFER_EXT, DepthRenderBuffer); Driver->extGlRenderbufferStorage(GL_RENDERBUFFER_EXT, Driver->getZBufferBits(), ImageSize.Width, ImageSize.Height); } #endif } //! destructor COpenGLFBODepthTexture::~COpenGLFBODepthTexture() { if (DepthRenderBuffer && UseStencil) glDeleteTextures(1, &DepthRenderBuffer); else Driver->extGlDeleteRenderbuffers(1, &DepthRenderBuffer); if (StencilRenderBuffer && StencilRenderBuffer != DepthRenderBuffer) glDeleteTextures(1, &StencilRenderBuffer); } //combine depth texture and rtt bool COpenGLFBODepthTexture::attach(ITexture* renderTex) { if (!renderTex) return false; video::COpenGLFBOTexture* rtt = static_cast(renderTex); rtt->bindRTT(); #ifdef GL_EXT_framebuffer_object if (UseStencil) { // attach stencil texture to stencil buffer Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, StencilRenderBuffer, 0); // attach depth texture to depth buffer Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, DepthRenderBuffer, 0); } else { // attach depth renderbuffer to depth buffer Driver->extGlFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, DepthRenderBuffer); } #endif // check the status if (!checkFBOStatus(Driver)) { os::Printer::log("FBO incomplete"); return false; } rtt->DepthTexture=this; grab(); // grab the depth buffer, not the RTT rtt->unbindRTT(); return true; } //! Bind Render Target Texture void COpenGLFBODepthTexture::bindRTT() { } //! Unbind Render Target Texture void COpenGLFBODepthTexture::unbindRTT() { } bool checkFBOStatus(COpenGLDriver* Driver) { #ifdef GL_EXT_framebuffer_object GLenum status = Driver->extGlCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); switch (status) { //Our FBO is perfect, return true case GL_FRAMEBUFFER_COMPLETE_EXT: return true; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: os::Printer::log("FBO has invalid read buffer", ELL_ERROR); break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: os::Printer::log("FBO has invalid draw buffer", ELL_ERROR); break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: os::Printer::log("FBO has one or several incomplete image attachments", ELL_ERROR); break; case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: os::Printer::log("FBO has one or several image attachments with different internal formats", ELL_ERROR); break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: os::Printer::log("FBO has one or several image attachments with different dimensions", ELL_ERROR); break; // not part of fbo_object anymore, but won't harm as it is just a return value #ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: os::Printer::log("FBO has a duplicate image attachment", ELL_ERROR); break; #endif case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: os::Printer::log("FBO missing an image attachment", ELL_ERROR); break; #ifdef GL_EXT_framebuffer_multisample case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: os::Printer::log("FBO wrong multisample setup", ELL_ERROR); break; #endif case GL_FRAMEBUFFER_UNSUPPORTED_EXT: os::Printer::log("FBO format unsupported", ELL_ERROR); break; default: break; } #endif os::Printer::log("FBO error", ELL_ERROR); // _IRR_DEBUG_BREAK_IF(true); return false; } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_OPENGL_ irrlicht-1.8.3/source/Irrlicht/COpenGLSLMaterialRenderer.h0000644000000000000000000001060712574354552022146 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_OPENGL_SHADER_LANGUAGE_MATERIAL_RENDERER_H_INCLUDED__ #define __C_OPENGL_SHADER_LANGUAGE_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #ifdef _IRR_WINDOWS_API_ #define WIN32_LEAN_AND_MEAN #include #include #include "glext.h" #else #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #define GL_GLEXT_LEGACY 1 #else #define GL_GLEXT_PROTOTYPES 1 #endif #if defined(_IRR_OSX_PLATFORM_) #include #else #include #endif #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #include "glext.h" #endif #endif #include "IMaterialRenderer.h" #include "IMaterialRendererServices.h" #include "IGPUProgrammingServices.h" #include "irrArray.h" #include "irrString.h" namespace irr { namespace video { class COpenGLDriver; class IShaderConstantSetCallBack; //! Class for using GLSL shaders with OpenGL //! Please note: This renderer implements its own IMaterialRendererServices class COpenGLSLMaterialRenderer : public IMaterialRenderer, public IMaterialRendererServices { public: //! Constructor COpenGLSLMaterialRenderer( COpenGLDriver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram = 0, const c8* vertexShaderEntryPointName = 0, E_VERTEX_SHADER_TYPE vsCompileTarget = video::EVST_VS_1_1, const c8* pixelShaderProgram = 0, const c8* pixelShaderEntryPointName = 0, E_PIXEL_SHADER_TYPE psCompileTarget = video::EPST_PS_1_1, const c8* geometryShaderProgram = 0, const c8* geometryShaderEntryPointName = "main", E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, IMaterialRenderer* baseMaterial = 0, s32 userData = 0); //! Destructor virtual ~COpenGLSLMaterialRenderer(); virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services); virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); virtual void OnUnsetMaterial(); //! Returns if the material is transparent. virtual bool isTransparent() const; // implementations for the render services virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates); virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count); virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count); virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count); virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1); virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count); virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count); virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count); virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1); virtual IVideoDriver* getVideoDriver(); protected: //! constructor only for use by derived classes who want to //! create a fall back material for example. COpenGLSLMaterialRenderer(COpenGLDriver* driver, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData=0); void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, const c8* geometryShaderProgram, scene::E_PRIMITIVE_TYPE inType=scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType=scene::EPT_TRIANGLE_STRIP, u32 verticesOut=0); bool createProgram(); bool createShader(GLenum shaderType, const char* shader); bool linkProgram(); COpenGLDriver* Driver; IShaderConstantSetCallBack* CallBack; IMaterialRenderer* BaseMaterial; struct SUniformInfo { core::stringc name; GLenum type; }; GLhandleARB Program; GLuint Program2; core::array UniformInfo; s32 UserData; }; } // end namespace video } // end namespace irr #endif // compile with OpenGL #endif // if included irrlicht-1.8.3/source/Irrlicht/COpenGLSLMaterialRenderer.cpp0000644000000000000000000004327212574354552022505 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // This file was originally written by William Finlayson. I (Nikolaus // Gebhardt) did some minor modifications and changes to it and integrated it // into Irrlicht. Thanks a lot to William for his work on this and that he gave // me his permission to add it into Irrlicht using the zlib license. // After Irrlicht 0.12, Michael Zoech did some improvements to this renderer, I // merged this into Irrlicht 0.14, thanks to him for his work. #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "COpenGLSLMaterialRenderer.h" #include "IGPUProgrammingServices.h" #include "IShaderConstantSetCallBack.h" #include "IMaterialRendererServices.h" #include "IVideoDriver.h" #include "os.h" #include "COpenGLDriver.h" namespace irr { namespace video { //! Constructor COpenGLSLMaterialRenderer::COpenGLSLMaterialRenderer(video::COpenGLDriver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, const c8* geometryShaderProgram, const c8* geometryShaderEntryPointName, E_GEOMETRY_SHADER_TYPE gsCompileTarget, scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 verticesOut, IShaderConstantSetCallBack* callback, video::IMaterialRenderer* baseMaterial, s32 userData) : Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), Program(0), Program2(0), UserData(userData) { #ifdef _DEBUG setDebugName("COpenGLSLMaterialRenderer"); #endif //entry points must always be main, and the compile target isn't selectable //it is fine to ignore what has been asked for, as the compiler should spot anything wrong //just check that GLSL is available if (BaseMaterial) BaseMaterial->grab(); if (CallBack) CallBack->grab(); if (!Driver->queryFeature(EVDF_ARB_GLSL)) return; init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram, geometryShaderProgram); } //! constructor only for use by derived classes who want to //! create a fall back material for example. COpenGLSLMaterialRenderer::COpenGLSLMaterialRenderer(COpenGLDriver* driver, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), Program(0), Program2(0), UserData(userData) { if (BaseMaterial) BaseMaterial->grab(); if (CallBack) CallBack->grab(); } //! Destructor COpenGLSLMaterialRenderer::~COpenGLSLMaterialRenderer() { if (CallBack) CallBack->drop(); if (Program) { GLhandleARB shaders[8]; GLint count; Driver->extGlGetAttachedObjects(Program, 8, &count, shaders); // avoid bugs in some drivers, which return larger numbers count=core::min_(count,8); for (GLint i=0; iextGlDeleteObject(shaders[i]); Driver->extGlDeleteObject(Program); Program = 0; } if (Program2) { GLuint shaders[8]; GLint count; Driver->extGlGetAttachedShaders(Program2, 8, &count, shaders); // avoid bugs in some drivers, which return larger numbers count=core::min_(count,8); for (GLint i=0; iextGlDeleteShader(shaders[i]); Driver->extGlDeleteProgram(Program2); Program2 = 0; } UniformInfo.clear(); if (BaseMaterial) BaseMaterial->drop(); } void COpenGLSLMaterialRenderer::init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, const c8* geometryShaderProgram, scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 verticesOut) { outMaterialTypeNr = -1; if (!createProgram()) return; #if defined(GL_ARB_vertex_shader) && defined (GL_ARB_fragment_shader) if (vertexShaderProgram) if (!createShader(GL_VERTEX_SHADER_ARB, vertexShaderProgram)) return; if (pixelShaderProgram) if (!createShader(GL_FRAGMENT_SHADER_ARB, pixelShaderProgram)) return; #endif #if defined(GL_ARB_geometry_shader4) || defined(GL_EXT_geometry_shader4) || defined(GL_NV_geometry_program4) || defined(GL_NV_geometry_shader4) if (geometryShaderProgram && Driver->queryFeature(EVDF_GEOMETRY_SHADER)) { if (!createShader(GL_GEOMETRY_SHADER_EXT, geometryShaderProgram)) return; #if defined(GL_ARB_geometry_shader4) || defined(GL_EXT_geometry_shader4) || defined(GL_NV_geometry_shader4) if (Program2) // Geometry shaders are supported only in OGL2.x+ drivers. { Driver->extGlProgramParameteri(Program2, GL_GEOMETRY_INPUT_TYPE_EXT, Driver->primitiveTypeToGL(inType)); Driver->extGlProgramParameteri(Program2, GL_GEOMETRY_OUTPUT_TYPE_EXT, Driver->primitiveTypeToGL(outType)); if (verticesOut==0) Driver->extGlProgramParameteri(Program2, GL_GEOMETRY_VERTICES_OUT_EXT, Driver->MaxGeometryVerticesOut); else Driver->extGlProgramParameteri(Program2, GL_GEOMETRY_VERTICES_OUT_EXT, core::min_(verticesOut, Driver->MaxGeometryVerticesOut)); } #elif defined(GL_NV_geometry_program4) if (verticesOut==0) Driver->extGlProgramVertexLimit(GL_GEOMETRY_PROGRAM_NV, Driver->MaxGeometryVerticesOut); else Driver->extGlProgramVertexLimit(GL_GEOMETRY_PROGRAM_NV, core::min_(verticesOut, Driver->MaxGeometryVerticesOut)); #endif } #endif if (!linkProgram()) return; // register myself as new material outMaterialTypeNr = Driver->addMaterialRenderer(this); } bool COpenGLSLMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { // call callback to set shader constants if (CallBack && (Program||Program2)) CallBack->OnSetConstants(this, UserData); return true; } void COpenGLSLMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services) { if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (Program2) Driver->extGlUseProgram(Program2); else if (Program) Driver->extGlUseProgramObject(Program); if (BaseMaterial) BaseMaterial->OnSetMaterial(material, material, true, this); } //let callback know used material if (CallBack) CallBack->OnSetMaterial(material); for (u32 i=0; isetActiveTexture(i, material.getTexture(i)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } void COpenGLSLMaterialRenderer::OnUnsetMaterial() { if (Program) Driver->extGlUseProgramObject(0); if (Program2) Driver->extGlUseProgram(0); if (BaseMaterial) BaseMaterial->OnUnsetMaterial(); } //! Returns if the material is transparent. bool COpenGLSLMaterialRenderer::isTransparent() const { return BaseMaterial ? BaseMaterial->isTransparent() : false; } bool COpenGLSLMaterialRenderer::createProgram() { if (Driver->Version>=200) Program2 = Driver->extGlCreateProgram(); else Program = Driver->extGlCreateProgramObject(); return true; } bool COpenGLSLMaterialRenderer::createShader(GLenum shaderType, const char* shader) { if (Program2) { GLuint shaderHandle = Driver->extGlCreateShader(shaderType); Driver->extGlShaderSource(shaderHandle, 1, &shader, NULL); Driver->extGlCompileShader(shaderHandle); GLint status = 0; #ifdef GL_VERSION_2_0 Driver->extGlGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &status); #endif if (status != GL_TRUE) { os::Printer::log("GLSL shader failed to compile", ELL_ERROR); // check error message and log it GLint maxLength=0; GLint length; #ifdef GL_VERSION_2_0 Driver->extGlGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH, &maxLength); #endif if (maxLength) { GLchar *infoLog = new GLchar[maxLength]; Driver->extGlGetShaderInfoLog(shaderHandle, maxLength, &length, infoLog); os::Printer::log(reinterpret_cast(infoLog), ELL_ERROR); delete [] infoLog; } return false; } Driver->extGlAttachShader(Program2, shaderHandle); } else { GLhandleARB shaderHandle = Driver->extGlCreateShaderObject(shaderType); Driver->extGlShaderSourceARB(shaderHandle, 1, &shader, NULL); Driver->extGlCompileShaderARB(shaderHandle); GLint status = 0; #ifdef GL_ARB_shader_objects Driver->extGlGetObjectParameteriv(shaderHandle, GL_OBJECT_COMPILE_STATUS_ARB, &status); #endif if (!status) { os::Printer::log("GLSL shader failed to compile", ELL_ERROR); // check error message and log it GLint maxLength=0; GLsizei length; #ifdef GL_ARB_shader_objects Driver->extGlGetObjectParameteriv(shaderHandle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxLength); #endif if (maxLength) { GLcharARB *infoLog = new GLcharARB[maxLength]; Driver->extGlGetInfoLog(shaderHandle, maxLength, &length, infoLog); os::Printer::log(reinterpret_cast(infoLog), ELL_ERROR); delete [] infoLog; } return false; } Driver->extGlAttachObject(Program, shaderHandle); } return true; } bool COpenGLSLMaterialRenderer::linkProgram() { if (Program2) { Driver->extGlLinkProgram(Program2); GLint status = 0; #ifdef GL_VERSION_2_0 Driver->extGlGetProgramiv(Program2, GL_LINK_STATUS, &status); #endif if (!status) { os::Printer::log("GLSL shader program failed to link", ELL_ERROR); // check error message and log it GLint maxLength=0; GLsizei length; #ifdef GL_VERSION_2_0 Driver->extGlGetProgramiv(Program2, GL_INFO_LOG_LENGTH, &maxLength); #endif if (maxLength) { GLchar *infoLog = new GLchar[maxLength]; Driver->extGlGetProgramInfoLog(Program2, maxLength, &length, infoLog); os::Printer::log(reinterpret_cast(infoLog), ELL_ERROR); delete [] infoLog; } return false; } // get uniforms information GLint num = 0; #ifdef GL_VERSION_2_0 Driver->extGlGetProgramiv(Program2, GL_ACTIVE_UNIFORMS, &num); #endif if (num == 0) { // no uniforms return true; } GLint maxlen = 0; #ifdef GL_VERSION_2_0 Driver->extGlGetProgramiv(Program2, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxlen); #endif if (maxlen == 0) { os::Printer::log("GLSL: failed to retrieve uniform information", ELL_ERROR); return false; } // seems that some implementations use an extra null terminator ++maxlen; c8 *buf = new c8[maxlen]; UniformInfo.clear(); UniformInfo.reallocate(num); for (GLint i=0; i < num; ++i) { SUniformInfo ui; memset(buf, 0, maxlen); GLint size; Driver->extGlGetActiveUniform(Program2, i, maxlen, 0, &size, &ui.type, reinterpret_cast(buf)); ui.name = buf; UniformInfo.push_back(ui); } delete [] buf; } else { Driver->extGlLinkProgramARB(Program); GLint status = 0; #ifdef GL_ARB_shader_objects Driver->extGlGetObjectParameteriv(Program, GL_OBJECT_LINK_STATUS_ARB, &status); #endif if (!status) { os::Printer::log("GLSL shader program failed to link", ELL_ERROR); // check error message and log it GLint maxLength=0; GLsizei length; #ifdef GL_ARB_shader_objects Driver->extGlGetObjectParameteriv(Program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxLength); #endif if (maxLength) { GLcharARB *infoLog = new GLcharARB[maxLength]; Driver->extGlGetInfoLog(Program, maxLength, &length, infoLog); os::Printer::log(reinterpret_cast(infoLog), ELL_ERROR); delete [] infoLog; } return false; } // get uniforms information GLint num = 0; #ifdef GL_ARB_shader_objects Driver->extGlGetObjectParameteriv(Program, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &num); #endif if (num == 0) { // no uniforms return true; } GLint maxlen = 0; #ifdef GL_ARB_shader_objects Driver->extGlGetObjectParameteriv(Program, GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, &maxlen); #endif if (maxlen == 0) { os::Printer::log("GLSL: failed to retrieve uniform information", ELL_ERROR); return false; } // seems that some implementations use an extra null terminator ++maxlen; c8 *buf = new c8[maxlen]; UniformInfo.clear(); UniformInfo.reallocate(num); for (int i=0; i < num; ++i) { SUniformInfo ui; memset(buf, 0, maxlen); GLint size; Driver->extGlGetActiveUniformARB(Program, i, maxlen, 0, &size, &ui.type, reinterpret_cast(buf)); ui.name = buf; UniformInfo.push_back(ui); } delete [] buf; } return true; } void COpenGLSLMaterialRenderer::setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) { // forward Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } bool COpenGLSLMaterialRenderer::setVertexShaderConstant(const c8* name, const f32* floats, int count) { return setPixelShaderConstant(name, floats, count); } bool COpenGLSLMaterialRenderer::setVertexShaderConstant(const c8* name, const bool* bools, int count) { return setPixelShaderConstant(name, bools, count); } bool COpenGLSLMaterialRenderer::setVertexShaderConstant(const c8* name, const s32* ints, int count) { return setPixelShaderConstant(name, ints, count); } void COpenGLSLMaterialRenderer::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { os::Printer::log("Cannot set constant, please use high level shader call instead.", ELL_WARNING); } bool COpenGLSLMaterialRenderer::setPixelShaderConstant(const c8* name, const f32* floats, int count) { u32 i; const u32 num = UniformInfo.size(); for (i=0; i < num; ++i) { if (UniformInfo[i].name == name) break; } if (i == num) return false; #if defined(GL_VERSION_2_0)||defined(GL_ARB_shader_objects) GLint Location=0; if (Program2) Location=Driver->extGlGetUniformLocation(Program2,name); else Location=Driver->extGlGetUniformLocationARB(Program,name); bool status = true; switch (UniformInfo[i].type) { case GL_FLOAT: Driver->extGlUniform1fv(Location, count, floats); break; case GL_FLOAT_VEC2: Driver->extGlUniform2fv(Location, count/2, floats); break; case GL_FLOAT_VEC3: Driver->extGlUniform3fv(Location, count/3, floats); break; case GL_FLOAT_VEC4: Driver->extGlUniform4fv(Location, count/4, floats); break; case GL_FLOAT_MAT2: Driver->extGlUniformMatrix2fv(Location, count/4, false, floats); break; case GL_FLOAT_MAT3: Driver->extGlUniformMatrix3fv(Location, count/9, false, floats); break; case GL_FLOAT_MAT4: Driver->extGlUniformMatrix4fv(Location, count/16, false, floats); break; case GL_SAMPLER_1D: case GL_SAMPLER_2D: case GL_SAMPLER_3D: case GL_SAMPLER_CUBE: case GL_SAMPLER_1D_SHADOW: case GL_SAMPLER_2D_SHADOW: { const GLint id = static_cast(*floats); Driver->extGlUniform1iv(Location, 1, &id); } break; default: status = false; break; } return status; #else return false; #endif } bool COpenGLSLMaterialRenderer::setPixelShaderConstant(const c8* name, const bool* bools, int count) { u32 i; const u32 num = UniformInfo.size(); for (i=0; i < num; ++i) { if (UniformInfo[i].name == name) break; } if (i == num) return false; #if defined(GL_VERSION_2_0)||defined(GL_ARB_shader_objects) GLint Location=0; if (Program2) Location=Driver->extGlGetUniformLocation(Program2,name); else Location=Driver->extGlGetUniformLocationARB(Program,name); bool status = true; switch (UniformInfo[i].type) { case GL_BOOL: Driver->extGlUniform1iv(Location, count, (GLint*)bools); break; case GL_BOOL_VEC2: Driver->extGlUniform2iv(Location, count/2, (GLint*)bools); break; case GL_BOOL_VEC3: Driver->extGlUniform3iv(Location, count/3, (GLint*)bools); break; case GL_BOOL_VEC4: Driver->extGlUniform4iv(Location, count/4, (GLint*)bools); break; default: status = false; break; } return status; #else return false; #endif } bool COpenGLSLMaterialRenderer::setPixelShaderConstant(const c8* name, const s32* ints, int count) { u32 i; const u32 num = UniformInfo.size(); for (i=0; i < num; ++i) { if (UniformInfo[i].name == name) break; } if (i == num) return false; #if defined(GL_VERSION_2_0)||defined(GL_ARB_shader_objects) GLint Location=0; if (Program2) Location=Driver->extGlGetUniformLocation(Program2,name); else Location=Driver->extGlGetUniformLocationARB(Program,name); bool status = true; switch (UniformInfo[i].type) { case GL_INT: Driver->extGlUniform1iv(Location, count, ints); break; case GL_INT_VEC2: Driver->extGlUniform2iv(Location, count/2, ints); break; case GL_INT_VEC3: Driver->extGlUniform3iv(Location, count/3, ints); break; case GL_INT_VEC4: Driver->extGlUniform4iv(Location, count/4, ints); break; case GL_SAMPLER_1D: case GL_SAMPLER_2D: case GL_SAMPLER_3D: case GL_SAMPLER_CUBE: case GL_SAMPLER_1D_SHADOW: case GL_SAMPLER_2D_SHADOW: Driver->extGlUniform1iv(Location, 1, ints); break; default: status = false; break; } return status; #else return false; #endif } void COpenGLSLMaterialRenderer::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { os::Printer::log("Cannot set constant, use high level shader call.", ELL_WARNING); } IVideoDriver* COpenGLSLMaterialRenderer::getVideoDriver() { return Driver; } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/COpenGLShaderMaterialRenderer.h0000644000000000000000000000527012574354552023036 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_OPENGL_SHADER_MATERIAL_RENDERER_H_INCLUDED__ #define __C_OPENGL_SHADER_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #define GL_GLEXT_LEGACY 1 #else #define GL_GLEXT_PROTOTYPES 1 #endif #ifdef _IRR_WINDOWS_API_ #define WIN32_LEAN_AND_MEAN #include #include #elif defined(_IRR_OSX_PLATFORM_) #include #elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_) #define NO_SDL_GLEXT #include #include #else #include #endif #include "IMaterialRenderer.h" namespace irr { namespace video { class COpenGLDriver; class IShaderConstantSetCallBack; class IMaterialRenderer; //! Class for using vertex and pixel shaders with OpenGL class COpenGLShaderMaterialRenderer : public IMaterialRenderer { public: //! Constructor COpenGLShaderMaterialRenderer(COpenGLDriver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData); //! Destructor virtual ~COpenGLShaderMaterialRenderer(); virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services); virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); virtual void OnUnsetMaterial(); //! Returns if the material is transparent. virtual bool isTransparent() const; protected: //! constructor only for use by derived classes who want to //! create a fall back material for example. COpenGLShaderMaterialRenderer(COpenGLDriver* driver, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData=0); // must not be called more than once! void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, E_VERTEX_TYPE type); bool createPixelShader(const c8* pxsh); bool createVertexShader(const c8* vtxsh); bool checkError(const irr::c8* type); COpenGLDriver* Driver; IShaderConstantSetCallBack* CallBack; IMaterialRenderer* BaseMaterial; GLuint VertexShader; // We have 4 values here, [0] is the non-fog version, the other three are // ARB_fog_linear, ARB_fog_exp, and ARB_fog_exp2 in that order core::array PixelShader; s32 UserData; }; } // end namespace video } // end namespace irr #endif #endif irrlicht-1.8.3/source/Irrlicht/COpenGLShaderMaterialRenderer.cpp0000644000000000000000000002152212574354552023367 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "COpenGLShaderMaterialRenderer.h" #include "IGPUProgrammingServices.h" #include "IShaderConstantSetCallBack.h" #include "IVideoDriver.h" #include "os.h" #include "COpenGLDriver.h" namespace irr { namespace video { //! Constructor COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(video::COpenGLDriver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), VertexShader(0), UserData(userData) { #ifdef _DEBUG setDebugName("COpenGLShaderMaterialRenderer"); #endif PixelShader.set_used(4); for (u32 i=0; i<4; ++i) { PixelShader[i]=0; } if (BaseMaterial) BaseMaterial->grab(); if (CallBack) CallBack->grab(); init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram, EVT_STANDARD); } //! constructor only for use by derived classes who want to //! create a fall back material for example. COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(COpenGLDriver* driver, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), VertexShader(0), UserData(userData) { PixelShader.set_used(4); for (u32 i=0; i<4; ++i) { PixelShader[i]=0; } if (BaseMaterial) BaseMaterial->grab(); if (CallBack) CallBack->grab(); } //! Destructor COpenGLShaderMaterialRenderer::~COpenGLShaderMaterialRenderer() { if (CallBack) CallBack->drop(); if (VertexShader) Driver->extGlDeletePrograms(1, &VertexShader); for (u32 i=0; iextGlDeletePrograms(1, &PixelShader[i]); if (BaseMaterial) BaseMaterial->drop(); } void COpenGLShaderMaterialRenderer::init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, E_VERTEX_TYPE type) { outMaterialTypeNr = -1; bool success; // create vertex shader success=createVertexShader(vertexShaderProgram); // create pixel shader if (!createPixelShader(pixelShaderProgram) || !success) return; // register as a new material outMaterialTypeNr = Driver->addMaterialRenderer(this); } bool COpenGLShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { // call callback to set shader constants if (CallBack && (VertexShader || PixelShader[0])) CallBack->OnSetConstants(service, UserData); return true; } void COpenGLShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services) { if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (VertexShader) { // set new vertex shader #ifdef GL_ARB_vertex_program Driver->extGlBindProgram(GL_VERTEX_PROGRAM_ARB, VertexShader); glEnable(GL_VERTEX_PROGRAM_ARB); #elif defined(GL_NV_vertex_program) Driver->extGlBindProgram(GL_VERTEX_PROGRAM_NV, VertexShader); glEnable(GL_VERTEX_PROGRAM_NV); #endif } // set new pixel shader if (PixelShader[0]) { GLuint nextShader=PixelShader[0]; if (material.FogEnable) { GLint curFogMode; glGetIntegerv(GL_FOG_MODE, &curFogMode); // if (Driver->LinearFog && PixelShader[1]) if (curFogMode==GL_LINEAR && PixelShader[1]) nextShader=PixelShader[1]; // else if (!Driver->LinearFog && PixelShader[2]) else if (curFogMode==GL_EXP && PixelShader[2]) nextShader=PixelShader[2]; else if (curFogMode==GL_EXP2 && PixelShader[3]) nextShader=PixelShader[3]; } #ifdef GL_ARB_fragment_program Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, nextShader); glEnable(GL_FRAGMENT_PROGRAM_ARB); #elif defined(GL_NV_fragment_program) Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_NV, nextShader); glEnable(GL_FRAGMENT_PROGRAM_NV); #endif } if (BaseMaterial) BaseMaterial->OnSetMaterial(material, material, true, services); } //let callback know used material if (CallBack) CallBack->OnSetMaterial(material); for (u32 i=0; isetActiveTexture(i, material.getTexture(i)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } void COpenGLShaderMaterialRenderer::OnUnsetMaterial() { // disable vertex shader #ifdef GL_ARB_vertex_program if (VertexShader) glDisable(GL_VERTEX_PROGRAM_ARB); #elif defined(GL_NV_vertex_program) if (VertexShader) glDisable(GL_VERTEX_PROGRAM_NV); #endif #ifdef GL_ARB_fragment_program if (PixelShader[0]) glDisable(GL_FRAGMENT_PROGRAM_ARB); #elif defined(GL_NV_fragment_program) if (PixelShader[0]) glDisable(GL_FRAGMENT_PROGRAM_NV); #endif if (BaseMaterial) BaseMaterial->OnUnsetMaterial(); } //! Returns if the material is transparent. bool COpenGLShaderMaterialRenderer::isTransparent() const { return BaseMaterial ? BaseMaterial->isTransparent() : false; } // This method needs a properly cleaned error state before the checked instruction is called bool COpenGLShaderMaterialRenderer::checkError(const irr::c8* type) { #if defined(GL_ARB_vertex_program) || defined(GL_NV_vertex_program) || defined(GL_ARB_fragment_program) || defined(GL_NV_fragment_program) GLenum g = glGetError(); if (g == GL_NO_ERROR) return false; core::stringc errString = type; errString += " compilation failed"; errString += " at position "; GLint errPos=-1; #if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); #else glGetIntegerv( GL_PROGRAM_ERROR_POSITION_NV, &errPos ); #endif errString += core::stringc(s32(errPos)); errString += ":\n"; #if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) errString += reinterpret_cast(glGetString(GL_PROGRAM_ERROR_STRING_ARB)); #else errString += reinterpret_cast(glGetString(GL_PROGRAM_ERROR_STRING_NV)); #endif #else core::stringc errString("Shaders not supported."); #endif os::Printer::log(errString.c_str(), ELL_ERROR); return true; } bool COpenGLShaderMaterialRenderer::createPixelShader(const c8* pxsh) { if (!pxsh) return true; const core::stringc inshdr(pxsh); core::stringc shdr; const s32 pos = inshdr.find("#_IRR_FOG_MODE_"); const u32 numShaders = (-1 != pos)?4:1; for (u32 i=0; iextGlGenPrograms(1, &PixelShader[i]); #ifdef GL_ARB_fragment_program Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader[i]); #elif defined GL_NV_fragment_program Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_NV, PixelShader[i]); #endif // clear error buffer while(glGetError() != GL_NO_ERROR) {} #ifdef GL_ARB_fragment_program // compile Driver->extGlProgramString(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, shdr.size(), shdr.c_str()); #elif defined GL_NV_fragment_program Driver->extGlLoadProgram(GL_FRAGMENT_PROGRAM_NV, PixelShader[i], shdr.size(), shdr.c_str()); #endif if (checkError("Pixel shader")) { Driver->extGlDeletePrograms(1, &PixelShader[i]); PixelShader[i]=0; return false; } } return true; } bool COpenGLShaderMaterialRenderer::createVertexShader(const c8* vtxsh) { if (!vtxsh) return true; Driver->extGlGenPrograms(1, &VertexShader); #ifdef GL_ARB_vertex_program Driver->extGlBindProgram(GL_VERTEX_PROGRAM_ARB, VertexShader); #elif defined GL_NV_vertex_program Driver->extGlBindProgram(GL_VERTEX_PROGRAM_NV, VertexShader); #endif // clear error buffer while(glGetError() != GL_NO_ERROR) {} // compile #ifdef GL_ARB_vertex_program Driver->extGlProgramString(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(vtxsh), vtxsh); #elif defined GL_NV_vertex_program Driver->extGlLoadProgram(GL_VERTEX_PROGRAM_NV, VertexShader, (GLsizei)strlen(vtxsh), vtxsh); #endif if (checkError("Vertex shader")) { Driver->extGlDeletePrograms(1, &VertexShader); VertexShader=0; return false; } return true; } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/COpenGLParallaxMapRenderer.h0000644000000000000000000000276212574354552022356 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_OPENGL_PARALLAX_MAP_RENDERER_H_INCLUDED__ #define __C_OPENGL_PARALLAX_MAP_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "COpenGLShaderMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" namespace irr { namespace video { //! Class for rendering normal maps with OpenGL class COpenGLParallaxMapRenderer : public COpenGLShaderMaterialRenderer, public IShaderConstantSetCallBack { public: //! Constructor COpenGLParallaxMapRenderer(video::COpenGLDriver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial); //! Destructor ~COpenGLParallaxMapRenderer(); //! Called by the engine when the vertex and/or pixel shader constants for an //! material renderer should be set. virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData); //! Returns the render capability of the material. virtual s32 getRenderCapability() const; virtual void OnSetMaterial(const SMaterial& material) { } virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services); protected: bool CompiledShaders; f32 CurrentScale; }; } // end namespace video } // end namespace irr #endif #endif irrlicht-1.8.3/source/Irrlicht/COpenGLParallaxMapRenderer.cpp0000644000000000000000000002755612574354552022721 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "COpenGLParallaxMapRenderer.h" #include "COpenGLDriver.h" #include "IGPUProgrammingServices.h" #include "IShaderConstantSetCallBack.h" #include "IVideoDriver.h" #include "os.h" namespace irr { namespace video { // Irrlicht Engine OpenGL render path parallax map vertex shader // I guess it could be optimized a lot, because I wrote it in D3D ASM and // transferred it 1:1 to OpenGL const char OPENGL_PARALLAX_MAP_VSH[] = "!!ARBvp1.0\n"\ "#input\n"\ "# 0-3: transposed world matrix;\n"\ "#;12: Light01 position \n"\ "#;13: x,y,z: Light01 color; .w: 1/LightRadius^2 \n"\ "#;14: Light02 position \n"\ "#;15: x,y,z: Light02 color; .w: 1/LightRadius^2 \n"\ "#;16: Eye position \n"\ "\n"\ "ATTRIB InPos = vertex.position;\n"\ "ATTRIB InColor = vertex.color;\n"\ "ATTRIB InNormal = vertex.normal;\n"\ "ATTRIB InTexCoord = vertex.texcoord[0];\n"\ "ATTRIB InTangent = vertex.texcoord[1];\n"\ "ATTRIB InBinormal = vertex.texcoord[2];\n"\ "\n"\ "#output\n"\ "OUTPUT OutPos = result.position;\n"\ "OUTPUT OutLightColor1 = result.color.primary;\n"\ "OUTPUT OutLightColor2 = result.color.secondary;\n"\ "OUTPUT OutTexCoord = result.texcoord[0];\n"\ "OUTPUT OutLightVector1 = result.texcoord[1];\n"\ "OUTPUT OutLightVector2 = result.texcoord[2];\n"\ "OUTPUT OutEyeVector = result.texcoord[3];\n"\ "\n"\ "PARAM MVP[4] = { state.matrix.mvp }; # modelViewProjection matrix.\n"\ "TEMP Temp;\n"\ "TEMP TempColor;\n"\ "TEMP TempLightVector1;\n"\ "TEMP TempLightVector2;\n"\ "TEMP TempEyeVector;\n"\ "TEMP TempTransLightV1;\n"\ "TEMP TempTransLightV2;\n"\ "\n"\ "# transform position to clip space \n"\ "DP4 OutPos.x, MVP[0], InPos;\n"\ "DP4 OutPos.y, MVP[1], InPos;\n"\ "DP4 Temp.z, MVP[2], InPos;\n"\ "DP4 OutPos.w, MVP[3], InPos;\n"\ "MOV OutPos.z, Temp.z;\n"\ "MOV result.fogcoord.x, Temp.z;\n"\ "\n"\ "# vertex - lightpositions \n"\ "SUB TempLightVector1, program.local[12], InPos; \n"\ "SUB TempLightVector2, program.local[14], InPos; \n"\ "\n"\ "# eye vector \n"\ "SUB Temp, program.local[16], InPos; \n"\ "\n"\ "# transform the light vector 1 with U, V, W \n"\ "DP3 TempTransLightV1.x, InTangent, TempLightVector1; \n"\ "DP3 TempTransLightV1.y, InBinormal, TempLightVector1; \n"\ "DP3 TempTransLightV1.z, InNormal, TempLightVector1; \n"\ "\n"\ "# transform the light vector 2 with U, V, W \n"\ "DP3 TempTransLightV2.x, InTangent, TempLightVector2; \n"\ "DP3 TempTransLightV2.y, InBinormal, TempLightVector2; \n"\ "DP3 TempTransLightV2.z, InNormal, TempLightVector2; \n"\ "\n"\ "# transform the eye vector with U, V, W \n"\ "DP3 TempEyeVector.x, InTangent, Temp; \n"\ "DP3 TempEyeVector.y, InBinormal, Temp; \n"\ "DP3 TempEyeVector.z, InNormal, Temp; \n"\ "\n"\ "# normalize light vector 1 \n"\ "DP3 TempTransLightV1.w, TempTransLightV1, TempTransLightV1; \n"\ "RSQ TempTransLightV1.w, TempTransLightV1.w; \n"\ "MUL TempTransLightV1, TempTransLightV1, TempTransLightV1.w;\n"\ "\n"\ "# normalize light vector 2 \n"\ "DP3 TempTransLightV2.w, TempTransLightV2, TempTransLightV2; \n"\ "RSQ TempTransLightV2.w, TempTransLightV2.w; \n"\ "MUL TempTransLightV2, TempTransLightV2, TempTransLightV2.w;\n"\ "\n"\ "# normalize eye vector \n"\ "DP3 TempEyeVector.w, TempEyeVector, TempEyeVector; \n"\ "RSQ TempEyeVector.w, TempEyeVector.w; \n"\ "MUL TempEyeVector, TempEyeVector, TempEyeVector.w;\n"\ "MUL TempEyeVector, TempEyeVector, {1,-1,-1,1}; # flip x \n"\ "\n"\ "\n"\ "# move light and eye vectors out\n"\ "MAD OutLightVector1, TempTransLightV1, {0.5,0.5,0.5,0.5}, {0.5,0.5,0.5,0.5}; \n"\ "MAD OutLightVector2, TempTransLightV2, {0.5,0.5,0.5,0.5}, {0.5,0.5,0.5,0.5}; \n"\ "MAD OutEyeVector, TempEyeVector, {0.5,0.5,0.5,0.5}, {0.5,0.5,0.5,0.5}; \n"\ "\n"\ "# calculate attenuation of light 1\n"\ "MOV TempLightVector1.w, {0,0,0,0}; \n"\ "DP3 TempLightVector1.x, TempLightVector1, TempLightVector1; \n"\ "MUL TempLightVector1.x, TempLightVector1.x, program.local[13].w; \n"\ "RSQ TempLightVector1, TempLightVector1.x; \n"\ "MUL OutLightColor1, TempLightVector1, program.local[13]; # resulting light color = lightcolor * attenuation \n"\ "\n"\ "# calculate attenuation of light 2\n"\ "MOV TempLightVector2.w, {0,0,0,0}; \n"\ "DP3 TempLightVector2.x, TempLightVector2, TempLightVector2; \n"\ "MUL TempLightVector2.x, TempLightVector2.x, program.local[15].w; \n"\ "RSQ TempLightVector2, TempLightVector2.x; \n"\ "MUL OutLightColor2, TempLightVector2, program.local[15]; # resulting light color = lightcolor * attenuation \n"\ "\n"\ "# move out texture coordinates and original alpha value\n"\ "MOV OutTexCoord, InTexCoord; \n"\ "MOV OutLightColor1.w, InColor.w; \n"\ "\n"\ "END\n"; // Irrlicht Engine OpenGL render path parallax map pixel shader // I guess it could be optimized a bit, because I wrote it in D3D ASM and // transfered it 1:1 to OpenGL const char OPENGL_PARALLAX_MAP_PSH[] = "!!ARBfp1.0\n"\ "#_IRR_FOG_MODE_\n"\ "\n"\ "#Input\n"\ "ATTRIB inTexCoord = fragment.texcoord[0]; \n"\ "ATTRIB light1Vector = fragment.texcoord[1]; \n"\ "ATTRIB light2Vector = fragment.texcoord[2]; \n"\ "ATTRIB eyeVector = fragment.texcoord[3]; \n"\ "ATTRIB light1Color = fragment.color.primary; \n"\ "ATTRIB light2Color = fragment.color.secondary; \n"\ "\n"\ "#Output\n"\ "OUTPUT outColor = result.color;\n"\ "TEMP temp;\n"\ "TEMP temp2;\n"\ "TEMP colorMapColor;\n"\ "TEMP normalMapColor;\n"\ "\n"\ "PARAM height_scale = program.local[0]; \n"\ "# fetch color and normal map; \n"\ "TXP normalMapColor, inTexCoord, texture[1], 2D; \n"\ "MAD normalMapColor, normalMapColor, {2,2,2,2}, {-1,-1,-1,-1}; \n"\ "\n"\ "\n"\ "# extract eye vector (so substract 0.5f and multiply by 2)\n"\ "MAD temp, eyeVector, {2,2,2,2}, {-1,-1,-1,-1};\n"\ "\n"\ "# height = height * scale \n"\ "MUL normalMapColor, normalMapColor, height_scale;\n"\ "\n"\ "# calculate new texture coord: height * eye + oldTexCoord\n"\ "MAD temp, temp, normalMapColor.wwww, inTexCoord;\n"\ "\n"\ "# fetch new textures \n"\ "TXP colorMapColor, temp, texture[0], 2D; \n"\ "TXP normalMapColor, temp, texture[1], 2D; \n"\ "\n"\ "# calculate color of light1; \n"\ "MAD normalMapColor, normalMapColor, {2,2,2,2}, {-1,-1,-1,-1}; \n"\ "MAD temp, light1Vector, {2,2,2,2}, {-1,-1,-1,-1}; \n"\ "DP3_SAT temp, normalMapColor, temp; \n"\ "MUL temp, light1Color, temp; \n"\ "\n"\ "# calculate color of light2; \n"\ "MAD temp2, light2Vector, {2,2,2,2}, {-1,-1,-1,-1}; \n"\ "DP3_SAT temp2, normalMapColor, temp2; \n"\ "MAD temp, light2Color, temp2, temp; \n"\ "\n"\ "# luminance * base color; \n"\ "MUL outColor, temp, colorMapColor; \n"\ "MOV outColor.a, light1Color.a; #write interpolated vertex alpha value\n"\ "\n"\ "END\n"; //! Constructor COpenGLParallaxMapRenderer::COpenGLParallaxMapRenderer(video::COpenGLDriver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial) : COpenGLShaderMaterialRenderer(driver, 0, baseMaterial), CompiledShaders(true) { #ifdef _DEBUG setDebugName("COpenGLParallaxMapRenderer"); #endif // set this as callback. We could have done this in // the initialization list, but some compilers don't like it. CallBack = this; // basically, this simply compiles the hard coded shaders if the // hardware is able to do them, otherwise it maps to the base material if (!driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1) || !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)) { // this hardware is not able to do shaders. Fall back to // base material. outMaterialTypeNr = driver->addMaterialRenderer(this); return; } // check if already compiled normal map shaders are there. video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_PARALLAX_MAP_SOLID); if (renderer) { // use the already compiled shaders video::COpenGLParallaxMapRenderer* nmr = reinterpret_cast(renderer); CompiledShaders = false; VertexShader = nmr->VertexShader; PixelShader = nmr->PixelShader; outMaterialTypeNr = driver->addMaterialRenderer(this); } else { // compile shaders on our own init(outMaterialTypeNr, OPENGL_PARALLAX_MAP_VSH, OPENGL_PARALLAX_MAP_PSH, EVT_TANGENTS); } // fallback if compilation has failed if (-1==outMaterialTypeNr) outMaterialTypeNr = driver->addMaterialRenderer(this); } //! Destructor COpenGLParallaxMapRenderer::~COpenGLParallaxMapRenderer() { if (CallBack == this) CallBack = 0; if (!CompiledShaders) { // prevent this from deleting shaders we did not create VertexShader = 0; PixelShader.clear(); } } void COpenGLParallaxMapRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services) { COpenGLShaderMaterialRenderer::OnSetMaterial(material, lastMaterial, resetAllRenderstates, services); CurrentScale = material.MaterialTypeParam; } //! Returns the render capability of the material. s32 COpenGLParallaxMapRenderer::getRenderCapability() const { if (Driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1) && Driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)) return 0; return 1; } //! Called by the engine when the vertex and/or pixel shader constants for an //! material renderer should be set. void COpenGLParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData) { video::IVideoDriver* driver = services->getVideoDriver(); // set transposed world matrix const core::matrix4& tWorld = driver->getTransform(video::ETS_WORLD).getTransposed(); services->setVertexShaderConstant(tWorld.pointer(), 0, 4); // set transposed worldViewProj matrix core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION)); worldViewProj *= driver->getTransform(video::ETS_VIEW); worldViewProj *= driver->getTransform(video::ETS_WORLD); core::matrix4 tr(worldViewProj.getTransposed()); services->setVertexShaderConstant(tr.pointer(), 8, 4); // here we fetch the fixed function lights from the driver // and set them as constants u32 cnt = driver->getDynamicLightCount(); // Load the inverse world matrix. core::matrix4 invWorldMat; driver->getTransform(video::ETS_WORLD).getInverse(invWorldMat); for (u32 i=0; i<2; ++i) { video::SLight light; if (igetDynamicLight(i); else { light.DiffuseColor.set(0,0,0); // make light dark light.Radius = 1.0f; } light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation // Transform the light by the inverse world matrix to get it into object space. invWorldMat.transformVect(light.Position); services->setVertexShaderConstant( reinterpret_cast(&light.Position), 12+(i*2), 1); services->setVertexShaderConstant( reinterpret_cast(&light.DiffuseColor), 13+(i*2), 1); } // Obtain the view position by transforming 0,0,0 by the inverse view matrix // and then multiply this by the inverse world matrix. core::vector3df viewPos(0.0f, 0.0f, 0.0f); core::matrix4 inverseView; driver->getTransform(video::ETS_VIEW).getInverse(inverseView); inverseView.transformVect(viewPos); invWorldMat.transformVect(viewPos); services->setVertexShaderConstant(reinterpret_cast(&viewPos.X), 16, 1); // set scale factor f32 factor = 0.02f; // default value if (CurrentScale != 0.0f) factor = CurrentScale; f32 c6[] = {factor, factor, factor, factor}; services->setPixelShaderConstant(c6, 0, 1); } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/COpenGLNormalMapRenderer.h0000644000000000000000000000234312574354552022035 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_OPENGL_NORMAL_MAP_RENDERER_H_INCLUDED__ #define __C_OPENGL_NORMAL_MAP_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "COpenGLShaderMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" namespace irr { namespace video { //! Class for rendering normal maps with OpenGL class COpenGLNormalMapRenderer : public COpenGLShaderMaterialRenderer, public IShaderConstantSetCallBack { public: //! Constructor COpenGLNormalMapRenderer(video::COpenGLDriver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial); //! Destructor ~COpenGLNormalMapRenderer(); //! Called by the engine when the vertex and/or pixel shader constants for an //! material renderer should be set. virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData); //! Returns the render capability of the material. virtual s32 getRenderCapability() const; protected: bool CompiledShaders; }; } // end namespace video } // end namespace irr #endif #endif irrlicht-1.8.3/source/Irrlicht/COpenGLNormalMapRenderer.cpp0000644000000000000000000002304112574354552022366 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "COpenGLNormalMapRenderer.h" #include "IGPUProgrammingServices.h" #include "IShaderConstantSetCallBack.h" #include "IVideoDriver.h" #include "os.h" #include "COpenGLDriver.h" namespace irr { namespace video { // Irrlicht Engine OpenGL render path normal map vertex shader // I guess it could be optimized a lot, because I wrote it in D3D ASM and // transferred it 1:1 to OpenGL const char OPENGL_NORMAL_MAP_VSH[] = "!!ARBvp1.0\n"\ "#input\n"\ "# 0-3: transposed world matrix;\n"\ "#;12: Light01 position \n"\ "#;13: x,y,z: Light01 color; .w: 1/LightRadius^2 \n"\ "#;14: Light02 position \n"\ "#;15: x,y,z: Light02 color; .w: 1/LightRadius^2 \n"\ "\n"\ "ATTRIB InPos = vertex.position;\n"\ "ATTRIB InColor = vertex.color;\n"\ "ATTRIB InNormal = vertex.normal;\n"\ "ATTRIB InTexCoord = vertex.texcoord[0];\n"\ "ATTRIB InTangent = vertex.texcoord[1];\n"\ "ATTRIB InBinormal = vertex.texcoord[2];\n"\ "\n"\ "#output\n"\ "OUTPUT OutPos = result.position;\n"\ "OUTPUT OutLightColor1 = result.color.primary;\n"\ "OUTPUT OutLightColor2 = result.color.secondary;\n"\ "OUTPUT OutTexCoord = result.texcoord[0];\n"\ "OUTPUT OutLightVector1 = result.texcoord[1];\n"\ "OUTPUT OutLightVector2 = result.texcoord[2];\n"\ "\n"\ "PARAM MVP[4] = { state.matrix.mvp }; # modelViewProjection matrix.\n"\ "TEMP Temp;\n"\ "TEMP TempColor;\n"\ "TEMP TempLightVector1;\n"\ "TEMP TempLightVector2;\n"\ "TEMP TempTransLightV1;\n"\ "TEMP TempTransLightV2;\n"\ "\n"\ "# transform position to clip space \n"\ "DP4 OutPos.x, MVP[0], InPos;\n"\ "DP4 OutPos.y, MVP[1], InPos;\n"\ "DP4 Temp.z, MVP[2], InPos;\n"\ "DP4 OutPos.w, MVP[3], InPos;\n"\ "MOV OutPos.z, Temp.z;\n"\ "MOV result.fogcoord.x, Temp.z;\n"\ "\n"\ "# vertex - lightpositions \n"\ "SUB TempLightVector1, program.local[12], InPos; \n"\ "SUB TempLightVector2, program.local[14], InPos; \n"\ "\n"\ "# transform the light vector 1 with U, V, W \n"\ "DP3 TempTransLightV1.x, InTangent, TempLightVector1; \n"\ "DP3 TempTransLightV1.y, InBinormal, TempLightVector1; \n"\ "DP3 TempTransLightV1.z, InNormal, TempLightVector1; \n"\ "\n"\ "# transform the light vector 2 with U, V, W \n"\ "DP3 TempTransLightV2.x, InTangent, TempLightVector2; \n"\ "DP3 TempTransLightV2.y, InBinormal, TempLightVector2; \n"\ "DP3 TempTransLightV2.z, InNormal, TempLightVector2; \n"\ "\n"\ "# normalize light vector 1 \n"\ "DP3 TempTransLightV1.w, TempTransLightV1, TempTransLightV1; \n"\ "RSQ TempTransLightV1.w, TempTransLightV1.w; \n"\ "MUL TempTransLightV1, TempTransLightV1, TempTransLightV1.w;\n"\ "\n"\ "# normalize light vector 2 \n"\ "DP3 TempTransLightV2.w, TempTransLightV2, TempTransLightV2; \n"\ "RSQ TempTransLightV2.w, TempTransLightV2.w; \n"\ "MUL TempTransLightV2, TempTransLightV2, TempTransLightV2.w;\n"\ "\n"\ "\n"\ "# move light vectors out\n"\ "MAD OutLightVector1, TempTransLightV1, {0.5,0.5,0.5,0.5}, {0.5,0.5,0.5,0.5}; \n"\ "MAD OutLightVector2, TempTransLightV2, {0.5,0.5,0.5,0.5}, {0.5,0.5,0.5,0.5}; \n"\ "\n"\ "# calculate attenuation of light 1\n"\ "MOV TempLightVector1.w, {0,0,0,0}; \n"\ "DP3 TempLightVector1.x, TempLightVector1, TempLightVector1; \n"\ "MUL TempLightVector1.x, TempLightVector1.x, program.local[13].w; \n"\ "RSQ TempLightVector1, TempLightVector1.x; \n"\ "MUL OutLightColor1, TempLightVector1, program.local[13]; # resulting light color = lightcolor * attenuation \n"\ "\n"\ "# calculate attenuation of light 2\n"\ "MOV TempLightVector2.w, {0,0,0,0}; \n"\ "DP3 TempLightVector2.x, TempLightVector2, TempLightVector2; \n"\ "MUL TempLightVector2.x, TempLightVector2.x, program.local[15].w; \n"\ "RSQ TempLightVector2, TempLightVector2.x; \n"\ "MUL OutLightColor2, TempLightVector2, program.local[15]; # resulting light color = lightcolor * attenuation \n"\ "\n"\ "# move out texture coordinates and original alpha value\n"\ "MOV OutTexCoord, InTexCoord; \n"\ "MOV OutLightColor1.w, InColor.w; \n"\ "\n"\ "END\n"; // Irrlicht Engine OpenGL render path normal map pixel shader // I guess it could be optimized a bit, because I wrote it in D3D ASM and // transfered it 1:1 to OpenGL const char OPENGL_NORMAL_MAP_PSH[] = "!!ARBfp1.0\n"\ "#_IRR_FOG_MODE_\n"\ "\n"\ "#Input\n"\ "ATTRIB inTexCoord = fragment.texcoord[0]; \n"\ "ATTRIB light1Vector = fragment.texcoord[1]; \n"\ "ATTRIB light2Vector = fragment.texcoord[2]; \n"\ "ATTRIB light1Color = fragment.color.primary; \n"\ "ATTRIB light2Color = fragment.color.secondary; \n"\ "\n"\ "#Output\n"\ "OUTPUT outColor = result.color;\n"\ "TEMP temp;\n"\ "TEMP temp2;\n"\ "TEMP colorMapColor;\n"\ "TEMP normalMapColor;\n"\ "\n"\ "# fetch color and normal map; \n"\ "TXP colorMapColor, inTexCoord, texture[0], 2D; \n"\ "TXP normalMapColor, inTexCoord, texture[1], 2D; \n"\ "\n"\ "# calculate color of light1; \n"\ "MAD normalMapColor, normalMapColor, {2,2,2,2}, {-1,-1,-1,-1}; \n"\ "MAD temp, light1Vector, {2,2,2,2}, {-1,-1,-1,-1}; \n"\ "DP3_SAT temp, normalMapColor, temp; \n"\ "MUL temp, light1Color, temp; \n"\ "\n"\ "# calculate color of light2; \n"\ "MAD temp2, light2Vector, {2,2,2,2}, {-1,-1,-1,-1}; \n"\ "DP3_SAT temp2, normalMapColor, temp2; \n"\ "MAD temp, light2Color, temp2, temp; \n"\ "\n"\ "# luminance * base color; \n"\ "MUL outColor, temp, colorMapColor; \n"\ "MOV outColor.a, light1Color.a; #write interpolated vertex alpha value\n"\ "\n"\ "END\n"; //! Constructor COpenGLNormalMapRenderer::COpenGLNormalMapRenderer(video::COpenGLDriver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial) : COpenGLShaderMaterialRenderer(driver, 0, baseMaterial), CompiledShaders(true) { #ifdef _DEBUG setDebugName("COpenGLNormalMapRenderer"); #endif // set this as callback. We could have done this in // the initialization list, but some compilers don't like it. CallBack = this; // basically, this thing simply compiles the hardcoded shaders if the // hardware is able to do them, otherwise it maps to the base material if (!driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1) || !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)) { // this hardware is not able to do shaders. Fall back to // base material. outMaterialTypeNr = driver->addMaterialRenderer(this); return; } // check if already compiled normal map shaders are there. video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_NORMAL_MAP_SOLID); if (renderer) { // use the already compiled shaders video::COpenGLNormalMapRenderer* nmr = reinterpret_cast(renderer); CompiledShaders = false; VertexShader = nmr->VertexShader; PixelShader = nmr->PixelShader; outMaterialTypeNr = driver->addMaterialRenderer(this); } else { // compile shaders on our own init(outMaterialTypeNr, OPENGL_NORMAL_MAP_VSH, OPENGL_NORMAL_MAP_PSH, EVT_TANGENTS); } // fallback if compilation has failed if (-1==outMaterialTypeNr) outMaterialTypeNr = driver->addMaterialRenderer(this); } //! Destructor COpenGLNormalMapRenderer::~COpenGLNormalMapRenderer() { if (CallBack == this) CallBack = 0; if (!CompiledShaders) { // prevent this from deleting shaders we did not create VertexShader = 0; PixelShader.clear(); } } //! Returns the render capability of the material. s32 COpenGLNormalMapRenderer::getRenderCapability() const { if (Driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1) && Driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)) return 0; return 1; } //! Called by the engine when the vertex and/or pixel shader constants for an //! material renderer should be set. void COpenGLNormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData) { video::IVideoDriver* driver = services->getVideoDriver(); // set transposed world matrix const core::matrix4& tWorld = driver->getTransform(video::ETS_WORLD).getTransposed(); services->setVertexShaderConstant(tWorld.pointer(), 0, 4); // set transposed worldViewProj matrix core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION)); worldViewProj *= driver->getTransform(video::ETS_VIEW); worldViewProj *= driver->getTransform(video::ETS_WORLD); core::matrix4 tr(worldViewProj.getTransposed()); services->setVertexShaderConstant(tr.pointer(), 8, 4); // here we fetch the fixed function lights from the driver // and set them as constants u32 cnt = driver->getDynamicLightCount(); // Load the inverse world matrix. core::matrix4 invWorldMat; driver->getTransform(video::ETS_WORLD).getInverse(invWorldMat); for (u32 i=0; i<2; ++i) { video::SLight light; if (igetDynamicLight(i); else { light.DiffuseColor.set(0,0,0); // make light dark light.Radius = 1.0f; } light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation // Transform the light by the inverse world matrix to get it into object space. invWorldMat.transformVect(light.Position); services->setVertexShaderConstant( reinterpret_cast(&light.Position), 12+(i*2), 1); services->setVertexShaderConstant( reinterpret_cast(&light.DiffuseColor), 13+(i*2), 1); } } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/COpenGLMaterialRenderer.h0000644000000000000000000006171312574354552021713 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_OPENGL_MATERIAL_RENDERER_H_INCLUDED__ #define __C_OPENGL_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "COpenGLDriver.h" #include "IMaterialRenderer.h" namespace irr { namespace video { //! Base class for all internal OpenGL material renderers class COpenGLMaterialRenderer : public IMaterialRenderer { public: //! Constructor COpenGLMaterialRenderer(video::COpenGLDriver* driver) : Driver(driver) { } protected: video::COpenGLDriver* Driver; }; //! Solid material renderer class COpenGLMaterialRenderer_SOLID : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_SOLID(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (resetAllRenderstates || (material.MaterialType != lastMaterial.MaterialType)) { // thanks to Murphy, the following line removed some // bugs with several OpenGL implementations. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } }; //! Generic Texture Blend class COpenGLMaterialRenderer_ONETEXTURE_BLEND : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_ONETEXTURE_BLEND(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); // if (material.MaterialType != lastMaterial.MaterialType || // material.MaterialTypeParam != lastMaterial.MaterialTypeParam || // resetAllRenderstates) { E_BLEND_FACTOR srcFact,dstFact; E_MODULATE_FUNC modulate; u32 alphaSource; unpack_textureBlendFunc(srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam); #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (f32) modulate ); #else glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, (f32) modulate ); #endif glBlendFunc(Driver->getGLBlend(srcFact), Driver->getGLBlend(dstFact)); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.f); glEnable(GL_BLEND); if ( textureBlendFunc_hasAlpha(srcFact) || textureBlendFunc_hasAlpha(dstFact) ) { if (alphaSource==EAS_VERTEX_COLOR) { #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); #else glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); #endif } else if (alphaSource==EAS_TEXTURE) { #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); #else glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); #endif } else { #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE); #else glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_TEXTURE); #endif } } } } virtual void OnUnsetMaterial() { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.f ); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); #else glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f ); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); #endif glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); } //! Returns if the material is transparent. /** Is not always transparent, but mostly. */ virtual bool isTransparent() const { return true; } }; //! Solid 2 layer material renderer class COpenGLMaterialRenderer_SOLID_2_LAYER : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_SOLID_2_LAYER(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PRIMARY_COLOR); glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA); #else glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR); glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); #endif } } } virtual void OnUnsetMaterial() { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR); #else glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR); #endif Driver->extGlActiveTexture(GL_TEXTURE0_ARB); } } }; //! Transparent add color material renderer class COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if ((material.MaterialType != lastMaterial.MaterialType) || resetAllRenderstates) { glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glEnable(GL_BLEND); } } virtual void OnUnsetMaterial() { glDisable(GL_BLEND); } //! Returns if the material is transparent. virtual bool isTransparent() const { return true; } }; //! Transparent vertex alpha material renderer class COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); #else glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT ); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); #endif glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); } } virtual void OnUnsetMaterial() { // default values glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE ); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE ); #else glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE ); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE ); #endif glDisable(GL_BLEND); } //! Returns if the material is transparent. virtual bool isTransparent() const { return true; } }; //! Transparent alpha channel material renderer class COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates || material.MaterialTypeParam != lastMaterial.MaterialTypeParam ) { #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); #else glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); #endif glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, material.MaterialTypeParam); } } virtual void OnUnsetMaterial() { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE ); #else glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE ); #endif glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); } //! Returns if the material is transparent. virtual bool isTransparent() const { return true; } }; //! Transparent alpha channel material renderer class COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } virtual void OnUnsetMaterial() { glDisable(GL_ALPHA_TEST); } //! Returns if the material is transparent. virtual bool isTransparent() const { return false; // this material is not really transparent because it does no blending. } }; //! material renderer for all kinds of lightmaps class COpenGLMaterialRenderer_LIGHTMAP : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_LIGHTMAP(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { // diffuse map switch (material.MaterialType) { case EMT_LIGHTMAP_LIGHTING: case EMT_LIGHTMAP_LIGHTING_M2: case EMT_LIGHTMAP_LIGHTING_M4: glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); break; case EMT_LIGHTMAP_ADD: case EMT_LIGHTMAP: case EMT_LIGHTMAP_M2: case EMT_LIGHTMAP_M4: default: glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); break; } if (Driver->queryFeature(EVDF_MULTITEXTURE)) { // lightmap Driver->extGlActiveTexture(GL_TEXTURE1_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); if (material.MaterialType == EMT_LIGHTMAP_ADD) glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD); else glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB); #else glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); if (material.MaterialType == EMT_LIGHTMAP_ADD) glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD); else glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT); #endif switch (material.MaterialType) { case EMT_LIGHTMAP_M4: case EMT_LIGHTMAP_LIGHTING_M4: #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 4.0f); #else glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 4.0f); #endif break; case EMT_LIGHTMAP_M2: case EMT_LIGHTMAP_LIGHTING_M2: #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2.0f); #else glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); #endif break; default: #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f); #else glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f); #endif } Driver->extGlActiveTexture(GL_TEXTURE0_ARB); } } } virtual void OnUnsetMaterial() { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.f ); #else glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f ); #endif glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); Driver->extGlActiveTexture(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } }; //! detail map material renderer class COpenGLMaterialRenderer_DETAIL_MAP : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_DETAIL_MAP(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { // diffuse map is default modulated // detail map on second layer if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); #else glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD_SIGNED_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); #endif } } } virtual void OnUnsetMaterial() { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); Driver->extGlActiveTexture(GL_TEXTURE0_ARB); } } }; //! sphere map material renderer class COpenGLMaterialRenderer_SPHERE_MAP : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_SPHERE_MAP(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); // texture needs to be flipped for OpenGL core::matrix4 tmp = Driver->getTransform(ETS_TEXTURE_0); tmp[5]*=-1; Driver->setTransform(ETS_TEXTURE_0, tmp); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); } } virtual void OnUnsetMaterial() { glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); } }; //! reflection 2 layer material renderer class COpenGLMaterialRenderer_REFLECTION_2_LAYER : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_REFLECTION_2_LAYER(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); #else glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); #endif } glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); } } virtual void OnUnsetMaterial() { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE0_ARB); } } }; //! reflection 2 layer material renderer class COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public COpenGLMaterialRenderer { public: COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(video::COpenGLDriver* d) : COpenGLMaterialRenderer(d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); #else glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_ARB); #endif if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); #ifdef GL_ARB_texture_env_combine glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); #else glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_ARB); #endif } glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); } } virtual void OnUnsetMaterial() { if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE0_ARB); } glDisable(GL_BLEND); } //! Returns if the material is transparent. virtual bool isTransparent() const { return true; } }; } // end namespace video } // end namespace irr #endif #endif irrlicht-1.8.3/source/Irrlicht/COpenGLExtensionHandler.h0000644000000000000000000024604612574354552021744 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h #ifndef __C_OPEN_GL_FEATURE_MAP_H_INCLUDED__ #define __C_OPEN_GL_FEATURE_MAP_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "EDriverFeatures.h" #include "irrTypes.h" #include "os.h" #if defined(_IRR_WINDOWS_API_) // include windows headers for HWND #define WIN32_LEAN_AND_MEAN #include #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #define GL_GLEXT_LEGACY 1 #endif #include #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #include "glext.h" #endif #include "wglext.h" #ifdef _MSC_VER #pragma comment(lib, "OpenGL32.lib") #endif #elif defined(_IRR_COMPILE_WITH_OSX_DEVICE_) #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #define GL_GLEXT_LEGACY 1 #endif #include #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #include "glext.h" #endif #elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_) && !defined(_IRR_COMPILE_WITH_X11_DEVICE_) #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #define GL_GLEXT_LEGACY 1 #define GLX_GLXEXT_LEGACY 1 #else #define GL_GLEXT_PROTOTYPES 1 #define GLX_GLXEXT_PROTOTYPES 1 #endif #define NO_SDL_GLEXT #include #include #include "glext.h" #else #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #define GL_GLEXT_LEGACY 1 #define GLX_GLXEXT_LEGACY 1 #else #define GL_GLEXT_PROTOTYPES 1 #define GLX_GLXEXT_PROTOTYPES 1 #endif #include #include #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #include "glext.h" #undef GLX_ARB_get_proc_address // avoid problems with local glxext.h #include "glxext.h" #endif #endif #ifndef GL_ARB_shader_objects /* GL types for program/shader text and shader object handles */ typedef char GLcharARB; typedef unsigned int GLhandleARB; #endif #ifndef GL_VERSION_2_0 /* GL type for program/shader text */ typedef char GLchar; #endif namespace irr { namespace video { static const char* const OpenGLFeatureStrings[] = { "GL_3DFX_multisample", "GL_3DFX_tbuffer", "GL_3DFX_texture_compression_FXT1", "GL_AMD_blend_minmax_factor", "GL_AMD_conservative_depth", "GL_AMD_debug_output", "GL_AMD_depth_clamp_separate", "GL_AMD_draw_buffers_blend", "GL_AMD_multi_draw_indirect", "GL_AMD_name_gen_delete", "GL_AMD_performance_monitor", "GL_AMD_sample_positions", "GL_AMD_seamless_cubemap_per_texture", "GL_AMD_shader_stencil_export", "GL_AMD_texture_texture4", "GL_AMD_transform_feedback3_lines_triangles", "GL_AMD_vertex_shader_tesselator", "GL_APPLE_aux_depth_stencil", "GL_APPLE_client_storage", "GL_APPLE_element_array", "GL_APPLE_fence", "GL_APPLE_float_pixels", "GL_APPLE_flush_buffer_range", "GL_APPLE_object_purgeable", "GL_APPLE_rgb_422", "GL_APPLE_row_bytes", "GL_APPLE_specular_vector", "GL_APPLE_texture_range", "GL_APPLE_transform_hint", "GL_APPLE_vertex_array_object", "GL_APPLE_vertex_array_range", "GL_APPLE_vertex_program_evaluators", "GL_APPLE_ycbcr_422", "GL_ARB_base_instance", "GL_ARB_blend_func_extended", "GL_ARB_cl_event", "GL_ARB_color_buffer_float", "GL_ARB_compatibility", "GL_ARB_compressed_texture_pixel_storage", "GL_ARB_conservative_depth", "GL_ARB_copy_buffer", "GL_ARB_debug_output", "GL_ARB_depth_buffer_float", "GL_ARB_depth_clamp", "GL_ARB_depth_texture", "GL_ARB_draw_buffers", "GL_ARB_draw_buffers_blend", "GL_ARB_draw_elements_base_vertex", "GL_ARB_draw_indirect", "GL_ARB_draw_instanced", "GL_ARB_ES2_compatibility", "GL_ARB_explicit_attrib_location", "GL_ARB_fragment_coord_conventions", "GL_ARB_fragment_program", "GL_ARB_fragment_program_shadow", "GL_ARB_fragment_shader", "GL_ARB_framebuffer_object", "GL_ARB_framebuffer_sRGB", "GL_ARB_get_program_binary", "GL_ARB_geometry_shader4", "GL_ARB_gpu_shader5", "GL_ARB_gpu_shader_fp64", "GL_ARB_half_float_pixel", "GL_ARB_half_float_vertex", "GL_ARB_imaging", "GL_ARB_instanced_arrays", "GL_ARB_internalformat_query", "GL_ARB_map_buffer_alignment", "GL_ARB_map_buffer_range", "GL_ARB_matrix_palette", "GL_ARB_multisample", "GL_ARB_multitexture", "GL_ARB_occlusion_query", "GL_ARB_occlusion_query2", "GL_ARB_pixel_buffer_object", "GL_ARB_point_parameters", "GL_ARB_point_sprite", "GL_ARB_provoking_vertex", "GL_ARB_robustness", "GL_ARB_sample_shading", "GL_ARB_sampler_objects", "GL_ARB_seamless_cube_map", "GL_ARB_separate_shader_objects", "GL_ARB_shader_atomic_counters", "GL_ARB_shader_bit_encoding", "GL_ARB_shader_image_load_store", "GL_ARB_shader_objects", "GL_ARB_shader_precision", "GL_ARB_shader_stencil_export", "GL_ARB_shader_subroutine", "GL_ARB_shader_texture_lod", "GL_ARB_shading_language_100", "GL_ARB_shading_language_420pack", "GL_ARB_shading_language_include", "GL_ARB_shading_language_packing", "GL_ARB_shadow", "GL_ARB_shadow_ambient", "GL_ARB_sync", "GL_ARB_tessellation_shader", "GL_ARB_texture_border_clamp", "GL_ARB_texture_buffer_object", "GL_ARB_texture_buffer_object_rgb32", "GL_ARB_texture_compression", "GL_ARB_texture_compression_bptc", "GL_ARB_texture_compression_rgtc", "GL_ARB_texture_cube_map", "GL_ARB_texture_cube_map_array", "GL_ARB_texture_env_add", "GL_ARB_texture_env_combine", "GL_ARB_texture_env_crossbar", "GL_ARB_texture_env_dot3", "GL_ARB_texture_float", "GL_ARB_texture_gather", "GL_ARB_texture_mirrored_repeat", "GL_ARB_texture_multisample", "GL_ARB_texture_non_power_of_two", "GL_ARB_texture_query_lod", "GL_ARB_texture_rectangle", "GL_ARB_texture_rg", "GL_ARB_texture_rgb10_a2ui", "GL_ARB_texture_storage", "GL_ARB_texture_swizzle", "GL_ARB_timer_query", "GL_ARB_transform_feedback2", "GL_ARB_transform_feedback3", "GL_ARB_transform_feedback_instanced", "GL_ARB_transpose_matrix", "GL_ARB_uniform_buffer_object", "GL_ARB_vertex_array_bgra", "GL_ARB_vertex_array_object", "GL_ARB_vertex_attrib_64bit", "GL_ARB_vertex_blend", "GL_ARB_vertex_buffer_object", "GL_ARB_vertex_program", "GL_ARB_vertex_shader", "GL_ARB_vertex_type_2_10_10_10_rev", "GL_ARB_viewport_array", "GL_ARB_window_pos", "GL_ATI_draw_buffers", "GL_ATI_element_array", "GL_ATI_envmap_bumpmap", "GL_ATI_fragment_shader", "GL_ATI_map_object_buffer", "GL_ATI_meminfo", "GL_ATI_pixel_format_float", "GL_ATI_pn_triangles", "GL_ATI_separate_stencil", "GL_ATI_text_fragment_shader", "GL_ATI_texture_env_combine3", "GL_ATI_texture_float", "GL_ATI_texture_mirror_once", "GL_ATI_vertex_array_object", "GL_ATI_vertex_attrib_array_object", "GL_ATI_vertex_streams", "GL_EXT_422_pixels", "GL_EXT_abgr", "GL_EXT_bgra", "GL_EXT_bindable_uniform", "GL_EXT_blend_color", "GL_EXT_blend_equation_separate", "GL_EXT_blend_func_separate", "GL_EXT_blend_logic_op", "GL_EXT_blend_minmax", "GL_EXT_blend_subtract", "GL_EXT_clip_volume_hint", "GL_EXT_cmyka", "GL_EXT_color_subtable", "GL_EXT_compiled_vertex_array", "GL_EXT_convolution", "GL_EXT_coordinate_frame", "GL_EXT_copy_texture", "GL_EXT_cull_vertex", "GL_EXT_depth_bounds_test", "GL_EXT_direct_state_access", "GL_EXT_draw_buffers2", "GL_EXT_draw_instanced", "GL_EXT_draw_range_elements", "GL_EXT_fog_coord", "GL_EXT_framebuffer_blit", "GL_EXT_framebuffer_multisample", "GL_EXT_framebuffer_multisample_blit_scaled", "GL_EXT_framebuffer_object", "GL_EXT_framebuffer_sRGB", "GL_EXT_geometry_shader4", "GL_EXT_gpu_program_parameters", "GL_EXT_gpu_shader4", "GL_EXT_histogram", "GL_EXT_index_array_formats", "GL_EXT_index_func", "GL_EXT_index_material", "GL_EXT_index_texture", "GL_EXT_light_texture", "GL_EXT_misc_attribute", "GL_EXT_multi_draw_arrays", "GL_EXT_multisample", "GL_EXT_packed_depth_stencil", "GL_EXT_packed_float", "GL_EXT_packed_pixels", "GL_EXT_paletted_texture", "GL_EXT_pixel_buffer_object", "GL_EXT_pixel_transform", "GL_EXT_pixel_transform_color_table", "GL_EXT_point_parameters", "GL_EXT_polygon_offset", "GL_EXT_provoking_vertex", "GL_EXT_rescale_normal", "GL_EXT_secondary_color", "GL_EXT_separate_shader_objects", "GL_EXT_separate_specular_color", "GL_EXT_shader_image_load_store", "GL_EXT_shadow_funcs", "GL_EXT_shared_texture_palette", "GL_EXT_stencil_clear_tag", "GL_EXT_stencil_two_side", "GL_EXT_stencil_wrap", "GL_EXT_subtexture", "GL_EXT_texture", "GL_EXT_texture3D", "GL_EXT_texture_array", "GL_EXT_texture_buffer_object", "GL_EXT_texture_compression_latc", "GL_EXT_texture_compression_rgtc", "GL_EXT_texture_compression_s3tc", "GL_EXT_texture_cube_map", "GL_EXT_texture_env_add", "GL_EXT_texture_env_combine", "GL_EXT_texture_env_dot3", "GL_EXT_texture_filter_anisotropic", "GL_EXT_texture_integer", "GL_EXT_texture_lod_bias", "GL_EXT_texture_mirror_clamp", "GL_EXT_texture_object", "GL_EXT_texture_perturb_normal", "GL_EXT_texture_shared_exponent", "GL_EXT_texture_snorm", "GL_EXT_texture_sRGB", "GL_EXT_texture_sRGB_decode", "GL_EXT_texture_swizzle", "GL_EXT_timer_query", "GL_EXT_transform_feedback", "GL_EXT_vertex_array", "GL_EXT_vertex_array_bgra", "GL_EXT_vertex_attrib_64bit", "GL_EXT_vertex_shader", "GL_EXT_vertex_weighting", "GL_EXT_x11_sync_object", "GL_FfdMaskSGIX", "GL_GREMEDY_frame_terminator", "GL_GREMEDY_string_marker", "GL_HP_convolution_border_modes", "GL_HP_image_transform", "GL_HP_occlusion_test", "GL_HP_texture_lighting", "GL_IBM_cull_vertex", "GL_IBM_multimode_draw_arrays", "GL_IBM_rasterpos_clip", "GL_IBM_texture_mirrored_repeat", "GL_IBM_vertex_array_lists", "GL_INGR_blend_func_separate", "GL_INGR_color_clamp", "GL_INGR_interlace_read", "GL_INGR_palette_buffer", "GL_INTEL_parallel_arrays", "GL_INTEL_texture_scissor", "GL_MESA_pack_invert", "GL_MESA_resize_buffers", "GL_MESA_window_pos", "GL_MESAX_texture_stack", "GL_MESA_ycbcr_texture", "GL_NV_blend_square", "GL_NV_conditional_render", "GL_NV_copy_depth_to_color", "GL_NV_copy_image", "GL_NV_depth_buffer_float", "GL_NV_depth_clamp", "GL_NV_evaluators", "GL_NV_explicit_multisample", "GL_NV_fence", "GL_NV_float_buffer", "GL_NV_fog_distance", "GL_NV_fragment_program", "GL_NV_fragment_program2", "GL_NV_fragment_program4", "GL_NV_fragment_program_option", "GL_NV_framebuffer_multisample_coverage", "GL_NV_geometry_program4", "GL_NV_geometry_shader4", "GL_NV_gpu_program4", "GL_NV_gpu_program5", "GL_NV_gpu_shader5", "GL_NV_half_float", "GL_NV_light_max_exponent", "GL_NV_multisample_coverage", "GL_NV_multisample_filter_hint", "GL_NV_occlusion_query", "GL_NV_packed_depth_stencil", "GL_NV_parameter_buffer_object", "GL_NV_parameter_buffer_object2", "GL_NV_pixel_data_range", "GL_NV_point_sprite", "GL_NV_present_video", "GL_NV_primitive_restart", "GL_NV_register_combiners", "GL_NV_register_combiners2", "GL_NV_shader_buffer_load", "GL_NV_shader_buffer_store", "GL_NV_tessellation_program5", "GL_NV_texgen_emboss", "GL_NV_texgen_reflection", "GL_NV_texture_barrier", "GL_NV_texture_compression_vtc", "GL_NV_texture_env_combine4", "GL_NV_texture_expand_normal", "GL_NV_texture_multisample", "GL_NV_texture_rectangle", "GL_NV_texture_shader", "GL_NV_texture_shader2", "GL_NV_texture_shader3", "GL_NV_transform_feedback", "GL_NV_transform_feedback2", "GL_NV_vdpau_interop", "GL_NV_vertex_array_range", "GL_NV_vertex_array_range2", "GL_NV_vertex_attrib_integer_64bit", "GL_NV_vertex_buffer_unified_memory", "GL_NV_vertex_program", "GL_NV_vertex_program1_1", "GL_NV_vertex_program2", "GL_NV_vertex_program2_option", "GL_NV_vertex_program3", "GL_NV_vertex_program4", "GL_NV_video_capture", "GL_OES_read_format", "GL_OML_interlace", "GL_OML_resample", "GL_OML_subsample", "GL_PGI_misc_hints", "GL_PGI_vertex_hints", "GL_REND_screen_coordinates", "GL_S3_s3tc", "GL_SGI_color_matrix", "GL_SGI_color_table", "GL_SGI_depth_pass_instrument", "GL_SGIS_detail_texture", "GL_SGIS_fog_function", "GL_SGIS_generate_mipmap", "GL_SGIS_multisample", "GL_SGIS_pixel_texture", "GL_SGIS_point_line_texgen", "GL_SGIS_point_parameters", "GL_SGIS_sharpen_texture", "GL_SGIS_texture4D", "GL_SGIS_texture_border_clamp", "GL_SGIS_texture_color_mask", "GL_SGIS_texture_edge_clamp", "GL_SGIS_texture_filter4", "GL_SGIS_texture_lod", "GL_SGIS_texture_select", "GL_SGI_texture_color_table", "GL_SGIX_async", "GL_SGIX_async_histogram", "GL_SGIX_async_pixel", "GL_SGIX_blend_alpha_minmax", "GL_SGIX_calligraphic_fragment", "GL_SGIX_clipmap", "GL_SGIX_convolution_accuracy", "GL_SGIX_depth_pass_instrument", "GL_SGIX_depth_texture", "GL_SGIX_flush_raster", "GL_SGIX_fog_offset", "GL_SGIX_fog_scale", "GL_SGIX_fragment_lighting", "GL_SGIX_framezoom", "GL_SGIX_igloo_interface", "GL_SGIX_impact_pixel_texture", "GL_SGIX_instruments", "GL_SGIX_interlace", "GL_SGIX_ir_instrument1", "GL_SGIX_list_priority", "GL_SGIX_pixel_texture", "GL_SGIX_pixel_tiles", "GL_SGIX_polynomial_ffd", "GL_SGIX_reference_plane", "GL_SGIX_resample", "GL_SGIX_scalebias_hint", "GL_SGIX_shadow", "GL_SGIX_shadow_ambient", "GL_SGIX_sprite", "GL_SGIX_subsample", "GL_SGIX_tag_sample_buffer", "GL_SGIX_texture_add_env", "GL_SGIX_texture_coordinate_clamp", "GL_SGIX_texture_lod_bias", "GL_SGIX_texture_multi_buffer", "GL_SGIX_texture_scale_bias", "GL_SGIX_texture_select", "GL_SGIX_vertex_preclip", "GL_SGIX_ycrcb", "GL_SGIX_ycrcba", "GL_SGIX_ycrcb_subsample", "GL_SUN_convolution_border_modes", "GL_SUN_global_alpha", "GL_SUN_mesh_array", "GL_SUN_slice_accum", "GL_SUN_triangle_list", "GL_SUN_vertex", "GL_SUNX_constant_data", "GL_WIN_phong_shading", "GL_WIN_specular_fog", // unofficial stuff "GL_NVX_gpu_memory_info" }; class COpenGLExtensionHandler { public: enum EOpenGLFeatures { IRR_3DFX_multisample = 0, IRR_3DFX_tbuffer, IRR_3DFX_texture_compression_FXT1, IRR_AMD_blend_minmax_factor, IRR_AMD_conservative_depth, IRR_AMD_debug_output, IRR_AMD_depth_clamp_separate, IRR_AMD_draw_buffers_blend, IRR_AMD_multi_draw_indirect, IRR_AMD_name_gen_delete, IRR_AMD_performance_monitor, IRR_AMD_sample_positions, IRR_AMD_seamless_cubemap_per_texture, IRR_AMD_shader_stencil_export, IRR_AMD_texture_texture4, IRR_AMD_transform_feedback3_lines_triangles, IRR_AMD_vertex_shader_tesselator, IRR_APPLE_aux_depth_stencil, IRR_APPLE_client_storage, IRR_APPLE_element_array, IRR_APPLE_fence, IRR_APPLE_float_pixels, IRR_APPLE_flush_buffer_range, IRR_APPLE_object_purgeable, IRR_APPLE_rgb_422, IRR_APPLE_row_bytes, IRR_APPLE_specular_vector, IRR_APPLE_texture_range, IRR_APPLE_transform_hint, IRR_APPLE_vertex_array_object, IRR_APPLE_vertex_array_range, IRR_APPLE_vertex_program_evaluators, IRR_APPLE_ycbcr_422, IRR_ARB_base_instance, IRR_ARB_blend_func_extended, IRR_ARB_cl_event, IRR_ARB_color_buffer_float, IRR_ARB_compatibility, IRR_ARB_compressed_texture_pixel_storage, IRR_ARB_conservative_depth, IRR_ARB_copy_buffer, IRR_ARB_debug_output, IRR_ARB_depth_buffer_float, IRR_ARB_depth_clamp, IRR_ARB_depth_texture, IRR_ARB_draw_buffers, IRR_ARB_draw_buffers_blend, IRR_ARB_draw_elements_base_vertex, IRR_ARB_draw_indirect, IRR_ARB_draw_instanced, IRR_ARB_ES2_compatibility, IRR_ARB_explicit_attrib_location, IRR_ARB_fragment_coord_conventions, IRR_ARB_fragment_program, IRR_ARB_fragment_program_shadow, IRR_ARB_fragment_shader, IRR_ARB_framebuffer_object, IRR_ARB_framebuffer_sRGB, IRR_ARB_geometry_shader4, IRR_ARB_get_program_binary, IRR_ARB_gpu_shader5, IRR_ARB_gpu_shader_fp64, IRR_ARB_half_float_pixel, IRR_ARB_half_float_vertex, IRR_ARB_imaging, IRR_ARB_instanced_arrays, IRR_ARB_internalformat_query, IRR_ARB_map_buffer_alignment, IRR_ARB_map_buffer_range, IRR_ARB_matrix_palette, IRR_ARB_multisample, IRR_ARB_multitexture, IRR_ARB_occlusion_query, IRR_ARB_occlusion_query2, IRR_ARB_pixel_buffer_object, IRR_ARB_point_parameters, IRR_ARB_point_sprite, IRR_ARB_provoking_vertex, IRR_ARB_robustness, IRR_ARB_sample_shading, IRR_ARB_sampler_objects, IRR_ARB_seamless_cube_map, IRR_ARB_separate_shader_objects, IRR_ARB_shader_atomic_counters, IRR_ARB_shader_bit_encoding, IRR_ARB_shader_image_load_store, IRR_ARB_shader_objects, IRR_ARB_shader_precision, IRR_ARB_shader_stencil_export, IRR_ARB_shader_subroutine, IRR_ARB_shader_texture_lod, IRR_ARB_shading_language_100, IRR_ARB_shading_language_420pack, IRR_ARB_shading_language_include, IRR_ARB_shading_language_packing, IRR_ARB_shadow, IRR_ARB_shadow_ambient, IRR_ARB_sync, IRR_ARB_tessellation_shader, IRR_ARB_texture_border_clamp, IRR_ARB_texture_buffer_object, IRR_ARB_texture_buffer_object_rgb32, IRR_ARB_texture_compression, IRR_ARB_texture_compression_bptc, IRR_ARB_texture_compression_rgtc, IRR_ARB_texture_cube_map, IRR_ARB_texture_cube_map_array, IRR_ARB_texture_env_add, IRR_ARB_texture_env_combine, IRR_ARB_texture_env_crossbar, IRR_ARB_texture_env_dot3, IRR_ARB_texture_float, IRR_ARB_texture_gather, IRR_ARB_texture_mirrored_repeat, IRR_ARB_texture_multisample, IRR_ARB_texture_non_power_of_two, IRR_ARB_texture_query_lod, IRR_ARB_texture_rectangle, IRR_ARB_texture_rg, IRR_ARB_texture_rgb10_a2ui, IRR_ARB_texture_storage, IRR_ARB_texture_swizzle, IRR_ARB_timer_query, IRR_ARB_transform_feedback2, IRR_ARB_transform_feedback3, IRR_ARB_transform_feedback_instanced, IRR_ARB_transpose_matrix, IRR_ARB_uniform_buffer_object, IRR_ARB_vertex_array_bgra, IRR_ARB_vertex_array_object, IRR_ARB_vertex_attrib_64bit, IRR_ARB_vertex_blend, IRR_ARB_vertex_buffer_object, IRR_ARB_vertex_program, IRR_ARB_vertex_shader, IRR_ARB_vertex_type_2_10_10_10_rev, IRR_ARB_viewport_array, IRR_ARB_window_pos, IRR_ATI_draw_buffers, IRR_ATI_element_array, IRR_ATI_envmap_bumpmap, IRR_ATI_fragment_shader, IRR_ATI_map_object_buffer, IRR_ATI_meminfo, IRR_ATI_pixel_format_float, IRR_ATI_pn_triangles, IRR_ATI_separate_stencil, IRR_ATI_text_fragment_shader, IRR_ATI_texture_env_combine3, IRR_ATI_texture_float, IRR_ATI_texture_mirror_once, IRR_ATI_vertex_array_object, IRR_ATI_vertex_attrib_array_object, IRR_ATI_vertex_streams, IRR_EXT_422_pixels, IRR_EXT_abgr, IRR_EXT_bgra, IRR_EXT_bindable_uniform, IRR_EXT_blend_color, IRR_EXT_blend_equation_separate, IRR_EXT_blend_func_separate, IRR_EXT_blend_logic_op, IRR_EXT_blend_minmax, IRR_EXT_blend_subtract, IRR_EXT_clip_volume_hint, IRR_EXT_cmyka, IRR_EXT_color_subtable, IRR_EXT_compiled_vertex_array, IRR_EXT_convolution, IRR_EXT_coordinate_frame, IRR_EXT_copy_texture, IRR_EXT_cull_vertex, IRR_EXT_depth_bounds_test, IRR_EXT_direct_state_access, IRR_EXT_draw_buffers2, IRR_EXT_draw_instanced, IRR_EXT_draw_range_elements, IRR_EXT_fog_coord, IRR_EXT_framebuffer_blit, IRR_EXT_framebuffer_multisample, IRR_EXT_framebuffer_multisample_blit_scaled, IRR_EXT_framebuffer_object, IRR_EXT_framebuffer_sRGB, IRR_EXT_geometry_shader4, IRR_EXT_gpu_program_parameters, IRR_EXT_gpu_shader4, IRR_EXT_histogram, IRR_EXT_index_array_formats, IRR_EXT_index_func, IRR_EXT_index_material, IRR_EXT_index_texture, IRR_EXT_light_texture, IRR_EXT_misc_attribute, IRR_EXT_multi_draw_arrays, IRR_EXT_multisample, IRR_EXT_packed_depth_stencil, IRR_EXT_packed_float, IRR_EXT_packed_pixels, IRR_EXT_paletted_texture, IRR_EXT_pixel_buffer_object, IRR_EXT_pixel_transform, IRR_EXT_pixel_transform_color_table, IRR_EXT_point_parameters, IRR_EXT_polygon_offset, IRR_EXT_provoking_vertex, IRR_EXT_rescale_normal, IRR_EXT_secondary_color, IRR_EXT_separate_shader_objects, IRR_EXT_separate_specular_color, IRR_EXT_shader_image_load_store, IRR_EXT_shadow_funcs, IRR_EXT_shared_texture_palette, IRR_EXT_stencil_clear_tag, IRR_EXT_stencil_two_side, IRR_EXT_stencil_wrap, IRR_EXT_subtexture, IRR_EXT_texture, IRR_EXT_texture3D, IRR_EXT_texture_array, IRR_EXT_texture_buffer_object, IRR_EXT_texture_compression_latc, IRR_EXT_texture_compression_rgtc, IRR_EXT_texture_compression_s3tc, IRR_EXT_texture_cube_map, IRR_EXT_texture_env_add, IRR_EXT_texture_env_combine, IRR_EXT_texture_env_dot3, IRR_EXT_texture_filter_anisotropic, IRR_EXT_texture_integer, IRR_EXT_texture_lod_bias, IRR_EXT_texture_mirror_clamp, IRR_EXT_texture_object, IRR_EXT_texture_perturb_normal, IRR_EXT_texture_shared_exponent, IRR_EXT_texture_snorm, IRR_EXT_texture_sRGB, IRR_EXT_texture_sRGB_decode, IRR_EXT_texture_swizzle, IRR_EXT_timer_query, IRR_EXT_transform_feedback, IRR_EXT_vertex_array, IRR_EXT_vertex_array_bgra, IRR_EXT_vertex_attrib_64bit, IRR_EXT_vertex_shader, IRR_EXT_vertex_weighting, IRR_EXT_x11_sync_object, IRR_FfdMaskSGIX, IRR_GREMEDY_frame_terminator, IRR_GREMEDY_string_marker, IRR_HP_convolution_border_modes, IRR_HP_image_transform, IRR_HP_occlusion_test, IRR_HP_texture_lighting, IRR_IBM_cull_vertex, IRR_IBM_multimode_draw_arrays, IRR_IBM_rasterpos_clip, IRR_IBM_texture_mirrored_repeat, IRR_IBM_vertex_array_lists, IRR_INGR_blend_func_separate, IRR_INGR_color_clamp, IRR_INGR_interlace_read, IRR_INGR_palette_buffer, IRR_INTEL_parallel_arrays, IRR_INTEL_texture_scissor, IRR_MESA_pack_invert, IRR_MESA_resize_buffers, IRR_MESA_window_pos, IRR_MESAX_texture_stack, IRR_MESA_ycbcr_texture, IRR_NV_blend_square, IRR_NV_conditional_render, IRR_NV_copy_depth_to_color, IRR_NV_copy_image, IRR_NV_depth_buffer_float, IRR_NV_depth_clamp, IRR_NV_evaluators, IRR_NV_explicit_multisample, IRR_NV_fence, IRR_NV_float_buffer, IRR_NV_fog_distance, IRR_NV_fragment_program, IRR_NV_fragment_program2, IRR_NV_fragment_program4, IRR_NV_fragment_program_option, IRR_NV_framebuffer_multisample_coverage, IRR_NV_geometry_program4, IRR_NV_geometry_shader4, IRR_NV_gpu_program4, IRR_NV_gpu_program5, IRR_NV_gpu_shader5, IRR_NV_half_float, IRR_NV_light_max_exponent, IRR_NV_multisample_coverage, IRR_NV_multisample_filter_hint, IRR_NV_occlusion_query, IRR_NV_packed_depth_stencil, IRR_NV_parameter_buffer_object, IRR_NV_parameter_buffer_object2, IRR_NV_pixel_data_range, IRR_NV_point_sprite, IRR_NV_present_video, IRR_NV_primitive_restart, IRR_NV_register_combiners, IRR_NV_register_combiners2, IRR_NV_shader_buffer_load, IRR_NV_shader_buffer_store, IRR_NV_tessellation_program5, IRR_NV_texgen_emboss, IRR_NV_texgen_reflection, IRR_NV_texture_barrier, IRR_NV_texture_compression_vtc, IRR_NV_texture_env_combine4, IRR_NV_texture_expand_normal, IRR_NV_texture_multisample, IRR_NV_texture_rectangle, IRR_NV_texture_shader, IRR_NV_texture_shader2, IRR_NV_texture_shader3, IRR_NV_transform_feedback, IRR_NV_transform_feedback2, IRR_NV_vdpau_interop, IRR_NV_vertex_array_range, IRR_NV_vertex_array_range2, IRR_NV_vertex_attrib_integer_64bit, IRR_NV_vertex_buffer_unified_memory, IRR_NV_vertex_program, IRR_NV_vertex_program1_1, IRR_NV_vertex_program2, IRR_NV_vertex_program2_option, IRR_NV_vertex_program3, IRR_NV_vertex_program4, IRR_NV_video_capture, IRR_OES_read_format, IRR_OML_interlace, IRR_OML_resample, IRR_OML_subsample, IRR_PGI_misc_hints, IRR_PGI_vertex_hints, IRR_REND_screen_coordinates, IRR_S3_s3tc, IRR_SGI_color_matrix, IRR_SGI_color_table, IRR_SGI_depth_pass_instrument, IRR_SGIS_detail_texture, IRR_SGIS_fog_function, IRR_SGIS_generate_mipmap, IRR_SGIS_multisample, IRR_SGIS_pixel_texture, IRR_SGIS_point_line_texgen, IRR_SGIS_point_parameters, IRR_SGIS_sharpen_texture, IRR_SGIS_texture4D, IRR_SGIS_texture_border_clamp, IRR_SGIS_texture_color_mask, IRR_SGIS_texture_edge_clamp, IRR_SGIS_texture_filter4, IRR_SGIS_texture_lod, IRR_SGIS_texture_select, IRR_SGI_texture_color_table, IRR_SGIX_async, IRR_SGIX_async_histogram, IRR_SGIX_async_pixel, IRR_SGIX_blend_alpha_minmax, IRR_SGIX_calligraphic_fragment, IRR_SGIX_clipmap, IRR_SGIX_convolution_accuracy, IRR_SGIX_depth_pass_instrument, IRR_SGIX_depth_texture, IRR_SGIX_flush_raster, IRR_SGIX_fog_offset, IRR_SGIX_fog_scale, IRR_SGIX_fragment_lighting, IRR_SGIX_framezoom, IRR_SGIX_igloo_interface, IRR_SGIX_impact_pixel_texture, IRR_SGIX_instruments, IRR_SGIX_interlace, IRR_SGIX_ir_instrument1, IRR_SGIX_list_priority, IRR_SGIX_pixel_texture, IRR_SGIX_pixel_tiles, IRR_SGIX_polynomial_ffd, IRR_SGIX_reference_plane, IRR_SGIX_resample, IRR_SGIX_scalebias_hint, IRR_SGIX_shadow, IRR_SGIX_shadow_ambient, IRR_SGIX_sprite, IRR_SGIX_subsample, IRR_SGIX_tag_sample_buffer, IRR_SGIX_texture_add_env, IRR_SGIX_texture_coordinate_clamp, IRR_SGIX_texture_lod_bias, IRR_SGIX_texture_multi_buffer, IRR_SGIX_texture_scale_bias, IRR_SGIX_texture_select, IRR_SGIX_vertex_preclip, IRR_SGIX_ycrcb, IRR_SGIX_ycrcba, IRR_SGIX_ycrcb_subsample, IRR_SUN_convolution_border_modes, IRR_SUN_global_alpha, IRR_SUN_mesh_array, IRR_SUN_slice_accum, IRR_SUN_triangle_list, IRR_SUN_vertex, IRR_SUNX_constant_data, IRR_WIN_phong_shading, IRR_WIN_specular_fog, IRR_NVX_gpu_memory_info, IRR_OpenGL_Feature_Count }; // constructor COpenGLExtensionHandler(); // deferred initialization void initExtensions(bool stencilBuffer); //! queries the features of the driver, returns true if feature is available bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const; //! queries the features of the driver, returns true if feature is available bool queryOpenGLFeature(EOpenGLFeatures feature) const { return FeatureAvailable[feature]; } //! show all features with availablity void dump() const; void dumpFramebufferFormats() const; // Some variables for properties bool StencilBuffer; bool MultiTextureExtension; bool TextureCompressionExtension; // Some non-boolean properties //! Maxmimum texture layers supported by the fixed pipeline u8 MaxSupportedTextures; //! Maxmimum texture layers supported by the engine u8 MaxTextureUnits; //! Maximum hardware lights supported u8 MaxLights; //! Maximal Anisotropy u8 MaxAnisotropy; //! Number of user clipplanes u8 MaxUserClipPlanes; //! Number of auxiliary buffers u8 MaxAuxBuffers; //! Number of rendertargets available as MRTs u8 MaxMultipleRenderTargets; //! Optimal number of indices per meshbuffer u32 MaxIndices; //! Maximal texture dimension u32 MaxTextureSize; //! Maximal vertices handled by geometry shaders u32 MaxGeometryVerticesOut; //! Maximal LOD Bias f32 MaxTextureLODBias; //! Minimal and maximal supported thickness for lines without smoothing GLfloat DimAliasedLine[2]; //! Minimal and maximal supported thickness for points without smoothing GLfloat DimAliasedPoint[2]; //! Minimal and maximal supported thickness for lines with smoothing GLfloat DimSmoothedLine[2]; //! Minimal and maximal supported thickness for points with smoothing GLfloat DimSmoothedPoint[2]; //! OpenGL version as Integer: 100*Major+Minor, i.e. 2.1 becomes 201 u16 Version; //! GLSL version as Integer: 100*Major+Minor u16 ShaderLanguageVersion; bool OcclusionQuerySupport; // public access to the (loaded) extensions. // general functions void extGlActiveTexture(GLenum texture); void extGlClientActiveTexture(GLenum texture); void extGlPointParameterf(GLint loc, GLfloat f); void extGlPointParameterfv(GLint loc, const GLfloat *v); void extGlStencilFuncSeparate (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); void extGlStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass); void extGlCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); // shader programming void extGlGenPrograms(GLsizei n, GLuint *programs); void extGlBindProgram(GLenum target, GLuint program); void extGlProgramString(GLenum target, GLenum format, GLsizei len, const GLvoid *string); void extGlLoadProgram(GLenum target, GLuint id, GLsizei len, const GLubyte *string); void extGlDeletePrograms(GLsizei n, const GLuint *programs); void extGlProgramLocalParameter4fv(GLenum, GLuint, const GLfloat *); GLhandleARB extGlCreateShaderObject(GLenum shaderType); GLuint extGlCreateShader(GLenum shaderType); // note: Due to the type confusion between shader_objects and OpenGL 2.0 // we have to add the ARB extension for proper method definitions in case // that handleARB and uint are the same type void extGlShaderSourceARB(GLhandleARB shader, GLsizei numOfStrings, const char **strings, const GLint *lenOfStrings); void extGlShaderSource(GLuint shader, GLsizei numOfStrings, const char **strings, const GLint *lenOfStrings); // note: Due to the type confusion between shader_objects and OpenGL 2.0 // we have to add the ARB extension for proper method definitions in case // that handleARB and uint are the same type void extGlCompileShaderARB(GLhandleARB shader); void extGlCompileShader(GLuint shader); GLhandleARB extGlCreateProgramObject(void); GLuint extGlCreateProgram(void); void extGlAttachObject(GLhandleARB program, GLhandleARB shader); void extGlAttachShader(GLuint program, GLuint shader); void extGlLinkProgramARB(GLhandleARB program); // note: Due to the type confusion between shader_objects and OpenGL 2.0 // we have to add the ARB extension for proper method definitions in case // that handleARB and uint are the same type void extGlLinkProgram(GLuint program); void extGlUseProgramObject(GLhandleARB prog); void extGlUseProgram(GLuint prog); void extGlDeleteObject(GLhandleARB object); void extGlDeleteProgram(GLuint object); void extGlDeleteShader(GLuint shader); void extGlGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); void extGlGetAttachedObjects(GLhandleARB program, GLsizei maxcount, GLsizei* count, GLhandleARB* shaders); void extGlGetInfoLog(GLhandleARB object, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); void extGlGetShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog); void extGlGetProgramInfoLog(GLuint program, GLsizei maxLength, GLsizei *length, GLchar *infoLog); void extGlGetObjectParameteriv(GLhandleARB object, GLenum type, GLint *param); void extGlGetShaderiv(GLuint shader, GLenum type, GLint *param); void extGlGetProgramiv(GLuint program, GLenum type, GLint *param); GLint extGlGetUniformLocationARB(GLhandleARB program, const char *name); GLint extGlGetUniformLocation(GLuint program, const char *name); void extGlUniform1fv(GLint loc, GLsizei count, const GLfloat *v); void extGlUniform2fv(GLint loc, GLsizei count, const GLfloat *v); void extGlUniform3fv(GLint loc, GLsizei count, const GLfloat *v); void extGlUniform4fv(GLint loc, GLsizei count, const GLfloat *v); void extGlUniform1bv(GLint loc, GLsizei count, const bool *v); void extGlUniform2bv(GLint loc, GLsizei count, const bool *v); void extGlUniform3bv(GLint loc, GLsizei count, const bool *v); void extGlUniform4bv(GLint loc, GLsizei count, const bool *v); void extGlUniform1iv(GLint loc, GLsizei count, const GLint *v); void extGlUniform2iv(GLint loc, GLsizei count, const GLint *v); void extGlUniform3iv(GLint loc, GLsizei count, const GLint *v); void extGlUniform4iv(GLint loc, GLsizei count, const GLint *v); void extGlUniformMatrix2fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat *v); void extGlUniformMatrix3fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat *v); void extGlUniformMatrix4fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat *v); void extGlGetActiveUniformARB(GLhandleARB program, GLuint index, GLsizei maxlength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); void extGlGetActiveUniform(GLuint program, GLuint index, GLsizei maxlength, GLsizei *length, GLint *size, GLenum *type, GLchar *name); // framebuffer objects void extGlBindFramebuffer(GLenum target, GLuint framebuffer); void extGlDeleteFramebuffers(GLsizei n, const GLuint *framebuffers); void extGlGenFramebuffers(GLsizei n, GLuint *framebuffers); GLenum extGlCheckFramebufferStatus(GLenum target); void extGlFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); void extGlBindRenderbuffer(GLenum target, GLuint renderbuffer); void extGlDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers); void extGlGenRenderbuffers(GLsizei n, GLuint *renderbuffers); void extGlRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); void extGlFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); void extGlGenerateMipmap(GLenum target); void extGlActiveStencilFace(GLenum face); void extGlDrawBuffers(GLsizei n, const GLenum *bufs); // vertex buffer object void extGlGenBuffers(GLsizei n, GLuint *buffers); void extGlBindBuffer(GLenum target, GLuint buffer); void extGlBufferData(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); void extGlDeleteBuffers(GLsizei n, const GLuint *buffers); void extGlBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); void extGlGetBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data); void *extGlMapBuffer (GLenum target, GLenum access); GLboolean extGlUnmapBuffer (GLenum target); GLboolean extGlIsBuffer (GLuint buffer); void extGlGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); void extGlGetBufferPointerv (GLenum target, GLenum pname, GLvoid **params); void extGlProvokingVertex(GLenum mode); void extGlColorMaskIndexed(GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a); void extGlEnableIndexed(GLenum target, GLuint index); void extGlDisableIndexed(GLenum target, GLuint index); void extGlBlendFuncIndexed(GLuint buf, GLenum src, GLenum dst); void extGlBlendEquationIndexed(GLuint buf, GLenum mode); void extGlProgramParameteri(GLuint program, GLenum pname, GLint value); // occlusion query void extGlGenQueries(GLsizei n, GLuint *ids); void extGlDeleteQueries(GLsizei n, const GLuint *ids); GLboolean extGlIsQuery(GLuint id); void extGlBeginQuery(GLenum target, GLuint id); void extGlEndQuery(GLenum target); void extGlGetQueryiv(GLenum target, GLenum pname, GLint *params); void extGlGetQueryObjectiv(GLuint id, GLenum pname, GLint *params); void extGlGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params); // generic vsync setting method for several extensions void extGlSwapInterval(int interval); // blend operations void extGlBlendEquation(GLenum mode); // the global feature array bool FeatureAvailable[IRR_OpenGL_Feature_Count]; protected: #if defined(_IRR_OPENGL_USE_EXTPOINTER_) PFNGLACTIVETEXTUREARBPROC pGlActiveTextureARB; PFNGLCLIENTACTIVETEXTUREARBPROC pGlClientActiveTextureARB; PFNGLGENPROGRAMSARBPROC pGlGenProgramsARB; PFNGLGENPROGRAMSNVPROC pGlGenProgramsNV; PFNGLBINDPROGRAMARBPROC pGlBindProgramARB; PFNGLBINDPROGRAMNVPROC pGlBindProgramNV; PFNGLDELETEPROGRAMSARBPROC pGlDeleteProgramsARB; PFNGLDELETEPROGRAMSNVPROC pGlDeleteProgramsNV; PFNGLPROGRAMSTRINGARBPROC pGlProgramStringARB; PFNGLLOADPROGRAMNVPROC pGlLoadProgramNV; PFNGLPROGRAMLOCALPARAMETER4FVARBPROC pGlProgramLocalParameter4fvARB; PFNGLCREATESHADEROBJECTARBPROC pGlCreateShaderObjectARB; PFNGLSHADERSOURCEARBPROC pGlShaderSourceARB; PFNGLCOMPILESHADERARBPROC pGlCompileShaderARB; PFNGLCREATEPROGRAMOBJECTARBPROC pGlCreateProgramObjectARB; PFNGLATTACHOBJECTARBPROC pGlAttachObjectARB; PFNGLLINKPROGRAMARBPROC pGlLinkProgramARB; PFNGLUSEPROGRAMOBJECTARBPROC pGlUseProgramObjectARB; PFNGLDELETEOBJECTARBPROC pGlDeleteObjectARB; PFNGLCREATEPROGRAMPROC pGlCreateProgram; PFNGLUSEPROGRAMPROC pGlUseProgram; PFNGLDELETEPROGRAMPROC pGlDeleteProgram; PFNGLDELETESHADERPROC pGlDeleteShader; PFNGLGETATTACHEDOBJECTSARBPROC pGlGetAttachedObjectsARB; PFNGLGETATTACHEDSHADERSPROC pGlGetAttachedShaders; PFNGLCREATESHADERPROC pGlCreateShader; PFNGLSHADERSOURCEPROC pGlShaderSource; PFNGLCOMPILESHADERPROC pGlCompileShader; PFNGLATTACHSHADERPROC pGlAttachShader; PFNGLLINKPROGRAMPROC pGlLinkProgram; PFNGLGETINFOLOGARBPROC pGlGetInfoLogARB; PFNGLGETSHADERINFOLOGPROC pGlGetShaderInfoLog; PFNGLGETPROGRAMINFOLOGPROC pGlGetProgramInfoLog; PFNGLGETOBJECTPARAMETERIVARBPROC pGlGetObjectParameterivARB; PFNGLGETSHADERIVPROC pGlGetShaderiv; PFNGLGETSHADERIVPROC pGlGetProgramiv; PFNGLGETUNIFORMLOCATIONARBPROC pGlGetUniformLocationARB; PFNGLGETUNIFORMLOCATIONPROC pGlGetUniformLocation; PFNGLUNIFORM1FVARBPROC pGlUniform1fvARB; PFNGLUNIFORM2FVARBPROC pGlUniform2fvARB; PFNGLUNIFORM3FVARBPROC pGlUniform3fvARB; PFNGLUNIFORM4FVARBPROC pGlUniform4fvARB; PFNGLUNIFORM1IVARBPROC pGlUniform1ivARB; PFNGLUNIFORM2IVARBPROC pGlUniform2ivARB; PFNGLUNIFORM3IVARBPROC pGlUniform3ivARB; PFNGLUNIFORM4IVARBPROC pGlUniform4ivARB; PFNGLUNIFORMMATRIX2FVARBPROC pGlUniformMatrix2fvARB; PFNGLUNIFORMMATRIX3FVARBPROC pGlUniformMatrix3fvARB; PFNGLUNIFORMMATRIX4FVARBPROC pGlUniformMatrix4fvARB; PFNGLGETACTIVEUNIFORMARBPROC pGlGetActiveUniformARB; PFNGLGETACTIVEUNIFORMPROC pGlGetActiveUniform; PFNGLPOINTPARAMETERFARBPROC pGlPointParameterfARB; PFNGLPOINTPARAMETERFVARBPROC pGlPointParameterfvARB; PFNGLSTENCILFUNCSEPARATEPROC pGlStencilFuncSeparate; PFNGLSTENCILOPSEPARATEPROC pGlStencilOpSeparate; PFNGLSTENCILFUNCSEPARATEATIPROC pGlStencilFuncSeparateATI; PFNGLSTENCILOPSEPARATEATIPROC pGlStencilOpSeparateATI; PFNGLCOMPRESSEDTEXIMAGE2DPROC pGlCompressedTexImage2D; // ARB framebuffer object PFNGLBINDFRAMEBUFFERPROC pGlBindFramebuffer; PFNGLDELETEFRAMEBUFFERSPROC pGlDeleteFramebuffers; PFNGLGENFRAMEBUFFERSPROC pGlGenFramebuffers; PFNGLCHECKFRAMEBUFFERSTATUSPROC pGlCheckFramebufferStatus; PFNGLFRAMEBUFFERTEXTURE2DPROC pGlFramebufferTexture2D; PFNGLBINDRENDERBUFFERPROC pGlBindRenderbuffer; PFNGLDELETERENDERBUFFERSPROC pGlDeleteRenderbuffers; PFNGLGENRENDERBUFFERSPROC pGlGenRenderbuffers; PFNGLRENDERBUFFERSTORAGEPROC pGlRenderbufferStorage; PFNGLFRAMEBUFFERRENDERBUFFERPROC pGlFramebufferRenderbuffer; PFNGLGENERATEMIPMAPPROC pGlGenerateMipmap; // EXT framebuffer object PFNGLBINDFRAMEBUFFEREXTPROC pGlBindFramebufferEXT; PFNGLDELETEFRAMEBUFFERSEXTPROC pGlDeleteFramebuffersEXT; PFNGLGENFRAMEBUFFERSEXTPROC pGlGenFramebuffersEXT; PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC pGlCheckFramebufferStatusEXT; PFNGLFRAMEBUFFERTEXTURE2DEXTPROC pGlFramebufferTexture2DEXT; PFNGLBINDRENDERBUFFEREXTPROC pGlBindRenderbufferEXT; PFNGLDELETERENDERBUFFERSEXTPROC pGlDeleteRenderbuffersEXT; PFNGLGENRENDERBUFFERSEXTPROC pGlGenRenderbuffersEXT; PFNGLRENDERBUFFERSTORAGEEXTPROC pGlRenderbufferStorageEXT; PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC pGlFramebufferRenderbufferEXT; PFNGLGENERATEMIPMAPEXTPROC pGlGenerateMipmapEXT; PFNGLACTIVESTENCILFACEEXTPROC pGlActiveStencilFaceEXT; PFNGLDRAWBUFFERSARBPROC pGlDrawBuffersARB; PFNGLDRAWBUFFERSATIPROC pGlDrawBuffersATI; PFNGLGENBUFFERSARBPROC pGlGenBuffersARB; PFNGLBINDBUFFERARBPROC pGlBindBufferARB; PFNGLBUFFERDATAARBPROC pGlBufferDataARB; PFNGLDELETEBUFFERSARBPROC pGlDeleteBuffersARB; PFNGLBUFFERSUBDATAARBPROC pGlBufferSubDataARB; PFNGLGETBUFFERSUBDATAARBPROC pGlGetBufferSubDataARB; PFNGLMAPBUFFERARBPROC pGlMapBufferARB; PFNGLUNMAPBUFFERARBPROC pGlUnmapBufferARB; PFNGLISBUFFERARBPROC pGlIsBufferARB; PFNGLGETBUFFERPARAMETERIVARBPROC pGlGetBufferParameterivARB; PFNGLGETBUFFERPOINTERVARBPROC pGlGetBufferPointervARB; PFNGLPROVOKINGVERTEXPROC pGlProvokingVertexARB; PFNGLPROVOKINGVERTEXEXTPROC pGlProvokingVertexEXT; PFNGLCOLORMASKINDEXEDEXTPROC pGlColorMaskIndexedEXT; PFNGLENABLEINDEXEDEXTPROC pGlEnableIndexedEXT; PFNGLDISABLEINDEXEDEXTPROC pGlDisableIndexedEXT; PFNGLBLENDFUNCINDEXEDAMDPROC pGlBlendFuncIndexedAMD; PFNGLBLENDFUNCIPROC pGlBlendFunciARB; PFNGLBLENDEQUATIONINDEXEDAMDPROC pGlBlendEquationIndexedAMD; PFNGLBLENDEQUATIONIPROC pGlBlendEquationiARB; PFNGLPROGRAMPARAMETERIARBPROC pGlProgramParameteriARB; PFNGLPROGRAMPARAMETERIEXTPROC pGlProgramParameteriEXT; PFNGLGENQUERIESARBPROC pGlGenQueriesARB; PFNGLDELETEQUERIESARBPROC pGlDeleteQueriesARB; PFNGLISQUERYARBPROC pGlIsQueryARB; PFNGLBEGINQUERYARBPROC pGlBeginQueryARB; PFNGLENDQUERYARBPROC pGlEndQueryARB; PFNGLGETQUERYIVARBPROC pGlGetQueryivARB; PFNGLGETQUERYOBJECTIVARBPROC pGlGetQueryObjectivARB; PFNGLGETQUERYOBJECTUIVARBPROC pGlGetQueryObjectuivARB; PFNGLGENOCCLUSIONQUERIESNVPROC pGlGenOcclusionQueriesNV; PFNGLDELETEOCCLUSIONQUERIESNVPROC pGlDeleteOcclusionQueriesNV; PFNGLISOCCLUSIONQUERYNVPROC pGlIsOcclusionQueryNV; PFNGLBEGINOCCLUSIONQUERYNVPROC pGlBeginOcclusionQueryNV; PFNGLENDOCCLUSIONQUERYNVPROC pGlEndOcclusionQueryNV; PFNGLGETOCCLUSIONQUERYIVNVPROC pGlGetOcclusionQueryivNV; PFNGLGETOCCLUSIONQUERYUIVNVPROC pGlGetOcclusionQueryuivNV; PFNGLBLENDEQUATIONEXTPROC pGlBlendEquationEXT; PFNGLBLENDEQUATIONPROC pGlBlendEquation; #if defined(WGL_EXT_swap_control) PFNWGLSWAPINTERVALEXTPROC pWglSwapIntervalEXT; #endif #if defined(GLX_SGI_swap_control) PFNGLXSWAPINTERVALSGIPROC pGlxSwapIntervalSGI; #endif #if defined(GLX_EXT_swap_control) PFNGLXSWAPINTERVALEXTPROC pGlxSwapIntervalEXT; #endif #if defined(GLX_MESA_swap_control) PFNGLXSWAPINTERVALMESAPROC pGlxSwapIntervalMESA; #endif #endif }; inline void COpenGLExtensionHandler::extGlActiveTexture(GLenum texture) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (MultiTextureExtension && pGlActiveTextureARB) pGlActiveTextureARB(texture); #else if (MultiTextureExtension) #ifdef GL_ARB_multitexture glActiveTextureARB(texture); #else glActiveTexture(texture); #endif #endif } inline void COpenGLExtensionHandler::extGlClientActiveTexture(GLenum texture) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (MultiTextureExtension && pGlClientActiveTextureARB) pGlClientActiveTextureARB(texture); #else if (MultiTextureExtension) glClientActiveTextureARB(texture); #endif } inline void COpenGLExtensionHandler::extGlGenPrograms(GLsizei n, GLuint *programs) { if (programs) memset(programs,0,n*sizeof(GLuint)); #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGenProgramsARB) pGlGenProgramsARB(n, programs); else if (pGlGenProgramsNV) pGlGenProgramsNV(n, programs); #elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glGenProgramsARB(n,programs); #elif defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program) glGenProgramsNV(n,programs); #else os::Printer::log("glGenPrograms not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlBindProgram(GLenum target, GLuint program) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlBindProgramARB) pGlBindProgramARB(target, program); else if (pGlBindProgramNV) pGlBindProgramNV(target, program); #elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glBindProgramARB(target, program); #elif defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program) glBindProgramNV(target, program); #else os::Printer::log("glBindProgram not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlProgramString(GLenum target, GLenum format, GLsizei len, const GLvoid *string) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlProgramStringARB) pGlProgramStringARB(target, format, len, string); #elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glProgramStringARB(target,format,len,string); #else os::Printer::log("glProgramString not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlLoadProgram(GLenum target, GLuint id, GLsizei len, const GLubyte *string) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlLoadProgramNV) pGlLoadProgramNV(target, id, len, string); #elif defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program) glLoadProgramNV(target,id,len,string); #else os::Printer::log("glLoadProgram not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlDeletePrograms(GLsizei n, const GLuint *programs) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlDeleteProgramsARB) pGlDeleteProgramsARB(n, programs); else if (pGlDeleteProgramsNV) pGlDeleteProgramsNV(n, programs); #elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glDeleteProgramsARB(n,programs); #elif defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program) glDeleteProgramsNV(n,programs); #else os::Printer::log("glDeletePrograms not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlProgramLocalParameter4fv(GLenum n, GLuint i, const GLfloat *f) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlProgramLocalParameter4fvARB) pGlProgramLocalParameter4fvARB(n,i,f); #elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glProgramLocalParameter4fvARB(n,i,f); #else os::Printer::log("glProgramLocalParameter4fv not supported", ELL_ERROR); #endif } inline GLhandleARB COpenGLExtensionHandler::extGlCreateShaderObject(GLenum shaderType) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlCreateShaderObjectARB) return pGlCreateShaderObjectARB(shaderType); #elif defined(GL_ARB_shader_objects) return glCreateShaderObjectARB(shaderType); #else os::Printer::log("glCreateShaderObject not supported", ELL_ERROR); #endif return 0; } inline GLuint COpenGLExtensionHandler::extGlCreateShader(GLenum shaderType) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlCreateShader) return pGlCreateShader(shaderType); #elif defined(GL_VERSION_2_0) return glCreateShader(shaderType); #else os::Printer::log("glCreateShader not supported", ELL_ERROR); #endif return 0; } inline void COpenGLExtensionHandler::extGlShaderSourceARB(GLhandleARB shader, GLsizei numOfStrings, const char **strings, const GLint *lenOfStrings) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlShaderSourceARB) pGlShaderSourceARB(shader, numOfStrings, strings, lenOfStrings); #elif defined(GL_ARB_shader_objects) glShaderSourceARB(shader, numOfStrings, strings, (GLint *)lenOfStrings); #else os::Printer::log("glShaderSource not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlShaderSource(GLuint shader, GLsizei numOfStrings, const char **strings, const GLint *lenOfStrings) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlShaderSource) pGlShaderSource(shader, numOfStrings, strings, lenOfStrings); #elif defined(GL_VERSION_2_0) glShaderSource(shader, numOfStrings, strings, (GLint *)lenOfStrings); #else os::Printer::log("glShaderSource not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlCompileShaderARB(GLhandleARB shader) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlCompileShaderARB) pGlCompileShaderARB(shader); #elif defined(GL_ARB_shader_objects) glCompileShaderARB(shader); #else os::Printer::log("glCompileShader not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlCompileShader(GLuint shader) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlCompileShader) pGlCompileShader(shader); #elif defined(GL_VERSION_2_0) glCompileShader(shader); #else os::Printer::log("glCompileShader not supported", ELL_ERROR); #endif } inline GLhandleARB COpenGLExtensionHandler::extGlCreateProgramObject(void) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlCreateProgramObjectARB) return pGlCreateProgramObjectARB(); #elif defined(GL_ARB_shader_objects) return glCreateProgramObjectARB(); #else os::Printer::log("glCreateProgramObject not supported", ELL_ERROR); #endif return 0; } inline GLuint COpenGLExtensionHandler::extGlCreateProgram(void) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlCreateProgram) return pGlCreateProgram(); #elif defined(GL_VERSION_2_0) return glCreateProgram(); #else os::Printer::log("glCreateProgram not supported", ELL_ERROR); #endif return 0; } inline void COpenGLExtensionHandler::extGlAttachObject(GLhandleARB program, GLhandleARB shader) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlAttachObjectARB) pGlAttachObjectARB(program, shader); #elif defined(GL_ARB_shader_objects) glAttachObjectARB(program, shader); #else os::Printer::log("glAttachObject not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlAttachShader(GLuint program, GLuint shader) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlAttachShader) pGlAttachShader(program, shader); #elif defined(GL_VERSION_2_0) glAttachShader(program, shader); #else os::Printer::log("glAttachShader not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlLinkProgramARB(GLhandleARB program) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlLinkProgramARB) pGlLinkProgramARB(program); #elif defined(GL_ARB_shader_objects) glLinkProgramARB(program); #else os::Printer::log("glLinkProgram not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlLinkProgram(GLuint program) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlLinkProgram) pGlLinkProgram(program); #elif defined(GL_VERSION_2_0) glLinkProgram(program); #else os::Printer::log("glLinkProgram not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlUseProgramObject(GLhandleARB prog) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUseProgramObjectARB) pGlUseProgramObjectARB(prog); #elif defined(GL_ARB_shader_objects) glUseProgramObjectARB(prog); #else os::Printer::log("glUseProgramObject not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlUseProgram(GLuint prog) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUseProgram) pGlUseProgram(prog); #elif defined(GL_VERSION_2_0) glUseProgram(prog); #else os::Printer::log("glUseProgram not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlDeleteObject(GLhandleARB object) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlDeleteObjectARB) pGlDeleteObjectARB(object); #elif defined(GL_ARB_shader_objects) glDeleteObjectARB(object); #else os::Printer::log("glDeleteObject not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlDeleteProgram(GLuint object) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlDeleteProgram) pGlDeleteProgram(object); #elif defined(GL_VERSION_2_0) glDeleteProgram(object); #else os::Printer::log("glDeleteProgram not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlDeleteShader(GLuint shader) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlDeleteShader) pGlDeleteShader(shader); #elif defined(GL_VERSION_2_0) glDeleteShader(shader); #else os::Printer::log("glDeleteShader not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetAttachedObjects(GLhandleARB program, GLsizei maxcount, GLsizei* count, GLhandleARB* shaders) { if (count) *count=0; #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetAttachedObjectsARB) pGlGetAttachedObjectsARB(program, maxcount, count, shaders); #elif defined(GL_ARB_shader_objects) glGetAttachedObjectsARB(program, maxcount, count, shaders); #else os::Printer::log("glGetAttachedObjects not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) { if (count) *count=0; #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetAttachedShaders) pGlGetAttachedShaders(program, maxcount, count, shaders); #elif defined(GL_VERSION_2_0) glGetAttachedShaders(program, maxcount, count, shaders); #else os::Printer::log("glGetAttachedShaders not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetInfoLog(GLhandleARB object, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog) { if (length) *length=0; #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetInfoLogARB) pGlGetInfoLogARB(object, maxLength, length, infoLog); #elif defined(GL_ARB_shader_objects) glGetInfoLogARB(object, maxLength, length, infoLog); #else os::Printer::log("glGetInfoLog not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog) { if (length) *length=0; #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetShaderInfoLog) pGlGetShaderInfoLog(shader, maxLength, length, infoLog); #elif defined(GL_VERSION_2_0) glGetShaderInfoLog(shader, maxLength, length, infoLog); #else os::Printer::log("glGetShaderInfoLog not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetProgramInfoLog(GLuint program, GLsizei maxLength, GLsizei *length, GLchar *infoLog) { if (length) *length=0; #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetProgramInfoLog) pGlGetProgramInfoLog(program, maxLength, length, infoLog); #elif defined(GL_VERSION_2_0) glGetProgramInfoLog(program, maxLength, length, infoLog); #else os::Printer::log("glGetProgramInfoLog not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetObjectParameteriv(GLhandleARB object, GLenum type, GLint *param) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetObjectParameterivARB) pGlGetObjectParameterivARB(object, type, param); #elif defined(GL_ARB_shader_objects) glGetObjectParameterivARB(object, type, param); #else os::Printer::log("glGetObjectParameteriv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetShaderiv(GLuint shader, GLenum type, GLint *param) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetShaderiv) pGlGetShaderiv(shader, type, param); #elif defined(GL_VERSION_2_0) glGetShaderiv(shader, type, param); #else os::Printer::log("glGetShaderiv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetProgramiv(GLuint program, GLenum type, GLint *param) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetProgramiv) pGlGetProgramiv(program, type, param); #elif defined(GL_VERSION_2_0) glGetProgramiv(program, type, param); #else os::Printer::log("glGetProgramiv not supported", ELL_ERROR); #endif } inline GLint COpenGLExtensionHandler::extGlGetUniformLocationARB(GLhandleARB program, const char *name) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetUniformLocationARB) return pGlGetUniformLocationARB(program, name); #elif defined(GL_ARB_shader_objects) return glGetUniformLocationARB(program, name); #else os::Printer::log("glGetUniformLocation not supported", ELL_ERROR); #endif return 0; } inline GLint COpenGLExtensionHandler::extGlGetUniformLocation(GLuint program, const char *name) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetUniformLocation) return pGlGetUniformLocation(program, name); #elif defined(GL_VERSION_2_0) return glGetUniformLocation(program, name); #else os::Printer::log("glGetUniformLocation not supported", ELL_ERROR); #endif return 0; } inline void COpenGLExtensionHandler::extGlUniform1fv(GLint loc, GLsizei count, const GLfloat *v) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUniform1fvARB) pGlUniform1fvARB(loc, count, v); #elif defined(GL_ARB_shader_objects) glUniform1fvARB(loc, count, v); #else os::Printer::log("glUniform1fv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlUniform2fv(GLint loc, GLsizei count, const GLfloat *v) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUniform2fvARB) pGlUniform2fvARB(loc, count, v); #elif defined(GL_ARB_shader_objects) glUniform2fvARB(loc, count, v); #else os::Printer::log("glUniform2fv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlUniform3fv(GLint loc, GLsizei count, const GLfloat *v) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUniform3fvARB) pGlUniform3fvARB(loc, count, v); #elif defined(GL_ARB_shader_objects) glUniform3fvARB(loc, count, v); #else os::Printer::log("glUniform3fv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlUniform4fv(GLint loc, GLsizei count, const GLfloat *v) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUniform4fvARB) pGlUniform4fvARB(loc, count, v); #elif defined(GL_ARB_shader_objects) glUniform4fvARB(loc, count, v); #else os::Printer::log("glUniform4fv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlUniform1iv(GLint loc, GLsizei count, const GLint *v) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUniform1ivARB) pGlUniform1ivARB(loc, count, v); #elif defined(GL_ARB_shader_objects) glUniform1ivARB(loc, count, v); #else os::Printer::log("glUniform1iv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlUniform2iv(GLint loc, GLsizei count, const GLint *v) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUniform2ivARB) pGlUniform2ivARB(loc, count, v); #elif defined(GL_ARB_shader_objects) glUniform2ivARB(loc, count, v); #else os::Printer::log("glUniform2iv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlUniform3iv(GLint loc, GLsizei count, const GLint *v) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUniform3ivARB) pGlUniform3ivARB(loc, count, v); #elif defined(GL_ARB_shader_objects) glUniform3ivARB(loc, count, v); #else os::Printer::log("glUniform3iv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlUniform4iv(GLint loc, GLsizei count, const GLint *v) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUniform4ivARB) pGlUniform4ivARB(loc, count, v); #elif defined(GL_ARB_shader_objects) glUniform4ivARB(loc, count, v); #else os::Printer::log("glUniform4iv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlUniformMatrix2fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat *v) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUniformMatrix2fvARB) pGlUniformMatrix2fvARB(loc, count, transpose, v); #elif defined(GL_ARB_shader_objects) glUniformMatrix2fvARB(loc, count, transpose, v); #else os::Printer::log("glUniformMatrix2fv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlUniformMatrix3fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat *v) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUniformMatrix3fvARB) pGlUniformMatrix3fvARB(loc, count, transpose, v); #elif defined(GL_ARB_shader_objects) glUniformMatrix3fvARB(loc, count, transpose, v); #else os::Printer::log("glUniformMatrix3fv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlUniformMatrix4fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat *v) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUniformMatrix4fvARB) pGlUniformMatrix4fvARB(loc, count, transpose, v); #elif defined(GL_ARB_shader_objects) glUniformMatrix4fvARB(loc, count, transpose, v); #else os::Printer::log("glUniformMatrix4fv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetActiveUniformARB(GLhandleARB program, GLuint index, GLsizei maxlength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name) { if (length) *length=0; #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetActiveUniformARB) pGlGetActiveUniformARB(program, index, maxlength, length, size, type, name); #elif defined(GL_ARB_shader_objects) glGetActiveUniformARB(program, index, maxlength, length, size, type, name); #else os::Printer::log("glGetActiveUniform not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetActiveUniform(GLuint program, GLuint index, GLsizei maxlength, GLsizei *length, GLint *size, GLenum *type, GLchar *name) { if (length) *length=0; #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetActiveUniform) pGlGetActiveUniform(program, index, maxlength, length, size, type, name); #elif defined(GL_VERSION_2_0) glGetActiveUniform(program, index, maxlength, length, size, type, name); #else os::Printer::log("glGetActiveUniform not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlPointParameterf(GLint loc, GLfloat f) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlPointParameterfARB) pGlPointParameterfARB(loc, f); #elif defined(GL_ARB_point_parameters) glPointParameterfARB(loc, f); #else os::Printer::log("glPointParameterf not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlPointParameterfv(GLint loc, const GLfloat *v) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlPointParameterfvARB) pGlPointParameterfvARB(loc, v); #elif defined(GL_ARB_point_parameters) glPointParameterfvARB(loc, v); #else os::Printer::log("glPointParameterfv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlStencilFuncSeparate (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlStencilFuncSeparate) pGlStencilFuncSeparate(frontfunc, backfunc, ref, mask); else if (pGlStencilFuncSeparateATI) pGlStencilFuncSeparateATI(frontfunc, backfunc, ref, mask); #elif defined(GL_VERSION_2_0) glStencilFuncSeparate(frontfunc, backfunc, ref, mask); #elif defined(GL_ATI_separate_stencil) glStencilFuncSeparateATI(frontfunc, backfunc, ref, mask); #else os::Printer::log("glStencilFuncSeparate not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlStencilOpSeparate) pGlStencilOpSeparate(face, fail, zfail, zpass); else if (pGlStencilOpSeparateATI) pGlStencilOpSeparateATI(face, fail, zfail, zpass); #elif defined(GL_VERSION_2_0) glStencilOpSeparate(face, fail, zfail, zpass); #elif defined(GL_ATI_separate_stencil) glStencilOpSeparateATI(face, fail, zfail, zpass); #else os::Printer::log("glStencilOpSeparate not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlCompressedTexImage2D) pGlCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); #elif defined(GL_ARB_texture_compression) glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); #else os::Printer::log("glCompressedTexImage2D not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlBindFramebuffer(GLenum target, GLuint framebuffer) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlBindFramebuffer) pGlBindFramebuffer(target, framebuffer); else if (pGlBindFramebufferEXT) pGlBindFramebufferEXT(target, framebuffer); #elif defined(GL_ARB_framebuffer_object) glBindFramebuffer(target, framebuffer); #elif defined(GL_EXT_framebuffer_object) glBindFramebufferEXT(target, framebuffer); #else os::Printer::log("glBindFramebuffer not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlDeleteFramebuffers) pGlDeleteFramebuffers(n, framebuffers); else if (pGlDeleteFramebuffersEXT) pGlDeleteFramebuffersEXT(n, framebuffers); #elif defined(GL_ARB_framebuffer_object) glDeleteFramebuffers(n, framebuffers); #elif defined(GL_EXT_framebuffer_object) glDeleteFramebuffersEXT(n, framebuffers); #else os::Printer::log("glDeleteFramebuffers not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGenFramebuffers(GLsizei n, GLuint *framebuffers) { if (framebuffers) memset(framebuffers,0,n*sizeof(GLuint)); #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGenFramebuffers) pGlGenFramebuffers(n, framebuffers); else if (pGlGenFramebuffersEXT) pGlGenFramebuffersEXT(n, framebuffers); #elif defined(GL_ARB_framebuffer_object) glGenFramebuffers(n, framebuffers); #elif defined(GL_EXT_framebuffer_object) glGenFramebuffersEXT(n, framebuffers); #else os::Printer::log("glGenFramebuffers not supported", ELL_ERROR); #endif } inline GLenum COpenGLExtensionHandler::extGlCheckFramebufferStatus(GLenum target) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlCheckFramebufferStatus) return pGlCheckFramebufferStatus(target); else if (pGlCheckFramebufferStatusEXT) return pGlCheckFramebufferStatusEXT(target); else return 0; #elif defined(GL_ARB_framebuffer_object) return glCheckFramebufferStatus(target); #elif defined(GL_EXT_framebuffer_object) return glCheckFramebufferStatusEXT(target); #else os::Printer::log("glCheckFramebufferStatus not supported", ELL_ERROR); return 0; #endif } inline void COpenGLExtensionHandler::extGlFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlFramebufferTexture2D) pGlFramebufferTexture2D(target, attachment, textarget, texture, level); else if (pGlFramebufferTexture2DEXT) pGlFramebufferTexture2DEXT(target, attachment, textarget, texture, level); #elif defined(GL_ARB_framebuffer_object) glFramebufferTexture2D(target, attachment, textarget, texture, level); #elif defined(GL_EXT_framebuffer_object) glFramebufferTexture2DEXT(target, attachment, textarget, texture, level); #else os::Printer::log("glFramebufferTexture2D not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlBindRenderbuffer(GLenum target, GLuint renderbuffer) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlBindRenderbuffer) pGlBindRenderbuffer(target, renderbuffer); else if (pGlBindRenderbufferEXT) pGlBindRenderbufferEXT(target, renderbuffer); #elif defined(GL_ARB_framebuffer_object) glBindRenderbuffer(target, renderbuffer); #elif defined(GL_EXT_framebuffer_object) glBindRenderbufferEXT(target, renderbuffer); #else os::Printer::log("glBindRenderbuffer not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlDeleteRenderbuffers) pGlDeleteRenderbuffers(n, renderbuffers); else if (pGlDeleteRenderbuffersEXT) pGlDeleteRenderbuffersEXT(n, renderbuffers); #elif defined(GL_ARB_framebuffer_object) glDeleteRenderbuffers(n, renderbuffers); #elif defined(GL_EXT_framebuffer_object) glDeleteRenderbuffersEXT(n, renderbuffers); #else os::Printer::log("glDeleteRenderbuffers not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGenRenderbuffers(GLsizei n, GLuint *renderbuffers) { if (renderbuffers) memset(renderbuffers,0,n*sizeof(GLuint)); #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGenRenderbuffers) pGlGenRenderbuffers(n, renderbuffers); else if (pGlGenRenderbuffersEXT) pGlGenRenderbuffersEXT(n, renderbuffers); #elif defined(GL_ARB_framebuffer_object) glGenRenderbuffers(n, renderbuffers); #elif defined(GL_EXT_framebuffer_object) glGenRenderbuffersEXT(n, renderbuffers); #else os::Printer::log("glGenRenderbuffers not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlRenderbufferStorage) pGlRenderbufferStorage(target, internalformat, width, height); else if (pGlRenderbufferStorageEXT) pGlRenderbufferStorageEXT(target, internalformat, width, height); #elif defined(GL_ARB_framebuffer_object) glRenderbufferStorage(target, internalformat, width, height); #elif defined(GL_EXT_framebuffer_object) glRenderbufferStorageEXT(target, internalformat, width, height); #else os::Printer::log("glRenderbufferStorage not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlFramebufferRenderbuffer) pGlFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); else if (pGlFramebufferRenderbufferEXT) pGlFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer); #elif defined(GL_ARB_framebuffer_object) glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); #elif defined(GL_EXT_framebuffer_object) glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer); #else os::Printer::log("glFramebufferRenderbuffer not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGenerateMipmap(GLenum target) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGenerateMipmap) pGlGenerateMipmap(target); else if (pGlGenerateMipmapEXT) pGlGenerateMipmapEXT(target); #elif defined(GL_ARB_framebuffer_object) glGenerateMipmap(target); #elif defined(GL_EXT_framebuffer_object) glGenerateMipmapEXT(target); #else os::Printer::log("glGenerateMipmap not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlActiveStencilFace(GLenum face) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlActiveStencilFaceEXT) pGlActiveStencilFaceEXT(face); #elif defined(GL_EXT_stencil_two_side) glActiveStencilFaceEXT(face); #else os::Printer::log("glActiveStencilFace not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlDrawBuffers(GLsizei n, const GLenum *bufs) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlDrawBuffersARB) pGlDrawBuffersARB(n, bufs); else if (pGlDrawBuffersATI) pGlDrawBuffersATI(n, bufs); #elif defined(GL_ARB_draw_buffers) glDrawBuffersARB(n, bufs); #elif defined(GL_ATI_draw_buffers) glDrawBuffersATI(n, bufs); #else os::Printer::log("glDrawBuffers not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGenBuffers(GLsizei n, GLuint *buffers) { if (buffers) memset(buffers,0,n*sizeof(GLuint)); #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGenBuffersARB) pGlGenBuffersARB(n, buffers); #elif defined(GL_ARB_vertex_buffer_object) glGenBuffers(n, buffers); #else os::Printer::log("glGenBuffers not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlBindBuffer(GLenum target, GLuint buffer) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlBindBufferARB) pGlBindBufferARB(target, buffer); #elif defined(GL_ARB_vertex_buffer_object) glBindBuffer(target, buffer); #else os::Printer::log("glBindBuffer not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlBufferData(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlBufferDataARB) pGlBufferDataARB(target, size, data, usage); #elif defined(GL_ARB_vertex_buffer_object) glBufferData(target, size, data, usage); #else os::Printer::log("glBufferData not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlDeleteBuffers(GLsizei n, const GLuint *buffers) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlDeleteBuffersARB) pGlDeleteBuffersARB(n, buffers); #elif defined(GL_ARB_vertex_buffer_object) glDeleteBuffers(n, buffers); #else os::Printer::log("glDeleteBuffers not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlBufferSubDataARB) pGlBufferSubDataARB(target, offset, size, data); #elif defined(GL_ARB_vertex_buffer_object) glBufferSubData(target, offset, size, data); #else os::Printer::log("glBufferSubData not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetBufferSubDataARB) pGlGetBufferSubDataARB(target, offset, size, data); #elif defined(GL_ARB_vertex_buffer_object) glGetBufferSubData(target, offset, size, data); #else os::Printer::log("glGetBufferSubData not supported", ELL_ERROR); #endif } inline void *COpenGLExtensionHandler::extGlMapBuffer(GLenum target, GLenum access) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlMapBufferARB) return pGlMapBufferARB(target, access); return 0; #elif defined(GL_ARB_vertex_buffer_object) return glMapBuffer(target, access); #else os::Printer::log("glMapBuffer not supported", ELL_ERROR); return 0; #endif } inline GLboolean COpenGLExtensionHandler::extGlUnmapBuffer(GLenum target) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlUnmapBufferARB) return pGlUnmapBufferARB(target); return false; #elif defined(GL_ARB_vertex_buffer_object) return glUnmapBuffer(target); #else os::Printer::log("glUnmapBuffer not supported", ELL_ERROR); return false; #endif } inline GLboolean COpenGLExtensionHandler::extGlIsBuffer(GLuint buffer) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlIsBufferARB) return pGlIsBufferARB(buffer); return false; #elif defined(GL_ARB_vertex_buffer_object) return glIsBuffer(buffer); #else os::Printer::log("glDeleteBuffers not supported", ELL_ERROR); return false; #endif } inline void COpenGLExtensionHandler::extGlGetBufferParameteriv(GLenum target, GLenum pname, GLint *params) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetBufferParameterivARB) pGlGetBufferParameterivARB(target, pname, params); #elif defined(GL_ARB_vertex_buffer_object) glGetBufferParameteriv(target, pname, params); #else os::Printer::log("glGetBufferParameteriv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetBufferPointerv(GLenum target, GLenum pname, GLvoid **params) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetBufferPointervARB) pGlGetBufferPointervARB(target, pname, params); #elif defined(GL_ARB_vertex_buffer_object) glGetBufferPointerv(target, pname, params); #else os::Printer::log("glGetBufferPointerv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlProvokingVertex(GLenum mode) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (FeatureAvailable[IRR_ARB_provoking_vertex] && pGlProvokingVertexARB) pGlProvokingVertexARB(mode); else if (FeatureAvailable[IRR_EXT_provoking_vertex] && pGlProvokingVertexEXT) pGlProvokingVertexEXT(mode); #elif defined(GL_ARB_provoking_vertex) glProvokingVertex(mode); #elif defined(GL_EXT_provoking_vertex) glProvokingVertexEXT(mode); #else os::Printer::log("glProvokingVertex not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlColorMaskIndexed(GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (FeatureAvailable[IRR_EXT_draw_buffers2] && pGlColorMaskIndexedEXT) pGlColorMaskIndexedEXT(buf, r, g, b, a); #elif defined(GL_EXT_draw_buffers2) glColorMaskIndexedEXT(buf, r, g, b, a); #else os::Printer::log("glColorMaskIndexed not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlEnableIndexed(GLenum target, GLuint index) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (FeatureAvailable[IRR_EXT_draw_buffers2] && pGlEnableIndexedEXT) pGlEnableIndexedEXT(target, index); #elif defined(GL_EXT_draw_buffers2) glEnableIndexedEXT(target, index); #else os::Printer::log("glEnableIndexed not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlDisableIndexed(GLenum target, GLuint index) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (FeatureAvailable[IRR_EXT_draw_buffers2] && pGlDisableIndexedEXT) pGlDisableIndexedEXT(target, index); #elif defined(GL_EXT_draw_buffers2) glDisableIndexedEXT(target, index); #else os::Printer::log("glDisableIndexed not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlBlendFuncIndexed(GLuint buf, GLenum src, GLenum dst) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (FeatureAvailable[IRR_ARB_draw_buffers_blend] && pGlBlendFunciARB) pGlBlendFunciARB(buf, src, dst); else if (FeatureAvailable[IRR_AMD_draw_buffers_blend] && pGlBlendFuncIndexedAMD) pGlBlendFuncIndexedAMD(buf, src, dst); #elif defined(GL_ARB_draw_buffers_blend) glBlendFunciARB(buf, src, dst); #elif defined(GL_AMD_draw_buffers_blend) glBlendFuncIndexedAMD(buf, src, dst); #else os::Printer::log("glBlendFuncIndexed not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlBlendEquationIndexed(GLuint buf, GLenum mode) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (FeatureAvailable[IRR_ARB_draw_buffers_blend] && pGlBlendEquationiARB) pGlBlendEquationiARB(buf, mode); else if (FeatureAvailable[IRR_AMD_draw_buffers_blend] && pGlBlendEquationIndexedAMD) pGlBlendEquationIndexedAMD(buf, mode); #elif defined(GL_ARB_draw_buffers_blend) glBlendEquationiARB(buf, mode); #elif defined(GL_AMD_draw_buffers_blend) glBlendEquationIndexedAMD(buf, mode); #else os::Printer::log("glBlendEquationIndexed not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlProgramParameteri(GLuint program, GLenum pname, GLint value) { #if defined(_IRR_OPENGL_USE_EXTPOINTER_) if (queryFeature(EVDF_GEOMETRY_SHADER)) { if (pGlProgramParameteriARB) pGlProgramParameteriARB(program, pname, value); else if (pGlProgramParameteriEXT) pGlProgramParameteriEXT(program, pname, value); } #elif defined(GL_ARB_geometry_shader4) glProgramParameteriARB(program, pname, value); #elif defined(GL_EXT_geometry_shader4) glProgramParameteriEXT(program, pname, value); #elif defined(GL_NV_geometry_program4) || defined(GL_NV_geometry_shader4) glProgramParameteriNV(program, pname, value); #else os::Printer::log("glProgramParameteri not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGenQueries(GLsizei n, GLuint *ids) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGenQueriesARB) pGlGenQueriesARB(n, ids); else if (pGlGenOcclusionQueriesNV) pGlGenOcclusionQueriesNV(n, ids); #elif defined(GL_ARB_occlusion_query) glGenQueriesARB(n, ids); #elif defined(GL_NV_occlusion_query) glGenOcclusionQueriesNV(n, ids); #else os::Printer::log("glGenQueries not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlDeleteQueries(GLsizei n, const GLuint *ids) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlDeleteQueriesARB) pGlDeleteQueriesARB(n, ids); else if (pGlDeleteOcclusionQueriesNV) pGlDeleteOcclusionQueriesNV(n, ids); #elif defined(GL_ARB_occlusion_query) glDeleteQueriesARB(n, ids); #elif defined(GL_NV_occlusion_query) glDeleteOcclusionQueriesNV(n, ids); #else os::Printer::log("glDeleteQueries not supported", ELL_ERROR); #endif } inline GLboolean COpenGLExtensionHandler::extGlIsQuery(GLuint id) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlIsQueryARB) return pGlIsQueryARB(id); else if (pGlIsOcclusionQueryNV) return pGlIsOcclusionQueryNV(id); return false; #elif defined(GL_ARB_occlusion_query) return glIsQueryARB(id); #elif defined(GL_NV_occlusion_query) return glIsOcclusionQueryNV(id); #else return false; #endif } inline void COpenGLExtensionHandler::extGlBeginQuery(GLenum target, GLuint id) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlBeginQueryARB) pGlBeginQueryARB(target, id); else if (pGlBeginOcclusionQueryNV) pGlBeginOcclusionQueryNV(id); #elif defined(GL_ARB_occlusion_query) glBeginQueryARB(target, id); #elif defined(GL_NV_occlusion_query) glBeginOcclusionQueryNV(id); #else os::Printer::log("glBeginQuery not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlEndQuery(GLenum target) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlEndQueryARB) pGlEndQueryARB(target); else if (pGlEndOcclusionQueryNV) pGlEndOcclusionQueryNV(); #elif defined(GL_ARB_occlusion_query) glEndQueryARB(target); #elif defined(GL_NV_occlusion_query) glEndOcclusionQueryNV(); #else os::Printer::log("glEndQuery not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetQueryiv(GLenum target, GLenum pname, GLint *params) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetQueryivARB) pGlGetQueryivARB(target, pname, params); #elif defined(GL_ARB_occlusion_query) glGetQueryivARB(target, pname, params); #else os::Printer::log("glGetQueryivARB not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetQueryObjectiv(GLuint id, GLenum pname, GLint *params) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetQueryObjectivARB) pGlGetQueryObjectivARB(id, pname, params); else if (pGlGetOcclusionQueryivNV) pGlGetOcclusionQueryivNV(id, pname, params); #elif defined(GL_ARB_occlusion_query) glGetQueryObjectivARB(id, pname, params); #elif defined(GL_NV_occlusion_query) glGetOcclusionQueryivNV(id, pname, params); #else os::Printer::log("glGetQueryObjectiv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGetQueryObjectuivARB) pGlGetQueryObjectuivARB(id, pname, params); else if (pGlGetOcclusionQueryuivNV) pGlGetOcclusionQueryuivNV(id, pname, params); #elif defined(GL_ARB_occlusion_query) glGetQueryObjectuivARB(id, pname, params); #elif defined(GL_NV_occlusion_query) glGetOcclusionQueryuivNV(id, pname, params); #else os::Printer::log("glGetQueryObjectuiv not supported", ELL_ERROR); #endif } inline void COpenGLExtensionHandler::extGlSwapInterval(int interval) { // we have wglext, so try to use that #if defined(_IRR_WINDOWS_API_) && defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) #ifdef WGL_EXT_swap_control if (pWglSwapIntervalEXT) pWglSwapIntervalEXT(interval); #endif #endif #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ //TODO: Check GLX_EXT_swap_control and GLX_MESA_swap_control #ifdef GLX_SGI_swap_control // does not work with interval==0 #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (interval && pGlxSwapIntervalSGI) pGlxSwapIntervalSGI(interval); #else if (interval) glXSwapIntervalSGI(interval); #endif #elif defined(GLX_EXT_swap_control) #ifdef _IRR_OPENGL_USE_EXTPOINTER_ Display *dpy = glXGetCurrentDisplay(); GLXDrawable drawable = glXGetCurrentDrawable(); if (pGlxSwapIntervalEXT) pGlxSwapIntervalEXT(dpy, drawable, interval); #else pGlXSwapIntervalEXT(dpy, drawable, interval); #endif #elif defined(GLX_MESA_swap_control) #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlxSwapIntervalMESA) pGlxSwapIntervalMESA(interval); #else pGlXSwapIntervalMESA(interval); #endif #endif #endif } inline void COpenGLExtensionHandler::extGlBlendEquation(GLenum mode) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlBlendEquation) pGlBlendEquation(mode); else if (pGlBlendEquationEXT) pGlBlendEquationEXT(mode); #elif defined(GL_EXT_blend_minmax) || defined(GL_EXT_blend_subtract) || defined(GL_EXT_blend_logic_op) glBlendEquationEXT(mode); #elif defined(GL_VERSION_1_2) glBlendEquation(mode); #else os::Printer::log("glBlendEquation not supported", ELL_ERROR); #endif } } } #endif #endif irrlicht-1.8.3/source/Irrlicht/COpenGLExtensionHandler.cpp0000644000000000000000000010775612574354552022303 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "COpenGLExtensionHandler.h" #include "irrString.h" #include "SMaterial.h" // for MATERIAL_MAX_TEXTURES #include "fast_atof.h" namespace irr { namespace video { COpenGLExtensionHandler::COpenGLExtensionHandler() : StencilBuffer(false), MultiTextureExtension(false), TextureCompressionExtension(false), MaxSupportedTextures(1), MaxTextureUnits(1), MaxLights(1), MaxAnisotropy(1), MaxUserClipPlanes(0), MaxAuxBuffers(0), MaxMultipleRenderTargets(1), MaxIndices(65535), MaxTextureSize(1), MaxGeometryVerticesOut(0), MaxTextureLODBias(0.f), Version(0), ShaderLanguageVersion(0), OcclusionQuerySupport(false) #ifdef _IRR_OPENGL_USE_EXTPOINTER_ ,pGlActiveTextureARB(0), pGlClientActiveTextureARB(0), pGlGenProgramsARB(0), pGlGenProgramsNV(0), pGlBindProgramARB(0), pGlBindProgramNV(0), pGlDeleteProgramsARB(0), pGlDeleteProgramsNV(0), pGlProgramStringARB(0), pGlLoadProgramNV(0), pGlProgramLocalParameter4fvARB(0), pGlCreateShaderObjectARB(0), pGlShaderSourceARB(0), pGlCompileShaderARB(0), pGlCreateProgramObjectARB(0), pGlAttachObjectARB(0), pGlLinkProgramARB(0), pGlUseProgramObjectARB(0), pGlDeleteObjectARB(0), pGlCreateProgram(0), pGlUseProgram(0), pGlDeleteProgram(0), pGlDeleteShader(0), pGlGetAttachedObjectsARB(0), pGlGetAttachedShaders(0), pGlCreateShader(0), pGlShaderSource(0), pGlCompileShader(0), pGlAttachShader(0), pGlLinkProgram(0), pGlGetInfoLogARB(0), pGlGetShaderInfoLog(0), pGlGetProgramInfoLog(0), pGlGetObjectParameterivARB(0), pGlGetShaderiv(0), pGlGetProgramiv(0), pGlGetUniformLocationARB(0), pGlGetUniformLocation(0), pGlUniform1fvARB(0), pGlUniform2fvARB(0), pGlUniform3fvARB(0), pGlUniform4fvARB(0), pGlUniform1ivARB(0), pGlUniform2ivARB(0), pGlUniform3ivARB(0), pGlUniform4ivARB(0), pGlUniformMatrix2fvARB(0), pGlUniformMatrix3fvARB(0), pGlUniformMatrix4fvARB(0), pGlGetActiveUniformARB(0), pGlGetActiveUniform(0), pGlPointParameterfARB(0), pGlPointParameterfvARB(0), pGlStencilFuncSeparate(0), pGlStencilOpSeparate(0), pGlStencilFuncSeparateATI(0), pGlStencilOpSeparateATI(0), pGlCompressedTexImage2D(0), // ARB framebuffer object pGlBindFramebuffer(0), pGlDeleteFramebuffers(0), pGlGenFramebuffers(0), pGlCheckFramebufferStatus(0), pGlFramebufferTexture2D(0), pGlBindRenderbuffer(0), pGlDeleteRenderbuffers(0), pGlGenRenderbuffers(0), pGlRenderbufferStorage(0), pGlFramebufferRenderbuffer(0), pGlGenerateMipmap(0), // EXT framebuffer object pGlBindFramebufferEXT(0), pGlDeleteFramebuffersEXT(0), pGlGenFramebuffersEXT(0), pGlCheckFramebufferStatusEXT(0), pGlFramebufferTexture2DEXT(0), pGlBindRenderbufferEXT(0), pGlDeleteRenderbuffersEXT(0), pGlGenRenderbuffersEXT(0), pGlRenderbufferStorageEXT(0), pGlFramebufferRenderbufferEXT(0), pGlGenerateMipmapEXT(0), // MRTs pGlDrawBuffersARB(0), pGlDrawBuffersATI(0), pGlGenBuffersARB(0), pGlBindBufferARB(0), pGlBufferDataARB(0), pGlDeleteBuffersARB(0), pGlBufferSubDataARB(0), pGlGetBufferSubDataARB(0), pGlMapBufferARB(0), pGlUnmapBufferARB(0), pGlIsBufferARB(0), pGlGetBufferParameterivARB(0), pGlGetBufferPointervARB(0), pGlProvokingVertexARB(0), pGlProvokingVertexEXT(0), pGlColorMaskIndexedEXT(0), pGlEnableIndexedEXT(0), pGlDisableIndexedEXT(0), pGlBlendFuncIndexedAMD(0), pGlBlendFunciARB(0), pGlBlendEquationIndexedAMD(0), pGlBlendEquationiARB(0), pGlProgramParameteriARB(0), pGlProgramParameteriEXT(0), pGlGenQueriesARB(0), pGlDeleteQueriesARB(0), pGlIsQueryARB(0), pGlBeginQueryARB(0), pGlEndQueryARB(0), pGlGetQueryivARB(0), pGlGetQueryObjectivARB(0), pGlGetQueryObjectuivARB(0), pGlGenOcclusionQueriesNV(0), pGlDeleteOcclusionQueriesNV(0), pGlIsOcclusionQueryNV(0), pGlBeginOcclusionQueryNV(0), pGlEndOcclusionQueryNV(0), pGlGetOcclusionQueryivNV(0), pGlGetOcclusionQueryuivNV(0), pGlBlendEquationEXT(0), pGlBlendEquation(0) #if defined(GLX_SGI_swap_control) ,pGlxSwapIntervalSGI(0) #endif #if defined(GLX_EXT_swap_control) ,pGlxSwapIntervalEXT(0) #endif #if defined(WGL_EXT_swap_control) ,pWglSwapIntervalEXT(0) #endif #if defined(GLX_MESA_swap_control) ,pGlxSwapIntervalMESA(0) #endif #endif // _IRR_OPENGL_USE_EXTPOINTER_ { for (u32 i=0; i(glGetString(GL_VERSION))); Version = static_cast(core::floor32(ogl_ver)*100+core::round32(core::fract(ogl_ver)*10.0f)); if ( Version >= 102) os::Printer::log("OpenGL driver version is 1.2 or better.", ELL_INFORMATION); else os::Printer::log("OpenGL driver version is not 1.2 or better.", ELL_WARNING); { const char* t = reinterpret_cast(glGetString(GL_EXTENSIONS)); size_t len = 0; c8 *str = 0; if (t) { len = strlen(t); str = new c8[len+1]; } c8* p = str; for (size_t i=0; i(t[i]); if (str[i] == ' ') { str[i] = 0; for (u32 j=0; j(x)) #elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_) && !defined(_IRR_COMPILE_WITH_X11_DEVICE_) #define IRR_OGL_LOAD_EXTENSION(x) SDL_GL_GetProcAddress(reinterpret_cast(x)) #else // Accessing the correct function is quite complex // All libraries should support the ARB version, however // since GLX 1.4 the non-ARB version is the official one // So we have to check the runtime environment and // choose the proper symbol // In case you still have problems please enable the // next line by uncommenting it // #define _IRR_GETPROCADDRESS_WORKAROUND_ #ifndef _IRR_GETPROCADDRESS_WORKAROUND_ __GLXextFuncPtr (*IRR_OGL_LOAD_EXTENSION_FUNCP)(const GLubyte*)=0; #ifdef GLX_VERSION_1_4 int major=0,minor=0; if (glXGetCurrentDisplay()) glXQueryVersion(glXGetCurrentDisplay(), &major, &minor); if ((major>1) || (minor>3)) IRR_OGL_LOAD_EXTENSION_FUNCP=glXGetProcAddress; else #endif IRR_OGL_LOAD_EXTENSION_FUNCP=glXGetProcAddressARB; #define IRR_OGL_LOAD_EXTENSION(X) IRR_OGL_LOAD_EXTENSION_FUNCP(reinterpret_cast(X)) #else #define IRR_OGL_LOAD_EXTENSION(X) glXGetProcAddressARB(reinterpret_cast(X)) #endif // workaround #endif // Windows, SDL, or Linux // get multitexturing function pointers pGlActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) IRR_OGL_LOAD_EXTENSION("glActiveTextureARB"); pGlClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC) IRR_OGL_LOAD_EXTENSION("glClientActiveTextureARB"); // get fragment and vertex program function pointers pGlGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) IRR_OGL_LOAD_EXTENSION("glGenProgramsARB"); pGlGenProgramsNV = (PFNGLGENPROGRAMSNVPROC) IRR_OGL_LOAD_EXTENSION("glGenProgramsNV"); pGlBindProgramARB = (PFNGLBINDPROGRAMARBPROC) IRR_OGL_LOAD_EXTENSION("glBindProgramARB"); pGlBindProgramNV = (PFNGLBINDPROGRAMNVPROC) IRR_OGL_LOAD_EXTENSION("glBindProgramNV"); pGlProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) IRR_OGL_LOAD_EXTENSION("glProgramStringARB"); pGlLoadProgramNV = (PFNGLLOADPROGRAMNVPROC) IRR_OGL_LOAD_EXTENSION("glLoadProgramNV"); pGlDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) IRR_OGL_LOAD_EXTENSION("glDeleteProgramsARB"); pGlDeleteProgramsNV = (PFNGLDELETEPROGRAMSNVPROC) IRR_OGL_LOAD_EXTENSION("glDeleteProgramsNV"); pGlProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) IRR_OGL_LOAD_EXTENSION("glProgramLocalParameter4fvARB"); pGlCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) IRR_OGL_LOAD_EXTENSION("glCreateShaderObjectARB"); pGlCreateShader = (PFNGLCREATESHADERPROC) IRR_OGL_LOAD_EXTENSION("glCreateShader"); pGlShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) IRR_OGL_LOAD_EXTENSION("glShaderSourceARB"); pGlShaderSource = (PFNGLSHADERSOURCEPROC) IRR_OGL_LOAD_EXTENSION("glShaderSource"); pGlCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) IRR_OGL_LOAD_EXTENSION("glCompileShaderARB"); pGlCompileShader = (PFNGLCOMPILESHADERPROC) IRR_OGL_LOAD_EXTENSION("glCompileShader"); pGlCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) IRR_OGL_LOAD_EXTENSION("glCreateProgramObjectARB"); pGlCreateProgram = (PFNGLCREATEPROGRAMPROC) IRR_OGL_LOAD_EXTENSION("glCreateProgram"); pGlAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) IRR_OGL_LOAD_EXTENSION("glAttachObjectARB"); pGlAttachShader = (PFNGLATTACHSHADERPROC) IRR_OGL_LOAD_EXTENSION("glAttachShader"); pGlLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) IRR_OGL_LOAD_EXTENSION("glLinkProgramARB"); pGlLinkProgram = (PFNGLLINKPROGRAMPROC) IRR_OGL_LOAD_EXTENSION("glLinkProgram"); pGlUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) IRR_OGL_LOAD_EXTENSION("glUseProgramObjectARB"); pGlUseProgram = (PFNGLUSEPROGRAMPROC) IRR_OGL_LOAD_EXTENSION("glUseProgram"); pGlDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) IRR_OGL_LOAD_EXTENSION("glDeleteObjectARB"); pGlDeleteProgram = (PFNGLDELETEPROGRAMPROC) IRR_OGL_LOAD_EXTENSION("glDeleteProgram"); pGlDeleteShader = (PFNGLDELETESHADERPROC) IRR_OGL_LOAD_EXTENSION("glDeleteShader"); pGlGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) IRR_OGL_LOAD_EXTENSION("glGetAttachedShaders"); pGlGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) IRR_OGL_LOAD_EXTENSION("glGetAttachedObjectsARB"); pGlGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) IRR_OGL_LOAD_EXTENSION("glGetInfoLogARB"); pGlGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) IRR_OGL_LOAD_EXTENSION("glGetShaderInfoLog"); pGlGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) IRR_OGL_LOAD_EXTENSION("glGetProgramInfoLog"); pGlGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) IRR_OGL_LOAD_EXTENSION("glGetObjectParameterivARB"); pGlGetShaderiv = (PFNGLGETSHADERIVPROC) IRR_OGL_LOAD_EXTENSION("glGetShaderiv"); pGlGetProgramiv = (PFNGLGETPROGRAMIVPROC) IRR_OGL_LOAD_EXTENSION("glGetProgramiv"); pGlGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) IRR_OGL_LOAD_EXTENSION("glGetUniformLocationARB"); pGlGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) IRR_OGL_LOAD_EXTENSION("glGetUniformLocation"); pGlUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) IRR_OGL_LOAD_EXTENSION("glUniform1fvARB"); pGlUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) IRR_OGL_LOAD_EXTENSION("glUniform2fvARB"); pGlUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) IRR_OGL_LOAD_EXTENSION("glUniform3fvARB"); pGlUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) IRR_OGL_LOAD_EXTENSION("glUniform4fvARB"); pGlUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) IRR_OGL_LOAD_EXTENSION("glUniform1ivARB"); pGlUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) IRR_OGL_LOAD_EXTENSION("glUniform2ivARB"); pGlUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) IRR_OGL_LOAD_EXTENSION("glUniform3ivARB"); pGlUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) IRR_OGL_LOAD_EXTENSION("glUniform4ivARB"); pGlUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) IRR_OGL_LOAD_EXTENSION("glUniformMatrix2fvARB"); pGlUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) IRR_OGL_LOAD_EXTENSION("glUniformMatrix3fvARB"); pGlUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) IRR_OGL_LOAD_EXTENSION("glUniformMatrix4fvARB"); pGlGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) IRR_OGL_LOAD_EXTENSION("glGetActiveUniformARB"); pGlGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) IRR_OGL_LOAD_EXTENSION("glGetActiveUniform"); // get point parameter extension pGlPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC) IRR_OGL_LOAD_EXTENSION("glPointParameterfARB"); pGlPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC) IRR_OGL_LOAD_EXTENSION("glPointParameterfvARB"); // get stencil extension pGlStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) IRR_OGL_LOAD_EXTENSION("glStencilFuncSeparate"); pGlStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) IRR_OGL_LOAD_EXTENSION("glStencilOpSeparate"); pGlStencilFuncSeparateATI = (PFNGLSTENCILFUNCSEPARATEATIPROC) IRR_OGL_LOAD_EXTENSION("glStencilFuncSeparateATI"); pGlStencilOpSeparateATI = (PFNGLSTENCILOPSEPARATEATIPROC) IRR_OGL_LOAD_EXTENSION("glStencilOpSeparateATI"); // compressed textures pGlCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) IRR_OGL_LOAD_EXTENSION("glCompressedTexImage2D"); // ARB FrameBufferObjects pGlBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) IRR_OGL_LOAD_EXTENSION("glBindFramebuffer"); pGlDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) IRR_OGL_LOAD_EXTENSION("glDeleteFramebuffers"); pGlGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) IRR_OGL_LOAD_EXTENSION("glGenFramebuffers"); pGlCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) IRR_OGL_LOAD_EXTENSION("glCheckFramebufferStatus"); pGlFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) IRR_OGL_LOAD_EXTENSION("glFramebufferTexture2D"); pGlBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) IRR_OGL_LOAD_EXTENSION("glBindRenderbuffer"); pGlDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) IRR_OGL_LOAD_EXTENSION("glDeleteRenderbuffers"); pGlGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) IRR_OGL_LOAD_EXTENSION("glGenRenderbuffers"); pGlRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) IRR_OGL_LOAD_EXTENSION("glRenderbufferStorage"); pGlFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) IRR_OGL_LOAD_EXTENSION("glFramebufferRenderbuffer"); pGlGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) IRR_OGL_LOAD_EXTENSION("glGenerateMipmap"); // EXT FrameBufferObjects pGlBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) IRR_OGL_LOAD_EXTENSION("glBindFramebufferEXT"); pGlDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) IRR_OGL_LOAD_EXTENSION("glDeleteFramebuffersEXT"); pGlGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) IRR_OGL_LOAD_EXTENSION("glGenFramebuffersEXT"); pGlCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) IRR_OGL_LOAD_EXTENSION("glCheckFramebufferStatusEXT"); pGlFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) IRR_OGL_LOAD_EXTENSION("glFramebufferTexture2DEXT"); pGlBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) IRR_OGL_LOAD_EXTENSION("glBindRenderbufferEXT"); pGlDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) IRR_OGL_LOAD_EXTENSION("glDeleteRenderbuffersEXT"); pGlGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) IRR_OGL_LOAD_EXTENSION("glGenRenderbuffersEXT"); pGlRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) IRR_OGL_LOAD_EXTENSION("glRenderbufferStorageEXT"); pGlFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) IRR_OGL_LOAD_EXTENSION("glFramebufferRenderbufferEXT"); pGlGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) IRR_OGL_LOAD_EXTENSION("glGenerateMipmapEXT"); pGlDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) IRR_OGL_LOAD_EXTENSION("glDrawBuffersARB"); pGlDrawBuffersATI = (PFNGLDRAWBUFFERSATIPROC) IRR_OGL_LOAD_EXTENSION("glDrawBuffersATI"); // get vertex buffer extension pGlGenBuffersARB = (PFNGLGENBUFFERSARBPROC) IRR_OGL_LOAD_EXTENSION("glGenBuffersARB"); pGlBindBufferARB = (PFNGLBINDBUFFERARBPROC) IRR_OGL_LOAD_EXTENSION("glBindBufferARB"); pGlBufferDataARB = (PFNGLBUFFERDATAARBPROC) IRR_OGL_LOAD_EXTENSION("glBufferDataARB"); pGlDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) IRR_OGL_LOAD_EXTENSION("glDeleteBuffersARB"); pGlBufferSubDataARB= (PFNGLBUFFERSUBDATAARBPROC) IRR_OGL_LOAD_EXTENSION("glBufferSubDataARB"); pGlGetBufferSubDataARB= (PFNGLGETBUFFERSUBDATAARBPROC)IRR_OGL_LOAD_EXTENSION("glGetBufferSubDataARB"); pGlMapBufferARB= (PFNGLMAPBUFFERARBPROC) IRR_OGL_LOAD_EXTENSION("glMapBufferARB"); pGlUnmapBufferARB= (PFNGLUNMAPBUFFERARBPROC) IRR_OGL_LOAD_EXTENSION("glUnmapBufferARB"); pGlIsBufferARB= (PFNGLISBUFFERARBPROC) IRR_OGL_LOAD_EXTENSION("glIsBufferARB"); pGlGetBufferParameterivARB= (PFNGLGETBUFFERPARAMETERIVARBPROC) IRR_OGL_LOAD_EXTENSION("glGetBufferParameterivARB"); pGlGetBufferPointervARB= (PFNGLGETBUFFERPOINTERVARBPROC) IRR_OGL_LOAD_EXTENSION("glGetBufferPointervARB"); pGlProvokingVertexARB= (PFNGLPROVOKINGVERTEXPROC) IRR_OGL_LOAD_EXTENSION("glProvokingVertex"); pGlProvokingVertexEXT= (PFNGLPROVOKINGVERTEXEXTPROC) IRR_OGL_LOAD_EXTENSION("glProvokingVertexEXT"); pGlColorMaskIndexedEXT= (PFNGLCOLORMASKINDEXEDEXTPROC) IRR_OGL_LOAD_EXTENSION("glColorMaskIndexedEXT"); pGlEnableIndexedEXT= (PFNGLENABLEINDEXEDEXTPROC) IRR_OGL_LOAD_EXTENSION("glEnableIndexedEXT"); pGlDisableIndexedEXT= (PFNGLDISABLEINDEXEDEXTPROC) IRR_OGL_LOAD_EXTENSION("glDisableIndexedEXT"); pGlBlendFuncIndexedAMD= (PFNGLBLENDFUNCINDEXEDAMDPROC) IRR_OGL_LOAD_EXTENSION("glBlendFuncIndexedAMD"); pGlBlendFunciARB= (PFNGLBLENDFUNCIPROC) IRR_OGL_LOAD_EXTENSION("glBlendFunciARB"); pGlBlendEquationIndexedAMD= (PFNGLBLENDEQUATIONINDEXEDAMDPROC) IRR_OGL_LOAD_EXTENSION("glBlendEquationIndexedAMD"); pGlBlendEquationiARB= (PFNGLBLENDEQUATIONIPROC) IRR_OGL_LOAD_EXTENSION("glBlendEquationiARB"); pGlProgramParameteriARB= (PFNGLPROGRAMPARAMETERIARBPROC) IRR_OGL_LOAD_EXTENSION("glProgramParameteriARB"); pGlProgramParameteriEXT= (PFNGLPROGRAMPARAMETERIEXTPROC) IRR_OGL_LOAD_EXTENSION("glProgramParameteriEXT"); // occlusion query pGlGenQueriesARB = (PFNGLGENQUERIESARBPROC) IRR_OGL_LOAD_EXTENSION("glGenQueriesARB"); pGlDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC) IRR_OGL_LOAD_EXTENSION("glDeleteQueriesARB"); pGlIsQueryARB = (PFNGLISQUERYARBPROC) IRR_OGL_LOAD_EXTENSION("glIsQueryARB"); pGlBeginQueryARB = (PFNGLBEGINQUERYARBPROC) IRR_OGL_LOAD_EXTENSION("glBeginQueryARB"); pGlEndQueryARB = (PFNGLENDQUERYARBPROC) IRR_OGL_LOAD_EXTENSION("glEndQueryARB"); pGlGetQueryivARB = (PFNGLGETQUERYIVARBPROC) IRR_OGL_LOAD_EXTENSION("glGetQueryivARB"); pGlGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC) IRR_OGL_LOAD_EXTENSION("glGetQueryObjectivARB"); pGlGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC) IRR_OGL_LOAD_EXTENSION("glGetQueryObjectuivARB"); pGlGenOcclusionQueriesNV = (PFNGLGENOCCLUSIONQUERIESNVPROC) IRR_OGL_LOAD_EXTENSION("glGenOcclusionQueriesNV"); pGlDeleteOcclusionQueriesNV = (PFNGLDELETEOCCLUSIONQUERIESNVPROC) IRR_OGL_LOAD_EXTENSION("glDeleteOcclusionQueriesNV"); pGlIsOcclusionQueryNV = (PFNGLISOCCLUSIONQUERYNVPROC) IRR_OGL_LOAD_EXTENSION("glIsOcclusionQueryNV"); pGlBeginOcclusionQueryNV = (PFNGLBEGINOCCLUSIONQUERYNVPROC) IRR_OGL_LOAD_EXTENSION("glBeginOcclusionQueryNV"); pGlEndOcclusionQueryNV = (PFNGLENDOCCLUSIONQUERYNVPROC) IRR_OGL_LOAD_EXTENSION("glEndOcclusionQueryNV"); pGlGetOcclusionQueryivNV = (PFNGLGETOCCLUSIONQUERYIVNVPROC) IRR_OGL_LOAD_EXTENSION("glGetOcclusionQueryivNV"); pGlGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC) IRR_OGL_LOAD_EXTENSION("glGetOcclusionQueryuivNV"); // blend equation pGlBlendEquationEXT = (PFNGLBLENDEQUATIONEXTPROC) IRR_OGL_LOAD_EXTENSION("glBlendEquationEXT"); pGlBlendEquation = (PFNGLBLENDEQUATIONPROC) IRR_OGL_LOAD_EXTENSION("glBlendEquation"); // get vsync extension #if defined(WGL_EXT_swap_control) && !defined(_IRR_COMPILE_WITH_SDL_DEVICE_) pWglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) IRR_OGL_LOAD_EXTENSION("wglSwapIntervalEXT"); #endif #if defined(GLX_SGI_swap_control) && !defined(_IRR_COMPILE_WITH_SDL_DEVICE_) pGlxSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)IRR_OGL_LOAD_EXTENSION("glXSwapIntervalSGI"); #endif #if defined(GLX_EXT_swap_control) && !defined(_IRR_COMPILE_WITH_SDL_DEVICE_) pGlxSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)IRR_OGL_LOAD_EXTENSION("glXSwapIntervalEXT"); #endif #if defined(GLX_MESA_swap_control) && !defined(_IRR_COMPILE_WITH_SDL_DEVICE_) pGlxSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)IRR_OGL_LOAD_EXTENSION("glXSwapIntervalMESA"); #endif #endif // use extension pointer GLint num=0; // set some properties #if defined(GL_ARB_multitexture) || defined(GL_VERSION_1_3) if (Version>102 || FeatureAvailable[IRR_ARB_multitexture]) { #if defined(GL_MAX_TEXTURE_UNITS) glGetIntegerv(GL_MAX_TEXTURE_UNITS, &num); #elif defined(GL_MAX_TEXTURE_UNITS_ARB) glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &num); #endif MaxSupportedTextures=static_cast(num); } #endif #if defined(GL_ARB_vertex_shader) || defined(GL_VERSION_2_0) if (Version>=200 || FeatureAvailable[IRR_ARB_vertex_shader]) { num=0; #if defined(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS) glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &num); #elif defined(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB) glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &num); #endif MaxSupportedTextures=core::max_(MaxSupportedTextures,static_cast(num)); } #endif glGetIntegerv(GL_MAX_LIGHTS, &num); MaxLights=static_cast(num); #ifdef GL_EXT_texture_filter_anisotropic if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic]) { glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &num); MaxAnisotropy=static_cast(num); } #endif #ifdef GL_VERSION_1_2 if (Version>101) { glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &num); MaxIndices=num; } #endif glGetIntegerv(GL_MAX_TEXTURE_SIZE, &num); MaxTextureSize=static_cast(num); if (queryFeature(EVDF_GEOMETRY_SHADER)) { #if defined(GL_ARB_geometry_shader4) || defined(GL_EXT_geometry_shader4) || defined(GL_NV_geometry_shader4) glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &num); MaxGeometryVerticesOut=static_cast(num); #elif defined(GL_NV_geometry_program4) extGlGetProgramiv(GEOMETRY_PROGRAM_NV, GL_MAX_PROGRAM_OUTPUT_VERTICES_NV, &num); MaxGeometryVerticesOut=static_cast(num); #endif } #ifdef GL_EXT_texture_lod_bias if (FeatureAvailable[IRR_EXT_texture_lod_bias]) glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS_EXT, &MaxTextureLODBias); #endif glGetIntegerv(GL_MAX_CLIP_PLANES, &num); MaxUserClipPlanes=static_cast(num); glGetIntegerv(GL_AUX_BUFFERS, &num); MaxAuxBuffers=static_cast(num); #ifdef GL_ARB_draw_buffers if (FeatureAvailable[IRR_ARB_draw_buffers]) { glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &num); MaxMultipleRenderTargets = static_cast(num); } #endif #if defined(GL_ATI_draw_buffers) #ifdef GL_ARB_draw_buffers else #endif if (FeatureAvailable[IRR_ATI_draw_buffers]) { glGetIntegerv(GL_MAX_DRAW_BUFFERS_ATI, &num); MaxMultipleRenderTargets = static_cast(num); } #endif glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, DimAliasedLine); glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, DimAliasedPoint); glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, DimSmoothedLine); glGetFloatv(GL_SMOOTH_POINT_SIZE_RANGE, DimSmoothedPoint); #if defined(GL_ARB_shading_language_100) || defined (GL_VERSION_2_0) if (FeatureAvailable[IRR_ARB_shading_language_100] || Version>=200) { glGetError(); // clean error buffer #ifdef GL_SHADING_LANGUAGE_VERSION const GLubyte* shaderVersion = glGetString(GL_SHADING_LANGUAGE_VERSION); #else const GLubyte* shaderVersion = glGetString(GL_SHADING_LANGUAGE_VERSION_ARB); #endif if (glGetError() == GL_INVALID_ENUM) ShaderLanguageVersion = 100; else { const f32 sl_ver = core::fast_atof(reinterpret_cast(shaderVersion)); ShaderLanguageVersion = static_cast(core::floor32(sl_ver)*100+core::round32(core::fract(sl_ver)*10.0f)); } } #endif #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (!pGlActiveTextureARB || !pGlClientActiveTextureARB) { MultiTextureExtension = false; os::Printer::log("Failed to load OpenGL's multitexture extension, proceeding without.", ELL_WARNING); } else #endif MaxTextureUnits = core::min_(MaxSupportedTextures, static_cast(MATERIAL_MAX_TEXTURES)); if (MaxTextureUnits < 2) { MultiTextureExtension = false; os::Printer::log("Warning: OpenGL device only has one texture unit. Disabling multitexturing.", ELL_WARNING); } #ifdef GL_ARB_occlusion_query if (FeatureAvailable[IRR_ARB_occlusion_query]) { extGlGetQueryiv(GL_SAMPLES_PASSED_ARB,GL_QUERY_COUNTER_BITS_ARB, &num); OcclusionQuerySupport=(num>0); } else #endif #ifdef GL_NV_occlusion_query if (FeatureAvailable[IRR_NV_occlusion_query]) { glGetIntegerv(GL_PIXEL_COUNTER_BITS_NV, &num); OcclusionQuerySupport=(num>0); } else #endif OcclusionQuerySupport=false; #ifdef _DEBUG if (FeatureAvailable[IRR_NVX_gpu_memory_info]) { // undocumented flags, so use the RAW values GLint val; glGetIntegerv(0x9047, &val); os::Printer::log("Dedicated video memory (kB)", core::stringc(val)); glGetIntegerv(0x9048, &val); os::Printer::log("Total video memory (kB)", core::stringc(val)); glGetIntegerv(0x9049, &val); os::Printer::log("Available video memory (kB)", core::stringc(val)); } #ifdef GL_ATI_meminfo if (FeatureAvailable[IRR_ATI_meminfo]) { GLint val[4]; glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, val); os::Printer::log("Free texture memory (kB)", core::stringc(val[0])); glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, val); os::Printer::log("Free VBO memory (kB)", core::stringc(val[0])); glGetIntegerv(GL_RENDERBUFFER_FREE_MEMORY_ATI, val); os::Printer::log("Free render buffer memory (kB)", core::stringc(val[0])); } #endif #endif } bool COpenGLExtensionHandler::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const { switch (feature) { case EVDF_RENDER_TO_TARGET: return true; case EVDF_HARDWARE_TL: return true; // we cannot tell other things case EVDF_MULTITEXTURE: return MultiTextureExtension; case EVDF_BILINEAR_FILTER: return true; case EVDF_MIP_MAP: return true; case EVDF_MIP_MAP_AUTO_UPDATE: return FeatureAvailable[IRR_SGIS_generate_mipmap] || FeatureAvailable[IRR_EXT_framebuffer_object] || FeatureAvailable[IRR_ARB_framebuffer_object]; case EVDF_STENCIL_BUFFER: return StencilBuffer; case EVDF_VERTEX_SHADER_1_1: case EVDF_ARB_VERTEX_PROGRAM_1: return FeatureAvailable[IRR_ARB_vertex_program] || FeatureAvailable[IRR_NV_vertex_program1_1]; case EVDF_PIXEL_SHADER_1_1: case EVDF_PIXEL_SHADER_1_2: case EVDF_ARB_FRAGMENT_PROGRAM_1: return FeatureAvailable[IRR_ARB_fragment_program] || FeatureAvailable[IRR_NV_fragment_program]; case EVDF_PIXEL_SHADER_2_0: case EVDF_VERTEX_SHADER_2_0: case EVDF_ARB_GLSL: return (FeatureAvailable[IRR_ARB_shading_language_100]||Version>=200); case EVDF_TEXTURE_NSQUARE: return true; // non-square is always supported case EVDF_TEXTURE_NPOT: // Some ATI cards seem to have only SW support in OpenGL 2.0 // drivers if the extension is not exposed, so we skip this // extra test for now! // return (FeatureAvailable[IRR_ARB_texture_non_power_of_two]||Version>=200); return (FeatureAvailable[IRR_ARB_texture_non_power_of_two]); case EVDF_FRAMEBUFFER_OBJECT: return FeatureAvailable[IRR_EXT_framebuffer_object] || FeatureAvailable[IRR_ARB_framebuffer_object]; case EVDF_VERTEX_BUFFER_OBJECT: return FeatureAvailable[IRR_ARB_vertex_buffer_object]; case EVDF_COLOR_MASK: return true; case EVDF_ALPHA_TO_COVERAGE: return FeatureAvailable[IRR_ARB_multisample]; case EVDF_GEOMETRY_SHADER: return FeatureAvailable[IRR_ARB_geometry_shader4] || FeatureAvailable[IRR_EXT_geometry_shader4] || FeatureAvailable[IRR_NV_geometry_program4] || FeatureAvailable[IRR_NV_geometry_shader4]; case EVDF_MULTIPLE_RENDER_TARGETS: return FeatureAvailable[IRR_ARB_draw_buffers] || FeatureAvailable[IRR_ATI_draw_buffers]; case EVDF_MRT_BLEND: case EVDF_MRT_COLOR_MASK: return FeatureAvailable[IRR_EXT_draw_buffers2]; case EVDF_MRT_BLEND_FUNC: return FeatureAvailable[IRR_ARB_draw_buffers_blend] || FeatureAvailable[IRR_AMD_draw_buffers_blend]; case EVDF_OCCLUSION_QUERY: return FeatureAvailable[IRR_ARB_occlusion_query] && OcclusionQuerySupport; case EVDF_POLYGON_OFFSET: // both features supported with OpenGL 1.1 return Version>=110; case EVDF_BLEND_OPERATIONS: return (Version>=120) || FeatureAvailable[IRR_EXT_blend_minmax] || FeatureAvailable[IRR_EXT_blend_subtract] || FeatureAvailable[IRR_EXT_blend_logic_op]; case EVDF_TEXTURE_MATRIX: #ifdef _IRR_COMPILE_WITH_CG_ // available iff. define is present case EVDF_CG: #endif return true; default: return false; }; } } } #endif irrlicht-1.8.3/source/Irrlicht/COpenGLDriver.h0000644000000000000000000005433412574354552017722 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h #ifndef __C_VIDEO_OPEN_GL_H_INCLUDED__ #define __C_VIDEO_OPEN_GL_H_INCLUDED__ #include "IrrCompileConfig.h" #include "SIrrCreationParameters.h" namespace irr { class CIrrDeviceWin32; class CIrrDeviceLinux; class CIrrDeviceSDL; class CIrrDeviceMacOSX; } #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "CNullDriver.h" #include "IMaterialRendererServices.h" // also includes the OpenGL stuff #include "COpenGLExtensionHandler.h" #ifdef _IRR_COMPILE_WITH_CG_ #include "Cg/cg.h" #endif namespace irr { namespace video { class COpenGLTexture; class COpenGLDriver : public CNullDriver, public IMaterialRendererServices, public COpenGLExtensionHandler { friend class COpenGLTexture; public: #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceWin32* device); //! inits the windows specific parts of the open gl driver bool initDriver(CIrrDeviceWin32* device); bool changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceWin32* device); #endif #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceLinux* device); //! inits the GLX specific parts of the open gl driver bool initDriver(CIrrDeviceLinux* device); bool changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceLinux* device); #endif #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceSDL* device); #endif #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceMacOSX *device); #endif //! generic version which overloads the unimplemented versions bool changeRenderContext(const SExposedVideoData& videoData, void* device) {return false;} //! destructor virtual ~COpenGLDriver(); //! clears the zbuffer virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! presents the rendered scene on the screen, returns false if failed virtual bool endScene(); //! sets transformation virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat); struct SHWBufferLink_opengl : public SHWBufferLink { SHWBufferLink_opengl(const scene::IMeshBuffer *_MeshBuffer): SHWBufferLink(_MeshBuffer), vbo_verticesID(0),vbo_indicesID(0){} GLuint vbo_verticesID; //tmp GLuint vbo_indicesID; //tmp GLuint vbo_verticesSize; //tmp GLuint vbo_indicesSize; //tmp }; //! updates hardware buffer if needed virtual bool updateHardwareBuffer(SHWBufferLink *HWBuffer); //! Create hardware buffer from mesh virtual SHWBufferLink *createHardwareBuffer(const scene::IMeshBuffer* mb); //! Delete hardware buffer (only some drivers can) virtual void deleteHardwareBuffer(SHWBufferLink *HWBuffer); //! Draw hardware buffer virtual void drawHardwareBuffer(SHWBufferLink *HWBuffer); //! Create occlusion query. /** Use node for identification and mesh for occlusion test. */ virtual void addOcclusionQuery(scene::ISceneNode* node, const scene::IMesh* mesh=0); //! Remove occlusion query. virtual void removeOcclusionQuery(scene::ISceneNode* node); //! Run occlusion query. Draws mesh stored in query. /** If the mesh shall not be rendered visible, use overrideMaterial to disable the color and depth buffer. */ virtual void runOcclusionQuery(scene::ISceneNode* node, bool visible=false); //! Update occlusion query. Retrieves results from GPU. /** If the query shall not block, set the flag to false. Update might not occur in this case, though */ virtual void updateOcclusionQuery(scene::ISceneNode* node, bool block=true); //! Return query result. /** Return value is the number of visible pixels/fragments. The value is a safe approximation, i.e. can be larger then the actual value of pixels. */ virtual u32 getOcclusionQueryResult(scene::ISceneNode* node) const; //! draws a vertex primitive list virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); //! draws a vertex primitive list in 2d virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); //! queries the features of the driver, returns true if feature is available virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const { return FeatureEnabled[feature] && COpenGLExtensionHandler::queryFeature(feature); } //! Sets a material. All 3d drawing functions draw geometry now //! using this material. //! \param material: Material to be used from now on. virtual void setMaterial(const SMaterial& material); //! draws a set of 2d images, using a color and the alpha channel of the //! texture if desired. void draw2DImageBatch(const video::ITexture* texture, const core::array >& positions, const core::array >& sourceRects, const core::rect* clipRect, SColor color, bool useAlphaChannelOfTexture); //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect = 0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false); //! draws a set of 2d images, using a color and the alpha /** channel of the texture if desired. The images are drawn beginning at pos and concatenated in one line. All drawings are clipped against clipRect (if != 0). The subtextures are defined by the array of sourceRects and are chosen by the indices given. \param texture: Texture to be drawn. \param pos: Upper left 2d destination position where the image will be drawn. \param sourceRects: Source rectangles of the image. \param indices: List of indices which choose the actual rectangle used each time. \param clipRect: Pointer to rectangle on the screen where the image is clipped to. This pointer can be 0. Then the image is not clipped. \param color: Color with which the image is colored. Note that the alpha component is used: If alpha is other than 255, the image will be transparent. \param useAlphaChannelOfTexture: If true, the alpha channel of the texture is used to draw the image. */ virtual void draw2DImage(const video::ITexture* texture, const core::position2d& pos, const core::array >& sourceRects, const core::array& indices, const core::rect* clipRect=0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false); //! Draws a part of the texture into the rectangle. virtual void draw2DImage(const video::ITexture* texture, const core::rect& destRect, const core::rect& sourceRect, const core::rect* clipRect = 0, const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false); //! draw an 2d rectangle virtual void draw2DRectangle(SColor color, const core::rect& pos, const core::rect* clip = 0); //!Draws an 2d rectangle with a gradient. virtual void draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip = 0); //! Draws a 2d line. virtual void draw2DLine(const core::position2d& start, const core::position2d& end, SColor color=SColor(255,255,255,255)); //! Draws a single pixel virtual void drawPixel(u32 x, u32 y, const SColor & color); //! Draws a 3d line. virtual void draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color = SColor(255,255,255,255)); //! \return Returns the name of the video driver. Example: In case of the Direct3D8 //! driver, it would return "Direct3D8.1". virtual const wchar_t* getName() const; //! deletes all dynamic lights there are virtual void deleteAllDynamicLights(); //! adds a dynamic light, returning an index to the light //! \param light: the light data to use to create the light //! \return An index to the light, or -1 if an error occurs virtual s32 addDynamicLight(const SLight& light); //! Turns a dynamic light on or off //! \param lightIndex: the index returned by addDynamicLight //! \param turnOn: true to turn the light on, false to turn it off virtual void turnLightOn(s32 lightIndex, bool turnOn); //! returns the maximal amount of dynamic lights the device can handle virtual u32 getMaximalDynamicLightAmount() const; //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. virtual void setAmbientLight(const SColorf& color); //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do //! this: First, draw all geometry. Then use this method, to draw the shadow //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. virtual void drawStencilShadowVolume(const core::array& triangles, bool zfail, u32 debugDataVisible=0); //! Fills the stencil shadow with color. After the shadow volume has been drawn //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this //! to draw the color of the shadow. virtual void drawStencilShadow(bool clearStencilBuffer=false, video::SColor leftUpEdge = video::SColor(0,0,0,0), video::SColor rightUpEdge = video::SColor(0,0,0,0), video::SColor leftDownEdge = video::SColor(0,0,0,0), video::SColor rightDownEdge = video::SColor(0,0,0,0)); //! sets a viewport virtual void setViewPort(const core::rect& area); //! Sets the fog mode. virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog); //! Only used by the internal engine. Used to notify the driver that //! the window was resized. virtual void OnResize(const core::dimension2d& size); //! Returns type of video driver virtual E_DRIVER_TYPE getDriverType() const; //! get color format of the current color buffer virtual ECOLOR_FORMAT getColorFormat() const; //! Returns the transformation set by setTransform virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const; //! Can be called by an IMaterialRenderer to make its work easier. virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderstates); //! Sets a vertex shader constant. virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1); //! Sets a pixel shader constant. virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1); //! Sets a constant for the vertex shader based on a name. virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count); //! Bool interface for the above. virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count); //! Int interface for the above. virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count); //! Sets a constant for the pixel shader based on a name. virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count); //! Bool interface for the above. virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count); //! Int interface for the above. virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count); //! sets the current Texture //! Returns whether setting was a success or not. bool setActiveTexture(u32 stage, const video::ITexture* texture); //! disables all textures beginning with the optional fromStage parameter. Otherwise all texture stages are disabled. //! Returns whether disabling was successful or not. bool disableTextures(u32 fromStage=0); //! Adds a new material renderer to the VideoDriver, using //! extGLGetObjectParameteriv(shaderHandle, GL_OBJECT_COMPILE_STATUS_ARB, &status) //! pixel and/or vertex shaders to render geometry. virtual s32 addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData); //! Adds a new material renderer to the VideoDriver, using GLSL to render geometry. virtual s32 addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, const c8* geometryShaderProgram, const c8* geometryShaderEntryPointName = "main", E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0, E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT); //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) virtual IVideoDriver* getVideoDriver(); //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. virtual u32 getMaximalPrimitiveCount() const; virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! set or reset render target virtual bool setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget, bool clearZBuffer, SColor color); //! set or reset render target texture virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color); //! Sets multiple render targets virtual bool setRenderTarget(const core::array& texture, bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=SColor(0,0,0,0)); //! Clears the ZBuffer. virtual void clearZBuffer(); //! Returns an image created from the last rendered frame. virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER); //! checks if an OpenGL error has happend and prints it //! for performance reasons only available in debug mode bool testGLError(); //! Set/unset a clipping plane. //! There are at least 6 clipping planes available for the user to set at will. //! \param index: The plane index. Must be between 0 and MaxUserClipPlanes. //! \param plane: The plane itself. //! \param enable: If true, enable the clipping plane else disable it. virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false); //! Enable/disable a clipping plane. //! There are at least 6 clipping planes available for the user to set at will. //! \param index: The plane index. Must be between 0 and MaxUserClipPlanes. //! \param enable: If true, enable the clipping plane else disable it. virtual void enableClipPlane(u32 index, bool enable); //! Enable the 2d override material virtual void enableMaterial2D(bool enable=true); //! Returns the graphics card vendor name. virtual core::stringc getVendorInfo() {return VendorName;} //! Returns the maximum texture size supported. virtual core::dimension2du getMaxTextureSize() const; ITexture* createDepthTexture(ITexture* texture, bool shared=true); void removeDepthTexture(ITexture* texture); //! Removes a texture from the texture cache and deletes it, freeing lot of memory. void removeTexture(ITexture* texture); //! Convert E_PRIMITIVE_TYPE to OpenGL equivalent GLenum primitiveTypeToGL(scene::E_PRIMITIVE_TYPE type) const; //! Convert E_BLEND_FACTOR to OpenGL equivalent GLenum getGLBlend(E_BLEND_FACTOR factor) const; //! Get ZBuffer bits. GLenum getZBufferBits() const; //! Get Cg context #ifdef _IRR_COMPILE_WITH_CG_ const CGcontext& getCgContext(); #endif private: //! clears the zbuffer and color buffer void clearBuffers(bool backBuffer, bool zBuffer, bool stencilBuffer, SColor color); bool updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer); bool updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer); void uploadClipPlane(u32 index); //! inits the parts of the open gl driver used on all platforms bool genericDriverInit(); //! returns a device dependent texture from a software surface (IImage) virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData); //! creates a transposed matrix in supplied GLfloat array to pass to OpenGL inline void getGLMatrix(GLfloat gl_matrix[16], const core::matrix4& m); inline void getGLTextureMatrix(GLfloat gl_matrix[16], const core::matrix4& m); //! Set GL pipeline to desired texture wrap modes of the material void setWrapMode(const SMaterial& material); //! get native wrap mode value GLint getTextureWrapMode(const u8 clamp); //! sets the needed renderstates void setRenderStates3DMode(); //! sets the needed renderstates void setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel); // returns the current size of the screen or rendertarget virtual const core::dimension2d& getCurrentRenderTargetSize() const; void createMaterialRenderers(); //! Assign a hardware light to the specified requested light, if any //! free hardware lights exist. //! \param[in] lightIndex: the index of the requesting light void assignHardwareLight(u32 lightIndex); //! helper function for render setup. void getColorBuffer(const void* vertices, u32 vertexCount, E_VERTEX_TYPE vType); //! helper function doing the actual rendering. void renderArray(const void* indexList, u32 primitiveCount, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); core::stringw Name; core::matrix4 Matrices[ETS_COUNT]; core::array ColorBuffer; //! enumeration for rendering modes such as 2d and 3d for minizing the switching of renderStates. enum E_RENDER_MODE { ERM_NONE = 0, // no render state has been set yet. ERM_2D, // 2d drawing rendermode ERM_3D // 3d rendering mode }; E_RENDER_MODE CurrentRenderMode; //! bool to make all renderstates reset if set to true. bool ResetRenderStates; bool Transformation3DChanged; u8 AntiAlias; SMaterial Material, LastMaterial; COpenGLTexture* RenderTargetTexture; core::array MRTargets; class STextureStageCache { const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES]; public: STextureStageCache() { for (u32 i=0; igrab(); CurrentTexture[stage]=tex; if (oldTexture) oldTexture->drop(); } } const ITexture* operator[](int stage) const { if ((u32)stage= 0; --i) { if (CurrentTexture[i] == tex) { tex->drop(); CurrentTexture[i] = 0; } } } void clear() { // Drop all the CurrentTexture handles for (u32 i=0; idrop(); CurrentTexture[i] = 0; } } } }; STextureStageCache CurrentTexture; core::array DepthTextures; struct SUserClipPlane { SUserClipPlane() : Enabled(false) {} core::plane3df Plane; bool Enabled; }; core::array UserClipPlanes; core::dimension2d CurrentRendertargetSize; core::stringc VendorName; core::matrix4 TextureFlipMatrix; //! Color buffer format ECOLOR_FORMAT ColorFormat; //! Render target type for render operations E_RENDER_TARGET CurrentTarget; SIrrlichtCreationParameters Params; //! All the lights that have been requested; a hardware limited //! number of them will be used at once. struct RequestedLight { RequestedLight(SLight const & lightData) : LightData(lightData), HardwareLightIndex(-1), DesireToBeOn(true) { } SLight LightData; s32 HardwareLightIndex; // GL_LIGHT0 - GL_LIGHT7 bool DesireToBeOn; }; core::array RequestedLights; #ifdef _IRR_WINDOWS_API_ HDC HDc; // Private GDI Device Context HWND Window; #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ CIrrDeviceWin32 *Win32Device; #endif #endif #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ GLXDrawable Drawable; Display* X11Display; CIrrDeviceLinux *X11Device; #endif #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ CIrrDeviceMacOSX *OSXDevice; #endif #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ CIrrDeviceSDL *SDLDevice; #endif #ifdef _IRR_COMPILE_WITH_CG_ CGcontext CgContext; #endif E_DEVICE_TYPE DeviceType; }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_OPENGL_ #endif irrlicht-1.8.3/source/Irrlicht/COpenGLDriver.cpp0000644000000000000000000043047112574354552020255 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "COpenGLDriver.h" // needed here also because of the create methods' parameters #include "CNullDriver.h" #ifdef _IRR_COMPILE_WITH_OPENGL_ #include "COpenGLTexture.h" #include "COpenGLMaterialRenderer.h" #include "COpenGLShaderMaterialRenderer.h" #include "COpenGLSLMaterialRenderer.h" #include "COpenGLCgMaterialRenderer.h" #include "COpenGLNormalMapRenderer.h" #include "COpenGLParallaxMapRenderer.h" #include "os.h" #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ #include "MacOSX/CIrrDeviceMacOSX.h" #endif #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ #include #endif namespace irr { namespace video { // ----------------------------------------------------------------------- // WINDOWS CONSTRUCTOR // ----------------------------------------------------------------------- #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ //! Windows constructor and init code COpenGLDriver::COpenGLDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceWin32* device) : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), AntiAlias(params.AntiAlias), RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), CurrentTarget(ERT_FRAME_BUFFER), Params(params), HDc(0), Window(static_cast(params.WindowId)), Win32Device(device), DeviceType(EIDT_WIN32) { #ifdef _DEBUG setDebugName("COpenGLDriver"); #endif #ifdef _IRR_COMPILE_WITH_CG_ CgContext = 0; #endif } bool COpenGLDriver::changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceWin32* device) { if (videoData.OpenGLWin32.HWnd && videoData.OpenGLWin32.HDc && videoData.OpenGLWin32.HRc) { if (!wglMakeCurrent((HDC)videoData.OpenGLWin32.HDc, (HGLRC)videoData.OpenGLWin32.HRc)) { os::Printer::log("Render Context switch failed."); return false; } else { HDc = (HDC)videoData.OpenGLWin32.HDc; } } // set back to main context else if (HDc != ExposedData.OpenGLWin32.HDc) { if (!wglMakeCurrent((HDC)ExposedData.OpenGLWin32.HDc, (HGLRC)ExposedData.OpenGLWin32.HRc)) { os::Printer::log("Render Context switch failed."); return false; } else { HDc = (HDC)ExposedData.OpenGLWin32.HDc; } } return true; } //! inits the open gl driver bool COpenGLDriver::initDriver(CIrrDeviceWin32* device) { // Create a window to test antialiasing support const fschar_t* ClassName = __TEXT("GLCIrrDeviceWin32"); HINSTANCE lhInstance = GetModuleHandle(0); // Register Class WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)DefWindowProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = lhInstance; wcex.hIcon = NULL; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = 0; wcex.lpszClassName = ClassName; wcex.hIconSm = 0; wcex.hIcon = 0; RegisterClassEx(&wcex); RECT clientSize; clientSize.top = 0; clientSize.left = 0; clientSize.right = Params.WindowSize.Width; clientSize.bottom = Params.WindowSize.Height; DWORD style = WS_POPUP; if (!Params.Fullscreen) style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; AdjustWindowRect(&clientSize, style, FALSE); const s32 realWidth = clientSize.right - clientSize.left; const s32 realHeight = clientSize.bottom - clientSize.top; const s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2; const s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2; HWND temporary_wnd=CreateWindow(ClassName, __TEXT(""), style, windowLeft, windowTop, realWidth, realHeight, NULL, NULL, lhInstance, NULL); if (!temporary_wnd) { os::Printer::log("Cannot create a temporary window.", ELL_ERROR); UnregisterClass(ClassName, lhInstance); return false; } HDc = GetDC(temporary_wnd); // Set up pixel format descriptor with desired parameters PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL (Params.Doublebuffer?PFD_DOUBLEBUFFER:0) | // Must Support Double Buffering (Params.Stereobuffer?PFD_STEREO:0), // Must Support Stereo Buffer PFD_TYPE_RGBA, // Request An RGBA Format Params.Bits, // Select Our Color Depth 0, 0, 0, 0, 0, 0, // Color Bits Ignored 0, // No Alpha Buffer 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored Params.ZBufferBits, // Z-Buffer (Depth Buffer) BYTE(Params.Stencilbuffer ? 1 : 0), // Stencil Buffer Depth 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 0, 0 // Layer Masks Ignored }; GLuint PixelFormat; for (u32 i=0; i<6; ++i) { if (i == 1) { if (Params.Stencilbuffer) { os::Printer::log("Cannot create a GL device with stencil buffer, disabling stencil shadows.", ELL_WARNING); Params.Stencilbuffer = false; pfd.cStencilBits = 0; } else continue; } else if (i == 2) { pfd.cDepthBits = 24; } else if (i == 3) { if (Params.Bits!=16) pfd.cDepthBits = 16; else continue; } else if (i == 4) { // try single buffer if (Params.Doublebuffer) pfd.dwFlags &= ~PFD_DOUBLEBUFFER; else continue; } else if (i == 5) { os::Printer::log("Cannot create a GL device context", "No suitable format for temporary window.", ELL_ERROR); ReleaseDC(temporary_wnd, HDc); DestroyWindow(temporary_wnd); UnregisterClass(ClassName, lhInstance); return false; } // choose pixelformat PixelFormat = ChoosePixelFormat(HDc, &pfd); if (PixelFormat) break; } SetPixelFormat(HDc, PixelFormat, &pfd); HGLRC hrc=wglCreateContext(HDc); if (!hrc) { os::Printer::log("Cannot create a temporary GL rendering context.", ELL_ERROR); ReleaseDC(temporary_wnd, HDc); DestroyWindow(temporary_wnd); UnregisterClass(ClassName, lhInstance); return false; } SExposedVideoData data; data.OpenGLWin32.HDc = HDc; data.OpenGLWin32.HRc = hrc; data.OpenGLWin32.HWnd = temporary_wnd; if (!changeRenderContext(data, device)) { os::Printer::log("Cannot activate a temporary GL rendering context.", ELL_ERROR); wglDeleteContext(hrc); ReleaseDC(temporary_wnd, HDc); DestroyWindow(temporary_wnd); UnregisterClass(ClassName, lhInstance); return false; } core::stringc wglExtensions; #ifdef WGL_ARB_extensions_string PFNWGLGETEXTENSIONSSTRINGARBPROC irrGetExtensionsString = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); if (irrGetExtensionsString) wglExtensions = irrGetExtensionsString(HDc); #elif defined(WGL_EXT_extensions_string) PFNWGLGETEXTENSIONSSTRINGEXTPROC irrGetExtensionsString = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT"); if (irrGetExtensionsString) wglExtensions = irrGetExtensionsString(HDc); #endif const bool pixel_format_supported = (wglExtensions.find("WGL_ARB_pixel_format") != -1); const bool multi_sample_supported = ((wglExtensions.find("WGL_ARB_multisample") != -1) || (wglExtensions.find("WGL_EXT_multisample") != -1) || (wglExtensions.find("WGL_3DFX_multisample") != -1) ); #ifdef _DEBUG os::Printer::log("WGL_extensions", wglExtensions); #endif #ifdef WGL_ARB_pixel_format PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat_ARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); if (pixel_format_supported && wglChoosePixelFormat_ARB) { // This value determines the number of samples used for antialiasing // My experience is that 8 does not show a big // improvement over 4, but 4 shows a big improvement // over 2. if(AntiAlias > 32) AntiAlias = 32; f32 fAttributes[] = {0.0, 0.0}; s32 iAttributes[] = { WGL_DRAW_TO_WINDOW_ARB,1, WGL_SUPPORT_OPENGL_ARB,1, WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, WGL_COLOR_BITS_ARB,(Params.Bits==32) ? 24 : 15, WGL_ALPHA_BITS_ARB,(Params.Bits==32) ? 8 : 1, WGL_DEPTH_BITS_ARB,Params.ZBufferBits, // 10,11 WGL_STENCIL_BITS_ARB,Params.Stencilbuffer ? 1 : 0, WGL_DOUBLE_BUFFER_ARB,Params.Doublebuffer ? 1 : 0, WGL_STEREO_ARB,Params.Stereobuffer ? 1 : 0, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, #ifdef WGL_ARB_multisample WGL_SAMPLES_ARB,AntiAlias, // 20,21 WGL_SAMPLE_BUFFERS_ARB, 1, #elif defined(WGL_EXT_multisample) WGL_SAMPLES_EXT,AntiAlias, // 20,21 WGL_SAMPLE_BUFFERS_EXT, 1, #elif defined(WGL_3DFX_multisample) WGL_SAMPLES_3DFX,AntiAlias, // 20,21 WGL_SAMPLE_BUFFERS_3DFX, 1, #endif #ifdef WGL_ARB_framebuffer_sRGB WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, Params.HandleSRGB ? 1:0, #elif defined(WGL_EXT_framebuffer_sRGB) WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT, Params.HandleSRGB ? 1:0, #endif // WGL_DEPTH_FLOAT_EXT, 1, 0,0,0,0 }; int iAttrSize = sizeof(iAttributes)/sizeof(int); const bool framebuffer_srgb_supported = ((wglExtensions.find("WGL_ARB_framebuffer_sRGB") != -1) || (wglExtensions.find("WGL_EXT_framebuffer_sRGB") != -1)); if (!framebuffer_srgb_supported) { memmove(&iAttributes[24],&iAttributes[26],sizeof(int)*(iAttrSize-26)); iAttrSize -= 2; } if (!multi_sample_supported) { memmove(&iAttributes[20],&iAttributes[24],sizeof(int)*(iAttrSize-24)); iAttrSize -= 4; } s32 rv=0; // Try to get an acceptable pixel format do { int pixelFormat=0; UINT numFormats=0; const BOOL valid = wglChoosePixelFormat_ARB(HDc,iAttributes,fAttributes,1,&pixelFormat,&numFormats); if (valid && numFormats) rv = pixelFormat; else iAttributes[21] -= 1; } while(rv==0 && iAttributes[21]>1); if (rv) { PixelFormat=rv; AntiAlias=iAttributes[21]; } } else #endif AntiAlias=0; wglMakeCurrent(HDc, NULL); wglDeleteContext(hrc); ReleaseDC(temporary_wnd, HDc); DestroyWindow(temporary_wnd); UnregisterClass(ClassName, lhInstance); // get hdc HDc=GetDC(Window); if (!HDc) { os::Printer::log("Cannot create a GL device context.", ELL_ERROR); return false; } // search for pixel format the simple way if (PixelFormat==0 || (!SetPixelFormat(HDc, PixelFormat, &pfd))) { for (u32 i=0; i<5; ++i) { if (i == 1) { if (Params.Stencilbuffer) { os::Printer::log("Cannot create a GL device with stencil buffer, disabling stencil shadows.", ELL_WARNING); Params.Stencilbuffer = false; pfd.cStencilBits = 0; } else continue; } else if (i == 2) { pfd.cDepthBits = 24; } if (i == 3) { if (Params.Bits!=16) pfd.cDepthBits = 16; else continue; } else if (i == 4) { os::Printer::log("Cannot create a GL device context", "No suitable format.", ELL_ERROR); return false; } // choose pixelformat PixelFormat = ChoosePixelFormat(HDc, &pfd); if (PixelFormat) break; } // set pixel format if (!SetPixelFormat(HDc, PixelFormat, &pfd)) { os::Printer::log("Cannot set the pixel format.", ELL_ERROR); return false; } } os::Printer::log("Pixel Format", core::stringc(PixelFormat).c_str(), ELL_DEBUG); // create rendering context #ifdef WGL_ARB_create_context PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs_ARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); if (wglCreateContextAttribs_ARB) { int iAttribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 1, 0 }; hrc=wglCreateContextAttribs_ARB(HDc, 0, iAttribs); } else #endif hrc=wglCreateContext(HDc); if (!hrc) { os::Printer::log("Cannot create a GL rendering context.", ELL_ERROR); return false; } // set exposed data ExposedData.OpenGLWin32.HDc = HDc; ExposedData.OpenGLWin32.HRc = hrc; ExposedData.OpenGLWin32.HWnd = Window; // activate rendering context if (!changeRenderContext(ExposedData, device)) { os::Printer::log("Cannot activate GL rendering context", ELL_ERROR); wglDeleteContext(hrc); return false; } int pf = GetPixelFormat(HDc); DescribePixelFormat(HDc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd); if (pfd.cAlphaBits != 0) { if (pfd.cRedBits == 8) ColorFormat = ECF_A8R8G8B8; else ColorFormat = ECF_A1R5G5B5; } else { if (pfd.cRedBits == 8) ColorFormat = ECF_R8G8B8; else ColorFormat = ECF_R5G6B5; } genericDriverInit(); extGlSwapInterval(Params.Vsync ? 1 : 0); return true; } #endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ // ----------------------------------------------------------------------- // MacOSX CONSTRUCTOR // ----------------------------------------------------------------------- #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ //! Windows constructor and init code COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceMacOSX *device) : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), AntiAlias(params.AntiAlias), RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), CurrentTarget(ERT_FRAME_BUFFER), Params(params), OSXDevice(device), DeviceType(EIDT_OSX) { #ifdef _DEBUG setDebugName("COpenGLDriver"); #endif #ifdef _IRR_COMPILE_WITH_CG_ CgContext = 0; #endif genericDriverInit(); } #endif // ----------------------------------------------------------------------- // LINUX CONSTRUCTOR // ----------------------------------------------------------------------- #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ //! Linux constructor and init code COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceLinux* device) : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), AntiAlias(params.AntiAlias), RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), CurrentTarget(ERT_FRAME_BUFFER), Params(params), X11Device(device), DeviceType(EIDT_X11) { #ifdef _DEBUG setDebugName("COpenGLDriver"); #endif #ifdef _IRR_COMPILE_WITH_CG_ CgContext = 0; #endif } bool COpenGLDriver::changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceLinux* device) { if (videoData.OpenGLLinux.X11Window) { if (videoData.OpenGLLinux.X11Display && videoData.OpenGLLinux.X11Context) { if (!glXMakeCurrent((Display*)videoData.OpenGLLinux.X11Display, videoData.OpenGLLinux.X11Window, (GLXContext)videoData.OpenGLLinux.X11Context)) { os::Printer::log("Render Context switch failed."); return false; } else { Drawable = videoData.OpenGLLinux.X11Window; X11Display = (Display*)videoData.OpenGLLinux.X11Display; } } else { // in case we only got a window ID, try with the existing values for display and context if (!glXMakeCurrent((Display*)ExposedData.OpenGLLinux.X11Display, videoData.OpenGLLinux.X11Window, (GLXContext)ExposedData.OpenGLLinux.X11Context)) { os::Printer::log("Render Context switch failed."); return false; } else { Drawable = videoData.OpenGLLinux.X11Window; X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; } } } // set back to main context else if (X11Display != ExposedData.OpenGLLinux.X11Display) { if (!glXMakeCurrent((Display*)ExposedData.OpenGLLinux.X11Display, ExposedData.OpenGLLinux.X11Window, (GLXContext)ExposedData.OpenGLLinux.X11Context)) { os::Printer::log("Render Context switch failed."); return false; } else { Drawable = ExposedData.OpenGLLinux.X11Window; X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; } } return true; } //! inits the open gl driver bool COpenGLDriver::initDriver(CIrrDeviceLinux* device) { ExposedData.OpenGLLinux.X11Context = glXGetCurrentContext(); ExposedData.OpenGLLinux.X11Display = glXGetCurrentDisplay(); ExposedData.OpenGLLinux.X11Window = (unsigned long)Params.WindowId; Drawable = glXGetCurrentDrawable(); X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; genericDriverInit(); // set vsync extGlSwapInterval(Params.Vsync ? 1 : 0); return true; } #endif // _IRR_COMPILE_WITH_X11_DEVICE_ // ----------------------------------------------------------------------- // SDL CONSTRUCTOR // ----------------------------------------------------------------------- #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ //! SDL constructor and init code COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceSDL* device) : CNullDriver(io, params.WindowSize), COpenGLExtensionHandler(), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), AntiAlias(params.AntiAlias), RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), CurrentTarget(ERT_FRAME_BUFFER), Params(params), SDLDevice(device), DeviceType(EIDT_SDL) { #ifdef _DEBUG setDebugName("COpenGLDriver"); #endif #ifdef _IRR_COMPILE_WITH_CG_ CgContext = 0; #endif genericDriverInit(); } #endif // _IRR_COMPILE_WITH_SDL_DEVICE_ //! destructor COpenGLDriver::~COpenGLDriver() { #ifdef _IRR_COMPILE_WITH_CG_ if (CgContext) cgDestroyContext(CgContext); #endif RequestedLights.clear(); deleteMaterialRenders(); CurrentTexture.clear(); // I get a blue screen on my laptop, when I do not delete the // textures manually before releasing the dc. Oh how I love this. deleteAllTextures(); removeAllOcclusionQueries(); removeAllHardwareBuffers(); #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ if (DeviceType == EIDT_WIN32) { if (ExposedData.OpenGLWin32.HRc) { if (!wglMakeCurrent(HDc, 0)) os::Printer::log("Release of dc and rc failed.", ELL_WARNING); if (!wglDeleteContext((HGLRC)ExposedData.OpenGLWin32.HRc)) os::Printer::log("Release of rendering context failed.", ELL_WARNING); } if (HDc) ReleaseDC(Window, HDc); } #endif } // ----------------------------------------------------------------------- // METHODS // ----------------------------------------------------------------------- bool COpenGLDriver::genericDriverInit() { Name=L"OpenGL "; Name.append(glGetString(GL_VERSION)); s32 pos=Name.findNext(L' ', 7); if (pos != -1) Name=Name.subString(0, pos); printVersion(); // print renderer information const GLubyte* renderer = glGetString(GL_RENDERER); const GLubyte* vendor = glGetString(GL_VENDOR); if (renderer && vendor) { os::Printer::log(reinterpret_cast(renderer), reinterpret_cast(vendor), ELL_INFORMATION); VendorName = reinterpret_cast(vendor); } u32 i; CurrentTexture.clear(); // load extensions initExtensions(Params.Stencilbuffer); if (queryFeature(EVDF_ARB_GLSL)) { char buf[32]; const u32 maj = ShaderLanguageVersion/100; snprintf(buf, 32, "%u.%u", maj, ShaderLanguageVersion-maj*100); os::Printer::log("GLSL version", buf, ELL_INFORMATION); } else os::Printer::log("GLSL not available.", ELL_INFORMATION); DriverAttributes->setAttribute("MaxTextures", MaxTextureUnits); DriverAttributes->setAttribute("MaxSupportedTextures", MaxSupportedTextures); DriverAttributes->setAttribute("MaxLights", MaxLights); DriverAttributes->setAttribute("MaxAnisotropy", MaxAnisotropy); DriverAttributes->setAttribute("MaxUserClipPlanes", MaxUserClipPlanes); DriverAttributes->setAttribute("MaxAuxBuffers", MaxAuxBuffers); DriverAttributes->setAttribute("MaxMultipleRenderTargets", MaxMultipleRenderTargets); DriverAttributes->setAttribute("MaxIndices", (s32)MaxIndices); DriverAttributes->setAttribute("MaxTextureSize", (s32)MaxTextureSize); DriverAttributes->setAttribute("MaxGeometryVerticesOut", (s32)MaxGeometryVerticesOut); DriverAttributes->setAttribute("MaxTextureLODBias", MaxTextureLODBias); DriverAttributes->setAttribute("Version", Version); DriverAttributes->setAttribute("ShaderLanguageVersion", ShaderLanguageVersion); DriverAttributes->setAttribute("AntiAlias", AntiAlias); glPixelStorei(GL_PACK_ALIGNMENT, 1); // Reset The Current Viewport glViewport(0, 0, Params.WindowSize.Width, Params.WindowSize.Height); UserClipPlanes.reallocate(MaxUserClipPlanes); for (i=0; i(i), core::IdentityMatrix); setAmbientLight(SColorf(0.0f,0.0f,0.0f,0.0f)); #ifdef GL_EXT_separate_specular_color if (FeatureAvailable[IRR_EXT_separate_specular_color]) glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); #endif glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); Params.HandleSRGB &= ((FeatureAvailable[IRR_ARB_framebuffer_sRGB] || FeatureAvailable[IRR_EXT_framebuffer_sRGB]) && FeatureAvailable[IRR_EXT_texture_sRGB]); #if defined(GL_ARB_framebuffer_sRGB) if (Params.HandleSRGB) glEnable(GL_FRAMEBUFFER_SRGB); #elif defined(GL_EXT_framebuffer_sRGB) if (Params.HandleSRGB) glEnable(GL_FRAMEBUFFER_SRGB_EXT); #endif // This is a fast replacement for NORMALIZE_NORMALS // if ((Version>101) || FeatureAvailable[IRR_EXT_rescale_normal]) // glEnable(GL_RESCALE_NORMAL_EXT); glClearDepth(1.0); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST); glDepthFunc(GL_LEQUAL); glFrontFace(GL_CW); // adjust flat coloring scheme to DirectX version #if defined(GL_ARB_provoking_vertex) || defined(GL_EXT_provoking_vertex) extGlProvokingVertex(GL_FIRST_VERTEX_CONVENTION_EXT); #endif // create material renderers createMaterialRenderers(); // set the renderstates setRenderStates3DMode(); glAlphaFunc(GL_GREATER, 0.f); // set fog mode setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); // create matrix for flipping textures TextureFlipMatrix.buildTextureTransform(0.0f, core::vector2df(0,0), core::vector2df(0,1.0f), core::vector2df(1.0f,-1.0f)); // We need to reset once more at the beginning of the first rendering. // This fixes problems with intermediate changes to the material during texture load. ResetRenderStates = true; #ifdef _IRR_COMPILE_WITH_CG_ CgContext = cgCreateContext(); #endif return true; } void COpenGLDriver::createMaterialRenderers() { // create OpenGL material renderers addAndDropMaterialRenderer(new COpenGLMaterialRenderer_SOLID(this)); addAndDropMaterialRenderer(new COpenGLMaterialRenderer_SOLID_2_LAYER(this)); // add the same renderer for all lightmap types COpenGLMaterialRenderer_LIGHTMAP* lmr = new COpenGLMaterialRenderer_LIGHTMAP(this); addMaterialRenderer(lmr); // for EMT_LIGHTMAP: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_ADD: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M2: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M4: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M2: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M4: lmr->drop(); // add remaining material renderer addAndDropMaterialRenderer(new COpenGLMaterialRenderer_DETAIL_MAP(this)); addAndDropMaterialRenderer(new COpenGLMaterialRenderer_SPHERE_MAP(this)); addAndDropMaterialRenderer(new COpenGLMaterialRenderer_REFLECTION_2_LAYER(this)); addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_ADD_COLOR(this)); addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(this)); addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(this)); addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_VERTEX_ALPHA(this)); addAndDropMaterialRenderer(new COpenGLMaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(this)); // add normal map renderers s32 tmp = 0; video::IMaterialRenderer* renderer = 0; renderer = new COpenGLNormalMapRenderer(this, tmp, MaterialRenderers[EMT_SOLID].Renderer); renderer->drop(); renderer = new COpenGLNormalMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer); renderer->drop(); renderer = new COpenGLNormalMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); renderer->drop(); // add parallax map renderers renderer = new COpenGLParallaxMapRenderer(this, tmp, MaterialRenderers[EMT_SOLID].Renderer); renderer->drop(); renderer = new COpenGLParallaxMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer); renderer->drop(); renderer = new COpenGLParallaxMapRenderer(this, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); renderer->drop(); // add basic 1 texture blending addAndDropMaterialRenderer(new COpenGLMaterialRenderer_ONETEXTURE_BLEND(this)); } //! presents the rendered scene on the screen, returns false if failed bool COpenGLDriver::endScene() { CNullDriver::endScene(); glFlush(); #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ if (DeviceType == EIDT_WIN32) return SwapBuffers(HDc) == TRUE; #endif #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ if (DeviceType == EIDT_X11) { glXSwapBuffers(X11Display, Drawable); return true; } #endif #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ if (DeviceType == EIDT_OSX) { OSXDevice->flush(); return true; } #endif #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ if (DeviceType == EIDT_SDL) { SDL_GL_SwapBuffers(); return true; } #endif // todo: console device present return false; } //! clears the zbuffer and color buffer void COpenGLDriver::clearBuffers(bool backBuffer, bool zBuffer, bool stencilBuffer, SColor color) { GLbitfield mask = 0; if (backBuffer) { const f32 inv = 1.0f / 255.0f; glClearColor(color.getRed() * inv, color.getGreen() * inv, color.getBlue() * inv, color.getAlpha() * inv); mask |= GL_COLOR_BUFFER_BIT; } if (zBuffer) { glDepthMask(GL_TRUE); LastMaterial.ZWriteEnable=true; mask |= GL_DEPTH_BUFFER_BIT; } if (stencilBuffer) mask |= GL_STENCIL_BUFFER_BIT; if (mask) glClear(mask); } //! init call for rendering start bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, const SExposedVideoData& videoData, core::rect* sourceRect) { CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); switch (DeviceType) { #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ case EIDT_WIN32: changeRenderContext(videoData, Win32Device); break; #endif #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ case EIDT_X11: changeRenderContext(videoData, X11Device); break; #endif default: changeRenderContext(videoData, (void*)0); break; } #if defined(_IRR_COMPILE_WITH_SDL_DEVICE_) if (DeviceType == EIDT_SDL) { // todo: SDL sets glFrontFace(GL_CCW) after driver creation, // it would be better if this was fixed elsewhere. glFrontFace(GL_CW); } #endif clearBuffers(backBuffer, zBuffer, false, color); return true; } //! Returns the transformation set by setTransform const core::matrix4& COpenGLDriver::getTransform(E_TRANSFORMATION_STATE state) const { return Matrices[state]; } //! sets transformation void COpenGLDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) { Matrices[state] = mat; Transformation3DChanged = true; switch (state) { case ETS_VIEW: case ETS_WORLD: { // OpenGL only has a model matrix, view and world is not existent. so lets fake these two. glMatrixMode(GL_MODELVIEW); // first load the viewing transformation for user clip planes glLoadMatrixf((Matrices[ETS_VIEW]).pointer()); // we have to update the clip planes to the latest view matrix for (u32 i=0; i= MATERIAL_MAX_TEXTURES) break; const bool isRTT = Material.getTexture(i) && Material.getTexture(i)->isRenderTarget(); if (MultiTextureExtension) extGlActiveTexture(GL_TEXTURE0_ARB + i); glMatrixMode(GL_TEXTURE); if (!isRTT && mat.isIdentity() ) glLoadIdentity(); else { GLfloat glmat[16]; if (isRTT) getGLTextureMatrix(glmat, mat * TextureFlipMatrix); else getGLTextureMatrix(glmat, mat); glLoadMatrixf(glmat); } break; } } } bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) { if (!HWBuffer) return false; if (!FeatureAvailable[IRR_ARB_vertex_buffer_object]) return false; #if defined(GL_ARB_vertex_buffer_object) const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; const void* vertices=mb->getVertices(); const u32 vertexCount=mb->getVertexCount(); const E_VERTEX_TYPE vType=mb->getVertexType(); const u32 vertexSize = getVertexPitchFromType(vType); const c8* vbuf = static_cast(vertices); core::array buffer; if (!FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra]) { //buffer vertex data, and convert colors... buffer.set_used(vertexSize * vertexCount); memcpy(buffer.pointer(), vertices, vertexSize * vertexCount); vbuf = buffer.const_pointer(); // in order to convert the colors into opengl format (RGBA) switch (vType) { case EVT_STANDARD: { S3DVertex* pb = reinterpret_cast(buffer.pointer()); const S3DVertex* po = static_cast(vertices); for (u32 i=0; i(buffer.pointer()); const S3DVertex2TCoords* po = static_cast(vertices); for (u32 i=0; i(buffer.pointer()); const S3DVertexTangents* po = static_cast(vertices); for (u32 i=0; ivbo_verticesID) { extGlGenBuffers(1, &HWBuffer->vbo_verticesID); if (!HWBuffer->vbo_verticesID) return false; newBuffer=true; } else if (HWBuffer->vbo_verticesSize < vertexCount*vertexSize) { newBuffer=true; } extGlBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID); //copy data to graphics card glGetError(); // clear error storage if (!newBuffer) extGlBufferSubData(GL_ARRAY_BUFFER, 0, vertexCount * vertexSize, vbuf); else { HWBuffer->vbo_verticesSize = vertexCount*vertexSize; if (HWBuffer->Mapped_Vertex==scene::EHM_STATIC) extGlBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vbuf, GL_STATIC_DRAW); else if (HWBuffer->Mapped_Vertex==scene::EHM_DYNAMIC) extGlBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vbuf, GL_DYNAMIC_DRAW); else //scene::EHM_STREAM extGlBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vbuf, GL_STREAM_DRAW); } extGlBindBuffer(GL_ARRAY_BUFFER, 0); return (glGetError() == GL_NO_ERROR); #else return false; #endif } bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) { if (!HWBuffer) return false; if (!FeatureAvailable[IRR_ARB_vertex_buffer_object]) return false; #if defined(GL_ARB_vertex_buffer_object) const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; const void* indices=mb->getIndices(); u32 indexCount= mb->getIndexCount(); GLenum indexSize; switch (mb->getIndexType()) { case EIT_16BIT: { indexSize=sizeof(u16); break; } case EIT_32BIT: { indexSize=sizeof(u32); break; } default: { return false; } } //get or create buffer bool newBuffer=false; if (!HWBuffer->vbo_indicesID) { extGlGenBuffers(1, &HWBuffer->vbo_indicesID); if (!HWBuffer->vbo_indicesID) return false; newBuffer=true; } else if (HWBuffer->vbo_indicesSize < indexCount*indexSize) { newBuffer=true; } extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID); //copy data to graphics card glGetError(); // clear error storage if (!newBuffer) extGlBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexCount * indexSize, indices); else { HWBuffer->vbo_indicesSize = indexCount*indexSize; if (HWBuffer->Mapped_Index==scene::EHM_STATIC) extGlBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STATIC_DRAW); else if (HWBuffer->Mapped_Index==scene::EHM_DYNAMIC) extGlBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_DYNAMIC_DRAW); else //scene::EHM_STREAM extGlBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STREAM_DRAW); } extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); return (glGetError() == GL_NO_ERROR); #else return false; #endif } //! updates hardware buffer if needed bool COpenGLDriver::updateHardwareBuffer(SHWBufferLink *HWBuffer) { if (!HWBuffer) return false; if (HWBuffer->Mapped_Vertex!=scene::EHM_NEVER) { if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex() || !((SHWBufferLink_opengl*)HWBuffer)->vbo_verticesID) { HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex(); if (!updateVertexHardwareBuffer((SHWBufferLink_opengl*)HWBuffer)) return false; } } if (HWBuffer->Mapped_Index!=scene::EHM_NEVER) { if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() || !((SHWBufferLink_opengl*)HWBuffer)->vbo_indicesID) { HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index(); if (!updateIndexHardwareBuffer((SHWBufferLink_opengl*)HWBuffer)) return false; } } return true; } //! Create hardware buffer from meshbuffer COpenGLDriver::SHWBufferLink *COpenGLDriver::createHardwareBuffer(const scene::IMeshBuffer* mb) { #if defined(GL_ARB_vertex_buffer_object) if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER)) return 0; SHWBufferLink_opengl *HWBuffer=new SHWBufferLink_opengl(mb); //add to map HWBufferMap.insert(HWBuffer->MeshBuffer, HWBuffer); HWBuffer->ChangedID_Vertex=HWBuffer->MeshBuffer->getChangedID_Vertex(); HWBuffer->ChangedID_Index=HWBuffer->MeshBuffer->getChangedID_Index(); HWBuffer->Mapped_Vertex=mb->getHardwareMappingHint_Vertex(); HWBuffer->Mapped_Index=mb->getHardwareMappingHint_Index(); HWBuffer->LastUsed=0; HWBuffer->vbo_verticesID=0; HWBuffer->vbo_indicesID=0; HWBuffer->vbo_verticesSize=0; HWBuffer->vbo_indicesSize=0; if (!updateHardwareBuffer(HWBuffer)) { deleteHardwareBuffer(HWBuffer); return 0; } return HWBuffer; #else return 0; #endif } void COpenGLDriver::deleteHardwareBuffer(SHWBufferLink *_HWBuffer) { if (!_HWBuffer) return; #if defined(GL_ARB_vertex_buffer_object) SHWBufferLink_opengl *HWBuffer=(SHWBufferLink_opengl*)_HWBuffer; if (HWBuffer->vbo_verticesID) { extGlDeleteBuffers(1, &HWBuffer->vbo_verticesID); HWBuffer->vbo_verticesID=0; } if (HWBuffer->vbo_indicesID) { extGlDeleteBuffers(1, &HWBuffer->vbo_indicesID); HWBuffer->vbo_indicesID=0; } #endif CNullDriver::deleteHardwareBuffer(_HWBuffer); } //! Draw hardware buffer void COpenGLDriver::drawHardwareBuffer(SHWBufferLink *_HWBuffer) { if (!_HWBuffer) return; updateHardwareBuffer(_HWBuffer); //check if update is needed _HWBuffer->LastUsed=0; //reset count #if defined(GL_ARB_vertex_buffer_object) SHWBufferLink_opengl *HWBuffer=(SHWBufferLink_opengl*)_HWBuffer; const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; const void *vertices=mb->getVertices(); const void *indexList=mb->getIndices(); if (HWBuffer->Mapped_Vertex!=scene::EHM_NEVER) { extGlBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID); vertices=0; } if (HWBuffer->Mapped_Index!=scene::EHM_NEVER) { extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID); indexList=0; } drawVertexPrimitiveList(vertices, mb->getVertexCount(), indexList, mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType()); if (HWBuffer->Mapped_Vertex!=scene::EHM_NEVER) extGlBindBuffer(GL_ARRAY_BUFFER, 0); if (HWBuffer->Mapped_Index!=scene::EHM_NEVER) extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); #endif } //! Create occlusion query. /** Use node for identification and mesh for occlusion test. */ void COpenGLDriver::addOcclusionQuery(scene::ISceneNode* node, const scene::IMesh* mesh) { if (!queryFeature(EVDF_OCCLUSION_QUERY)) return; CNullDriver::addOcclusionQuery(node, mesh); const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if ((index != -1) && (OcclusionQueries[index].UID == 0)) extGlGenQueries(1, reinterpret_cast(&OcclusionQueries[index].UID)); } //! Remove occlusion query. void COpenGLDriver::removeOcclusionQuery(scene::ISceneNode* node) { const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if (index != -1) { if (OcclusionQueries[index].UID != 0) extGlDeleteQueries(1, reinterpret_cast(&OcclusionQueries[index].UID)); CNullDriver::removeOcclusionQuery(node); } } //! Run occlusion query. Draws mesh stored in query. /** If the mesh shall not be rendered visible, use overrideMaterial to disable the color and depth buffer. */ void COpenGLDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible) { if (!node) return; const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if (index != -1) { if (OcclusionQueries[index].UID) extGlBeginQuery( #ifdef GL_ARB_occlusion_query GL_SAMPLES_PASSED_ARB, #else 0, #endif OcclusionQueries[index].UID); CNullDriver::runOcclusionQuery(node,visible); if (OcclusionQueries[index].UID) extGlEndQuery( #ifdef GL_ARB_occlusion_query GL_SAMPLES_PASSED_ARB); #else 0); #endif testGLError(); } } //! Update occlusion query. Retrieves results from GPU. /** If the query shall not block, set the flag to false. Update might not occur in this case, though */ void COpenGLDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block) { const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if (index != -1) { // not yet started if (OcclusionQueries[index].Run==u32(~0)) return; GLint available = block?GL_TRUE:GL_FALSE; if (!block) extGlGetQueryObjectiv(OcclusionQueries[index].UID, #ifdef GL_ARB_occlusion_query GL_QUERY_RESULT_AVAILABLE_ARB, #elif defined(GL_NV_occlusion_query) GL_PIXEL_COUNT_AVAILABLE_NV, #else 0, #endif &available); testGLError(); if (available==GL_TRUE) { extGlGetQueryObjectiv(OcclusionQueries[index].UID, #ifdef GL_ARB_occlusion_query GL_QUERY_RESULT_ARB, #elif defined(GL_NV_occlusion_query) GL_PIXEL_COUNT_NV, #else 0, #endif &available); if (queryFeature(EVDF_OCCLUSION_QUERY)) OcclusionQueries[index].Result = available; } testGLError(); } } //! Return query result. /** Return value is the number of visible pixels/fragments. The value is a safe approximation, i.e. can be larger than the actual value of pixels. */ u32 COpenGLDriver::getOcclusionQueryResult(scene::ISceneNode* node) const { const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if (index != -1) return OcclusionQueries[index].Result; else return ~0; } // small helper function to create vertex buffer object adress offsets static inline u8* buffer_offset(const long offset) { return ((u8*)0 + offset); } //! draws a vertex primitive list void COpenGLDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { if (!primitiveCount || !vertexCount) return; if (!checkPrimitiveCount(primitiveCount)) return; CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType); if (vertices && !FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra]) getColorBuffer(vertices, vertexCount, vType); // draw everything setRenderStates3DMode(); if (MultiTextureExtension) extGlClientActiveTexture(GL_TEXTURE0_ARB); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); if ((pType!=scene::EPT_POINTS) && (pType!=scene::EPT_POINT_SPRITES)) glEnableClientState(GL_TEXTURE_COORD_ARRAY); if ((pType!=scene::EPT_POINTS) && (pType!=scene::EPT_POINT_SPRITES)) glEnableClientState(GL_NORMAL_ARRAY); //due to missing defines in OSX headers, we have to be more specific with this check //#if defined(GL_ARB_vertex_array_bgra) || defined(GL_EXT_vertex_array_bgra) #ifdef GL_BGRA const GLint colorSize=(FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])?GL_BGRA:4; #else const GLint colorSize=4; #endif if (vertices) { if (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra]) { switch (vType) { case EVT_STANDARD: glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), &(static_cast(vertices))[0].Color); break; case EVT_2TCOORDS: glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), &(static_cast(vertices))[0].Color); break; case EVT_TANGENTS: glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), &(static_cast(vertices))[0].Color); break; } } else { // avoid passing broken pointer to OpenGL _IRR_DEBUG_BREAK_IF(ColorBuffer.size()==0); glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]); } } switch (vType) { case EVT_STANDARD: if (vertices) { glNormalPointer(GL_FLOAT, sizeof(S3DVertex), &(static_cast(vertices))[0].Normal); glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast(vertices))[0].TCoords); glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex), &(static_cast(vertices))[0].Pos); } else { glNormalPointer(GL_FLOAT, sizeof(S3DVertex), buffer_offset(12)); glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), buffer_offset(24)); glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex), 0); } if (MultiTextureExtension && CurrentTexture[1]) { extGlClientActiveTexture(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (vertices) glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast(vertices))[0].TCoords); else glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); } break; case EVT_2TCOORDS: if (vertices) { glNormalPointer(GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast(vertices))[0].Normal); glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast(vertices))[0].TCoords); glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast(vertices))[0].Pos); } else { glNormalPointer(GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(12)); glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), buffer_offset(24)); glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(28)); glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(0)); } if (MultiTextureExtension) { extGlClientActiveTexture(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (vertices) glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast(vertices))[0].TCoords2); else glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(36)); } break; case EVT_TANGENTS: if (vertices) { glNormalPointer(GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast(vertices))[0].Normal); glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast(vertices))[0].TCoords); glVertexPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast(vertices))[0].Pos); } else { glNormalPointer(GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(12)); glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), buffer_offset(24)); glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(28)); glVertexPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(0)); } if (MultiTextureExtension) { extGlClientActiveTexture(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (vertices) glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast(vertices))[0].Tangent); else glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(36)); extGlClientActiveTexture(GL_TEXTURE2_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (vertices) glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast(vertices))[0].Binormal); else glTexCoordPointer(3, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(48)); } break; } renderArray(indexList, primitiveCount, pType, iType); if (MultiTextureExtension) { if (vType==EVT_TANGENTS) { extGlClientActiveTexture(GL_TEXTURE2_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } if ((vType!=EVT_STANDARD) || CurrentTexture[1]) { extGlClientActiveTexture(GL_TEXTURE1_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } extGlClientActiveTexture(GL_TEXTURE0_ARB); } glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } void COpenGLDriver::getColorBuffer(const void* vertices, u32 vertexCount, E_VERTEX_TYPE vType) { // convert colors to gl color format. vertexCount *= 4; //reused as color component count ColorBuffer.set_used(vertexCount); u32 i; switch (vType) { case EVT_STANDARD: { const S3DVertex* p = static_cast(vertices); for (i=0; iColor.toOpenGLColor(&ColorBuffer[i]); ++p; } } break; case EVT_2TCOORDS: { const S3DVertex2TCoords* p = static_cast(vertices); for (i=0; iColor.toOpenGLColor(&ColorBuffer[i]); ++p; } } break; case EVT_TANGENTS: { const S3DVertexTangents* p = static_cast(vertices); for (i=0; iColor.toOpenGLColor(&ColorBuffer[i]); ++p; } } break; } } void COpenGLDriver::renderArray(const void* indexList, u32 primitiveCount, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { GLenum indexSize=0; switch (iType) { case EIT_16BIT: { indexSize=GL_UNSIGNED_SHORT; break; } case EIT_32BIT: { indexSize=GL_UNSIGNED_INT; break; } } switch (pType) { case scene::EPT_POINTS: case scene::EPT_POINT_SPRITES: { #ifdef GL_ARB_point_sprite if (pType==scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite]) glEnable(GL_POINT_SPRITE_ARB); #endif // prepare size and attenuation (where supported) GLfloat particleSize=Material.Thickness; // if (AntiAlias) // particleSize=core::clamp(particleSize, DimSmoothedPoint[0], DimSmoothedPoint[1]); // else particleSize=core::clamp(particleSize, DimAliasedPoint[0], DimAliasedPoint[1]); #if defined(GL_VERSION_1_4) || defined(GL_ARB_point_parameters) || defined(GL_EXT_point_parameters) || defined(GL_SGIS_point_parameters) const float att[] = {1.0f, 1.0f, 0.0f}; #if defined(GL_VERSION_1_4) extGlPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, att); // extGlPointParameterf(GL_POINT_SIZE_MIN,1.f); extGlPointParameterf(GL_POINT_SIZE_MAX, particleSize); extGlPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE, 1.0f); #elif defined(GL_ARB_point_parameters) extGlPointParameterfv(GL_POINT_DISTANCE_ATTENUATION_ARB, att); // extGlPointParameterf(GL_POINT_SIZE_MIN_ARB,1.f); extGlPointParameterf(GL_POINT_SIZE_MAX_ARB, particleSize); extGlPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 1.0f); #elif defined(GL_EXT_point_parameters) extGlPointParameterfv(GL_DISTANCE_ATTENUATION_EXT, att); // extGlPointParameterf(GL_POINT_SIZE_MIN_EXT,1.f); extGlPointParameterf(GL_POINT_SIZE_MAX_EXT, particleSize); extGlPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 1.0f); #elif defined(GL_SGIS_point_parameters) extGlPointParameterfv(GL_DISTANCE_ATTENUATION_SGIS, att); // extGlPointParameterf(GL_POINT_SIZE_MIN_SGIS,1.f); extGlPointParameterf(GL_POINT_SIZE_MAX_SGIS, particleSize); extGlPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_SGIS, 1.0f); #endif #endif glPointSize(particleSize); #ifdef GL_ARB_point_sprite if (pType==scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite]) glTexEnvf(GL_POINT_SPRITE_ARB,GL_COORD_REPLACE, GL_TRUE); #endif glDrawArrays(GL_POINTS, 0, primitiveCount); #ifdef GL_ARB_point_sprite if (pType==scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_ARB_point_sprite]) { glDisable(GL_POINT_SPRITE_ARB); glTexEnvf(GL_POINT_SPRITE_ARB,GL_COORD_REPLACE, GL_FALSE); } #endif } break; case scene::EPT_LINE_STRIP: glDrawElements(GL_LINE_STRIP, primitiveCount+1, indexSize, indexList); break; case scene::EPT_LINE_LOOP: glDrawElements(GL_LINE_LOOP, primitiveCount, indexSize, indexList); break; case scene::EPT_LINES: glDrawElements(GL_LINES, primitiveCount*2, indexSize, indexList); break; case scene::EPT_TRIANGLE_STRIP: glDrawElements(GL_TRIANGLE_STRIP, primitiveCount+2, indexSize, indexList); break; case scene::EPT_TRIANGLE_FAN: glDrawElements(GL_TRIANGLE_FAN, primitiveCount+2, indexSize, indexList); break; case scene::EPT_TRIANGLES: glDrawElements(GL_TRIANGLES, primitiveCount*3, indexSize, indexList); break; case scene::EPT_QUAD_STRIP: glDrawElements(GL_QUAD_STRIP, primitiveCount*2+2, indexSize, indexList); break; case scene::EPT_QUADS: glDrawElements(GL_QUADS, primitiveCount*4, indexSize, indexList); break; case scene::EPT_POLYGON: glDrawElements(GL_POLYGON, primitiveCount, indexSize, indexList); break; } } //! draws a vertex primitive list in 2d void COpenGLDriver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { if (!primitiveCount || !vertexCount) return; if (!checkPrimitiveCount(primitiveCount)) return; CNullDriver::draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType); if (vertices && !FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra]) getColorBuffer(vertices, vertexCount, vType); // draw everything this->setActiveTexture(0, Material.getTexture(0)); if (Material.MaterialType==EMT_ONETEXTURE_BLEND) { E_BLEND_FACTOR srcFact; E_BLEND_FACTOR dstFact; E_MODULATE_FUNC modulo; u32 alphaSource; unpack_textureBlendFunc ( srcFact, dstFact, modulo, alphaSource, Material.MaterialTypeParam); setRenderStates2DMode(alphaSource&video::EAS_VERTEX_COLOR, (Material.getTexture(0) != 0), (alphaSource&video::EAS_TEXTURE) != 0); } else setRenderStates2DMode(Material.MaterialType==EMT_TRANSPARENT_VERTEX_ALPHA, (Material.getTexture(0) != 0), Material.MaterialType==EMT_TRANSPARENT_ALPHA_CHANNEL); if (MultiTextureExtension) extGlClientActiveTexture(GL_TEXTURE0_ARB); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); if ((pType!=scene::EPT_POINTS) && (pType!=scene::EPT_POINT_SPRITES)) glEnableClientState(GL_TEXTURE_COORD_ARRAY); //due to missing defines in OSX headers, we have to be more specific with this check //#if defined(GL_ARB_vertex_array_bgra) || defined(GL_EXT_vertex_array_bgra) #ifdef GL_BGRA const GLint colorSize=(FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])?GL_BGRA:4; #else const GLint colorSize=4; #endif if (vertices) { if (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra]) { switch (vType) { case EVT_STANDARD: glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), &(static_cast(vertices))[0].Color); break; case EVT_2TCOORDS: glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), &(static_cast(vertices))[0].Color); break; case EVT_TANGENTS: glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), &(static_cast(vertices))[0].Color); break; } } else { // avoid passing broken pointer to OpenGL _IRR_DEBUG_BREAK_IF(ColorBuffer.size()==0); glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]); } } switch (vType) { case EVT_STANDARD: if (vertices) { glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast(vertices))[0].TCoords); glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast(vertices))[0].Pos); } else { glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), buffer_offset(24)); glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex), 0); } if (MultiTextureExtension && CurrentTexture[1]) { extGlClientActiveTexture(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (vertices) glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), &(static_cast(vertices))[0].TCoords); else glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex), buffer_offset(28)); } break; case EVT_2TCOORDS: if (vertices) { glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast(vertices))[0].TCoords); glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast(vertices))[0].Pos); } else { glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex2TCoords), buffer_offset(24)); glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(28)); glVertexPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(0)); } if (MultiTextureExtension) { extGlClientActiveTexture(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (vertices) glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &(static_cast(vertices))[0].TCoords2); else glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), buffer_offset(36)); } break; case EVT_TANGENTS: if (vertices) { glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast(vertices))[0].TCoords); glVertexPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), &(static_cast(vertices))[0].Pos); } else { glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertexTangents), buffer_offset(24)); glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(28)); glVertexPointer(2, GL_FLOAT, sizeof(S3DVertexTangents), buffer_offset(0)); } break; } renderArray(indexList, primitiveCount, pType, iType); if (MultiTextureExtension) { if ((vType!=EVT_STANDARD) || CurrentTexture[1]) { extGlClientActiveTexture(GL_TEXTURE1_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } extGlClientActiveTexture(GL_TEXTURE0_ARB); } glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } //! draws a set of 2d images, using a color and the alpha channel of the //! texture if desired. void COpenGLDriver::draw2DImageBatch(const video::ITexture* texture, const core::array >& positions, const core::array >& sourceRects, const core::rect* clipRect, SColor color, bool useAlphaChannelOfTexture) { if (!texture) return; const u32 drawCount = core::min_(positions.size(), sourceRects.size()); const core::dimension2d& ss = texture->getOriginalSize(); const f32 invW = 1.f / static_cast(ss.Width); const f32 invH = 1.f / static_cast(ss.Height); const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); disableTextures(1); if (!setActiveTexture(0, texture)) return; setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); glBegin(GL_QUADS); for (u32 i=0; i targetPos(positions[i]); core::position2d sourcePos(sourceRects[i].UpperLeftCorner); // This needs to be signed as it may go negative. core::dimension2d sourceSize(sourceRects[i].getSize()); if (clipRect) { if (targetPos.X < clipRect->UpperLeftCorner.X) { sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; if (sourceSize.Width <= 0) continue; sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; targetPos.X = clipRect->UpperLeftCorner.X; } if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; if (sourceSize.Width <= 0) continue; } if (targetPos.Y < clipRect->UpperLeftCorner.Y) { sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; if (sourceSize.Height <= 0) continue; sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; targetPos.Y = clipRect->UpperLeftCorner.Y; } if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; if (sourceSize.Height <= 0) continue; } } // clip these coordinates if (targetPos.X<0) { sourceSize.Width += targetPos.X; if (sourceSize.Width <= 0) continue; sourcePos.X -= targetPos.X; targetPos.X = 0; } if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; if (sourceSize.Width <= 0) continue; } if (targetPos.Y<0) { sourceSize.Height += targetPos.Y; if (sourceSize.Height <= 0) continue; sourcePos.Y -= targetPos.Y; targetPos.Y = 0; } if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; if (sourceSize.Height <= 0) continue; } // ok, we've clipped everything. // now draw it. const core::rect tcoords( sourcePos.X * invW, sourcePos.Y * invH, (sourcePos.X + sourceSize.Width) * invW, (sourcePos.Y + sourceSize.Height) * invH); const core::rect poss(targetPos, sourceSize); glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.UpperLeftCorner.Y)); glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.UpperLeftCorner.Y)); glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.LowerRightCorner.Y)); glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.LowerRightCorner.Y)); } glEnd(); } //! draws a 2d image, using a color and the alpha channel of the texture if //! desired. The image is drawn at pos, clipped against clipRect (if != 0). //! Only the subtexture defined by sourceRect is used. void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect, SColor color, bool useAlphaChannelOfTexture) { if (!texture) return; if (!sourceRect.isValid()) return; core::position2d targetPos(pos); core::position2d sourcePos(sourceRect.UpperLeftCorner); // This needs to be signed as it may go negative. core::dimension2d sourceSize(sourceRect.getSize()); if (clipRect) { if (targetPos.X < clipRect->UpperLeftCorner.X) { sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; if (sourceSize.Width <= 0) return; sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; targetPos.X = clipRect->UpperLeftCorner.X; } if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; if (sourceSize.Width <= 0) return; } if (targetPos.Y < clipRect->UpperLeftCorner.Y) { sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; if (sourceSize.Height <= 0) return; sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; targetPos.Y = clipRect->UpperLeftCorner.Y; } if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; if (sourceSize.Height <= 0) return; } } // clip these coordinates if (targetPos.X<0) { sourceSize.Width += targetPos.X; if (sourceSize.Width <= 0) return; sourcePos.X -= targetPos.X; targetPos.X = 0; } const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; if (sourceSize.Width <= 0) return; } if (targetPos.Y<0) { sourceSize.Height += targetPos.Y; if (sourceSize.Height <= 0) return; sourcePos.Y -= targetPos.Y; targetPos.Y = 0; } if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; if (sourceSize.Height <= 0) return; } // ok, we've clipped everything. // now draw it. const core::dimension2d& ss = texture->getOriginalSize(); const f32 invW = 1.f / static_cast(ss.Width); const f32 invH = 1.f / static_cast(ss.Height); const core::rect tcoords( sourcePos.X * invW, sourcePos.Y * invH, (sourcePos.X + sourceSize.Width) * invW, (sourcePos.Y + sourceSize.Height) * invH); const core::rect poss(targetPos, sourceSize); disableTextures(1); if (!setActiveTexture(0, texture)) return; setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); glBegin(GL_QUADS); glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.UpperLeftCorner.Y)); glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.UpperLeftCorner.Y)); glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.LowerRightCorner.Y)); glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.LowerRightCorner.Y)); glEnd(); } //! The same, but with a four element array of colors, one for each vertex void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect& destRect, const core::rect& sourceRect, const core::rect* clipRect, const video::SColor* const colors, bool useAlphaChannelOfTexture) { if (!texture) return; const core::dimension2d& ss = texture->getOriginalSize(); const f32 invW = 1.f / static_cast(ss.Width); const f32 invH = 1.f / static_cast(ss.Height); const core::rect tcoords( sourceRect.UpperLeftCorner.X * invW, sourceRect.UpperLeftCorner.Y * invH, sourceRect.LowerRightCorner.X * invW, sourceRect.LowerRightCorner.Y *invH); const video::SColor temp[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; const video::SColor* const useColor = colors ? colors : temp; disableTextures(1); setActiveTexture(0, texture); setRenderStates2DMode(useColor[0].getAlpha()<255 || useColor[1].getAlpha()<255 || useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255, true, useAlphaChannelOfTexture); if (clipRect) { if (!clipRect->isValid()) return; glEnable(GL_SCISSOR_TEST); const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height-clipRect->LowerRightCorner.Y, clipRect->getWidth(), clipRect->getHeight()); } glBegin(GL_QUADS); glColor4ub(useColor[0].getRed(), useColor[0].getGreen(), useColor[0].getBlue(), useColor[0].getAlpha()); glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); glVertex2f(GLfloat(destRect.UpperLeftCorner.X), GLfloat(destRect.UpperLeftCorner.Y)); glColor4ub(useColor[3].getRed(), useColor[3].getGreen(), useColor[3].getBlue(), useColor[3].getAlpha()); glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); glVertex2f(GLfloat(destRect.LowerRightCorner.X), GLfloat(destRect.UpperLeftCorner.Y)); glColor4ub(useColor[2].getRed(), useColor[2].getGreen(), useColor[2].getBlue(), useColor[2].getAlpha()); glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); glVertex2f(GLfloat(destRect.LowerRightCorner.X), GLfloat(destRect.LowerRightCorner.Y)); glColor4ub(useColor[1].getRed(), useColor[1].getGreen(), useColor[1].getBlue(), useColor[1].getAlpha()); glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); glVertex2f(GLfloat(destRect.UpperLeftCorner.X), GLfloat(destRect.LowerRightCorner.Y)); glEnd(); if (clipRect) glDisable(GL_SCISSOR_TEST); } //! draws a set of 2d images, using a color and the alpha channel of the //! texture if desired. The images are drawn beginning at pos and concatenated //! in one line. All drawings are clipped against clipRect (if != 0). //! The subtextures are defined by the array of sourceRects and are chosen //! by the indices given. void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::position2d& pos, const core::array >& sourceRects, const core::array& indices, const core::rect* clipRect, SColor color, bool useAlphaChannelOfTexture) { if (!texture) return; disableTextures(1); if (!setActiveTexture(0, texture)) return; setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); if (clipRect) { if (!clipRect->isValid()) return; glEnable(GL_SCISSOR_TEST); const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height-clipRect->LowerRightCorner.Y, clipRect->getWidth(),clipRect->getHeight()); } const core::dimension2d& ss = texture->getOriginalSize(); core::position2d targetPos(pos); const f32 invW = 1.f / static_cast(ss.Width); const f32 invH = 1.f / static_cast(ss.Height); for (u32 i=0; i tcoords( sourceRects[currentIndex].UpperLeftCorner.X * invW, sourceRects[currentIndex].UpperLeftCorner.Y * invH, sourceRects[currentIndex].LowerRightCorner.X * invW, sourceRects[currentIndex].LowerRightCorner.Y * invH); const core::rect poss(targetPos, sourceRects[currentIndex].getSize()); glBegin(GL_QUADS); glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.UpperLeftCorner.Y)); glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.UpperLeftCorner.Y)); glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.LowerRightCorner.Y)); glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.LowerRightCorner.Y)); glEnd(); targetPos.X += sourceRects[currentIndex].getWidth(); } if (clipRect) glDisable(GL_SCISSOR_TEST); } //! draw a 2d rectangle void COpenGLDriver::draw2DRectangle(SColor color, const core::rect& position, const core::rect* clip) { disableTextures(); setRenderStates2DMode(color.getAlpha() < 255, false, false); core::rect pos = position; if (clip) pos.clipAgainst(*clip); if (!pos.isValid()) return; glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); glRectf(GLfloat(pos.UpperLeftCorner.X), GLfloat(pos.UpperLeftCorner.Y), GLfloat(pos.LowerRightCorner.X), GLfloat(pos.LowerRightCorner.Y)); } //! draw an 2d rectangle void COpenGLDriver::draw2DRectangle(const core::rect& position, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip) { core::rect pos = position; if (clip) pos.clipAgainst(*clip); if (!pos.isValid()) return; disableTextures(); setRenderStates2DMode(colorLeftUp.getAlpha() < 255 || colorRightUp.getAlpha() < 255 || colorLeftDown.getAlpha() < 255 || colorRightDown.getAlpha() < 255, false, false); glBegin(GL_QUADS); glColor4ub(colorLeftUp.getRed(), colorLeftUp.getGreen(), colorLeftUp.getBlue(), colorLeftUp.getAlpha()); glVertex2f(GLfloat(pos.UpperLeftCorner.X), GLfloat(pos.UpperLeftCorner.Y)); glColor4ub(colorRightUp.getRed(), colorRightUp.getGreen(), colorRightUp.getBlue(), colorRightUp.getAlpha()); glVertex2f(GLfloat(pos.LowerRightCorner.X), GLfloat(pos.UpperLeftCorner.Y)); glColor4ub(colorRightDown.getRed(), colorRightDown.getGreen(), colorRightDown.getBlue(), colorRightDown.getAlpha()); glVertex2f(GLfloat(pos.LowerRightCorner.X), GLfloat(pos.LowerRightCorner.Y)); glColor4ub(colorLeftDown.getRed(), colorLeftDown.getGreen(), colorLeftDown.getBlue(), colorLeftDown.getAlpha()); glVertex2f(GLfloat(pos.UpperLeftCorner.X), GLfloat(pos.LowerRightCorner.Y)); glEnd(); } //! Draws a 2d line. void COpenGLDriver::draw2DLine(const core::position2d& start, const core::position2d& end, SColor color) { if (start==end) drawPixel(start.X, start.Y, color); else { disableTextures(); setRenderStates2DMode(color.getAlpha() < 255, false, false); glBegin(GL_LINES); glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); GLfloat x=(GLfloat)start.X; GLfloat y=(GLfloat)start.Y; if (x>end.X) x += 0.5f; if (y>end.Y) y += 0.5f; glVertex2f(GLfloat(x), GLfloat(y)); x=(GLfloat)end.X; y=(GLfloat)end.Y; if (x>start.X) x += 0.5f; if (y>start.Y) y += 0.5f; glVertex2f(GLfloat(x), GLfloat(y)); glEnd(); } } //! Draws a pixel void COpenGLDriver::drawPixel(u32 x, u32 y, const SColor &color) { const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); if (x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height) return; disableTextures(); setRenderStates2DMode(color.getAlpha() < 255, false, false); glBegin(GL_POINTS); glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); glVertex2i(x, y); glEnd(); } bool COpenGLDriver::setActiveTexture(u32 stage, const video::ITexture* texture) { if (stage >= MaxSupportedTextures) return false; if (CurrentTexture[stage]==texture) return true; if (MultiTextureExtension) extGlActiveTexture(GL_TEXTURE0_ARB + stage); CurrentTexture.set(stage,texture); if (!texture) { glDisable(GL_TEXTURE_2D); return true; } else { if (texture->getDriverType() != EDT_OPENGL) { glDisable(GL_TEXTURE_2D); CurrentTexture.set(stage, 0); os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); return false; } glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, static_cast(texture)->getOpenGLTextureName()); } return true; } //! disables all textures beginning with the optional fromStage parameter. Otherwise all texture stages are disabled. //! Returns whether disabling was successful or not. bool COpenGLDriver::disableTextures(u32 fromStage) { bool result=true; for (u32 i=fromStage; i= 0; --i) { setActiveTexture(i, material.getTexture(i)); setTransform ((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + i), Material.getTextureMatrix(i)); } } //! prints error if an error happened. bool COpenGLDriver::testGLError() { #ifdef _DEBUG GLenum g = glGetError(); switch (g) { case GL_NO_ERROR: return false; case GL_INVALID_ENUM: os::Printer::log("GL_INVALID_ENUM", ELL_ERROR); break; case GL_INVALID_VALUE: os::Printer::log("GL_INVALID_VALUE", ELL_ERROR); break; case GL_INVALID_OPERATION: os::Printer::log("GL_INVALID_OPERATION", ELL_ERROR); break; case GL_STACK_OVERFLOW: os::Printer::log("GL_STACK_OVERFLOW", ELL_ERROR); break; case GL_STACK_UNDERFLOW: os::Printer::log("GL_STACK_UNDERFLOW", ELL_ERROR); break; case GL_OUT_OF_MEMORY: os::Printer::log("GL_OUT_OF_MEMORY", ELL_ERROR); break; case GL_TABLE_TOO_LARGE: os::Printer::log("GL_TABLE_TOO_LARGE", ELL_ERROR); break; #if defined(GL_EXT_framebuffer_object) case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: os::Printer::log("GL_INVALID_FRAMEBUFFER_OPERATION", ELL_ERROR); break; #endif }; // _IRR_DEBUG_BREAK_IF(true); return true; #else return false; #endif } //! sets the needed renderstates void COpenGLDriver::setRenderStates3DMode() { if (CurrentRenderMode != ERM_3D) { // Reset Texture Stages glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // switch back the matrices glMatrixMode(GL_MODELVIEW); glLoadMatrixf((Matrices[ETS_VIEW] * Matrices[ETS_WORLD]).pointer()); glMatrixMode(GL_PROJECTION); glLoadMatrixf(Matrices[ETS_PROJECTION].pointer()); ResetRenderStates = true; #ifdef GL_EXT_clip_volume_hint if (FeatureAvailable[IRR_EXT_clip_volume_hint]) glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_NICEST); #endif } if (ResetRenderStates || LastMaterial != Material) { // unset old material if (LastMaterial.MaterialType != Material.MaterialType && static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); // set new material. if (static_cast(Material.MaterialType) < MaterialRenderers.size()) MaterialRenderers[Material.MaterialType].Renderer->OnSetMaterial( Material, LastMaterial, ResetRenderStates, this); LastMaterial = Material; ResetRenderStates = false; } if (static_cast(Material.MaterialType) < MaterialRenderers.size()) MaterialRenderers[Material.MaterialType].Renderer->OnRender(this, video::EVT_STANDARD); CurrentRenderMode = ERM_3D; } //! Get native wrap mode value GLint COpenGLDriver::getTextureWrapMode(const u8 clamp) { GLint mode=GL_REPEAT; switch (clamp) { case ETC_REPEAT: mode=GL_REPEAT; break; case ETC_CLAMP: mode=GL_CLAMP; break; case ETC_CLAMP_TO_EDGE: #ifdef GL_VERSION_1_2 if (Version>101) mode=GL_CLAMP_TO_EDGE; else #endif #ifdef GL_SGIS_texture_edge_clamp if (FeatureAvailable[IRR_SGIS_texture_edge_clamp]) mode=GL_CLAMP_TO_EDGE_SGIS; else #endif // fallback mode=GL_CLAMP; break; case ETC_CLAMP_TO_BORDER: #ifdef GL_VERSION_1_3 if (Version>102) mode=GL_CLAMP_TO_BORDER; else #endif #ifdef GL_ARB_texture_border_clamp if (FeatureAvailable[IRR_ARB_texture_border_clamp]) mode=GL_CLAMP_TO_BORDER_ARB; else #endif #ifdef GL_SGIS_texture_border_clamp if (FeatureAvailable[IRR_SGIS_texture_border_clamp]) mode=GL_CLAMP_TO_BORDER_SGIS; else #endif // fallback mode=GL_CLAMP; break; case ETC_MIRROR: #ifdef GL_VERSION_1_4 if (Version>103) mode=GL_MIRRORED_REPEAT; else #endif #ifdef GL_ARB_texture_border_clamp if (FeatureAvailable[IRR_ARB_texture_mirrored_repeat]) mode=GL_MIRRORED_REPEAT_ARB; else #endif #ifdef GL_IBM_texture_mirrored_repeat if (FeatureAvailable[IRR_IBM_texture_mirrored_repeat]) mode=GL_MIRRORED_REPEAT_IBM; else #endif mode=GL_REPEAT; break; case ETC_MIRROR_CLAMP: #ifdef GL_EXT_texture_mirror_clamp if (FeatureAvailable[IRR_EXT_texture_mirror_clamp]) mode=GL_MIRROR_CLAMP_EXT; else #endif #if defined(GL_ATI_texture_mirror_once) if (FeatureAvailable[IRR_ATI_texture_mirror_once]) mode=GL_MIRROR_CLAMP_ATI; else #endif mode=GL_CLAMP; break; case ETC_MIRROR_CLAMP_TO_EDGE: #ifdef GL_EXT_texture_mirror_clamp if (FeatureAvailable[IRR_EXT_texture_mirror_clamp]) mode=GL_MIRROR_CLAMP_TO_EDGE_EXT; else #endif #if defined(GL_ATI_texture_mirror_once) if (FeatureAvailable[IRR_ATI_texture_mirror_once]) mode=GL_MIRROR_CLAMP_TO_EDGE_ATI; else #endif mode=GL_CLAMP; break; case ETC_MIRROR_CLAMP_TO_BORDER: #ifdef GL_EXT_texture_mirror_clamp if (FeatureAvailable[IRR_EXT_texture_mirror_clamp]) mode=GL_MIRROR_CLAMP_TO_BORDER_EXT; else #endif mode=GL_CLAMP; break; } return mode; } void COpenGLDriver::setWrapMode(const SMaterial& material) { // texture address mode // Has to be checked always because it depends on the textures for (u32 u=0; u0) break; // stop loop glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[u].TextureWrapU)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[u].TextureWrapV)); } } //! Can be called by an IMaterialRenderer to make its work easier. void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderStates) { if (resetAllRenderStates || lastmaterial.ColorMaterial != material.ColorMaterial) { switch (material.ColorMaterial) { case ECM_NONE: glDisable(GL_COLOR_MATERIAL); break; case ECM_DIFFUSE: glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); break; case ECM_AMBIENT: glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT); break; case ECM_EMISSIVE: glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION); break; case ECM_SPECULAR: glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR); break; case ECM_DIFFUSE_AND_AMBIENT: glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); break; } if (material.ColorMaterial != ECM_NONE) glEnable(GL_COLOR_MATERIAL); } if (resetAllRenderStates || lastmaterial.AmbientColor != material.AmbientColor || lastmaterial.DiffuseColor != material.DiffuseColor || lastmaterial.EmissiveColor != material.EmissiveColor || lastmaterial.ColorMaterial != material.ColorMaterial) { GLfloat color[4]; const f32 inv = 1.0f / 255.0f; if ((material.ColorMaterial != video::ECM_AMBIENT) && (material.ColorMaterial != video::ECM_DIFFUSE_AND_AMBIENT)) { color[0] = material.AmbientColor.getRed() * inv; color[1] = material.AmbientColor.getGreen() * inv; color[2] = material.AmbientColor.getBlue() * inv; color[3] = material.AmbientColor.getAlpha() * inv; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color); } if ((material.ColorMaterial != video::ECM_DIFFUSE) && (material.ColorMaterial != video::ECM_DIFFUSE_AND_AMBIENT)) { color[0] = material.DiffuseColor.getRed() * inv; color[1] = material.DiffuseColor.getGreen() * inv; color[2] = material.DiffuseColor.getBlue() * inv; color[3] = material.DiffuseColor.getAlpha() * inv; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color); } if (material.ColorMaterial != video::ECM_EMISSIVE) { color[0] = material.EmissiveColor.getRed() * inv; color[1] = material.EmissiveColor.getGreen() * inv; color[2] = material.EmissiveColor.getBlue() * inv; color[3] = material.EmissiveColor.getAlpha() * inv; glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color); } } if (resetAllRenderStates || lastmaterial.SpecularColor != material.SpecularColor || lastmaterial.Shininess != material.Shininess || lastmaterial.ColorMaterial != material.ColorMaterial) { GLfloat color[4]={0.f,0.f,0.f,1.f}; const f32 inv = 1.0f / 255.0f; glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material.Shininess); // disable Specular colors if no shininess is set if ((material.Shininess != 0.0f) && (material.ColorMaterial != video::ECM_SPECULAR)) { #ifdef GL_EXT_separate_specular_color if (FeatureAvailable[IRR_EXT_separate_specular_color]) glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); #endif color[0] = material.SpecularColor.getRed() * inv; color[1] = material.SpecularColor.getGreen() * inv; color[2] = material.SpecularColor.getBlue() * inv; color[3] = material.SpecularColor.getAlpha() * inv; } #ifdef GL_EXT_separate_specular_color else if (FeatureAvailable[IRR_EXT_separate_specular_color]) glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); #endif glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color); } // Texture filter // Has to be checked always because it depends on the textures // Filtering has to be set for each texture layer for (u32 i=0; i0) break; #ifdef GL_EXT_texture_lod_bias if (FeatureAvailable[IRR_EXT_texture_lod_bias]) { if (material.TextureLayer[i].LODBias) { const float tmp = core::clamp(material.TextureLayer[i].LODBias * 0.125f, -MaxTextureLODBias, MaxTextureLODBias); glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, tmp); } else glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.f); } #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST); if (material.UseMipMaps && CurrentTexture[i]->hasMipMaps()) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR : material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST); else glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST); #ifdef GL_EXT_texture_filter_anisotropic if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic]) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, material.TextureLayer[i].AnisotropicFilter>1 ? core::min_(MaxAnisotropy, material.TextureLayer[i].AnisotropicFilter) : 1); #endif } // fillmode if (resetAllRenderStates || (lastmaterial.Wireframe != material.Wireframe) || (lastmaterial.PointCloud != material.PointCloud)) glPolygonMode(GL_FRONT_AND_BACK, material.Wireframe ? GL_LINE : material.PointCloud? GL_POINT : GL_FILL); // shademode if (resetAllRenderStates || (lastmaterial.GouraudShading != material.GouraudShading)) { if (material.GouraudShading) glShadeModel(GL_SMOOTH); else glShadeModel(GL_FLAT); } // lighting if (resetAllRenderStates || (lastmaterial.Lighting != material.Lighting)) { if (material.Lighting) glEnable(GL_LIGHTING); else glDisable(GL_LIGHTING); } // zbuffer if (resetAllRenderStates || lastmaterial.ZBuffer != material.ZBuffer) { switch (material.ZBuffer) { case ECFN_NEVER: glDisable(GL_DEPTH_TEST); break; case ECFN_LESSEQUAL: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); break; case ECFN_EQUAL: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_EQUAL); break; case ECFN_LESS: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); break; case ECFN_NOTEQUAL: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_NOTEQUAL); break; case ECFN_GREATEREQUAL: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_GEQUAL); break; case ECFN_GREATER: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_GREATER); break; case ECFN_ALWAYS: glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); break; } } // zwrite // if (resetAllRenderStates || lastmaterial.ZWriteEnable != material.ZWriteEnable) { if (material.ZWriteEnable && (AllowZWriteOnTransparent || !material.isTransparent())) { glDepthMask(GL_TRUE); } else glDepthMask(GL_FALSE); } // back face culling if (resetAllRenderStates || (lastmaterial.FrontfaceCulling != material.FrontfaceCulling) || (lastmaterial.BackfaceCulling != material.BackfaceCulling)) { if ((material.FrontfaceCulling) && (material.BackfaceCulling)) { glCullFace(GL_FRONT_AND_BACK); glEnable(GL_CULL_FACE); } else if (material.BackfaceCulling) { glCullFace(GL_BACK); glEnable(GL_CULL_FACE); } else if (material.FrontfaceCulling) { glCullFace(GL_FRONT); glEnable(GL_CULL_FACE); } else glDisable(GL_CULL_FACE); } // fog if (resetAllRenderStates || lastmaterial.FogEnable != material.FogEnable) { if (material.FogEnable) glEnable(GL_FOG); else glDisable(GL_FOG); } // normalization if (resetAllRenderStates || lastmaterial.NormalizeNormals != material.NormalizeNormals) { if (material.NormalizeNormals) glEnable(GL_NORMALIZE); else glDisable(GL_NORMALIZE); } // Color Mask if (resetAllRenderStates || lastmaterial.ColorMask != material.ColorMask) { glColorMask( (material.ColorMask & ECP_RED)?GL_TRUE:GL_FALSE, (material.ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE, (material.ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE, (material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); } if (queryFeature(EVDF_BLEND_OPERATIONS) && (resetAllRenderStates|| lastmaterial.BlendOperation != material.BlendOperation)) { if (material.BlendOperation==EBO_NONE) glDisable(GL_BLEND); else { glEnable(GL_BLEND); #if defined(GL_EXT_blend_subtract) || defined(GL_EXT_blend_minmax) || defined(GL_EXT_blend_logic_op) || defined(GL_VERSION_1_2) switch (material.BlendOperation) { case EBO_SUBTRACT: #if defined(GL_EXT_blend_subtract) if (FeatureAvailable[IRR_EXT_blend_subtract] || (Version>=120)) extGlBlendEquation(GL_FUNC_SUBTRACT_EXT); #elif defined(GL_VERSION_1_2) if (Version>=120) extGlBlendEquation(GL_FUNC_SUBTRACT); #endif break; case EBO_REVSUBTRACT: #if defined(GL_EXT_blend_subtract) if (FeatureAvailable[IRR_EXT_blend_subtract] || (Version>=120)) extGlBlendEquation(GL_FUNC_REVERSE_SUBTRACT_EXT); #elif defined(GL_VERSION_1_2) if (Version>=120) extGlBlendEquation(GL_FUNC_REVERSE_SUBTRACT); #endif break; case EBO_MIN: #if defined(GL_EXT_blend_minmax) if (FeatureAvailable[IRR_EXT_blend_minmax] || (Version>=120)) extGlBlendEquation(GL_MIN_EXT); #elif defined(GL_VERSION_1_2) if (Version>=120) extGlBlendEquation(GL_MIN); #endif break; case EBO_MAX: #if defined(GL_EXT_blend_minmax) if (FeatureAvailable[IRR_EXT_blend_minmax] || (Version>=120)) extGlBlendEquation(GL_MAX_EXT); #elif defined(GL_VERSION_1_2) if (Version>=120) extGlBlendEquation(GL_MAX); #endif break; case EBO_MIN_FACTOR: #if defined(GL_AMD_blend_minmax_factor) if (FeatureAvailable[IRR_AMD_blend_minmax_factor]) extGlBlendEquation(GL_FACTOR_MIN_AMD); #endif // fallback in case of missing extension #if defined(GL_VERSION_1_2) #if defined(GL_AMD_blend_minmax_factor) else #endif if (Version>=120) extGlBlendEquation(GL_MIN); #endif break; case EBO_MAX_FACTOR: #if defined(GL_AMD_blend_minmax_factor) if (FeatureAvailable[IRR_AMD_blend_minmax_factor]) extGlBlendEquation(GL_FACTOR_MAX_AMD); #endif // fallback in case of missing extension #if defined(GL_VERSION_1_2) #if defined(GL_AMD_blend_minmax_factor) else #endif if (Version>=120) extGlBlendEquation(GL_MAX); #endif break; case EBO_MIN_ALPHA: #if defined(GL_SGIX_blend_alpha_minmax) if (FeatureAvailable[IRR_SGIX_blend_alpha_minmax]) extGlBlendEquation(GL_ALPHA_MIN_SGIX); // fallback in case of missing extension else if (FeatureAvailable[IRR_EXT_blend_minmax]) extGlBlendEquation(GL_MIN_EXT); #endif break; case EBO_MAX_ALPHA: #if defined(GL_SGIX_blend_alpha_minmax) if (FeatureAvailable[IRR_SGIX_blend_alpha_minmax]) extGlBlendEquation(GL_ALPHA_MAX_SGIX); // fallback in case of missing extension else if (FeatureAvailable[IRR_EXT_blend_minmax]) extGlBlendEquation(GL_MAX_EXT); #endif break; default: #if defined(GL_EXT_blend_subtract) || defined(GL_EXT_blend_minmax) || defined(GL_EXT_blend_logic_op) extGlBlendEquation(GL_FUNC_ADD_EXT); #elif defined(GL_VERSION_1_2) extGlBlendEquation(GL_FUNC_ADD); #endif break; } #endif } } // Polygon Offset if (queryFeature(EVDF_POLYGON_OFFSET) && (resetAllRenderStates || lastmaterial.PolygonOffsetDirection != material.PolygonOffsetDirection || lastmaterial.PolygonOffsetFactor != material.PolygonOffsetFactor)) { glDisable(lastmaterial.Wireframe?GL_POLYGON_OFFSET_LINE:lastmaterial.PointCloud?GL_POLYGON_OFFSET_POINT:GL_POLYGON_OFFSET_FILL); if (material.PolygonOffsetFactor) { glDisable(material.Wireframe?GL_POLYGON_OFFSET_LINE:material.PointCloud?GL_POLYGON_OFFSET_POINT:GL_POLYGON_OFFSET_FILL); glEnable(material.Wireframe?GL_POLYGON_OFFSET_LINE:material.PointCloud?GL_POLYGON_OFFSET_POINT:GL_POLYGON_OFFSET_FILL); } if (material.PolygonOffsetDirection==EPO_BACK) glPolygonOffset(1.0f, (GLfloat)material.PolygonOffsetFactor); else glPolygonOffset(-1.0f, (GLfloat)-material.PolygonOffsetFactor); } // thickness if (resetAllRenderStates || lastmaterial.Thickness != material.Thickness) { if (AntiAlias) { // glPointSize(core::clamp(static_cast(material.Thickness), DimSmoothedPoint[0], DimSmoothedPoint[1])); // we don't use point smoothing glPointSize(core::clamp(static_cast(material.Thickness), DimAliasedPoint[0], DimAliasedPoint[1])); glLineWidth(core::clamp(static_cast(material.Thickness), DimSmoothedLine[0], DimSmoothedLine[1])); } else { glPointSize(core::clamp(static_cast(material.Thickness), DimAliasedPoint[0], DimAliasedPoint[1])); glLineWidth(core::clamp(static_cast(material.Thickness), DimAliasedLine[0], DimAliasedLine[1])); } } // Anti aliasing if (resetAllRenderStates || lastmaterial.AntiAliasing != material.AntiAliasing) { if (FeatureAvailable[IRR_ARB_multisample]) { if (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE) glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); else if (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE) glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); if ((AntiAlias >= 2) && (material.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY))) { glEnable(GL_MULTISAMPLE_ARB); #ifdef GL_NV_multisample_filter_hint if (FeatureAvailable[IRR_NV_multisample_filter_hint]) { if ((material.AntiAliasing & EAAM_QUALITY) == EAAM_QUALITY) glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); else glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); } #endif } else glDisable(GL_MULTISAMPLE_ARB); } if ((material.AntiAliasing & EAAM_LINE_SMOOTH) != (lastmaterial.AntiAliasing & EAAM_LINE_SMOOTH)) { if (material.AntiAliasing & EAAM_LINE_SMOOTH) glEnable(GL_LINE_SMOOTH); else if (lastmaterial.AntiAliasing & EAAM_LINE_SMOOTH) glDisable(GL_LINE_SMOOTH); } if ((material.AntiAliasing & EAAM_POINT_SMOOTH) != (lastmaterial.AntiAliasing & EAAM_POINT_SMOOTH)) { if (material.AntiAliasing & EAAM_POINT_SMOOTH) // often in software, and thus very slow glEnable(GL_POINT_SMOOTH); else if (lastmaterial.AntiAliasing & EAAM_POINT_SMOOTH) glDisable(GL_POINT_SMOOTH); } } setWrapMode(material); // be sure to leave in texture stage 0 if (MultiTextureExtension) extGlActiveTexture(GL_TEXTURE0_ARB); } //! Enable the 2d override material void COpenGLDriver::enableMaterial2D(bool enable) { if (!enable) CurrentRenderMode = ERM_NONE; CNullDriver::enableMaterial2D(enable); } //! sets the needed renderstates void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel) { if (CurrentRenderMode != ERM_2D || Transformation3DChanged) { // unset last 3d material if (CurrentRenderMode == ERM_3D) { if (static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); } if (Transformation3DChanged) { glMatrixMode(GL_PROJECTION); const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); core::matrix4 m(core::matrix4::EM4CONST_NOTHING); m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0f, 1.0f); m.setTranslation(core::vector3df(-1,1,0)); glLoadMatrixf(m.pointer()); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.375f, 0.375f, 0.0f); // Make sure we set first texture matrix if (MultiTextureExtension) extGlActiveTexture(GL_TEXTURE0_ARB); Transformation3DChanged = false; } if (!OverrideMaterial2DEnabled) { setBasicRenderStates(InitMaterial2D, LastMaterial, true); LastMaterial = InitMaterial2D; } glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #ifdef GL_EXT_clip_volume_hint if (FeatureAvailable[IRR_EXT_clip_volume_hint]) glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST); #endif } if (OverrideMaterial2DEnabled) { OverrideMaterial2D.Lighting=false; setBasicRenderStates(OverrideMaterial2D, LastMaterial, false); LastMaterial = OverrideMaterial2D; } // no alphaChannel without texture alphaChannel &= texture; if (alphaChannel || alpha) { glEnable(GL_BLEND); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.f); } else { glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); } if (texture) { if (!OverrideMaterial2DEnabled) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } Material.setTexture(0, const_cast(CurrentTexture[0])); setTransform(ETS_TEXTURE_0, core::IdentityMatrix); // Due to the transformation change, the previous line would call a reset each frame // but we can safely reset the variable as it was false before Transformation3DChanged=false; if (alphaChannel) { // if alpha and alpha texture just modulate, otherwise use only the alpha channel if (alpha) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } else { #if defined(GL_ARB_texture_env_combine) || defined(GL_EXT_texture_env_combine) if (FeatureAvailable[IRR_ARB_texture_env_combine]||FeatureAvailable[IRR_EXT_texture_env_combine]) { #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); // rgb always modulates glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); #else glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); // rgb always modulates glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); #endif } else #endif glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } else { if (alpha) { #if defined(GL_ARB_texture_env_combine) || defined(GL_EXT_texture_env_combine) if (FeatureAvailable[IRR_ARB_texture_env_combine]||FeatureAvailable[IRR_EXT_texture_env_combine]) { #ifdef GL_ARB_texture_env_combine glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); // rgb always modulates glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); #else glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); // rgb always modulates glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); #endif } else #endif glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } else { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } } CurrentRenderMode = ERM_2D; } //! \return Returns the name of the video driver. const wchar_t* COpenGLDriver::getName() const { return Name.c_str(); } //! deletes all dynamic lights there are void COpenGLDriver::deleteAllDynamicLights() { for (s32 i=0; i= (s32)RequestedLights.size()) return; RequestedLight & requestedLight = RequestedLights[lightIndex]; requestedLight.DesireToBeOn = turnOn; if(turnOn) { if(-1 == requestedLight.HardwareLightIndex) assignHardwareLight(lightIndex); } else { if(-1 != requestedLight.HardwareLightIndex) { // It's currently assigned, so free up the hardware light glDisable(requestedLight.HardwareLightIndex); requestedLight.HardwareLightIndex = -1; // Now let the first light that's waiting on a free hardware light grab it for(u32 requested = 0; requested < RequestedLights.size(); ++requested) if(RequestedLights[requested].DesireToBeOn && -1 == RequestedLights[requested].HardwareLightIndex) { assignHardwareLight(requested); break; } } } } //! returns the maximal amount of dynamic lights the device can handle u32 COpenGLDriver::getMaximalDynamicLightAmount() const { return MaxLights; } //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. void COpenGLDriver::setAmbientLight(const SColorf& color) { GLfloat data[4] = {color.r, color.g, color.b, color.a}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, data); } // this code was sent in by Oliver Klems, thank you! (I modified the glViewport // method just a bit. void COpenGLDriver::setViewPort(const core::rect& area) { if (area == ViewPort) return; core::rect vp = area; core::rect rendert(0,0, getCurrentRenderTargetSize().Width, getCurrentRenderTargetSize().Height); vp.clipAgainst(rendert); if (vp.getHeight()>0 && vp.getWidth()>0) { glViewport(vp.UpperLeftCorner.X, getCurrentRenderTargetSize().Height - vp.UpperLeftCorner.Y - vp.getHeight(), vp.getWidth(), vp.getHeight()); ViewPort = vp; } } //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do //! this: First, draw all geometry. Then use this method, to draw the shadow //! volume. Next use IVideoDriver::drawStencilShadow() to visualize the shadow. void COpenGLDriver::drawStencilShadowVolume(const core::array& triangles, bool zfail, u32 debugDataVisible) { const u32 count=triangles.size(); if (!StencilBuffer || !count) return; // unset last 3d material if (CurrentRenderMode == ERM_3D && static_cast(Material.MaterialType) < MaterialRenderers.size()) { MaterialRenderers[Material.MaterialType].Renderer->OnUnsetMaterial(); ResetRenderStates = true; } // store current OpenGL state glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT | GL_STENCIL_BUFFER_BIT); glDisable(GL_LIGHTING); glDisable(GL_FOG); glDepthFunc(GL_LESS); glDepthMask(GL_FALSE); // no depth buffer writing if (debugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); if (!(debugDataVisible & (scene::EDS_SKELETON|scene::EDS_MESH_WIRE_OVERLAY))) { glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no color buffer drawing glEnable(GL_STENCIL_TEST); } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3,GL_FLOAT,sizeof(core::vector3df),triangles.const_pointer()); glStencilMask(~0); glStencilFunc(GL_ALWAYS, 0, ~0); GLenum incr = GL_INCR; GLenum decr = GL_DECR; #ifdef GL_EXT_stencil_wrap if (FeatureAvailable[IRR_EXT_stencil_wrap]) { incr = GL_INCR_WRAP_EXT; decr = GL_DECR_WRAP_EXT; } #endif #ifdef GL_NV_depth_clamp if (FeatureAvailable[IRR_NV_depth_clamp]) glEnable(GL_DEPTH_CLAMP_NV); #endif // The first parts are not correctly working, yet. #if 0 #ifdef GL_EXT_stencil_two_side if (FeatureAvailable[IRR_EXT_stencil_two_side]) { glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); glDisable(GL_CULL_FACE); if (zfail) { extGlActiveStencilFace(GL_BACK); glStencilOp(GL_KEEP, incr, GL_KEEP); glStencilMask(~0); glStencilFunc(GL_ALWAYS, 0, ~0); extGlActiveStencilFace(GL_FRONT); glStencilOp(GL_KEEP, decr, GL_KEEP); } else // zpass { extGlActiveStencilFace(GL_BACK); glStencilOp(GL_KEEP, GL_KEEP, decr); glStencilMask(~0); glStencilFunc(GL_ALWAYS, 0, ~0); extGlActiveStencilFace(GL_FRONT); glStencilOp(GL_KEEP, GL_KEEP, incr); } glStencilMask(~0); glStencilFunc(GL_ALWAYS, 0, ~0); glDrawArrays(GL_TRIANGLES,0,count); glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); } else #endif if (FeatureAvailable[IRR_ATI_separate_stencil]) { glDisable(GL_CULL_FACE); if (zfail) { extGlStencilOpSeparate(GL_BACK, GL_KEEP, incr, GL_KEEP); extGlStencilOpSeparate(GL_FRONT, GL_KEEP, decr, GL_KEEP); } else // zpass { extGlStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, decr); extGlStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, incr); } extGlStencilFuncSeparate(GL_ALWAYS, GL_ALWAYS, 0, ~0); glStencilMask(~0); glDrawArrays(GL_TRIANGLES,0,count); } else #endif { glEnable(GL_CULL_FACE); if (zfail) { glCullFace(GL_FRONT); glStencilOp(GL_KEEP, incr, GL_KEEP); glDrawArrays(GL_TRIANGLES,0,count); glCullFace(GL_BACK); glStencilOp(GL_KEEP, decr, GL_KEEP); glDrawArrays(GL_TRIANGLES,0,count); } else // zpass { glCullFace(GL_BACK); glStencilOp(GL_KEEP, GL_KEEP, incr); glDrawArrays(GL_TRIANGLES,0,count); glCullFace(GL_FRONT); glStencilOp(GL_KEEP, GL_KEEP, decr); glDrawArrays(GL_TRIANGLES,0,count); } } #ifdef GL_NV_depth_clamp if (FeatureAvailable[IRR_NV_depth_clamp]) glDisable(GL_DEPTH_CLAMP_NV); #endif glDisable(GL_POLYGON_OFFSET_FILL); glDisableClientState(GL_VERTEX_ARRAY); //not stored on stack glPopAttrib(); } //! Fills the stencil shadow with color. After the shadow volume has been drawn //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this //! to draw the color of the shadow. void COpenGLDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge, video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge) { if (!StencilBuffer) return; disableTextures(); // store attributes glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT | GL_STENCIL_BUFFER_BIT | GL_LIGHTING_BIT); glDisable(GL_LIGHTING); glDisable(GL_FOG); glDepthMask(GL_FALSE); glShadeModel(GL_FLAT); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_NOTEQUAL, 0, ~0); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // draw a shadow rectangle covering the entire screen using stencil buffer glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glBegin(GL_QUADS); glColor4ub(leftDownEdge.getRed(), leftDownEdge.getGreen(), leftDownEdge.getBlue(), leftDownEdge.getAlpha()); glVertex3f(-1.f,-1.f,-0.9f); glColor4ub(leftUpEdge.getRed(), leftUpEdge.getGreen(), leftUpEdge.getBlue(), leftUpEdge.getAlpha()); glVertex3f(-1.f, 1.f,-0.9f); glColor4ub(rightUpEdge.getRed(), rightUpEdge.getGreen(), rightUpEdge.getBlue(), rightUpEdge.getAlpha()); glVertex3f(1.f, 1.f,-0.9f); glColor4ub(rightDownEdge.getRed(), rightDownEdge.getGreen(), rightDownEdge.getBlue(), rightDownEdge.getAlpha()); glVertex3f(1.f,-1.f,-0.9f); glEnd(); clearBuffers(false, false, clearStencilBuffer, 0x0); // restore settings glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPopAttrib(); } //! Sets the fog mode. void COpenGLDriver::setFog(SColor c, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog) { CNullDriver::setFog(c, fogType, start, end, density, pixelFog, rangeFog); glFogf(GL_FOG_MODE, GLfloat((fogType==EFT_FOG_LINEAR)? GL_LINEAR : (fogType==EFT_FOG_EXP)?GL_EXP:GL_EXP2)); #ifdef GL_EXT_fog_coord if (FeatureAvailable[IRR_EXT_fog_coord]) glFogi(GL_FOG_COORDINATE_SOURCE, GL_FRAGMENT_DEPTH); #endif #ifdef GL_NV_fog_distance if (FeatureAvailable[IRR_NV_fog_distance]) { if (rangeFog) glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV); else glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV); } #endif if (fogType==EFT_FOG_LINEAR) { glFogf(GL_FOG_START, start); glFogf(GL_FOG_END, end); } else glFogf(GL_FOG_DENSITY, density); if (pixelFog) glHint(GL_FOG_HINT, GL_NICEST); else glHint(GL_FOG_HINT, GL_FASTEST); SColorf color(c); GLfloat data[4] = {color.r, color.g, color.b, color.a}; glFogfv(GL_FOG_COLOR, data); } //! Draws a 3d line. void COpenGLDriver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color) { setRenderStates3DMode(); glBegin(GL_LINES); glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); glVertex3f(start.X, start.Y, start.Z); glVertex3f(end.X, end.Y, end.Z); glEnd(); } //! Removes a texture from the texture cache and deletes it, freeing lot of memory. void COpenGLDriver::removeTexture(ITexture* texture) { if (!texture) return; CNullDriver::removeTexture(texture); // Remove this texture from CurrentTexture as well CurrentTexture.remove(texture); } //! Only used by the internal engine. Used to notify the driver that //! the window was resized. void COpenGLDriver::OnResize(const core::dimension2d& size) { CNullDriver::OnResize(size); glViewport(0, 0, size.Width, size.Height); Transformation3DChanged = true; } //! Returns type of video driver E_DRIVER_TYPE COpenGLDriver::getDriverType() const { return EDT_OPENGL; } //! returns color format ECOLOR_FORMAT COpenGLDriver::getColorFormat() const { return ColorFormat; } //! Sets a vertex shader constant. void COpenGLDriver::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { #ifdef GL_ARB_vertex_program for (s32 i=0; isetPixelShaderConstant(), not VideoDriver->setPixelShaderConstant()."); return false; } //! Bool interface for the above. bool COpenGLDriver::setPixelShaderConstant(const c8* name, const bool* bools, int count) { os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant()."); return false; } //! Int interface for the above. bool COpenGLDriver::setPixelShaderConstant(const c8* name, const s32* ints, int count) { os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant()."); return false; } //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. s32 COpenGLDriver::addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) { s32 nr = -1; COpenGLShaderMaterialRenderer* r = new COpenGLShaderMaterialRenderer( this, nr, vertexShaderProgram, pixelShaderProgram, callback, getMaterialRenderer(baseMaterial), userData); r->drop(); return nr; } //! Adds a new material renderer to the VideoDriver, using GLSL to render geometry. s32 COpenGLDriver::addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, const c8* geometryShaderProgram, const c8* geometryShaderEntryPointName, E_GEOMETRY_SHADER_TYPE gsCompileTarget, scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 verticesOut, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData, E_GPU_SHADING_LANGUAGE shadingLang) { s32 nr = -1; #ifdef _IRR_COMPILE_WITH_CG_ if (shadingLang == EGSL_CG) { COpenGLCgMaterialRenderer* r = new COpenGLCgMaterialRenderer( this, nr, vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget, inType, outType, verticesOut, callback,getMaterialRenderer(baseMaterial), userData); r->drop(); } else #endif { COpenGLSLMaterialRenderer* r = new COpenGLSLMaterialRenderer( this, nr, vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget, inType, outType, verticesOut, callback,getMaterialRenderer(baseMaterial), userData); r->drop(); } return nr; } //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) IVideoDriver* COpenGLDriver::getVideoDriver() { return this; } ITexture* COpenGLDriver::addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format) { //disable mip-mapping bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false); video::ITexture* rtt = 0; #if defined(GL_EXT_framebuffer_object) // if driver supports FrameBufferObjects, use them if (queryFeature(EVDF_FRAMEBUFFER_OBJECT)) { rtt = new COpenGLFBOTexture(size, name, this, format); if (rtt) { bool success = false; addTexture(rtt); ITexture* tex = createDepthTexture(rtt); if (tex) { success = static_cast(tex)->attach(rtt); if ( !success ) { removeDepthTexture(tex); } tex->drop(); } rtt->drop(); if (!success) { removeTexture(rtt); rtt=0; } } } else #endif { // the simple texture is only possible for size <= screensize // we try to find an optimal size with the original constraints core::dimension2du destSize(core::min_(size.Width,ScreenSize.Width), core::min_(size.Height,ScreenSize.Height)); destSize = destSize.getOptimalSize((size==size.getOptimalSize()), false, false); rtt = addTexture(destSize, name, ECF_A8R8G8B8); if (rtt) { static_cast(rtt)->setIsRenderTarget(true); } } //restore mip-mapping setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, generateMipLevels); return rtt; } //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. u32 COpenGLDriver::getMaximalPrimitiveCount() const { return 0x7fffffff; } //! set or reset render target bool COpenGLDriver::setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget, bool clearZBuffer, SColor color) { if (target != CurrentTarget) setRenderTarget(0, false, false, 0x0); if (ERT_RENDER_TEXTURE == target) { os::Printer::log("For render textures call setRenderTarget with the actual texture as first parameter.", ELL_ERROR); return false; } if (ERT_MULTI_RENDER_TEXTURES == target) { os::Printer::log("For multiple render textures call setRenderTarget with the texture array as first parameter.", ELL_ERROR); return false; } if (Params.Stereobuffer && (ERT_STEREO_RIGHT_BUFFER == target)) { if (Params.Doublebuffer) glDrawBuffer(GL_BACK_RIGHT); else glDrawBuffer(GL_FRONT_RIGHT); } else if (Params.Stereobuffer && ERT_STEREO_BOTH_BUFFERS == target) { if (Params.Doublebuffer) glDrawBuffer(GL_BACK); else glDrawBuffer(GL_FRONT); } else if ((target >= ERT_AUX_BUFFER0) && (target-ERT_AUX_BUFFER0 < MaxAuxBuffers)) { glDrawBuffer(GL_AUX0+target-ERT_AUX_BUFFER0); } else { if (Params.Doublebuffer) glDrawBuffer(GL_BACK_LEFT); else glDrawBuffer(GL_FRONT_LEFT); // exit with false, but also with working color buffer if (target != ERT_FRAME_BUFFER) return false; } CurrentTarget=target; clearBuffers(clearTarget, clearZBuffer, false, color); return true; } //! set or reset render target bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color) { // check for right driver type if (texture && texture->getDriverType() != EDT_OPENGL) { os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); return false; } #if defined(GL_EXT_framebuffer_object) if (CurrentTarget==ERT_MULTI_RENDER_TEXTURES) { for (u32 i=0; iunbindRTT(); } if (texture) { // we want to set a new target. so do this. glViewport(0, 0, texture->getSize().Width, texture->getSize().Height); RenderTargetTexture = static_cast(texture); // calls glDrawBuffer as well RenderTargetTexture->bindRTT(); CurrentRendertargetSize = texture->getSize(); CurrentTarget=ERT_RENDER_TEXTURE; } else { glViewport(0,0,ScreenSize.Width,ScreenSize.Height); RenderTargetTexture = 0; CurrentRendertargetSize = core::dimension2d(0,0); CurrentTarget=ERT_FRAME_BUFFER; glDrawBuffer(Params.Doublebuffer?GL_BACK_LEFT:GL_FRONT_LEFT); } // we need to update the matrices due to the rendersize change. Transformation3DChanged=true; } clearBuffers(clearBackBuffer, clearZBuffer, false, color); return true; } //! Sets multiple render targets bool COpenGLDriver::setRenderTarget(const core::array& targets, bool clearBackBuffer, bool clearZBuffer, SColor color) { // if simply disabling the MRT via array call if (targets.size()==0) return setRenderTarget(0, clearBackBuffer, clearZBuffer, color); // if disabling old MRT, but enabling new one as well if ((MRTargets.size()!=0) && (targets != MRTargets)) setRenderTarget(0, clearBackBuffer, clearZBuffer, color); // if no change, simply clear buffers else if (targets == MRTargets) { clearBuffers(clearBackBuffer, clearZBuffer, false, color); return true; } // copy to storage for correct disabling MRTargets=targets; u32 maxMultipleRTTs = core::min_(static_cast(MaxMultipleRenderTargets), targets.size()); // determine common size core::dimension2du rttSize = CurrentRendertargetSize; if (targets[0].TargetType==ERT_RENDER_TEXTURE) { if (!targets[0].RenderTexture) { os::Printer::log("Missing render texture for MRT.", ELL_ERROR); return false; } rttSize=targets[0].RenderTexture->getSize(); } for (u32 i = 0; i < maxMultipleRTTs; ++i) { // check for right driver type if (targets[i].TargetType==ERT_RENDER_TEXTURE) { if (!targets[i].RenderTexture) { maxMultipleRTTs=i; os::Printer::log("Missing render texture for MRT.", ELL_WARNING); break; } if (targets[i].RenderTexture->getDriverType() != EDT_OPENGL) { maxMultipleRTTs=i; os::Printer::log("Tried to set a texture not owned by this driver.", ELL_WARNING); break; } // check for valid render target if (!targets[i].RenderTexture->isRenderTarget() || !static_cast(targets[i].RenderTexture)->isFrameBufferObject()) { maxMultipleRTTs=i; os::Printer::log("Tried to set a non FBO-RTT as render target.", ELL_WARNING); break; } // check for valid size if (rttSize != targets[i].RenderTexture->getSize()) { maxMultipleRTTs=i; os::Printer::log("Render target texture has wrong size.", ELL_WARNING); break; } } } if (maxMultipleRTTs==0) { os::Printer::log("No valid MRTs.", ELL_ERROR); return false; } // init FBO, if any for (u32 i=0; i 1) { CurrentTarget=ERT_MULTI_RENDER_TEXTURES; core::array MRTs; MRTs.set_used(maxMultipleRTTs); for(u32 i = 0; i < maxMultipleRTTs; i++) { if (FeatureAvailable[IRR_EXT_draw_buffers2]) { extGlColorMaskIndexed(i, (targets[i].ColorMask & ECP_RED)?GL_TRUE:GL_FALSE, (targets[i].ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE, (targets[i].ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE, (targets[i].ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); if (targets[i].BlendOp==EBO_NONE) extGlDisableIndexed(GL_BLEND, i); else extGlEnableIndexed(GL_BLEND, i); } #if defined(GL_AMD_draw_buffers_blend) || defined(GL_ARB_draw_buffers_blend) if (FeatureAvailable[IRR_AMD_draw_buffers_blend] || FeatureAvailable[IRR_ARB_draw_buffers_blend]) { extGlBlendFuncIndexed(i, getGLBlend(targets[i].BlendFuncSrc), getGLBlend(targets[i].BlendFuncDst)); switch(targets[i].BlendOp) { case EBO_SUBTRACT: extGlBlendEquationIndexed(i, GL_FUNC_SUBTRACT); break; case EBO_REVSUBTRACT: extGlBlendEquationIndexed(i, GL_FUNC_REVERSE_SUBTRACT); break; case EBO_MIN: extGlBlendEquationIndexed(i, GL_MIN); break; case EBO_MAX: extGlBlendEquationIndexed(i, GL_MAX); break; case EBO_MIN_FACTOR: case EBO_MIN_ALPHA: #if defined(GL_AMD_blend_minmax_factor) if (FeatureAvailable[IRR_AMD_blend_minmax_factor]) extGlBlendEquationIndexed(i, GL_FACTOR_MIN_AMD); // fallback in case of missing extension else #endif extGlBlendEquation(GL_MIN); break; case EBO_MAX_FACTOR: case EBO_MAX_ALPHA: #if defined(GL_AMD_blend_minmax_factor) if (FeatureAvailable[IRR_AMD_blend_minmax_factor]) extGlBlendEquationIndexed(i, GL_FACTOR_MAX_AMD); // fallback in case of missing extension else #endif extGlBlendEquation(GL_MAX); break; default: extGlBlendEquationIndexed(i, GL_FUNC_ADD); break; } } #endif if (targets[i].TargetType==ERT_RENDER_TEXTURE) { GLenum attachment = GL_NONE; #ifdef GL_EXT_framebuffer_object // attach texture to FrameBuffer Object on Color [i] attachment = GL_COLOR_ATTACHMENT0_EXT+i; if ((i != 0) && (targets[i].RenderTexture != RenderTargetTexture)) extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, static_cast(targets[i].RenderTexture)->getOpenGLTextureName(), 0); #endif MRTs[i]=attachment; } else { switch(targets[i].TargetType) { case ERT_FRAME_BUFFER: MRTs[i]=GL_BACK_LEFT; break; case ERT_STEREO_BOTH_BUFFERS: MRTs[i]=GL_BACK; break; case ERT_STEREO_RIGHT_BUFFER: MRTs[i]=GL_BACK_RIGHT; break; case ERT_STEREO_LEFT_BUFFER: MRTs[i]=GL_BACK_LEFT; break; default: MRTs[i]=GL_AUX0+(targets[i].TargetType-ERT_AUX_BUFFER0); break; } } } extGlDrawBuffers(maxMultipleRTTs, MRTs.const_pointer()); } clearBuffers(clearBackBuffer, clearZBuffer, false, color); return true; } // returns the current size of the screen or rendertarget const core::dimension2d& COpenGLDriver::getCurrentRenderTargetSize() const { if (CurrentRendertargetSize.Width == 0) return ScreenSize; else return CurrentRendertargetSize; } //! Clears the ZBuffer. void COpenGLDriver::clearZBuffer() { clearBuffers(false, true, false, 0x0); } //! Returns an image created from the last rendered frame. IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target) { if (target==video::ERT_MULTI_RENDER_TEXTURES || target==video::ERT_RENDER_TEXTURE || target==video::ERT_STEREO_BOTH_BUFFERS) return 0; // allows to read pixels in top-to-bottom order #ifdef GL_MESA_pack_invert if (FeatureAvailable[IRR_MESA_pack_invert]) glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); #endif if (format==video::ECF_UNKNOWN) format=getColorFormat(); GLenum fmt; GLenum type; switch (format) { case ECF_A1R5G5B5: fmt = GL_BGRA; type = GL_UNSIGNED_SHORT_1_5_5_5_REV; break; case ECF_R5G6B5: fmt = GL_RGB; type = GL_UNSIGNED_SHORT_5_6_5; break; case ECF_R8G8B8: fmt = GL_RGB; type = GL_UNSIGNED_BYTE; break; case ECF_A8R8G8B8: fmt = GL_BGRA; if (Version > 101) type = GL_UNSIGNED_INT_8_8_8_8_REV; else type = GL_UNSIGNED_BYTE; break; case ECF_R16F: if (FeatureAvailable[IRR_ARB_texture_rg]) fmt = GL_RED; else fmt = GL_LUMINANCE; #ifdef GL_ARB_half_float_pixel if (FeatureAvailable[IRR_ARB_half_float_pixel]) type = GL_HALF_FLOAT_ARB; else #endif { type = GL_FLOAT; format = ECF_R32F; } break; case ECF_G16R16F: #ifdef GL_ARB_texture_rg if (FeatureAvailable[IRR_ARB_texture_rg]) fmt = GL_RG; else #endif fmt = GL_LUMINANCE_ALPHA; #ifdef GL_ARB_half_float_pixel if (FeatureAvailable[IRR_ARB_half_float_pixel]) type = GL_HALF_FLOAT_ARB; else #endif { type = GL_FLOAT; format = ECF_G32R32F; } break; case ECF_A16B16G16R16F: fmt = GL_BGRA; #ifdef GL_ARB_half_float_pixel if (FeatureAvailable[IRR_ARB_half_float_pixel]) type = GL_HALF_FLOAT_ARB; else #endif { type = GL_FLOAT; format = ECF_A32B32G32R32F; } break; case ECF_R32F: if (FeatureAvailable[IRR_ARB_texture_rg]) fmt = GL_RED; else fmt = GL_LUMINANCE; type = GL_FLOAT; break; case ECF_G32R32F: #ifdef GL_ARB_texture_rg if (FeatureAvailable[IRR_ARB_texture_rg]) fmt = GL_RG; else #endif fmt = GL_LUMINANCE_ALPHA; type = GL_FLOAT; break; case ECF_A32B32G32R32F: fmt = GL_BGRA; type = GL_FLOAT; break; default: fmt = GL_BGRA; type = GL_UNSIGNED_BYTE; break; } IImage* newImage = createImage(format, ScreenSize); u8* pixels = 0; if (newImage) pixels = static_cast(newImage->lock()); if (pixels) { GLenum tgt=GL_FRONT; switch (target) { case video::ERT_FRAME_BUFFER: break; case video::ERT_STEREO_LEFT_BUFFER: tgt=GL_FRONT_LEFT; break; case video::ERT_STEREO_RIGHT_BUFFER: tgt=GL_FRONT_RIGHT; break; default: tgt=GL_AUX0+(target-video::ERT_AUX_BUFFER0); break; } glReadBuffer(tgt); glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, fmt, type, pixels); testGLError(); glReadBuffer(GL_BACK); } #ifdef GL_MESA_pack_invert if (FeatureAvailable[IRR_MESA_pack_invert]) glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE); else #endif if (pixels) { // opengl images are horizontally flipped, so we have to fix that here. const s32 pitch=newImage->getPitch(); u8* p2 = pixels + (ScreenSize.Height - 1) * pitch; u8* tmpBuffer = new u8[pitch]; for (u32 i=0; i < ScreenSize.Height; i += 2) { memcpy(tmpBuffer, pixels, pitch); // for (u32 j=0; junlock(); if (testGLError() || !pixels) { newImage->drop(); return 0; } } return newImage; } //! get depth texture for the given render target texture ITexture* COpenGLDriver::createDepthTexture(ITexture* texture, bool shared) { if ((texture->getDriverType() != EDT_OPENGL) || (!texture->isRenderTarget())) return 0; COpenGLTexture* tex = static_cast(texture); if (!tex->isFrameBufferObject()) return 0; if (shared) { for (u32 i=0; igetSize()==texture->getSize()) { DepthTextures[i]->grab(); return DepthTextures[i]; } } DepthTextures.push_back(new COpenGLFBODepthTexture(texture->getSize(), "depth1", this)); return DepthTextures.getLast(); } return (new COpenGLFBODepthTexture(texture->getSize(), "depth1", this)); } void COpenGLDriver::removeDepthTexture(ITexture* texture) { for (u32 i=0; i= MaxUserClipPlanes) return false; UserClipPlanes[index].Plane=plane; enableClipPlane(index, enable); return true; } void COpenGLDriver::uploadClipPlane(u32 index) { // opengl needs an array of doubles for the plane equation GLdouble clip_plane[4]; clip_plane[0] = UserClipPlanes[index].Plane.Normal.X; clip_plane[1] = UserClipPlanes[index].Plane.Normal.Y; clip_plane[2] = UserClipPlanes[index].Plane.Normal.Z; clip_plane[3] = UserClipPlanes[index].Plane.D; glClipPlane(GL_CLIP_PLANE0 + index, clip_plane); } //! Enable/disable a clipping plane. void COpenGLDriver::enableClipPlane(u32 index, bool enable) { if (index >= MaxUserClipPlanes) return; if (enable) { if (!UserClipPlanes[index].Enabled) { uploadClipPlane(index); glEnable(GL_CLIP_PLANE0 + index); } } else glDisable(GL_CLIP_PLANE0 + index); UserClipPlanes[index].Enabled=enable; } core::dimension2du COpenGLDriver::getMaxTextureSize() const { return core::dimension2du(MaxTextureSize, MaxTextureSize); } //! Convert E_PRIMITIVE_TYPE to OpenGL equivalent GLenum COpenGLDriver::primitiveTypeToGL(scene::E_PRIMITIVE_TYPE type) const { switch (type) { case scene::EPT_POINTS: return GL_POINTS; case scene::EPT_LINE_STRIP: return GL_LINE_STRIP; case scene::EPT_LINE_LOOP: return GL_LINE_LOOP; case scene::EPT_LINES: return GL_LINES; case scene::EPT_TRIANGLE_STRIP: return GL_TRIANGLE_STRIP; case scene::EPT_TRIANGLE_FAN: return GL_TRIANGLE_FAN; case scene::EPT_TRIANGLES: return GL_TRIANGLES; case scene::EPT_QUAD_STRIP: return GL_QUAD_STRIP; case scene::EPT_QUADS: return GL_QUADS; case scene::EPT_POLYGON: return GL_POLYGON; case scene::EPT_POINT_SPRITES: #ifdef GL_ARB_point_sprite return GL_POINT_SPRITE_ARB; #else return GL_POINTS; #endif } return GL_TRIANGLES; } GLenum COpenGLDriver::getGLBlend(E_BLEND_FACTOR factor) const { GLenum r = 0; switch (factor) { case EBF_ZERO: r = GL_ZERO; break; case EBF_ONE: r = GL_ONE; break; case EBF_DST_COLOR: r = GL_DST_COLOR; break; case EBF_ONE_MINUS_DST_COLOR: r = GL_ONE_MINUS_DST_COLOR; break; case EBF_SRC_COLOR: r = GL_SRC_COLOR; break; case EBF_ONE_MINUS_SRC_COLOR: r = GL_ONE_MINUS_SRC_COLOR; break; case EBF_SRC_ALPHA: r = GL_SRC_ALPHA; break; case EBF_ONE_MINUS_SRC_ALPHA: r = GL_ONE_MINUS_SRC_ALPHA; break; case EBF_DST_ALPHA: r = GL_DST_ALPHA; break; case EBF_ONE_MINUS_DST_ALPHA: r = GL_ONE_MINUS_DST_ALPHA; break; case EBF_SRC_ALPHA_SATURATE: r = GL_SRC_ALPHA_SATURATE; break; } return r; } GLenum COpenGLDriver::getZBufferBits() const { GLenum bits = 0; switch (Params.ZBufferBits) { case 16: bits = GL_DEPTH_COMPONENT16; break; case 24: bits = GL_DEPTH_COMPONENT24; break; case 32: bits = GL_DEPTH_COMPONENT32; break; default: bits = GL_DEPTH_COMPONENT; break; } return bits; } #ifdef _IRR_COMPILE_WITH_CG_ const CGcontext& COpenGLDriver::getCgContext() { return CgContext; } #endif } // end namespace } // end namespace #endif // _IRR_COMPILE_WITH_OPENGL_ namespace irr { namespace video { // ----------------------------------- // WINDOWS VERSION // ----------------------------------- #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceWin32* device) { #ifdef _IRR_COMPILE_WITH_OPENGL_ COpenGLDriver* ogl = new COpenGLDriver(params, io, device); if (!ogl->initDriver(device)) { ogl->drop(); ogl = 0; } return ogl; #else return 0; #endif // _IRR_COMPILE_WITH_OPENGL_ } #endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ // ----------------------------------- // MACOSX VERSION // ----------------------------------- #if defined(_IRR_COMPILE_WITH_OSX_DEVICE_) IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceMacOSX *device) { #ifdef _IRR_COMPILE_WITH_OPENGL_ return new COpenGLDriver(params, io, device); #else return 0; #endif // _IRR_COMPILE_WITH_OPENGL_ } #endif // _IRR_COMPILE_WITH_OSX_DEVICE_ // ----------------------------------- // X11 VERSION // ----------------------------------- #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceLinux* device) { #ifdef _IRR_COMPILE_WITH_OPENGL_ COpenGLDriver* ogl = new COpenGLDriver(params, io, device); if (!ogl->initDriver(device)) { ogl->drop(); ogl = 0; } return ogl; #else return 0; #endif // _IRR_COMPILE_WITH_OPENGL_ } #endif // _IRR_COMPILE_WITH_X11_DEVICE_ // ----------------------------------- // SDL VERSION // ----------------------------------- #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceSDL* device) { #ifdef _IRR_COMPILE_WITH_OPENGL_ return new COpenGLDriver(params, io, device); #else return 0; #endif // _IRR_COMPILE_WITH_OPENGL_ } #endif // _IRR_COMPILE_WITH_SDL_DEVICE_ } // end namespace } // end namespace irrlicht-1.8.3/source/Irrlicht/COpenGLCgMaterialRenderer.h0000644000000000000000000000607012574354552022160 0ustar rootroot// Copyright (C) 2012-2012 Patryk Nadrowski // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_OPENGL_CG_MATERIAL_RENDERER_H_INCLUDED__ #define __C_OPENGL_CG_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #if defined(_IRR_COMPILE_WITH_OPENGL_) && defined(_IRR_COMPILE_WITH_CG_) #ifdef _IRR_WINDOWS_API_ #define WIN32_LEAN_AND_MEAN #include #include #include "glext.h" #else #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #define GL_GLEXT_LEGACY 1 #else #define GL_GLEXT_PROTOTYPES 1 #endif #if defined(_IRR_OSX_PLATFORM_) #include #else #include #endif #if defined(_IRR_OPENGL_USE_EXTPOINTER_) #include "glext.h" #endif #endif #include "CCgMaterialRenderer.h" #include "Cg/cgGL.h" #ifdef _MSC_VER #pragma comment(lib, "cgGL.lib") #endif namespace irr { namespace video { class COpenGLDriver; class IShaderConstantSetCallBack; class COpenGLCgUniformSampler2D : public CCgUniform { public: COpenGLCgUniformSampler2D(const CGparameter& parameter, bool global); void update(const void* data, const SMaterial& material) const; }; class COpenGLCgMaterialRenderer : public CCgMaterialRenderer { public: COpenGLCgMaterialRenderer(COpenGLDriver* driver, s32& materialType, const c8* vertexProgram = 0, const c8* vertexEntry = "main", E_VERTEX_SHADER_TYPE vertexProfile = video::EVST_VS_1_1, const c8* fragmentProgram = 0, const c8* fragmentEntry = "main", E_PIXEL_SHADER_TYPE fragmentProfile = video::EPST_PS_1_1, const c8* geometryProgram = 0, const c8* geometryEntry = "main", E_GEOMETRY_SHADER_TYPE geometryProfile = video::EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 vertices = 0, IShaderConstantSetCallBack* callback = 0, IMaterialRenderer* baseMaterial = 0, s32 userData = 0); virtual ~COpenGLCgMaterialRenderer(); virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services); virtual bool OnRender(IMaterialRendererServices* services, E_VERTEX_TYPE vtxtype); virtual void OnUnsetMaterial(); virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates); virtual IVideoDriver* getVideoDriver(); protected: void init(s32& materialType, const c8* vertexProgram = 0, const c8* vertexEntry = "main", E_VERTEX_SHADER_TYPE vertexProfile = video::EVST_VS_1_1, const c8* fragmentProgram = 0, const c8* fragmentEntry = "main", E_PIXEL_SHADER_TYPE fragmentProfile = video::EPST_PS_1_1, const c8* geometryProgram = 0, const c8* geometryEntry = "main", E_GEOMETRY_SHADER_TYPE geometryProfile = video::EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 vertices = 0); COpenGLDriver* Driver; }; } } #endif #endif irrlicht-1.8.3/source/Irrlicht/COpenGLCgMaterialRenderer.cpp0000644000000000000000000001531612574354552022516 0ustar rootroot// Copyright (C) 2012-2012 Patryk Nadrowski // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #if defined(_IRR_COMPILE_WITH_OPENGL_) && defined(_IRR_COMPILE_WITH_CG_) #include "COpenGLCgMaterialRenderer.h" #include "COpenGLDriver.h" #include "COpenGLTexture.h" namespace irr { namespace video { COpenGLCgUniformSampler2D::COpenGLCgUniformSampler2D(const CGparameter& parameter, bool global) : CCgUniform(parameter, global) { Type = CG_SAMPLER2D; } void COpenGLCgUniformSampler2D::update(const void* data, const SMaterial& material) const { s32* Data = (s32*)data; s32 LayerID = *Data; if (material.TextureLayer[LayerID].Texture) { int TextureID = reinterpret_cast(material.TextureLayer[LayerID].Texture)->getOpenGLTextureName(); cgGLSetTextureParameter(Parameter, TextureID); cgGLEnableTextureParameter(Parameter); } } COpenGLCgMaterialRenderer::COpenGLCgMaterialRenderer(COpenGLDriver* driver, s32& materialType, const c8* vertexProgram, const c8* vertexEntry, E_VERTEX_SHADER_TYPE vertexProfile, const c8* fragmentProgram, const c8* fragmentEntry, E_PIXEL_SHADER_TYPE fragmentProfile, const c8* geometryProgram, const c8* geometryEntry, E_GEOMETRY_SHADER_TYPE geometryProfile, scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 vertices, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : Driver(driver), CCgMaterialRenderer(callback, baseMaterial, userData) { #ifdef _DEBUG setDebugName("COpenGLCgMaterialRenderer"); #endif init(materialType, vertexProgram, vertexEntry, vertexProfile, fragmentProgram, fragmentEntry, fragmentProfile, geometryProgram, geometryEntry, geometryProfile, inType, outType, vertices); } COpenGLCgMaterialRenderer::~COpenGLCgMaterialRenderer() { if (VertexProgram) { cgGLUnloadProgram(VertexProgram); cgDestroyProgram(VertexProgram); } if (FragmentProgram) { cgGLUnloadProgram(FragmentProgram); cgDestroyProgram(FragmentProgram); } if (GeometryProgram) { cgGLUnloadProgram(GeometryProgram); cgDestroyProgram(GeometryProgram); } } void COpenGLCgMaterialRenderer::OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Material = material; if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (VertexProgram) { cgGLEnableProfile(VertexProfile); cgGLBindProgram(VertexProgram); } if (FragmentProgram) { cgGLEnableProfile(FragmentProfile); cgGLBindProgram(FragmentProgram); } if (GeometryProgram) { cgGLEnableProfile(GeometryProfile); cgGLBindProgram(GeometryProgram); } if (BaseMaterial) BaseMaterial->OnSetMaterial(material, material, true, this); } if (CallBack) CallBack->OnSetMaterial(material); for (u32 i=0; isetActiveTexture(i, material.getTexture(i)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } bool COpenGLCgMaterialRenderer::OnRender(IMaterialRendererServices* services, E_VERTEX_TYPE vtxtype) { if (CallBack && (VertexProgram || FragmentProgram || GeometryProgram)) CallBack->OnSetConstants(this, UserData); return true; } void COpenGLCgMaterialRenderer::OnUnsetMaterial() { if (VertexProgram) { cgGLUnbindProgram(VertexProfile); cgGLDisableProfile(VertexProfile); } if (FragmentProgram) { cgGLUnbindProgram(FragmentProfile); cgGLDisableProfile(FragmentProfile); } if (GeometryProgram) { cgGLUnbindProgram(GeometryProfile); cgGLDisableProfile(GeometryProfile); } if (BaseMaterial) BaseMaterial->OnUnsetMaterial(); Material = IdentityMaterial;; } void COpenGLCgMaterialRenderer::setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) { Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } IVideoDriver* COpenGLCgMaterialRenderer::getVideoDriver() { return Driver; } void COpenGLCgMaterialRenderer::init(s32& materialType, const c8* vertexProgram, const c8* vertexEntry, E_VERTEX_SHADER_TYPE vertexProfile, const c8* fragmentProgram, const c8* fragmentEntry, E_PIXEL_SHADER_TYPE fragmentProfile, const c8* geometryProgram, const c8* geometryEntry, E_GEOMETRY_SHADER_TYPE geometryProfile, scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 vertices) { bool Status = true; CGerror Error = CG_NO_ERROR; materialType = -1; // TODO: add profile selection if (vertexProgram) { VertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); if (VertexProfile) VertexProgram = cgCreateProgram(Driver->getCgContext(), CG_SOURCE, vertexProgram, VertexProfile, vertexEntry, 0); if (!VertexProgram) { Error = cgGetError(); os::Printer::log("Cg vertex program failed to compile:", ELL_ERROR); os::Printer::log(cgGetLastListing(Driver->getCgContext()), ELL_ERROR); Status = false; } else cgGLLoadProgram(VertexProgram); } if (fragmentProgram) { FragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); if (FragmentProfile) FragmentProgram = cgCreateProgram(Driver->getCgContext(), CG_SOURCE, fragmentProgram, FragmentProfile, fragmentEntry, 0); if (!FragmentProgram) { Error = cgGetError(); os::Printer::log("Cg fragment program failed to compile:", ELL_ERROR); os::Printer::log(cgGetLastListing(Driver->getCgContext()), ELL_ERROR); Status = false; } else cgGLLoadProgram(FragmentProgram); } if (geometryProgram) { GeometryProfile = cgGLGetLatestProfile(CG_GL_GEOMETRY); if (GeometryProfile) GeometryProgram = cgCreateProgram(Driver->getCgContext(), CG_SOURCE, geometryProgram, GeometryProfile, geometryEntry, 0); if (!GeometryProgram) { Error = cgGetError(); os::Printer::log("Cg geometry program failed to compile:", ELL_ERROR); os::Printer::log(cgGetLastListing(Driver->getCgContext()), ELL_ERROR); Status = false; } else cgGLLoadProgram(GeometryProgram); } getUniformList(); // create OpenGL specifics sampler uniforms. for (unsigned int i = 0; i < UniformInfo.size(); ++i) { if (UniformInfo[i]->getType() == CG_SAMPLER2D) { bool IsGlobal = true; if (UniformInfo[i]->getSpace() == CG_PROGRAM) IsGlobal = false; CCgUniform* Uniform = new COpenGLCgUniformSampler2D(UniformInfo[i]->getParameter(), IsGlobal); delete UniformInfo[i]; UniformInfo[i] = Uniform; } } if (Status) materialType = Driver->addMaterialRenderer(this); } } } #endif irrlicht-1.8.3/source/Irrlicht/COgreMeshFileLoader.h0000644000000000000000000001570212574354552021056 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // orginally written by Christian Stehno, modified by Nikolaus Gebhardt #ifndef __C_OGRE_MESH_FILE_LOADER_H_INCLUDED__ #define __C_OGRE_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "IFileSystem.h" #include "IVideoDriver.h" #include "irrString.h" #include "SMesh.h" #include "SMeshBuffer.h" #include "SMeshBufferLightMap.h" #include "IMeshManipulator.h" #include "matrix4.h" #include "quaternion.h" #include "CSkinnedMesh.h" namespace irr { namespace scene { //! Meshloader capable of loading ogre meshes. class COgreMeshFileLoader : public IMeshLoader { public: //! Constructor COgreMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver); //! destructor virtual ~COgreMeshFileLoader(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: // byte-align structures #include "irrpack.h" struct ChunkHeader { u16 id; u32 length; } PACK_STRUCT; // Default alignment #include "irrunpack.h" struct ChunkData { ChunkData() : read(0) {} ChunkHeader header; u32 read; }; struct OgreTexture { core::array Filename; core::stringc Alias; core::stringc CoordsType; core::stringc MipMaps; core::stringc Alpha; }; struct OgrePass { OgrePass() : AmbientTokenColor(false), DiffuseTokenColor(false), SpecularTokenColor(false), EmissiveTokenColor(false), MaxLights(8), PointSize(1.0f), PointSprites(false), PointSizeMin(0), PointSizeMax(0) {} video::SMaterial Material; OgreTexture Texture; bool AmbientTokenColor; bool DiffuseTokenColor; bool SpecularTokenColor; bool EmissiveTokenColor; u32 MaxLights; f32 PointSize; bool PointSprites; u32 PointSizeMin; u32 PointSizeMax; }; struct OgreTechnique { OgreTechnique() : Name(""), LODIndex(0) {} core::stringc Name; core::stringc Scheme; u16 LODIndex; core::array Passes; }; struct OgreMaterial { OgreMaterial() : Name(""), ReceiveShadows(true), TransparencyCastsShadows(false) {} core::stringc Name; bool ReceiveShadows; bool TransparencyCastsShadows; core::array LODDistances; core::array Techniques; }; struct OgreVertexBuffer { OgreVertexBuffer() : BindIndex(0), VertexSize(0), Data(0) {} u16 BindIndex; u16 VertexSize; core::array Data; }; struct OgreVertexElement { u16 Source, Type, Semantic, Offset, Index; }; struct OgreGeometry { s32 NumVertex; core::array Elements; core::array Buffers; core::array Vertices; core::array Normals; core::array Colors; core::array TexCoords; }; struct OgreTextureAlias { OgreTextureAlias() {}; OgreTextureAlias(const core::stringc& a, const core::stringc& b) : Texture(a), Alias(b) {}; core::stringc Texture; core::stringc Alias; }; struct OgreBoneAssignment { s32 VertexID; u16 BoneID; f32 Weight; }; struct OgreSubMesh { core::stringc Material; bool SharedVertices; core::array Indices; OgreGeometry Geometry; u16 Operation; core::array TextureAliases; core::array BoneAssignments; bool Indices32Bit; }; struct OgreMesh { bool SkeletalAnimation; OgreGeometry Geometry; core::array SubMeshes; core::array BoneAssignments; core::vector3df BBoxMinEdge; core::vector3df BBoxMaxEdge; f32 BBoxRadius; }; struct OgreBone { core::stringc Name; core::vector3df Position; core::quaternion Orientation; core::vector3df Scale; u16 Handle; u16 Parent; }; struct OgreKeyframe { u16 BoneID; f32 Time; core::vector3df Position; core::quaternion Orientation; core::vector3df Scale; }; struct OgreAnimation { core::stringc Name; f32 Length; core::array Keyframes; }; struct OgreSkeleton { core::array Bones; core::array Animations; }; bool readChunk(io::IReadFile* file); bool readObjectChunk(io::IReadFile* file, ChunkData& parent, OgreMesh& mesh); bool readGeometry(io::IReadFile* file, ChunkData& parent, OgreGeometry& geometry); bool readVertexDeclaration(io::IReadFile* file, ChunkData& parent, OgreGeometry& geometry); bool readVertexBuffer(io::IReadFile* file, ChunkData& parent, OgreGeometry& geometry); bool readSubMesh(io::IReadFile* file, ChunkData& parent, OgreSubMesh& subMesh); void readChunkData(io::IReadFile* file, ChunkData& data); void readString(io::IReadFile* file, ChunkData& data, core::stringc& out); void readBool(io::IReadFile* file, ChunkData& data, bool& out); void readInt(io::IReadFile* file, ChunkData& data, s32* out, u32 num=1); void readShort(io::IReadFile* file, ChunkData& data, u16* out, u32 num=1); void readFloat(io::IReadFile* file, ChunkData& data, f32* out, u32 num=1); void readVector(io::IReadFile* file, ChunkData& data, core::vector3df& out); void readQuaternion(io::IReadFile* file, ChunkData& data, core::quaternion& out); void composeMeshBufferMaterial(scene::IMeshBuffer* mb, const core::stringc& materialName); scene::SMeshBuffer* composeMeshBuffer(const core::array& indices, const OgreGeometry& geom); scene::SMeshBufferLightMap* composeMeshBufferLightMap(const core::array& indices, const OgreGeometry& geom); scene::IMeshBuffer* composeMeshBufferSkinned(scene::CSkinnedMesh& mesh, const core::array& indices, const OgreGeometry& geom); void composeObject(void); bool readColor(io::IReadFile* meshFile, video::SColor& col); void getMaterialToken(io::IReadFile* file, core::stringc& token, bool noNewLine=false); void readTechnique(io::IReadFile* meshFile, OgreMaterial& mat); void readPass(io::IReadFile* file, OgreTechnique& technique); void loadMaterials(io::IReadFile* file); bool loadSkeleton(io::IReadFile* meshFile, const core::stringc& name); void clearMeshes(); io::IFileSystem* FileSystem; video::IVideoDriver* Driver; core::stringc Version; bool SwapEndian; core::array Meshes; io::path CurrentlyLoadingFromPath; core::array Materials; OgreSkeleton Skeleton; IMesh* Mesh; u32 NumUV; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/COgreMeshFileLoader.cpp0000644000000000000000000012701712574354552021414 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // orginally written by Christian Stehno, modified by Nikolaus Gebhardt #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OGRE_LOADER_ #include "COgreMeshFileLoader.h" #include "os.h" #include "SMeshBuffer.h" #include "SAnimatedMesh.h" #include "IReadFile.h" #include "fast_atof.h" #include "coreutil.h" #ifdef _DEBUG #define IRR_OGRE_LOADER_DEBUG #endif namespace irr { namespace scene { namespace { enum OGRE_CHUNKS { // Main Chunks COGRE_HEADER= 0x1000, COGRE_SKELETON= 0x2000, COGRE_MESH= 0x3000, // sub chunks of COGRE_MESH COGRE_SUBMESH= 0x4000, COGRE_GEOMETRY= 0x5000, COGRE_SKELETON_LINK= 0x6000, COGRE_BONE_ASSIGNMENT= 0x7000, COGRE_MESH_LOD= 0x8000, COGRE_MESH_BOUNDS= 0x9000, COGRE_MESH_SUBMESH_NAME_TABLE= 0xA000, COGRE_MESH_EDGE_LISTS= 0xB000, // sub chunks of COGRE_SKELETON COGRE_BONE_PARENT= 0x3000, COGRE_ANIMATION= 0x4000, COGRE_ANIMATION_TRACK= 0x4100, COGRE_ANIMATION_KEYFRAME= 0x4110, COGRE_ANIMATION_LINK= 0x5000, // sub chunks of COGRE_SUBMESH COGRE_SUBMESH_OPERATION= 0x4010, COGRE_SUBMESH_BONE_ASSIGNMENT= 0x4100, COGRE_SUBMESH_TEXTURE_ALIAS= 0x4200, // sub chunks of COGRE_GEOMETRY COGRE_GEOMETRY_VERTEX_DECLARATION= 0x5100, COGRE_GEOMETRY_VERTEX_ELEMENT= 0x5110, COGRE_GEOMETRY_VERTEX_BUFFER= 0x5200, COGRE_GEOMETRY_VERTEX_BUFFER_DATA= 0x5210 }; } //! Constructor COgreMeshFileLoader::COgreMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver) : FileSystem(fs), Driver(driver), SwapEndian(false), Mesh(0), NumUV(0) { #ifdef _DEBUG setDebugName("COgreMeshFileLoader"); #endif if (FileSystem) FileSystem->grab(); if (Driver) Driver->grab(); } //! destructor COgreMeshFileLoader::~COgreMeshFileLoader() { clearMeshes(); if (FileSystem) FileSystem->drop(); if (Driver) Driver->drop(); if (Mesh) Mesh->drop(); } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool COgreMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "mesh" ); } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* COgreMeshFileLoader::createMesh(io::IReadFile* file) { s16 id; file->read(&id, 2); if (id == COGRE_HEADER) SwapEndian=false; else if (id == 0x0010) SwapEndian=true; else return 0; ChunkData data; readString(file, data, Version); if ((Version != "[MeshSerializer_v1.30]") && (Version != "[MeshSerializer_v1.40]") && (Version != "[MeshSerializer_v1.41]")) return 0; clearMeshes(); if (Mesh) Mesh->drop(); CurrentlyLoadingFromPath = FileSystem->getFileDir(file->getFileName()); loadMaterials(file); if (readChunk(file)) { // delete data loaded from file clearMeshes(); if (Skeleton.Bones.size()) { ISkinnedMesh* tmp = static_cast(Mesh); static_cast(Mesh)->updateBoundingBox(); Skeleton.Animations.clear(); Skeleton.Bones.clear(); Mesh=0; return tmp; } else { for (u32 i=0; igetMeshBufferCount(); ++i) ((SMeshBuffer*)Mesh->getMeshBuffer(i))->recalculateBoundingBox(); ((SMesh*)Mesh)->recalculateBoundingBox(); SAnimatedMesh* am = new SAnimatedMesh(); am->Type = EAMT_3DS; am->addMesh(Mesh); am->recalculateBoundingBox(); Mesh->drop(); Mesh = 0; return am; } } Mesh->drop(); Mesh = 0; return 0; } bool COgreMeshFileLoader::readChunk(io::IReadFile* file) { while(file->getPos() < file->getSize()) { ChunkData data; readChunkData(file, data); switch(data.header.id) { case COGRE_MESH: { Meshes.push_back(OgreMesh()); readObjectChunk(file, data, Meshes.getLast()); if (Skeleton.Bones.size()) Mesh = new CSkinnedMesh(); else Mesh = new SMesh(); composeObject(); } break; default: return true; } } return true; } bool COgreMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData& parent, OgreMesh& mesh) { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Read Object Chunk", ELL_DEBUG); #endif readBool(file, parent, mesh.SkeletalAnimation); bool skeleton_loaded=false; while ((parent.read < parent.header.length)&&(file->getPos() < file->getSize())) { ChunkData data; readChunkData(file, data); switch(data.header.id) { case COGRE_GEOMETRY: readGeometry(file, data, mesh.Geometry); break; case COGRE_SUBMESH: mesh.SubMeshes.push_back(OgreSubMesh()); readSubMesh(file, data, mesh.SubMeshes.getLast()); break; case COGRE_MESH_BOUNDS: { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Read Mesh Bounds", ELL_DEBUG); #endif readVector(file, data, mesh.BBoxMinEdge); readVector(file, data, mesh.BBoxMaxEdge); readFloat(file, data, &mesh.BBoxRadius); } break; case COGRE_SKELETON_LINK: { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Read Skeleton link", ELL_DEBUG); #endif core::stringc name; readString(file, data, name); loadSkeleton(file, name); skeleton_loaded=true; } break; case COGRE_BONE_ASSIGNMENT: { mesh.BoneAssignments.push_back(OgreBoneAssignment()); readInt(file, data, &mesh.BoneAssignments.getLast().VertexID); readShort(file, data, &mesh.BoneAssignments.getLast().BoneID); readFloat(file, data, &mesh.BoneAssignments.getLast().Weight); } break; case COGRE_MESH_LOD: case COGRE_MESH_SUBMESH_NAME_TABLE: case COGRE_MESH_EDGE_LISTS: // ignore chunk file->seek(data.header.length-data.read, true); data.read += data.header.length-data.read; break; default: #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Skipping", core::stringc(data.header.id), ELL_DEBUG); #endif // ignore chunk file->seek(data.header.length-data.read, true); data.read += data.header.length-data.read; break; } parent.read += data.read; } if (!skeleton_loaded) loadSkeleton(file, FileSystem->getFileBasename(file->getFileName(), false)); return true; } bool COgreMeshFileLoader::readGeometry(io::IReadFile* file, ChunkData& parent, OgreGeometry& geometry) { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Read Geometry", ELL_DEBUG); #endif readInt(file, parent, &geometry.NumVertex); while(parent.read < parent.header.length) { ChunkData data; readChunkData(file, data); switch(data.header.id) { case COGRE_GEOMETRY_VERTEX_DECLARATION: readVertexDeclaration(file, data, geometry); break; case COGRE_GEOMETRY_VERTEX_BUFFER: readVertexBuffer(file, data, geometry); break; default: // ignore chunk #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Skipping", core::stringc(data.header.id), ELL_DEBUG); #endif file->seek(data.header.length-data.read, true); data.read += data.header.length-data.read; } parent.read += data.read; } if (parent.read != parent.header.length) os::Printer::log("Incorrect geometry length. File might be corrupted."); return true; } bool COgreMeshFileLoader::readVertexDeclaration(io::IReadFile* file, ChunkData& parent, OgreGeometry& geometry) { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Read Vertex Declaration", ELL_DEBUG); #endif NumUV = 0; while(parent.read < parent.header.length) { ChunkData data; readChunkData(file, data); switch(data.header.id) { case COGRE_GEOMETRY_VERTEX_ELEMENT: { geometry.Elements.push_back(OgreVertexElement()); OgreVertexElement& elem = geometry.Elements.getLast(); readShort(file, data, &elem.Source); readShort(file, data, &elem.Type); readShort(file, data, &elem.Semantic); if (elem.Semantic == 7) //Tex coords { ++NumUV; } readShort(file, data, &elem.Offset); elem.Offset /= sizeof(f32); readShort(file, data, &elem.Index); } break; default: // ignore chunk file->seek(data.header.length-data.read, true); data.read += data.header.length-data.read; } parent.read += data.read; } if (parent.read != parent.header.length) os::Printer::log("Incorrect vertex declaration length. File might be corrupted."); return true; } bool COgreMeshFileLoader::readVertexBuffer(io::IReadFile* file, ChunkData& parent, OgreGeometry& geometry) { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Read Vertex Buffer", ELL_DEBUG); #endif OgreVertexBuffer buf; readShort(file, parent, &buf.BindIndex); readShort(file, parent, &buf.VertexSize); buf.VertexSize /= sizeof(f32); ChunkData data; readChunkData(file, data); if (data.header.id == COGRE_GEOMETRY_VERTEX_BUFFER_DATA) { buf.Data.set_used(geometry.NumVertex*buf.VertexSize); readFloat(file, data, buf.Data.pointer(), geometry.NumVertex*buf.VertexSize); } geometry.Buffers.push_back(buf); parent.read += data.read; if (parent.read != parent.header.length) os::Printer::log("Incorrect vertex buffer length. File might be corrupted."); return true; } bool COgreMeshFileLoader::readSubMesh(io::IReadFile* file, ChunkData& parent, OgreSubMesh& subMesh) { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Read Submesh", ELL_DEBUG); #endif readString(file, parent, subMesh.Material); #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("using material", subMesh.Material, ELL_DEBUG); #endif readBool(file, parent, subMesh.SharedVertices); s32 numIndices; readInt(file, parent, &numIndices); subMesh.Indices.set_used(numIndices); readBool(file, parent, subMesh.Indices32Bit); if (subMesh.Indices32Bit) readInt(file, parent, subMesh.Indices.pointer(), numIndices); else { for (s32 i=0; iseek(-(long)sizeof(ChunkHeader), true); return true; } parent.read += data.read; } if (parent.read != parent.header.length) os::Printer::log("Incorrect submesh length. File might be corrupted."); #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Done with submesh", ELL_DEBUG); #endif return true; } void COgreMeshFileLoader::composeMeshBufferMaterial(scene::IMeshBuffer* mb, const core::stringc& materialName) { video::SMaterial& material=mb->getMaterial(); for (u32 k=0; kexistFile(Materials[k].Techniques[0].Passes[0].Texture.Filename[i])) material.setTexture(i, Driver->getTexture(Materials[k].Techniques[0].Passes[0].Texture.Filename[i])); else material.setTexture(i, Driver->getTexture((CurrentlyLoadingFromPath+"/"+FileSystem->getFileBasename(Materials[k].Techniques[0].Passes[0].Texture.Filename[i])))); } break; } } } scene::SMeshBuffer* COgreMeshFileLoader::composeMeshBuffer(const core::array& indices, const OgreGeometry& geom) { scene::SMeshBuffer *mb=new scene::SMeshBuffer(); u32 i; mb->Indices.set_used(indices.size()); for (i=0; iIndices[i]=indices[i]; mb->Vertices.set_used(geom.NumVertex); for (i=0; iVertices[k].Color=mb->Material.DiffuseColor; mb->Vertices[k].Pos.set(geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); ePos += eSize; } } } } if (geom.Elements[i].Semantic==4) //Normal { for (u32 j=0; jVertices[k].Normal.set(geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); ePos += eSize; } } } } if (geom.Elements[i].Semantic==7) //TexCoord { for (u32 j=0; jVertices[k].TCoords.set(geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1]); ePos += eSize; } } } } } return mb; } scene::SMeshBufferLightMap* COgreMeshFileLoader::composeMeshBufferLightMap(const core::array& indices, const OgreGeometry& geom) { scene::SMeshBufferLightMap *mb=new scene::SMeshBufferLightMap(); u32 i; mb->Indices.set_used(indices.size()); for (i=0; iIndices[i]=indices[i]; mb->Vertices.set_used(geom.NumVertex); for (i=0; iVertices[k].Color=mb->Material.DiffuseColor; mb->Vertices[k].Pos.set(geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); ePos += eSize; } } } } if (geom.Elements[i].Semantic==4) //Normal { for (u32 j=0; jVertices[k].Normal.set(geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); ePos += eSize; } } } } if (geom.Elements[i].Semantic==7) //TexCoord { for (u32 j=0; jePos+3); for (s32 k=0; kVertices[k].TCoords.set(geom.Buffers[j].Data[ePos], geom.Buffers[j].Data[ePos+1]); if (secondCoord) mb->Vertices[k].TCoords2.set(geom.Buffers[j].Data[ePos+2], geom.Buffers[j].Data[ePos+3]); else mb->Vertices[k].TCoords2.set(geom.Buffers[j].Data[ePos], geom.Buffers[j].Data[ePos+1]); ePos += eSize; } } } } } return mb; } scene::IMeshBuffer* COgreMeshFileLoader::composeMeshBufferSkinned(scene::CSkinnedMesh& mesh, const core::array& indices, const OgreGeometry& geom) { scene::SSkinMeshBuffer *mb=mesh.addMeshBuffer(); if (NumUV>1) { mb->convertTo2TCoords(); mb->Vertices_2TCoords.set_used(geom.NumVertex); } else mb->Vertices_Standard.set_used(geom.NumVertex); u32 i; mb->Indices.set_used(indices.size()); for (i=0; iIndices[i+0]=indices[i+2]; mb->Indices[i+1]=indices[i+1]; mb->Indices[i+2]=indices[i+0]; } for (i=0; i1) mb->Vertices_2TCoords[k].Color=mb->Material.DiffuseColor; else mb->Vertices_Standard[k].Color=mb->Material.DiffuseColor; mb->getPosition(k).set(-geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); ePos += eSize; } } } } if (geom.Elements[i].Semantic==4) //Normal { for (u32 j=0; jgetNormal(k).set(-geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]); ePos += eSize; } } } } if (geom.Elements[i].Semantic==7) //TexCoord { for (u32 j=0; jePos+3); for (s32 k=0; kgetTCoords(k).set(geom.Buffers[j].Data[ePos], geom.Buffers[j].Data[ePos+1]); if (NumUV>1) { if (secondCoord) mb->Vertices_2TCoords[k].TCoords2.set(geom.Buffers[j].Data[ePos+2], geom.Buffers[j].Data[ePos+3]); else mb->Vertices_2TCoords[k].TCoords2.set(geom.Buffers[j].Data[ePos], geom.Buffers[j].Data[ePos+1]); } ePos += eSize; } } } } } return mb; } void COgreMeshFileLoader::composeObject(void) { for (u32 i=0; iaddMeshBuffer(mb); mb->drop(); } } } } if (Skeleton.Bones.size()) { CSkinnedMesh* m = (CSkinnedMesh*)Mesh; // Create Joints for (u32 i=0; iaddJoint(); joint->Name=Skeleton.Bones[i].Name; // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched to getMatrix_transposed instead of getMatrix for downward compatibility. // Not tested so far if this was correct or wrong before quaternion fix! Skeleton.Bones[i].Orientation.getMatrix_transposed(joint->LocalMatrix); if (Skeleton.Bones[i].Scale != core::vector3df(1,1,1)) { core::matrix4 scaleMatrix; scaleMatrix.setScale( Skeleton.Bones[i].Scale ); joint->LocalMatrix *= scaleMatrix; } joint->LocalMatrix.setTranslation( Skeleton.Bones[i].Position ); } // Joints hierarchy for (u32 i=0; igetJointCount()) { m->getAllJoints()[Skeleton.Bones[i].Parent]->Children.push_back(m->getAllJoints()[Skeleton.Bones[i].Handle]); } } // Weights u32 bufCount=0; for (u32 i=0; igetJointCount()) { ISkinnedMesh::SWeight* w = m->addWeight(m->getAllJoints()[ba.BoneID]); w->strength=ba.Weight; w->vertex_id=ba.VertexID; w->buffer_id=bufCount; } } ++bufCount; } } for (u32 i=0; igetAllJoints()[frame.BoneID]; ISkinnedMesh::SPositionKey* poskey = m->addPositionKey(keyjoint); poskey->frame=frame.Time*25; poskey->position=keyjoint->LocalMatrix.getTranslation()+frame.Position; ISkinnedMesh::SRotationKey* rotkey = m->addRotationKey(keyjoint); rotkey->frame=frame.Time*25; // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched from keyjoint->LocalMatrix to keyjoint->LocalMatrix.getTransposed() for downward compatibility. // Not tested so far if this was correct or wrong before quaternion fix! rotkey->rotation=core::quaternion(keyjoint->LocalMatrix.getTransposed())*frame.Orientation; ISkinnedMesh::SScaleKey* scalekey = m->addScaleKey(keyjoint); scalekey->frame=frame.Time*25; scalekey->scale=frame.Scale; } } m->finalize(); } } void COgreMeshFileLoader::getMaterialToken(io::IReadFile* file, core::stringc& token, bool noNewLine) { bool parseString=false; c8 c=0; token = ""; if (file->getPos() >= file->getSize()) return; file->read(&c, sizeof(c8)); // search for word beginning while ( core::isspace(c) && (file->getPos() < file->getSize())) { if (noNewLine && c=='\n') { file->seek(-1, true); return; } file->read(&c, sizeof(c8)); } // check if we read a string if (c=='"') { parseString = true; file->read(&c, sizeof(c8)); } do { if (c=='/') { file->read(&c, sizeof(c8)); // check for comments, cannot be part of strings if (!parseString && (c=='/')) { // skip comments while(c!='\n') file->read(&c, sizeof(c8)); if (!token.size()) { // if we start with a comment we need to skip // following whitespaces, so restart getMaterialToken(file, token, noNewLine); return; } else { // else continue with next character file->read(&c, sizeof(c8)); continue; } } else { // else append first slash and check if second char // ends this token token.append('/'); if ((!parseString && core::isspace(c)) || (parseString && (c=='"'))) return; } } token.append(c); file->read(&c, sizeof(c8)); // read until a token delimiter is found } while (((!parseString && !core::isspace(c)) || (parseString && (c!='"'))) && (file->getPos() < file->getSize())); // we want to skip the last quotes of a string , but other chars might be the next // token already. if (!parseString) file->seek(-1, true); } bool COgreMeshFileLoader::readColor(io::IReadFile* file, video::SColor& col) { core::stringc token; getMaterialToken(file, token); if (token!="vertexcolour") { video::SColorf col_f; col_f.r=core::fast_atof(token.c_str()); getMaterialToken(file, token); col_f.g=core::fast_atof(token.c_str()); getMaterialToken(file, token); col_f.b=core::fast_atof(token.c_str()); getMaterialToken(file, token, true); if (token.size()) col_f.a=core::fast_atof(token.c_str()); else col_f.a=1.0f; if ((col_f.r==0.0f)&&(col_f.g==0.0f)&&(col_f.b==0.0f)) col.set(255,255,255,255); else col=col_f.toSColor(); return false; } return true; } void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique) { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Read Pass"); #endif core::stringc token; technique.Passes.push_back(OgrePass()); OgrePass& pass=technique.Passes.getLast(); getMaterialToken(file, token); //open brace or name if (token != "{") getMaterialToken(file, token); //open brace getMaterialToken(file, token); if (token == "}") return; u32 inBlocks=1; u32 textureUnit=0; while(inBlocks) { if (token=="ambient") pass.AmbientTokenColor=readColor(file, pass.Material.AmbientColor); else if (token=="diffuse") pass.DiffuseTokenColor=readColor(file, pass.Material.DiffuseColor); else if (token=="specular") { pass.SpecularTokenColor=readColor(file, pass.Material.SpecularColor); getMaterialToken(file, token); pass.Material.Shininess=core::fast_atof(token.c_str()); } else if (token=="emissive") pass.EmissiveTokenColor=readColor(file, pass.Material.EmissiveColor); else if (token=="scene_blend") { // TODO: Choose correct values getMaterialToken(file, token); if (token=="add") pass.Material.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR; else if (token=="modulate") pass.Material.MaterialType=video::EMT_SOLID; else if (token=="alpha_blend") pass.Material.MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL; else if (token=="colour_blend") pass.Material.MaterialType=video::EMT_TRANSPARENT_VERTEX_ALPHA; else getMaterialToken(file, token); } else if (token=="depth_check") { getMaterialToken(file, token); if (token!="on") pass.Material.ZBuffer=video::ECFN_NEVER; } else if (token=="depth_write") { getMaterialToken(file, token); pass.Material.ZWriteEnable=(token=="on"); } else if (token=="depth_func") { getMaterialToken(file, token); // Function name if (token=="always_fail") pass.Material.ZBuffer=video::ECFN_NEVER; else if (token=="always_pass") pass.Material.ZBuffer=video::ECFN_ALWAYS; else if (token=="equal") pass.Material.ZBuffer=video::ECFN_EQUAL; else if (token=="greater") pass.Material.ZBuffer=video::ECFN_GREATER; else if (token=="greater_equal") pass.Material.ZBuffer=video::ECFN_GREATEREQUAL; else if (token=="less") pass.Material.ZBuffer=video::ECFN_LESS; else if (token=="less_equal") pass.Material.ZBuffer=video::ECFN_LESSEQUAL; else if (token=="not_equal") pass.Material.ZBuffer=video::ECFN_NOTEQUAL; } else if (token=="normalise_normals") { getMaterialToken(file, token); pass.Material.NormalizeNormals=(token=="on"); } else if (token=="depth_bias") { getMaterialToken(file, token); // bias value } else if (token=="alpha_rejection") { getMaterialToken(file, token); // function name getMaterialToken(file, token); // value pass.Material.MaterialTypeParam=core::fast_atof(token.c_str()); } else if (token=="alpha_to_coverage") { getMaterialToken(file, token); if (token=="on") pass.Material.AntiAliasing |= video::EAAM_ALPHA_TO_COVERAGE; } else if (token=="colour_write") { getMaterialToken(file, token); pass.Material.ColorMask = (token=="on")?video::ECP_ALL:video::ECP_NONE; } else if (token=="cull_hardware") { getMaterialToken(file, token); // rotation name } else if (token=="cull_software") { getMaterialToken(file, token); // culling side } else if (token=="lighting") { getMaterialToken(file, token); pass.Material.Lighting=(token=="on"); } else if (token=="shading") { getMaterialToken(file, token); // We take phong as gouraud pass.Material.GouraudShading=(token!="flat"); } else if (token=="polygon_mode") { getMaterialToken(file, token); pass.Material.Wireframe=(token=="wireframe"); pass.Material.PointCloud=(token=="points"); } else if (token=="max_lights") { getMaterialToken(file, token); pass.MaxLights=core::strtoul10(token.c_str()); } else if (token=="point_size") { getMaterialToken(file, token); pass.PointSize=core::fast_atof(token.c_str()); } else if (token=="point_sprites") { getMaterialToken(file, token); pass.PointSprites=(token=="on"); } else if (token=="point_size_min") { getMaterialToken(file, token); pass.PointSizeMin=core::strtoul10(token.c_str()); } else if (token=="point_size_max") { getMaterialToken(file, token); pass.PointSizeMax=core::strtoul10(token.c_str()); } else if (token=="texture_unit") { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Read Texture unit", ELL_DEBUG); #endif getMaterialToken(file, token); //open brace getMaterialToken(file, token); while(token != "}") { if (token=="texture") { getMaterialToken(file, token); pass.Texture.Filename.push_back(token); #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Read Texture", token, ELL_DEBUG); #endif getMaterialToken(file, pass.Texture.CoordsType, true); getMaterialToken(file, pass.Texture.MipMaps, true); getMaterialToken(file, pass.Texture.Alpha, true); // Hmm, we might need more hints for other material types using two textures... if (textureUnit>0) pass.Material.MaterialType=video::EMT_LIGHTMAP; } else if (token=="filtering") { getMaterialToken(file, token); pass.Material.TextureLayer[textureUnit].AnisotropicFilter=0; if (token=="point") { pass.Material.TextureLayer[textureUnit].BilinearFilter=false; pass.Material.TextureLayer[textureUnit].TrilinearFilter=false; getMaterialToken(file, token); getMaterialToken(file, token); } else if (token=="linear") { getMaterialToken(file, token); if (token=="point") { pass.Material.TextureLayer[textureUnit].BilinearFilter=false; pass.Material.TextureLayer[textureUnit].TrilinearFilter=false; getMaterialToken(file, token); } else { pass.Material.TextureLayer[textureUnit].BilinearFilter=true; getMaterialToken(file, token); pass.Material.TextureLayer[textureUnit].TrilinearFilter=(token=="linear"); } } else { pass.Material.TextureLayer[textureUnit].BilinearFilter=(token=="bilinear"); pass.Material.TextureLayer[textureUnit].TrilinearFilter=(token=="trilinear"); pass.Material.TextureLayer[textureUnit].AnisotropicFilter=(token=="anisotropic")?2:1; } } else if (token=="max_anisotropy") { getMaterialToken(file, token); pass.Material.TextureLayer[textureUnit].AnisotropicFilter=(u8)core::strtoul10(token.c_str()); } else if (token=="texture_alias") { getMaterialToken(file, pass.Texture.Alias); } else if (token=="mipmap_bias") { getMaterialToken(file, token); pass.Material.TextureLayer[textureUnit].LODBias=(s8)core::fast_atof(token.c_str()); } else if (token=="colour_op") { // TODO: Choose correct values getMaterialToken(file, token); if (token=="add") pass.Material.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR; else if (token=="modulate") pass.Material.MaterialType=video::EMT_SOLID; else if (token=="alpha_blend") pass.Material.MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL; else if (token=="colour_blend") pass.Material.MaterialType=video::EMT_TRANSPARENT_VERTEX_ALPHA; else getMaterialToken(file, token); } getMaterialToken(file, token); } ++textureUnit; } else if (token=="shadow_caster_program_ref") { do { getMaterialToken(file, token); } while (token != "}"); } else if (token=="shadow_caster_vertex_program_ref") { do { getMaterialToken(file, token); } while (token != "}"); } else if (token=="vertex_program_ref") { do { getMaterialToken(file, token); } while (token != "}"); } //fog_override, iteration, point_size_attenuation //not considered yet! getMaterialToken(file, token); if (token=="{") ++inBlocks; else if (token=="}") --inBlocks; } } void COgreMeshFileLoader::readTechnique(io::IReadFile* file, OgreMaterial& mat) { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Read Technique"); #endif core::stringc token; mat.Techniques.push_back(OgreTechnique()); OgreTechnique& technique=mat.Techniques.getLast(); getMaterialToken(file, technique.Name); //open brace or name if (technique.Name != "{") getMaterialToken(file, token); //open brace else technique.Name=core::stringc((int)mat.Techniques.size()); getMaterialToken(file, token); while (token != "}") { if (token == "pass") readPass(file, technique); else if (token == "scheme") getMaterialToken(file, token); else if (token == "lod_index") getMaterialToken(file, token); getMaterialToken(file, token); } } void COgreMeshFileLoader::loadMaterials(io::IReadFile* meshFile) { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Load Materials", ELL_DEBUG); #endif core::stringc token; io::IReadFile* file = 0; io::path filename = FileSystem->getFileBasename(meshFile->getFileName(), false) + ".material"; if (FileSystem->existFile(filename)) file = FileSystem->createAndOpenFile(filename); else file = FileSystem->createAndOpenFile(FileSystem->getFileDir(meshFile->getFileName())+"/"+filename); if (!file) { os::Printer::log("Could not load OGRE material", filename); return; } getMaterialToken(file, token); while (file->getPos() < file->getSize()) { if ((token == "fragment_program") || (token == "vertex_program")) { // skip whole block u32 blocks=1; do { getMaterialToken(file, token); } while (token != "{"); do { getMaterialToken(file, token); if (token == "{") ++blocks; else if (token == "}") --blocks; } while (blocks); getMaterialToken(file, token); continue; } if (token != "material") { if (token.trim().size()) os::Printer::log("Unknown material group", token.c_str()); break; } Materials.push_back(OgreMaterial()); OgreMaterial& mat = Materials.getLast(); getMaterialToken(file, mat.Name); #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Load Material", mat.Name.c_str(), ELL_DEBUG); #endif getMaterialToken(file, token); //open brace getMaterialToken(file, token); while(token != "}") { if (token=="lod_distances") // can have several items getMaterialToken(file, token); else if (token=="receive_shadows") { getMaterialToken(file, token); mat.ReceiveShadows=(token=="on"); } else if (token=="transparency_casts_shadows") { getMaterialToken(file, token); mat.TransparencyCastsShadows=(token=="on"); } else if (token=="set_texture_alias") { getMaterialToken(file, token); getMaterialToken(file, token); } else if (token=="technique") readTechnique(file, mat); getMaterialToken(file, token); } getMaterialToken(file, token); } file->drop(); #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Finished loading Materials", ELL_DEBUG); #endif } bool COgreMeshFileLoader::loadSkeleton(io::IReadFile* meshFile, const core::stringc& name) { #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Load Skeleton", name, ELL_DEBUG); #endif io::IReadFile* file = 0; io::path filename; if (FileSystem->existFile(name)) file = FileSystem->createAndOpenFile(name); else if (FileSystem->existFile(filename = FileSystem->getFileDir(meshFile->getFileName())+"/"+name)) file = FileSystem->createAndOpenFile(filename); else if (FileSystem->existFile(filename = FileSystem->getFileBasename(meshFile->getFileName(), false) + ".skeleton")) file = FileSystem->createAndOpenFile(filename); else file = FileSystem->createAndOpenFile(FileSystem->getFileDir(meshFile->getFileName())+"/"+filename); if (!file) { os::Printer::log("Could not load matching skeleton", name); return false; } s16 id; file->read(&id, 2); if (SwapEndian) id = os::Byteswap::byteswap(id); if (id != COGRE_HEADER) { file->drop(); return false; } core::stringc skeletonVersion; ChunkData head; readString(file, head, skeletonVersion); if (skeletonVersion != "[Serializer_v1.10]") { file->drop(); return false; } u16 bone=0; f32 animationTotal=0.f; while(file->getPos() < file->getSize()) { ChunkData data; readChunkData(file, data); switch(data.header.id) { case COGRE_SKELETON: { Skeleton.Bones.push_back(OgreBone()); OgreBone& bone = Skeleton.Bones.getLast(); readString(file, data, bone.Name); readShort(file, data, &bone.Handle); readVector(file, data, bone.Position); readQuaternion(file, data, bone.Orientation); #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Bone", bone.Name+" ("+core::stringc(bone.Handle)+")", ELL_DEBUG); os::Printer::log("Position", core::stringc(bone.Position.X)+" "+core::stringc(bone.Position.Y)+" "+core::stringc(bone.Position.Z), ELL_DEBUG); os::Printer::log("Rotation quat", core::stringc(bone.Orientation.W)+" "+core::stringc(bone.Orientation.X)+" "+core::stringc(bone.Orientation.Y)+" "+core::stringc(bone.Orientation.Z), ELL_DEBUG); // core::vector3df rot; // bone.Orientation.toEuler(rot); // rot *= core::RADTODEG; // os::Printer::log("Rotation", core::stringc(rot.X)+" "+core::stringc(rot.Y)+" "+core::stringc(rot.Z)); #endif if (data.read<(data.header.length-bone.Name.size())) { readVector(file, data, bone.Scale); bone.Scale.X *= -1.f; } else bone.Scale=core::vector3df(1,1,1); bone.Parent=0xffff; } break; case COGRE_BONE_PARENT: { u16 parent; readShort(file, data, &bone); readShort(file, data, &parent); if (bonedrop(); return true; } void COgreMeshFileLoader::readChunkData(io::IReadFile* file, ChunkData& data) { file->read(&data.header, sizeof(ChunkHeader)); if (SwapEndian) { data.header.id = os::Byteswap::byteswap(data.header.id); data.header.length = os::Byteswap::byteswap(data.header.length); } data.read += sizeof(ChunkHeader); } void COgreMeshFileLoader::readString(io::IReadFile* file, ChunkData& data, core::stringc& out) { c8 c = 0; out = ""; while (c!='\n') { file->read(&c, sizeof(c8)); if (c!='\n') out.append(c); } data.read+=out.size()+1; } void COgreMeshFileLoader::readBool(io::IReadFile* file, ChunkData& data, bool& out) { // normal C type because we read a bit string char c = 0; file->read(&c, sizeof(char)); out=(c!=0); ++data.read; } void COgreMeshFileLoader::readInt(io::IReadFile* file, ChunkData& data, s32* out, u32 num) { // normal C type because we read a bit string file->read(out, sizeof(int)*num); if (SwapEndian) { for (u32 i=0; iread(out, sizeof(short)*num); if (SwapEndian) { for (u32 i=0; iread(out, sizeof(float)*num); if (SwapEndian) { for (u32 i=0; i& box, const core::matrix4* transform=0) const; //! Gets all triangles which have or may have contact with a 3d line. virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform=0) const; private: struct SOctreeNode { SOctreeNode() { for (u32 i=0; i!=8; ++i) Child[i] = 0; } ~SOctreeNode() { for (u32 i=0; i!=8; ++i) delete Child[i]; } core::array Triangles; SOctreeNode* Child[8]; core::aabbox3d Box; }; void constructOctree(SOctreeNode* node); void deleteEmptyNodes(SOctreeNode* node); void getTrianglesFromOctree(SOctreeNode* node, s32& trianglesWritten, s32 maximumSize, const core::aabbox3d& box, const core::matrix4* transform, core::triangle3df* triangles) const; void getTrianglesFromOctree(SOctreeNode* node, s32& trianglesWritten, s32 maximumSize, const core::line3d& line, const core::matrix4* transform, core::triangle3df* triangles) const; SOctreeNode* Root; s32 NodeCount; s32 MinimalPolysPerNode; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/COctreeTriangleSelector.cpp0000644000000000000000000001531412574354552022360 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "COctreeTriangleSelector.h" #include "ISceneNode.h" #include "os.h" namespace irr { namespace scene { //! constructor COctreeTriangleSelector::COctreeTriangleSelector(const IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode) : CTriangleSelector(mesh, node), Root(0), NodeCount(0), MinimalPolysPerNode(minimalPolysPerNode) { #ifdef _DEBUG setDebugName("COctreeTriangleSelector"); #endif if (!Triangles.empty()) { const u32 start = os::Timer::getRealTime(); // create the triangle octree Root = new SOctreeNode(); Root->Triangles = Triangles; constructOctree(Root); c8 tmp[256]; sprintf(tmp, "Needed %ums to create OctreeTriangleSelector.(%d nodes, %u polys)", os::Timer::getRealTime() - start, NodeCount, Triangles.size()); os::Printer::log(tmp, ELL_INFORMATION); } } //! destructor COctreeTriangleSelector::~COctreeTriangleSelector() { delete Root; } void COctreeTriangleSelector::constructOctree(SOctreeNode* node) { ++NodeCount; node->Box.reset(node->Triangles[0].pointA); // get bounding box const u32 cnt = node->Triangles.size(); for (u32 i=0; iBox.addInternalPoint(node->Triangles[i].pointA); node->Box.addInternalPoint(node->Triangles[i].pointB); node->Box.addInternalPoint(node->Triangles[i].pointC); } const core::vector3df& middle = node->Box.getCenter(); core::vector3df edges[8]; node->Box.getEdges(edges); core::aabbox3d box; core::array keepTriangles; // calculate children if (!node->Box.isEmpty() && (s32)node->Triangles.size() > MinimalPolysPerNode) for (s32 ch=0; ch<8; ++ch) { box.reset(middle); box.addInternalPoint(edges[ch]); node->Child[ch] = new SOctreeNode(); for (s32 i=0; i<(s32)node->Triangles.size(); ++i) { if (node->Triangles[i].isTotalInsideBox(box)) { node->Child[ch]->Triangles.push_back(node->Triangles[i]); //node->Triangles.erase(i); //--i; } else { keepTriangles.push_back(node->Triangles[i]); } } memcpy(node->Triangles.pointer(), keepTriangles.pointer(), sizeof(core::triangle3df)*keepTriangles.size()); node->Triangles.set_used(keepTriangles.size()); keepTriangles.set_used(0); if (node->Child[ch]->Triangles.empty()) { delete node->Child[ch]; node->Child[ch] = 0; } else constructOctree(node->Child[ch]); } } //! Gets all triangles which lie within a specific bounding box. void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::aabbox3d& box, const core::matrix4* transform) const { core::matrix4 mat(core::matrix4::EM4CONST_NOTHING); core::aabbox3d invbox = box; if (SceneNode) { SceneNode->getAbsoluteTransformation().getInverse(mat); mat.transformBoxEx(invbox); } if (transform) mat = *transform; else mat.makeIdentity(); if (SceneNode) mat *= SceneNode->getAbsoluteTransformation(); s32 trianglesWritten = 0; if (Root) getTrianglesFromOctree(Root, trianglesWritten, arraySize, invbox, &mat, triangles); outTriangleCount = trianglesWritten; } void COctreeTriangleSelector::getTrianglesFromOctree( SOctreeNode* node, s32& trianglesWritten, s32 maximumSize, const core::aabbox3d& box, const core::matrix4* mat, core::triangle3df* triangles) const { if (!box.intersectsWithBox(node->Box)) return; const u32 cnt = node->Triangles.size(); for (u32 i=0; iTriangles[i]; // This isn't an accurate test, but it's fast, and the // API contract doesn't guarantee complete accuracy. if (srcTri.isTotalOutsideBox(box)) continue; core::triangle3df& dstTri = triangles[trianglesWritten]; mat->transformVect(dstTri.pointA, srcTri.pointA ); mat->transformVect(dstTri.pointB, srcTri.pointB ); mat->transformVect(dstTri.pointC, srcTri.pointC ); ++trianglesWritten; // Halt when the out array is full. if (trianglesWritten == maximumSize) return; } for (u32 i=0; i<8; ++i) if (node->Child[i]) getTrianglesFromOctree(node->Child[i], trianglesWritten, maximumSize, box, mat, triangles); } //! Gets all triangles which have or may have contact with a 3d line. // new version: from user Piraaate void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform) const { #if 0 core::aabbox3d box(line.start); box.addInternalPoint(line.end); // TODO: Could be optimized for line a little bit more. COctreeTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, box, transform); #else core::matrix4 mat ( core::matrix4::EM4CONST_NOTHING ); core::vector3df vectStartInv ( line.start ), vectEndInv ( line.end ); if (SceneNode) { mat = SceneNode->getAbsoluteTransformation(); mat.makeInverse(); mat.transformVect(vectStartInv, line.start); mat.transformVect(vectEndInv, line.end); } core::line3d invline(vectStartInv, vectEndInv); mat.makeIdentity(); if (transform) mat = (*transform); if (SceneNode) mat *= SceneNode->getAbsoluteTransformation(); s32 trianglesWritten = 0; if (Root) getTrianglesFromOctree(Root, trianglesWritten, arraySize, invline, &mat, triangles); outTriangleCount = trianglesWritten; #endif } void COctreeTriangleSelector::getTrianglesFromOctree(SOctreeNode* node, s32& trianglesWritten, s32 maximumSize, const core::line3d& line, const core::matrix4* transform, core::triangle3df* triangles) const { if (!node->Box.intersectsWithLine(line)) return; s32 cnt = node->Triangles.size(); if (cnt + trianglesWritten > maximumSize) cnt -= cnt + trianglesWritten - maximumSize; s32 i; if ( transform->isIdentity() ) { for (i=0; iTriangles[i]; ++trianglesWritten; } } else { for (i=0; iTriangles[i]; transform->transformVect(triangles[trianglesWritten].pointA); transform->transformVect(triangles[trianglesWritten].pointB); transform->transformVect(triangles[trianglesWritten].pointC); ++trianglesWritten; } } for (i=0; i<8; ++i) if (node->Child[i]) getTrianglesFromOctree(node->Child[i], trianglesWritten, maximumSize, line, transform, triangles); } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/COctreeSceneNode.h0000644000000000000000000000721412574354552020422 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_OCTREE_SCENE_NODE_H_INCLUDED__ #define __C_OCTREE_SCENE_NODE_H_INCLUDED__ #include "IMeshSceneNode.h" #include "Octree.h" namespace irr { namespace scene { //! implementation of the IBspTreeSceneNode class COctreeSceneNode : public IMeshSceneNode { public: //! constructor COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, s32 minimalPolysPerNode=512); //! destructor virtual ~COctreeSceneNode(); virtual void OnRegisterSceneNode(); //! renders the node. virtual void render(); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! creates the tree bool createTree(IMesh* mesh); //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. virtual video::SMaterial& getMaterial(u32 i); //! returns amount of materials used by this scene node. virtual u32 getMaterialCount() const; //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_OCTREE; } //! Sets a new mesh to display virtual void setMesh(IMesh* mesh); //! Get the currently defined mesh for display. virtual IMesh* getMesh(void); //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. virtual void setReadOnlyMaterials(bool readonly); //! Check if the scene node should not copy the materials of the mesh but use them in a read only style virtual bool isReadOnlyMaterials() const; //! Creates shadow volume scene node as child of this node //! and returns a pointer to it. virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh, s32 id, bool zfailmethod=true, f32 infinity=10000.0f); //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. virtual bool removeChild(ISceneNode* child); private: void deleteTree(); core::aabbox3d Box; Octree* StdOctree; core::array< Octree::SMeshChunk > StdMeshes; Octree* LightMapOctree; core::array< Octree::SMeshChunk > LightMapMeshes; Octree* TangentsOctree; core::array< Octree::SMeshChunk > TangentsMeshes; video::E_VERTEX_TYPE VertexType; core::array< video::SMaterial > Materials; core::stringc MeshName; s32 MinimalPolysPerNode; s32 PassCount; IMesh * Mesh; IShadowVolumeSceneNode* Shadow; //! use VBOs for rendering where possible bool UseVBOs; //! use visibility information together with VBOs bool UseVisibilityAndVBOs; //! use bounding box or frustum for calculate polys bool BoxBased; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/COctreeSceneNode.cpp0000644000000000000000000004416212574354552020760 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "COctreeSceneNode.h" #include "Octree.h" #include "ISceneManager.h" #include "IVideoDriver.h" #include "ICameraSceneNode.h" #include "IMeshCache.h" #include "IAnimatedMesh.h" #include "IMaterialRenderer.h" #include "os.h" #include "CShadowVolumeSceneNode.h" namespace irr { namespace scene { //! constructor COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, s32 minimalPolysPerNode) : IMeshSceneNode(parent, mgr, id), StdOctree(0), LightMapOctree(0), TangentsOctree(0), VertexType((video::E_VERTEX_TYPE)-1), MinimalPolysPerNode(minimalPolysPerNode), Mesh(0), Shadow(0), UseVBOs(OCTREE_USE_HARDWARE), UseVisibilityAndVBOs(OCTREE_USE_VISIBILITY), BoxBased(OCTREE_BOX_BASED) { #ifdef _DEBUG setDebugName("COctreeSceneNode"); #endif } //! destructor COctreeSceneNode::~COctreeSceneNode() { if (Shadow) Shadow->drop(); deleteTree(); } void COctreeSceneNode::OnRegisterSceneNode() { if (IsVisible) { // because this node supports rendering of mixed mode meshes consisting of // transparent and solid material at the same time, we need to go through all // materials, check of what type they are and register this node for the right // render pass according to that. video::IVideoDriver* driver = SceneManager->getVideoDriver(); PassCount = 0; u32 transparentCount = 0; u32 solidCount = 0; // count transparent and solid materials in this scene node for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); if (rnd && rnd->isTransparent()) ++transparentCount; else ++solidCount; if (solidCount && transparentCount) break; } // register according to material types counted if (solidCount) SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); if (transparentCount) SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); ISceneNode::OnRegisterSceneNode(); } } //! renders the node. void COctreeSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); if (VertexType == -1 || !driver) return; ICameraSceneNode* camera = SceneManager->getActiveCamera(); if (!camera) return; bool isTransparentPass = SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; ++PassCount; driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); if (Shadow) Shadow->updateShadowVolumes(); SViewFrustum frust = *camera->getViewFrustum(); //transform the frustum to the current absolute transformation if ( !AbsoluteTransformation.isIdentity() ) { core::matrix4 invTrans(AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE); frust.transform(invTrans); } const core::aabbox3d &box = frust.getBoundingBox(); switch (VertexType) { case video::EVT_STANDARD: { if (BoxBased) StdOctree->calculatePolys(box); else StdOctree->calculatePolys(frust); const Octree::SIndexData* d = StdOctree->getIndexData(); for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); const bool transparent = (rnd && rnd->isTransparent()); // only render transparent buffer if this is the transparent render pass // and solid only in solid pass if (transparent == isTransparentPass) { driver->setMaterial(Materials[i]); driver->drawIndexedTriangleList( &StdMeshes[i].Vertices[0], StdMeshes[i].Vertices.size(), d[i].Indices, d[i].CurrentSize / 3); } } // for debug purposes only if (DebugDataVisible && !Materials.empty() && PassCount==1) { const core::aabbox3df& box = frust.getBoundingBox(); core::array< const core::aabbox3d* > boxes; video::SMaterial m; m.Lighting = false; driver->setMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { StdOctree->getBoundingBoxes(box, boxes); for (u32 b=0; b!=boxes.size(); ++b) driver->draw3DBox(*boxes[b]); } if ( DebugDataVisible & scene::EDS_BBOX ) driver->draw3DBox(Box,video::SColor(0,255,0,0)); } } break; case video::EVT_2TCOORDS: { if (BoxBased) LightMapOctree->calculatePolys(box); else LightMapOctree->calculatePolys(frust); const Octree::SIndexData* d = LightMapOctree->getIndexData(); for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); const bool transparent = (rnd && rnd->isTransparent()); // only render transparent buffer if this is the transparent render pass // and solid only in solid pass if (transparent == isTransparentPass) { driver->setMaterial(Materials[i]); if (UseVBOs) { if (UseVisibilityAndVBOs) { u16* oldPointer = LightMapMeshes[i].Indices.pointer(); const u32 oldSize = LightMapMeshes[i].Indices.size(); LightMapMeshes[i].Indices.set_free_when_destroyed(false); LightMapMeshes[i].Indices.set_pointer(d[i].Indices, d[i].CurrentSize, false, false); LightMapMeshes[i].setDirty(scene::EBT_INDEX); driver->drawMeshBuffer ( &LightMapMeshes[i] ); LightMapMeshes[i].Indices.set_pointer(oldPointer, oldSize); LightMapMeshes[i].setDirty(scene::EBT_INDEX); } else driver->drawMeshBuffer ( &LightMapMeshes[i] ); } else driver->drawIndexedTriangleList( &LightMapMeshes[i].Vertices[0], LightMapMeshes[i].Vertices.size(), d[i].Indices, d[i].CurrentSize / 3); } } // for debug purposes only if (DebugDataVisible && !Materials.empty() && PassCount==1) { const core::aabbox3d &box = frust.getBoundingBox(); core::array< const core::aabbox3d* > boxes; video::SMaterial m; m.Lighting = false; driver->setMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { LightMapOctree->getBoundingBoxes(box, boxes); for (u32 b=0; bdraw3DBox(*boxes[b]); } if ( DebugDataVisible & scene::EDS_BBOX ) driver->draw3DBox(Box,video::SColor(0,255,0,0)); } } break; case video::EVT_TANGENTS: { if (BoxBased) TangentsOctree->calculatePolys(box); else TangentsOctree->calculatePolys(frust); const Octree::SIndexData* d = TangentsOctree->getIndexData(); for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); const bool transparent = (rnd && rnd->isTransparent()); // only render transparent buffer if this is the transparent render pass // and solid only in solid pass if (transparent == isTransparentPass) { driver->setMaterial(Materials[i]); driver->drawIndexedTriangleList( &TangentsMeshes[i].Vertices[0], TangentsMeshes[i].Vertices.size(), d[i].Indices, d[i].CurrentSize / 3); } } // for debug purposes only if (DebugDataVisible && !Materials.empty() && PassCount==1) { const core::aabbox3d &box = frust.getBoundingBox(); core::array< const core::aabbox3d* > boxes; video::SMaterial m; m.Lighting = false; driver->setMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { TangentsOctree->getBoundingBoxes(box, boxes); for (u32 b=0; bdraw3DBox(*boxes[b]); } if ( DebugDataVisible & scene::EDS_BBOX ) driver->draw3DBox(Box,video::SColor(0,255,0,0)); } } break; } } //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. bool COctreeSceneNode::removeChild(ISceneNode* child) { if (child && Shadow == child) { Shadow->drop(); Shadow = 0; } return ISceneNode::removeChild(child); } //! Creates shadow volume scene node as child of this node //! and returns a pointer to it. IShadowVolumeSceneNode* COctreeSceneNode::addShadowVolumeSceneNode( const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity) { if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) return 0; if (!shadowMesh) shadowMesh = Mesh; // if null is given, use the mesh of node if (Shadow) Shadow->drop(); Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity); return Shadow; } //! returns the axis aligned bounding box of this node const core::aabbox3d& COctreeSceneNode::getBoundingBox() const { return Box; } //! creates the tree /* This method has a lot of duplication and overhead. Moreover, the tangents mesh conversion does not really work. I think we need a a proper mesh implementation for octrees, which handle all vertex types internally. Converting all structures to just one vertex type is always problematic. Thanks to Auria for fixing major parts of this method. */ bool COctreeSceneNode::createTree(IMesh* mesh) { if (!mesh) return false; MeshName = SceneManager->getMeshCache()->getMeshName(mesh); mesh->grab(); deleteTree(); Mesh = mesh; const u32 beginTime = os::Timer::getRealTime(); u32 nodeCount = 0; u32 polyCount = 0; u32 i; Box = mesh->getBoundingBox(); if (mesh->getMeshBufferCount()) { // check for "larger" buffer types VertexType = video::EVT_STANDARD; u32 meshReserve = 0; for (i=0; igetMeshBufferCount(); ++i) { const IMeshBuffer* b = mesh->getMeshBuffer(i); if (b->getVertexCount() && b->getIndexCount()) { ++meshReserve; if (b->getVertexType() == video::EVT_2TCOORDS) VertexType = video::EVT_2TCOORDS; else if (b->getVertexType() == video::EVT_TANGENTS) VertexType = video::EVT_TANGENTS; } } Materials.reallocate(Materials.size()+meshReserve); switch(VertexType) { case video::EVT_STANDARD: { StdMeshes.reallocate(StdMeshes.size() + meshReserve); for (i=0; igetMeshBufferCount(); ++i) { IMeshBuffer* b = mesh->getMeshBuffer(i); if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); StdMeshes.push_back(Octree::SMeshChunk()); Octree::SMeshChunk &nchunk = StdMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); switch (b->getVertexType()) { case video::EVT_STANDARD: for (v=0; vgetVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]); break; case video::EVT_2TCOORDS: for (v=0; vgetVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]); break; case video::EVT_TANGENTS: for (v=0; vgetVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); break; } polyCount += b->getIndexCount(); nchunk.Indices.reallocate(b->getIndexCount()); for (v=0; vgetIndexCount(); ++v) nchunk.Indices.push_back(b->getIndices()[v]); } } StdOctree = new Octree(StdMeshes, MinimalPolysPerNode); nodeCount = StdOctree->getNodeCount(); } break; case video::EVT_2TCOORDS: { LightMapMeshes.reallocate(LightMapMeshes.size() + meshReserve); for ( i=0; i < mesh->getMeshBufferCount(); ++i) { IMeshBuffer* b = mesh->getMeshBuffer(i); if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); LightMapMeshes.push_back(Octree::SMeshChunk()); Octree::SMeshChunk& nchunk = LightMapMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; if (UseVisibilityAndVBOs) { nchunk.setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX); nchunk.setHardwareMappingHint(scene::EHM_DYNAMIC, scene::EBT_INDEX); } else nchunk.setHardwareMappingHint(scene::EHM_STATIC); u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); switch (b->getVertexType()) { case video::EVT_STANDARD: for (v=0; vgetVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]); break; case video::EVT_2TCOORDS: for (v=0; vgetVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]); break; case video::EVT_TANGENTS: for (v=0; vgetVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); break; } polyCount += b->getIndexCount(); nchunk.Indices.reallocate(b->getIndexCount()); for (v=0; vgetIndexCount(); ++v) nchunk.Indices.push_back(b->getIndices()[v]); } } LightMapOctree = new Octree(LightMapMeshes, MinimalPolysPerNode); nodeCount = LightMapOctree->getNodeCount(); } break; case video::EVT_TANGENTS: { TangentsMeshes.reallocate(TangentsMeshes.size() + meshReserve); for (u32 i=0; igetMeshBufferCount(); ++i) { IMeshBuffer* b = mesh->getMeshBuffer(i); if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); TangentsMeshes.push_back(Octree::SMeshChunk()); Octree::SMeshChunk& nchunk = TangentsMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); switch (b->getVertexType()) { case video::EVT_STANDARD: for (v=0; vgetVertexCount(); ++v) { const video::S3DVertex& tmpV = ((video::S3DVertex*)b->getVertices())[v]; nchunk.Vertices.push_back(video::S3DVertexTangents(tmpV.Pos, tmpV.Color, tmpV.TCoords)); } break; case video::EVT_2TCOORDS: for (v=0; vgetVertexCount(); ++v) { const video::S3DVertex2TCoords& tmpV = ((video::S3DVertex2TCoords*)b->getVertices())[v]; nchunk.Vertices.push_back(video::S3DVertexTangents(tmpV.Pos, tmpV.Color, tmpV.TCoords)); } break; case video::EVT_TANGENTS: for (v=0; vgetVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); break; } polyCount += b->getIndexCount(); nchunk.Indices.reallocate(b->getIndexCount()); for (v=0; vgetIndexCount(); ++v) nchunk.Indices.push_back(b->getIndices()[v]); } } TangentsOctree = new Octree(TangentsMeshes, MinimalPolysPerNode); nodeCount = TangentsOctree->getNodeCount(); } break; } } const u32 endTime = os::Timer::getRealTime(); c8 tmp[255]; sprintf(tmp, "Needed %ums to create Octree SceneNode.(%u nodes, %u polys)", endTime - beginTime, nodeCount, polyCount/3); os::Printer::log(tmp, ELL_INFORMATION); return true; } //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. video::SMaterial& COctreeSceneNode::getMaterial(u32 i) { if ( i >= Materials.size() ) return ISceneNode::getMaterial(i); return Materials[i]; } //! returns amount of materials used by this scene node. u32 COctreeSceneNode::getMaterialCount() const { return Materials.size(); } //! Writes attributes of the scene node. void COctreeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { ISceneNode::serializeAttributes(out, options); out->addInt("MinimalPolysPerNode", MinimalPolysPerNode); out->addString("Mesh", MeshName.c_str()); } //! Reads attributes of the scene node. void COctreeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { const s32 oldMinimal = MinimalPolysPerNode; MinimalPolysPerNode = in->getAttributeAsInt("MinimalPolysPerNode"); io::path newMeshStr = in->getAttributeAsString("Mesh"); IMesh* newMesh = 0; if (newMeshStr == "") newMeshStr = MeshName; IAnimatedMesh* newAnimatedMesh = SceneManager->getMesh(newMeshStr.c_str()); if (newAnimatedMesh) newMesh = newAnimatedMesh->getMesh(0); if (newMesh && ((MeshName != newMeshStr) || (MinimalPolysPerNode != oldMinimal))) { // recalculate tree createTree(newMesh); } ISceneNode::deserializeAttributes(in, options); } void COctreeSceneNode::deleteTree() { delete StdOctree; StdOctree = 0; StdMeshes.clear(); delete LightMapOctree; LightMapOctree = 0; LightMapMeshes.clear(); delete TangentsOctree; TangentsOctree = 0; TangentsMeshes.clear(); Materials.clear(); if(Mesh) Mesh->drop(); } void COctreeSceneNode::setMesh(IMesh* mesh) { createTree(mesh); } IMesh* COctreeSceneNode::getMesh(void) { return Mesh; } void COctreeSceneNode::setReadOnlyMaterials(bool readonly) { // Do nothing } bool COctreeSceneNode::isReadOnlyMaterials() const { return false; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/COCTLoader.h0000644000000000000000000000767512574354552017204 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // Because I (Nikolaus Gebhardt) did some changes to Murphy McCauley's loader, // I'm writing this down here: // - Replaced all dependencies to STL and stdio with irr:: methods/constructs // - Disabled logging define // - Changed some minor things (Don't remember what exactly.) // Thanks a lot to Murphy McCauley for writing this loader. // // COCTLoader by Murphy McCauley (February 2005) // An Irrlicht loader for OCT files // // OCT file format information comes from the sourcecode of the Fluid Studios // Radiosity Processor by Paul Nettle. You can get that sourcecode from // http://www.fluidstudios.com . // // Parts of this code are from Irrlicht's CQ3LevelMesh and C3DSMeshFileLoader, // and are Copyright (C) 2002-2004 Nikolaus Gebhardt. // // Use of this code is subject to the following: // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would be // appreciated but is not required. // 2. Altered source versions must be plainly marked as such, and must not be // misrepresented as being the original software. // 3. This notice may not be removed or altered from any source distribution. // 4. You may not use this software to directly or indirectly cause harm to others. #ifndef __C_OCT_LOADER_H_INCLUDED__ #define __C_OCT_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "IReadFile.h" #include "SMesh.h" #include "irrString.h" namespace irr { namespace io { class IFileSystem; } // end namespace io namespace scene { class ISceneManager; class ISceneNode; class COCTLoader : public IMeshLoader { public: //! constructor COCTLoader(ISceneManager* smgr, io::IFileSystem* fs); //! destructor virtual ~COCTLoader(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); void OCTLoadLights(io::IReadFile* file, ISceneNode * parent = 0, f32 radius = 500.0f, f32 intensityScale = 0.0000001f*2.5, bool rewind = true); private: struct octHeader { u32 numVerts; u32 numFaces; u32 numTextures; u32 numLightmaps; u32 numLights; }; struct octHeaderEx { u32 magic; // 'OCTX' - 0x4F435458L u32 numLightmaps; u32 lightmapWidth; u32 lightmapHeight; u32 containsVertexNormals; }; struct octFace { u32 firstVert; u32 numVerts; u32 textureID; u32 lightmapID; f32 plane[4]; }; struct octVert { f32 tc[2]; f32 lc[2]; f32 pos[3]; }; struct octTexture { u32 id; char fileName[64]; }; struct octLightmap { u32 id; u8 data[128][128][3]; }; struct octLight { f32 pos[3]; f32 color[3]; u32 intensity; }; ISceneManager* SceneManager; io::IFileSystem* FileSystem; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/COCTLoader.cpp0000644000000000000000000002372412574354552017530 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // originally written by Murphy McCauley, see COCTLoader.h for details. // // COCTLoader by Murphy McCauley (February 2005) // An Irrlicht loader for OCT files // // See the header file for additional information including use and distribution rights. #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OCT_LOADER_ #include "COCTLoader.h" #include "IVideoDriver.h" #include "IFileSystem.h" #include "os.h" #include "SAnimatedMesh.h" #include "SMeshBufferLightMap.h" #include "irrString.h" #include "ISceneManager.h" namespace irr { namespace scene { //! constructor COCTLoader::COCTLoader(ISceneManager* smgr, io::IFileSystem* fs) : SceneManager(smgr), FileSystem(fs) { #ifdef _DEBUG setDebugName("COCTLoader"); #endif if (FileSystem) FileSystem->grab(); } //! destructor COCTLoader::~COCTLoader() { if (FileSystem) FileSystem->drop(); } // Doesn't really belong here, but it's jammed in for now. void COCTLoader::OCTLoadLights(io::IReadFile* file, scene::ISceneNode * parent, f32 radius, f32 intensityScale, bool rewind) { if (rewind) file->seek(0); octHeader header; file->read(&header, sizeof(octHeader)); file->seek(sizeof(octVert)*header.numVerts, true); file->seek(sizeof(octFace)*header.numFaces, true); file->seek(sizeof(octTexture)*header.numTextures, true); file->seek(sizeof(octLightmap)*header.numLightmaps, true); octLight * lights = new octLight[header.numLights]; file->read(lights, header.numLights * sizeof(octLight)); //TODO: Skip past my extended data just for good form for (u32 i = 0; i < header.numLights; i++) { const f32 intensity = lights[i].intensity * intensityScale; SceneManager->addLightSceneNode(parent, core::vector3df(lights[i].pos[0], lights[i].pos[2], lights[i].pos[1]), video::SColorf(lights[i].color[0] * intensity, lights[i].color[1] * intensity, lights[i].color[2] * intensity, 1.0f), radius); } } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* COCTLoader::createMesh(io::IReadFile* file) { if (!file) return 0; octHeader header; file->read(&header, sizeof(octHeader)); octVert * verts = new octVert[header.numVerts]; octFace * faces = new octFace[header.numFaces]; octTexture * textures = new octTexture[header.numTextures]; octLightmap * lightmaps = new octLightmap[header.numLightmaps]; octLight * lights = new octLight[header.numLights]; file->read(verts, sizeof(octVert) * header.numVerts); file->read(faces, sizeof(octFace) * header.numFaces); //TODO: Make sure id is in the legal range for Textures and Lightmaps u32 i; for (i = 0; i < header.numTextures; i++) { octTexture t; file->read(&t, sizeof(octTexture)); textures[t.id] = t; } for (i = 0; i < header.numLightmaps; i++) { octLightmap t; file->read(&t, sizeof(octLightmap)); lightmaps[t.id] = t; } file->read(lights, sizeof(octLight) * header.numLights); //TODO: Now read in my extended OCT header (flexible lightmaps and vertex normals) // This is the method Nikolaus Gebhardt used in the Q3 loader -- create a // meshbuffer for every possible combination of lightmap and texture including // a "null" texture and "null" lightmap. Ones that end up with nothing in them // will be removed later. SMesh * Mesh = new SMesh(); for (i=0; i<(header.numTextures+1) * (header.numLightmaps+1); ++i) { scene::SMeshBufferLightMap* buffer = new scene::SMeshBufferLightMap(); buffer->Material.MaterialType = video::EMT_LIGHTMAP; buffer->Material.Lighting = false; Mesh->addMeshBuffer(buffer); buffer->drop(); } // Build the mesh buffers for (i = 0; i < header.numFaces; i++) { if (faces[i].numVerts < 3) continue; const f32* const a = verts[faces[i].firstVert].pos; const f32* const b = verts[faces[i].firstVert+1].pos; const f32* const c = verts[faces[i].firstVert+2].pos; const core::vector3df normal = core::plane3df(core::vector3df(a[0],a[1],a[2]), core::vector3df(b[0],c[1],c[2]), core::vector3df(c[0],c[1],c[2])).Normal; const u32 textureID = core::min_(s32(faces[i].textureID), s32(header.numTextures - 1)) + 1; const u32 lightmapID = core::min_(s32(faces[i].lightmapID),s32(header.numLightmaps - 1)) + 1; SMeshBufferLightMap * meshBuffer = (SMeshBufferLightMap*)Mesh->getMeshBuffer(lightmapID * (header.numTextures + 1) + textureID); const u32 base = meshBuffer->Vertices.size(); // Add this face's verts u32 v; for (v = 0; v < faces[i].numVerts; ++v) { octVert * vv = &verts[faces[i].firstVert + v]; video::S3DVertex2TCoords vert; vert.Pos.set(vv->pos[0], vv->pos[1], vv->pos[2]); vert.Color = video::SColor(0,255,255,255); vert.Normal.set(normal); if (textureID == 0) { // No texture -- just a lightmap. Thus, use lightmap coords for texture 1. // (the actual texture will be swapped later) vert.TCoords.set(vv->lc[0], vv->lc[1]); } else { vert.TCoords.set(vv->tc[0], vv->tc[1]); vert.TCoords2.set(vv->lc[0], vv->lc[1]); } meshBuffer->Vertices.push_back(vert); } // Now add the indices // This weird loop turns convex polygons into triangle strips. // I do it this way instead of a simple fan because it usually looks a lot better in wireframe, for example. // High, Low u32 h = faces[i].numVerts - 1; u32 l = 0; for (v = 0; v < faces[i].numVerts - 2; ++v) { const u32 center = (v & 1)? h - 1: l + 1; meshBuffer->Indices.push_back(base + h); meshBuffer->Indices.push_back(base + l); meshBuffer->Indices.push_back(base + center); if (v & 1) --h; else ++l; } } // load textures core::array tex; tex.reallocate(header.numTextures + 1); tex.push_back(0); const core::stringc relpath = FileSystem->getFileDir(file->getFileName())+"/"; for (i = 1; i < (header.numTextures + 1); i++) { core::stringc path(textures[i-1].fileName); path.replace('\\','/'); if (FileSystem->existFile(path)) tex.push_back(SceneManager->getVideoDriver()->getTexture(path)); else // try to read in the relative path of the OCT file tex.push_back(SceneManager->getVideoDriver()->getTexture( (relpath + path) )); } // prepare lightmaps core::array lig; lig.set_used(header.numLightmaps + 1); lig[0] = 0; const u32 lightmapWidth = 128; const u32 lightmapHeight = 128; const core::dimension2d lmapsize(lightmapWidth, lightmapHeight); bool oldMipMapState = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); video::IImage* tmpImage = SceneManager->getVideoDriver()->createImage(video::ECF_R8G8B8, lmapsize); for (i = 1; i < (header.numLightmaps + 1); ++i) { core::stringc lightmapname = file->getFileName(); lightmapname += ".lightmap."; lightmapname += (int)i; const octLightmap* lm = &lightmaps[i-1]; for (u32 x=0; xsetPixel(x, y, video::SColor(255, lm->data[x][y][2], lm->data[x][y][1], lm->data[x][y][0])); } } lig[i] = SceneManager->getVideoDriver()->addTexture(lightmapname.c_str(), tmpImage); } tmpImage->drop(); SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); // Free stuff delete [] verts; delete [] faces; delete [] textures; delete [] lightmaps; delete [] lights; // attach materials for (i = 0; i < header.numLightmaps + 1; i++) { for (u32 j = 0; j < header.numTextures + 1; j++) { u32 mb = i * (header.numTextures + 1) + j; SMeshBufferLightMap * meshBuffer = (SMeshBufferLightMap*)Mesh->getMeshBuffer(mb); meshBuffer->Material.setTexture(0, tex[j]); meshBuffer->Material.setTexture(1, lig[i]); if (meshBuffer->Material.getTexture(0) == 0) { // This material has no texture, so we'll just show the lightmap if there is one. // We swapped the texture coordinates earlier. meshBuffer->Material.setTexture(0, meshBuffer->Material.getTexture(1)); meshBuffer->Material.setTexture(1, 0); } if (meshBuffer->Material.getTexture(1) == 0) { // If there is only one texture, it should be solid and lit. // Among other things, this way you can preview OCT lights. meshBuffer->Material.MaterialType = video::EMT_SOLID; meshBuffer->Material.Lighting = true; } } } // delete all buffers without geometry in it. i = 0; while(i < Mesh->MeshBuffers.size()) { if (Mesh->MeshBuffers[i]->getVertexCount() == 0 || Mesh->MeshBuffers[i]->getIndexCount() == 0 || Mesh->MeshBuffers[i]->getMaterial().getTexture(0) == 0) { // Meshbuffer is empty -- drop it Mesh->MeshBuffers[i]->drop(); Mesh->MeshBuffers.erase(i); } else { ++i; } } // create bounding box for (i = 0; i < Mesh->MeshBuffers.size(); ++i) { Mesh->MeshBuffers[i]->recalculateBoundingBox(); } Mesh->recalculateBoundingBox(); // Set up an animated mesh to hold the mesh SAnimatedMesh* AMesh = new SAnimatedMesh(); AMesh->Type = EAMT_OCT; AMesh->addMesh(Mesh); AMesh->recalculateBoundingBox(); Mesh->drop(); return AMesh; } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool COCTLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "oct" ); } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_OCT_LOADER_ irrlicht-1.8.3/source/Irrlicht/COBJMeshWriter.h0000644000000000000000000000272712574354552020045 0ustar rootroot// Copyright (C) 2008-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_OBJ_MESH_WRITER_H_INCLUDED__ #define __IRR_OBJ_MESH_WRITER_H_INCLUDED__ #include "IMeshWriter.h" #include "S3DVertex.h" #include "irrString.h" namespace irr { namespace io { class IFileSystem; } // end namespace io namespace scene { class IMeshBuffer; class ISceneManager; //! class to write meshes, implementing a OBJ writer class COBJMeshWriter : public IMeshWriter { public: COBJMeshWriter(scene::ISceneManager* smgr, io::IFileSystem* fs); virtual ~COBJMeshWriter(); //! Returns the type of the mesh writer virtual EMESH_WRITER_TYPE getType() const; //! writes a mesh virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE); protected: // create vector output with line end into string void getVectorAsStringLine(const core::vector3df& v, core::stringc& s) const; // create vector output with line end into string void getVectorAsStringLine(const core::vector2df& v, core::stringc& s) const; // create color output with line end into string void getColorAsStringLine(const video::SColor& color, const c8* const prefix, core::stringc& s) const; scene::ISceneManager* SceneManager; io::IFileSystem* FileSystem; }; } // end namespace } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/COBJMeshWriter.cpp0000644000000000000000000001360112574354552020371 0ustar rootroot// Copyright (C) 2008-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OBJ_WRITER_ #include "COBJMeshWriter.h" #include "os.h" #include "IMesh.h" #include "IMeshBuffer.h" #include "IAttributes.h" #include "ISceneManager.h" #include "IMeshCache.h" #include "IWriteFile.h" #include "IFileSystem.h" #include "ITexture.h" namespace irr { namespace scene { COBJMeshWriter::COBJMeshWriter(scene::ISceneManager* smgr, io::IFileSystem* fs) : SceneManager(smgr), FileSystem(fs) { #ifdef _DEBUG setDebugName("COBJMeshWriter"); #endif if (SceneManager) SceneManager->grab(); if (FileSystem) FileSystem->grab(); } COBJMeshWriter::~COBJMeshWriter() { if (SceneManager) SceneManager->drop(); if (FileSystem) FileSystem->drop(); } //! Returns the type of the mesh writer EMESH_WRITER_TYPE COBJMeshWriter::getType() const { return EMWT_OBJ; } //! writes a mesh bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { if (!file) return false; os::Printer::log("Writing mesh", file->getFileName()); // write OBJ MESH header const core::stringc name(FileSystem->getFileBasename(SceneManager->getMeshCache()->getMeshName(mesh), false)+".mtl"); file->write("# exported by Irrlicht\n",23); file->write("mtllib ",7); file->write(name.c_str(),name.size()); file->write("\n\n",2); // write mesh buffers core::array mat; u32 allVertexCount=1; // count vertices over the whole file for (u32 i=0; igetMeshBufferCount(); ++i) { core::stringc num(i+1); IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer && buffer->getVertexCount()) { file->write("g grp", 5); file->write(num.c_str(), num.size()); file->write("\n",1); u32 j; const u32 vertexCount = buffer->getVertexCount(); for (j=0; jwrite("v ",2); getVectorAsStringLine(buffer->getPosition(j), num); file->write(num.c_str(), num.size()); } for (j=0; jwrite("vt ",3); getVectorAsStringLine(buffer->getTCoords(j), num); file->write(num.c_str(), num.size()); } for (j=0; jwrite("vn ",3); getVectorAsStringLine(buffer->getNormal(j), num); file->write(num.c_str(), num.size()); } file->write("usemtl mat",10); num = ""; for (j=0; jgetMaterial()) { num = core::stringc(j); break; } } if (num == "") { num = core::stringc(mat.size()); mat.push_back(&buffer->getMaterial()); } file->write(num.c_str(), num.size()); file->write("\n",1); const u32 indexCount = buffer->getIndexCount(); for (j=0; jwrite("f ",2); num = core::stringc(buffer->getIndices()[j+2]+allVertexCount); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write(" ",1); num = core::stringc(buffer->getIndices()[j+1]+allVertexCount); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write(" ",1); num = core::stringc(buffer->getIndices()[j+0]+allVertexCount); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write(" ",1); file->write("\n",1); } file->write("\n",1); allVertexCount += vertexCount; } } if (mat.size() == 0) return true; file = FileSystem->createAndWriteFile( name ); if (file) { os::Printer::log("Writing material", file->getFileName()); file->write("# exported by Irrlicht\n\n",24); for (u32 i=0; iwrite("newmtl mat",10); file->write(num.c_str(),num.size()); file->write("\n",1); getColorAsStringLine(mat[i]->AmbientColor, "Ka", num); file->write(num.c_str(),num.size()); getColorAsStringLine(mat[i]->DiffuseColor, "Kd", num); file->write(num.c_str(),num.size()); getColorAsStringLine(mat[i]->SpecularColor, "Ks", num); file->write(num.c_str(),num.size()); getColorAsStringLine(mat[i]->EmissiveColor, "Ke", num); file->write(num.c_str(),num.size()); num = core::stringc((double)(mat[i]->Shininess/0.128f)); file->write("Ns ", 3); file->write(num.c_str(),num.size()); file->write("\n", 1); if (mat[i]->getTexture(0)) { file->write("map_Kd ", 7); file->write(mat[i]->getTexture(0)->getName().getPath().c_str(), mat[i]->getTexture(0)->getName().getPath().size()); file->write("\n",1); } file->write("\n",1); } file->drop(); } return true; } void COBJMeshWriter::getVectorAsStringLine(const core::vector3df& v, core::stringc& s) const { s = core::stringc(-v.X); s += " "; s += core::stringc(v.Y); s += " "; s += core::stringc(v.Z); s += "\n"; } void COBJMeshWriter::getVectorAsStringLine(const core::vector2df& v, core::stringc& s) const { s = core::stringc(v.X); s += " "; s += core::stringc(-v.Y); s += "\n"; } void COBJMeshWriter::getColorAsStringLine(const video::SColor& color, const c8* const prefix, core::stringc& s) const { s = prefix; s += " "; s += core::stringc((double)(color.getRed()/255.f)); s += " "; s += core::stringc((double)(color.getGreen()/255.f)); s += " "; s += core::stringc((double)(color.getBlue()/255.f)); s += "\n"; } } // end namespace } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/COBJMeshFileLoader.h0000644000000000000000000001061012574354552020565 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_OBJ_MESH_FILE_LOADER_H_INCLUDED__ #define __C_OBJ_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "IFileSystem.h" #include "ISceneManager.h" #include "irrString.h" #include "SMeshBuffer.h" #include "irrMap.h" namespace irr { namespace scene { //! Meshloader capable of loading obj meshes. class COBJMeshFileLoader : public IMeshLoader { public: //! Constructor COBJMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs); //! destructor virtual ~COBJMeshFileLoader(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".obj") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: struct SObjMtl { SObjMtl() : Meshbuffer(0), Bumpiness (1.0f), Illumination(0), RecalculateNormals(false) { Meshbuffer = new SMeshBuffer(); Meshbuffer->Material.Shininess = 0.0f; Meshbuffer->Material.AmbientColor = video::SColorf(0.2f, 0.2f, 0.2f, 1.0f).toSColor(); Meshbuffer->Material.DiffuseColor = video::SColorf(0.8f, 0.8f, 0.8f, 1.0f).toSColor(); Meshbuffer->Material.SpecularColor = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f).toSColor(); } SObjMtl(const SObjMtl& o) : Name(o.Name), Group(o.Group), Bumpiness(o.Bumpiness), Illumination(o.Illumination), RecalculateNormals(false) { Meshbuffer = new SMeshBuffer(); Meshbuffer->Material = o.Meshbuffer->Material; } core::map VertMap; scene::SMeshBuffer *Meshbuffer; core::stringc Name; core::stringc Group; f32 Bumpiness; c8 Illumination; bool RecalculateNormals; }; // helper method for material reading const c8* readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const io::path& relPath); // returns a pointer to the first printable character available in the buffer const c8* goFirstWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines=true); // returns a pointer to the first printable character after the first non-printable const c8* goNextWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines=true); // returns a pointer to the next printable character after the first line break const c8* goNextLine(const c8* buf, const c8* const bufEnd); // copies the current word from the inBuf to the outBuf u32 copyWord(c8* outBuf, const c8* inBuf, u32 outBufLength, const c8* const pBufEnd); // copies the current line from the inBuf to the outBuf core::stringc copyLine(const c8* inBuf, const c8* const bufEnd); // combination of goNextWord followed by copyWord const c8* goAndCopyNextWord(c8* outBuf, const c8* inBuf, u32 outBufLength, const c8* const pBufEnd); //! Read the material from the given file void readMTL(const c8* fileName, const io::path& relPath); //! Find and return the material with the given name SObjMtl* findMtl(const core::stringc& mtlName, const core::stringc& grpName); //! Read RGB color const c8* readColor(const c8* bufPtr, video::SColor& color, const c8* const pBufEnd); //! Read 3d vector of floats const c8* readVec3(const c8* bufPtr, core::vector3df& vec, const c8* const pBufEnd); //! Read 2d vector of floats const c8* readUV(const c8* bufPtr, core::vector2df& vec, const c8* const pBufEnd); //! Read boolean value represented as 'on' or 'off' const c8* readBool(const c8* bufPtr, bool& tf, const c8* const bufEnd); // reads and convert to integer the vertex indices in a line of obj file's face statement // -1 for the index if it doesn't exist // indices are changed to 0-based index instead of 1-based from the obj file bool retrieveVertexIndices(c8* vertexData, s32* idx, const c8* bufEnd, u32 vbsize, u32 vtsize, u32 vnsize); void cleanUp(); scene::ISceneManager* SceneManager; io::IFileSystem* FileSystem; core::array Materials; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/COBJMeshFileLoader.cpp0000644000000000000000000006465212574354552021137 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OBJ_LOADER_ #include "COBJMeshFileLoader.h" #include "IMeshManipulator.h" #include "IVideoDriver.h" #include "SMesh.h" #include "SMeshBuffer.h" #include "SAnimatedMesh.h" #include "IReadFile.h" #include "IAttributes.h" #include "fast_atof.h" #include "coreutil.h" #include "os.h" namespace irr { namespace scene { #ifdef _DEBUG #define _IRR_DEBUG_OBJ_LOADER_ #endif static const u32 WORD_BUFFER_LENGTH = 512; //! Constructor COBJMeshFileLoader::COBJMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) : SceneManager(smgr), FileSystem(fs) { #ifdef _DEBUG setDebugName("COBJMeshFileLoader"); #endif if (FileSystem) FileSystem->grab(); } //! destructor COBJMeshFileLoader::~COBJMeshFileLoader() { if (FileSystem) FileSystem->drop(); } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool COBJMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "obj" ); } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) { const long filesize = file->getSize(); if (!filesize) return 0; const u32 WORD_BUFFER_LENGTH = 512; core::array vertexBuffer; core::array normalsBuffer; core::array textureCoordBuffer; SObjMtl * currMtl = new SObjMtl(); Materials.push_back(currMtl); u32 smoothingGroup=0; const io::path fullName = file->getFileName(); const io::path relPath = FileSystem->getFileDir(fullName)+"/"; c8* buf = new c8[filesize]; memset(buf, 0, filesize); file->read((void*)buf, filesize); const c8* const bufEnd = buf+filesize; // Process obj information const c8* bufPtr = buf; core::stringc grpName, mtlName; bool mtlChanged=false; bool useGroups = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_GROUPS); bool useMaterials = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_MATERIAL_FILES); while(bufPtr != bufEnd) { switch(bufPtr[0]) { case 'm': // mtllib (material) { if (useMaterials) { c8 name[WORD_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(name, bufPtr, WORD_BUFFER_LENGTH, bufEnd); #ifdef _IRR_DEBUG_OBJ_LOADER_ os::Printer::log("Reading material file",name); #endif readMTL(name, relPath); } } break; case 'v': // v, vn, vt switch(bufPtr[1]) { case ' ': // vertex { core::vector3df vec; bufPtr = readVec3(bufPtr, vec, bufEnd); vertexBuffer.push_back(vec); } break; case 'n': // normal { core::vector3df vec; bufPtr = readVec3(bufPtr, vec, bufEnd); normalsBuffer.push_back(vec); } break; case 't': // texcoord { core::vector2df vec; bufPtr = readUV(bufPtr, vec, bufEnd); textureCoordBuffer.push_back(vec); } break; } break; case 'g': // group name { c8 grp[WORD_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(grp, bufPtr, WORD_BUFFER_LENGTH, bufEnd); #ifdef _IRR_DEBUG_OBJ_LOADER_ os::Printer::log("Loaded group start",grp, ELL_DEBUG); #endif if (useGroups) { if (0 != grp[0]) grpName = grp; else grpName = "default"; } mtlChanged=true; } break; case 's': // smoothing can be a group or off (equiv. to 0) { c8 smooth[WORD_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(smooth, bufPtr, WORD_BUFFER_LENGTH, bufEnd); #ifdef _IRR_DEBUG_OBJ_LOADER_ os::Printer::log("Loaded smoothing group start",smooth, ELL_DEBUG); #endif if (core::stringc("off")==smooth) smoothingGroup=0; else smoothingGroup=core::strtoul10(smooth); } break; case 'u': // usemtl // get name of material { c8 matName[WORD_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(matName, bufPtr, WORD_BUFFER_LENGTH, bufEnd); #ifdef _IRR_DEBUG_OBJ_LOADER_ os::Printer::log("Loaded material start",matName, ELL_DEBUG); #endif mtlName=matName; mtlChanged=true; } break; case 'f': // face { c8 vertexWord[WORD_BUFFER_LENGTH]; // for retrieving vertex data video::S3DVertex v; // Assign vertex color from currently active material's diffuse color if (mtlChanged) { // retrieve the material SObjMtl *useMtl = findMtl(mtlName, grpName); // only change material if we found it if (useMtl) currMtl = useMtl; mtlChanged=false; } if (currMtl) v.Color = currMtl->Meshbuffer->Material.DiffuseColor; // get all vertices data in this face (current line of obj file) const core::stringc wordBuffer = copyLine(bufPtr, bufEnd); const c8* linePtr = wordBuffer.c_str(); const c8* const endPtr = linePtr+wordBuffer.size(); core::array faceCorners; faceCorners.reallocate(32); // should be large enough // read in all vertices linePtr = goNextWord(linePtr, endPtr); while (0 != linePtr[0]) { // Array to communicate with retrieveVertexIndices() // sends the buffer sizes and gets the actual indices // if index not set returns -1 s32 Idx[3]; Idx[1] = Idx[2] = -1; // read in next vertex's data u32 wlength = copyWord(vertexWord, linePtr, WORD_BUFFER_LENGTH, endPtr); // this function will also convert obj's 1-based index to c++'s 0-based index retrieveVertexIndices(vertexWord, Idx, vertexWord+wlength+1, vertexBuffer.size(), textureCoordBuffer.size(), normalsBuffer.size()); v.Pos = vertexBuffer[Idx[0]]; if ( -1 != Idx[1] ) v.TCoords = textureCoordBuffer[Idx[1]]; else v.TCoords.set(0.0f,0.0f); if ( -1 != Idx[2] ) v.Normal = normalsBuffer[Idx[2]]; else { v.Normal.set(0.0f,0.0f,0.0f); currMtl->RecalculateNormals=true; } int vertLocation; core::map::Node* n = currMtl->VertMap.find(v); if (n) { vertLocation = n->getValue(); } else { currMtl->Meshbuffer->Vertices.push_back(v); vertLocation = currMtl->Meshbuffer->Vertices.size() -1; currMtl->VertMap.insert(v, vertLocation); } faceCorners.push_back(vertLocation); // go to next vertex linePtr = goNextWord(linePtr, endPtr); } // triangulate the face for ( u32 i = 1; i < faceCorners.size() - 1; ++i ) { // Add a triangle currMtl->Meshbuffer->Indices.push_back( faceCorners[i+1] ); currMtl->Meshbuffer->Indices.push_back( faceCorners[i] ); currMtl->Meshbuffer->Indices.push_back( faceCorners[0] ); } faceCorners.set_used(0); // fast clear faceCorners.reallocate(32); } break; case '#': // comment default: break; } // end switch(bufPtr[0]) // eat up rest of line bufPtr = goNextLine(bufPtr, bufEnd); } // end while(bufPtr && (bufPtr-bufMeshbuffer->getIndexCount() > 0 ) { Materials[m]->Meshbuffer->recalculateBoundingBox(); if (Materials[m]->RecalculateNormals) SceneManager->getMeshManipulator()->recalculateNormals(Materials[m]->Meshbuffer); if (Materials[m]->Meshbuffer->Material.MaterialType == video::EMT_PARALLAX_MAP_SOLID) { SMesh tmp; tmp.addMeshBuffer(Materials[m]->Meshbuffer); IMesh* tangentMesh = SceneManager->getMeshManipulator()->createMeshWithTangents(&tmp); mesh->addMeshBuffer(tangentMesh->getMeshBuffer(0)); tangentMesh->drop(); } else mesh->addMeshBuffer( Materials[m]->Meshbuffer ); } } // Create the Animated mesh if there's anything in the mesh SAnimatedMesh* animMesh = 0; if ( 0 != mesh->getMeshBufferCount() ) { mesh->recalculateBoundingBox(); animMesh = new SAnimatedMesh(); animMesh->Type = EAMT_OBJ; animMesh->addMesh(mesh); animMesh->recalculateBoundingBox(); } // Clean up the allocate obj file contents delete [] buf; // more cleaning up cleanUp(); mesh->drop(); return animMesh; } const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const io::path& relPath) { u8 type=0; // map_Kd - diffuse color texture map // map_Ks - specular color texture map // map_Ka - ambient color texture map // map_Ns - shininess texture map if ((!strncmp(bufPtr,"map_bump",8)) || (!strncmp(bufPtr,"bump",4))) type=1; // normal map else if ((!strncmp(bufPtr,"map_d",5)) || (!strncmp(bufPtr,"map_opacity",11))) type=2; // opacity map else if (!strncmp(bufPtr,"map_refl",8)) type=3; // reflection map // extract new material's name c8 textureNameBuf[WORD_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); f32 bumpiness = 6.0f; bool clamp = false; // handle options while (textureNameBuf[0]=='-') { if (!strncmp(bufPtr,"-bm",3)) { bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); currMaterial->Meshbuffer->Material.MaterialTypeParam=core::fast_atof(textureNameBuf); bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); continue; } else if (!strncmp(bufPtr,"-blendu",7)) bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); else if (!strncmp(bufPtr,"-blendv",7)) bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); else if (!strncmp(bufPtr,"-cc",3)) bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); else if (!strncmp(bufPtr,"-clamp",6)) bufPtr = readBool(bufPtr, clamp, bufEnd); else if (!strncmp(bufPtr,"-texres",7)) bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); else if (!strncmp(bufPtr,"-type",5)) bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); else if (!strncmp(bufPtr,"-mm",3)) { bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); } else if (!strncmp(bufPtr,"-o",2)) // texture coord translation { bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); // next parameters are optional, so skip rest of loop if no number is found bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); if (!core::isdigit(textureNameBuf[0])) continue; bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); if (!core::isdigit(textureNameBuf[0])) continue; } else if (!strncmp(bufPtr,"-s",2)) // texture coord scale { bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); // next parameters are optional, so skip rest of loop if no number is found bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); if (!core::isdigit(textureNameBuf[0])) continue; bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); if (!core::isdigit(textureNameBuf[0])) continue; } else if (!strncmp(bufPtr,"-t",2)) { bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); // next parameters are optional, so skip rest of loop if no number is found bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); if (!core::isdigit(textureNameBuf[0])) continue; bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); if (!core::isdigit(textureNameBuf[0])) continue; } // get next word bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); } if ((type==1) && (core::isdigit(textureNameBuf[0]))) { currMaterial->Meshbuffer->Material.MaterialTypeParam=core::fast_atof(textureNameBuf); bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); } if (clamp) currMaterial->Meshbuffer->Material.setFlag(video::EMF_TEXTURE_WRAP, video::ETC_CLAMP); io::path texname(textureNameBuf); texname.replace('\\', '/'); video::ITexture * texture = 0; bool newTexture=false; if (texname.size()) { io::path texnameWithUserPath( SceneManager->getParameters()->getAttributeAsString(OBJ_TEXTURE_PATH) ); if ( texnameWithUserPath.size() ) { texnameWithUserPath += '/'; texnameWithUserPath += texname; } if (FileSystem->existFile(texnameWithUserPath)) texture = SceneManager->getVideoDriver()->getTexture(texnameWithUserPath); else if (FileSystem->existFile(texname)) { newTexture = SceneManager->getVideoDriver()->findTexture(texname) == 0; texture = SceneManager->getVideoDriver()->getTexture(texname); } else { newTexture = SceneManager->getVideoDriver()->findTexture(relPath + texname) == 0; // try to read in the relative path, the .obj is loaded from texture = SceneManager->getVideoDriver()->getTexture( relPath + texname ); } } if ( texture ) { if (type==0) currMaterial->Meshbuffer->Material.setTexture(0, texture); else if (type==1) { if (newTexture) SceneManager->getVideoDriver()->makeNormalMapTexture(texture, bumpiness); currMaterial->Meshbuffer->Material.setTexture(1, texture); currMaterial->Meshbuffer->Material.MaterialType=video::EMT_PARALLAX_MAP_SOLID; currMaterial->Meshbuffer->Material.MaterialTypeParam=0.035f; } else if (type==2) { currMaterial->Meshbuffer->Material.setTexture(0, texture); currMaterial->Meshbuffer->Material.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR; } else if (type==3) { // currMaterial->Meshbuffer->Material.Textures[1] = texture; // currMaterial->Meshbuffer->Material.MaterialType=video::EMT_REFLECTION_2_LAYER; } // Set diffuse material color to white so as not to affect texture color // Because Maya set diffuse color Kd to black when you use a diffuse color map // But is this the right thing to do? currMaterial->Meshbuffer->Material.DiffuseColor.set( currMaterial->Meshbuffer->Material.DiffuseColor.getAlpha(), 255, 255, 255 ); } return bufPtr; } void COBJMeshFileLoader::readMTL(const c8* fileName, const io::path& relPath) { const io::path realFile(fileName); io::IReadFile * mtlReader; if (FileSystem->existFile(realFile)) mtlReader = FileSystem->createAndOpenFile(realFile); else if (FileSystem->existFile(relPath + realFile)) mtlReader = FileSystem->createAndOpenFile(relPath + realFile); else if (FileSystem->existFile(FileSystem->getFileBasename(realFile))) mtlReader = FileSystem->createAndOpenFile(FileSystem->getFileBasename(realFile)); else mtlReader = FileSystem->createAndOpenFile(relPath + FileSystem->getFileBasename(realFile)); if (!mtlReader) // fail to open and read file { os::Printer::log("Could not open material file", realFile, ELL_WARNING); return; } const long filesize = mtlReader->getSize(); if (!filesize) { os::Printer::log("Skipping empty material file", realFile, ELL_WARNING); mtlReader->drop(); return; } c8* buf = new c8[filesize]; mtlReader->read((void*)buf, filesize); const c8* bufEnd = buf+filesize; SObjMtl* currMaterial = 0; const c8* bufPtr = buf; while(bufPtr != bufEnd) { switch(*bufPtr) { case 'n': // newmtl { // if there's an existing material, store it first if ( currMaterial ) Materials.push_back( currMaterial ); // extract new material's name c8 mtlNameBuf[WORD_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(mtlNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); currMaterial = new SObjMtl; currMaterial->Name = mtlNameBuf; } break; case 'i': // illum - illumination if ( currMaterial ) { const u32 COLOR_BUFFER_LENGTH = 16; c8 illumStr[COLOR_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(illumStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); currMaterial->Illumination = (c8)atol(illumStr); } break; case 'N': if ( currMaterial ) { switch(bufPtr[1]) { case 's': // Ns - shininess { const u32 COLOR_BUFFER_LENGTH = 16; c8 nsStr[COLOR_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(nsStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); f32 shininessValue = core::fast_atof(nsStr); // wavefront shininess is from [0, 1000], so scale for OpenGL shininessValue *= 0.128f; currMaterial->Meshbuffer->Material.Shininess = shininessValue; } break; case 'i': // Ni - refraction index { c8 tmpbuf[WORD_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(tmpbuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); } break; } } break; case 'K': if ( currMaterial ) { switch(bufPtr[1]) { case 'd': // Kd = diffuse { bufPtr = readColor(bufPtr, currMaterial->Meshbuffer->Material.DiffuseColor, bufEnd); } break; case 's': // Ks = specular { bufPtr = readColor(bufPtr, currMaterial->Meshbuffer->Material.SpecularColor, bufEnd); } break; case 'a': // Ka = ambience { bufPtr=readColor(bufPtr, currMaterial->Meshbuffer->Material.AmbientColor, bufEnd); } break; case 'e': // Ke = emissive { bufPtr=readColor(bufPtr, currMaterial->Meshbuffer->Material.EmissiveColor, bufEnd); } break; } // end switch(bufPtr[1]) } // end case 'K': if ( 0 != currMaterial )... break; case 'b': // bump case 'm': // texture maps if (currMaterial) { bufPtr=readTextures(bufPtr, bufEnd, currMaterial, relPath); } break; case 'd': // d - transparency if ( currMaterial ) { const u32 COLOR_BUFFER_LENGTH = 16; c8 dStr[COLOR_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(dStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); f32 dValue = core::fast_atof(dStr); currMaterial->Meshbuffer->Material.DiffuseColor.setAlpha( (s32)(dValue * 255) ); if (dValue<1.0f) currMaterial->Meshbuffer->Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; } break; case 'T': if ( currMaterial ) { switch ( bufPtr[1] ) { case 'f': // Tf - Transmitivity const u32 COLOR_BUFFER_LENGTH = 16; c8 redStr[COLOR_BUFFER_LENGTH]; c8 greenStr[COLOR_BUFFER_LENGTH]; c8 blueStr[COLOR_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(redStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); bufPtr = goAndCopyNextWord(greenStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); bufPtr = goAndCopyNextWord(blueStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); f32 transparency = ( core::fast_atof(redStr) + core::fast_atof(greenStr) + core::fast_atof(blueStr) ) / 3; currMaterial->Meshbuffer->Material.DiffuseColor.setAlpha( (s32)(transparency * 255) ); if (transparency < 1.0f) currMaterial->Meshbuffer->Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; } } break; default: // comments or not recognised break; } // end switch(bufPtr[0]) // go to next line bufPtr = goNextLine(bufPtr, bufEnd); } // end while (bufPtr) // end of file. if there's an existing material, store it if ( currMaterial ) Materials.push_back( currMaterial ); delete [] buf; mtlReader->drop(); } //! Read RGB color const c8* COBJMeshFileLoader::readColor(const c8* bufPtr, video::SColor& color, const c8* const bufEnd) { const u32 COLOR_BUFFER_LENGTH = 16; c8 colStr[COLOR_BUFFER_LENGTH]; color.setAlpha(255); bufPtr = goAndCopyNextWord(colStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); color.setRed((s32)(core::fast_atof(colStr) * 255.0f)); bufPtr = goAndCopyNextWord(colStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); color.setGreen((s32)(core::fast_atof(colStr) * 255.0f)); bufPtr = goAndCopyNextWord(colStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); color.setBlue((s32)(core::fast_atof(colStr) * 255.0f)); return bufPtr; } //! Read 3d vector of floats const c8* COBJMeshFileLoader::readVec3(const c8* bufPtr, core::vector3df& vec, const c8* const bufEnd) { const u32 WORD_BUFFER_LENGTH = 256; c8 wordBuffer[WORD_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); vec.X=-core::fast_atof(wordBuffer); // change handedness bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); vec.Y=core::fast_atof(wordBuffer); bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); vec.Z=core::fast_atof(wordBuffer); return bufPtr; } //! Read 2d vector of floats const c8* COBJMeshFileLoader::readUV(const c8* bufPtr, core::vector2df& vec, const c8* const bufEnd) { const u32 WORD_BUFFER_LENGTH = 256; c8 wordBuffer[WORD_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); vec.X=core::fast_atof(wordBuffer); bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); vec.Y=1-core::fast_atof(wordBuffer); // change handedness return bufPtr; } //! Read boolean value represented as 'on' or 'off' const c8* COBJMeshFileLoader::readBool(const c8* bufPtr, bool& tf, const c8* const bufEnd) { const u32 BUFFER_LENGTH = 8; c8 tfStr[BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(tfStr, bufPtr, BUFFER_LENGTH, bufEnd); tf = strcmp(tfStr, "off") != 0; return bufPtr; } COBJMeshFileLoader::SObjMtl* COBJMeshFileLoader::findMtl(const core::stringc& mtlName, const core::stringc& grpName) { COBJMeshFileLoader::SObjMtl* defMaterial = 0; // search existing Materials for best match // exact match does return immediately, only name match means a new group for (u32 i = 0; i < Materials.size(); ++i) { if ( Materials[i]->Name == mtlName ) { if ( Materials[i]->Group == grpName ) return Materials[i]; else defMaterial = Materials[i]; } } // we found a partial match if (defMaterial) { Materials.push_back(new SObjMtl(*defMaterial)); Materials.getLast()->Group = grpName; return Materials.getLast(); } // we found a new group for a non-existant material else if (grpName.size()) { Materials.push_back(new SObjMtl(*Materials[0])); Materials.getLast()->Group = grpName; return Materials.getLast(); } return 0; } //! skip space characters and stop on first non-space const c8* COBJMeshFileLoader::goFirstWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines) { // skip space characters if (acrossNewlines) while((buf != bufEnd) && core::isspace(*buf)) ++buf; else while((buf != bufEnd) && core::isspace(*buf) && (*buf != '\n')) ++buf; return buf; } //! skip current word and stop at beginning of next one const c8* COBJMeshFileLoader::goNextWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines) { // skip current word while(( buf != bufEnd ) && !core::isspace(*buf)) ++buf; return goFirstWord(buf, bufEnd, acrossNewlines); } //! Read until line break is reached and stop at the next non-space character const c8* COBJMeshFileLoader::goNextLine(const c8* buf, const c8* const bufEnd) { // look for newline characters while(buf != bufEnd) { // found it, so leave if (*buf=='\n' || *buf=='\r') break; ++buf; } return goFirstWord(buf, bufEnd); } u32 COBJMeshFileLoader::copyWord(c8* outBuf, const c8* const inBuf, u32 outBufLength, const c8* const bufEnd) { if (!outBufLength) return 0; if (!inBuf) { *outBuf = 0; return 0; } u32 i = 0; while(inBuf[i]) { if (core::isspace(inBuf[i]) || &(inBuf[i]) == bufEnd) break; ++i; } u32 length = core::min_(i, outBufLength-1); for (u32 j=0; j 2 ) { // error checking, shouldn't reach here unless file is wrong idxType = 0; } } else { // set all missing values to disable (=-1) while (++idxType < 3) idx[idxType]=-1; ++p; break; // while } } // go to the next char ++p; } return true; } void COBJMeshFileLoader::cleanUp() { for (u32 i=0; i < Materials.size(); ++i ) { Materials[i]->Meshbuffer->drop(); delete Materials[i]; } Materials.clear(); } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_OBJ_LOADER_ irrlicht-1.8.3/source/Irrlicht/CNullDriver.h0000644000000000000000000010023312574354552017476 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_VIDEO_NULL_H_INCLUDED__ #define __C_VIDEO_NULL_H_INCLUDED__ #include "IVideoDriver.h" #include "IFileSystem.h" #include "IImagePresenter.h" #include "IGPUProgrammingServices.h" #include "irrArray.h" #include "irrString.h" #include "irrMap.h" #include "IAttributes.h" #include "IMesh.h" #include "IMeshBuffer.h" #include "IMeshSceneNode.h" #include "CFPSCounter.h" #include "S3DVertex.h" #include "SVertexIndex.h" #include "SLight.h" #include "SExposedVideoData.h" #ifdef _MSC_VER #pragma warning( disable: 4996) #endif namespace irr { namespace io { class IWriteFile; class IReadFile; } // end namespace io namespace video { class IImageLoader; class IImageWriter; class CNullDriver : public IVideoDriver, public IGPUProgrammingServices { public: //! constructor CNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize); //! destructor virtual ~CNullDriver(); virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); virtual bool endScene(); //! Disable a feature of the driver. virtual void disableFeature(E_VIDEO_DRIVER_FEATURE feature, bool flag=true); //! queries the features of the driver, returns true if feature is available virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const; //! Get attributes of the actual video driver const io::IAttributes& getDriverAttributes() const; //! sets transformation virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat); //! Retrieve the number of image loaders virtual u32 getImageLoaderCount() const; //! Retrieve the given image loader virtual IImageLoader* getImageLoader(u32 n); //! Retrieve the number of image writers virtual u32 getImageWriterCount() const; //! Retrieve the given image writer virtual IImageWriter* getImageWriter(u32 n); //! sets a material virtual void setMaterial(const SMaterial& material); //! loads a Texture virtual ITexture* getTexture(const io::path& filename); //! loads a Texture virtual ITexture* getTexture(io::IReadFile* file); //! Returns a texture by index virtual ITexture* getTextureByIndex(u32 index); //! Returns amount of textures currently loaded virtual u32 getTextureCount() const; //! Renames a texture virtual void renameTexture(ITexture* texture, const io::path& newName); //! creates a Texture virtual ITexture* addTexture(const core::dimension2d& size, const io::path& name, ECOLOR_FORMAT format = ECF_A8R8G8B8); //! sets a render target virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color); //! set or reset special render targets virtual bool setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget, bool clearZBuffer, SColor color); //! Sets multiple render targets virtual bool setRenderTarget(const core::array& texture, bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=SColor(0,0,0,0)); //! sets a viewport virtual void setViewPort(const core::rect& area); //! gets the area of the current viewport virtual const core::rect& getViewPort() const; //! draws a vertex primitive list virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType=EVT_STANDARD, scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, E_INDEX_TYPE iType=EIT_16BIT); //! draws a vertex primitive list in 2d virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType=EVT_STANDARD, scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, E_INDEX_TYPE iType=EIT_16BIT); //! Draws a 3d line. virtual void draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color = SColor(255,255,255,255)); //! Draws a 3d triangle. virtual void draw3DTriangle(const core::triangle3df& triangle, SColor color = SColor(255,255,255,255)); //! Draws a 3d axis aligned box. virtual void draw3DBox(const core::aabbox3d& box, SColor color = SColor(255,255,255,255)); //! draws an 2d image virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos); //! draws a set of 2d images, using a color and the alpha /** channel of the texture if desired. The images are drawn beginning at pos and concatenated in one line. All drawings are clipped against clipRect (if != 0). The subtextures are defined by the array of sourceRects and are chosen by the indices given. \param texture: Texture to be drawn. \param pos: Upper left 2d destination position where the image will be drawn. \param sourceRects: Source rectangles of the image. \param indices: List of indices which choose the actual rectangle used each time. \param kerningWidth: offset on position \param clipRect: Pointer to rectangle on the screen where the image is clipped to. This pointer can be 0. Then the image is not clipped. \param color: Color with which the image is colored. Note that the alpha component is used: If alpha is other than 255, the image will be transparent. \param useAlphaChannelOfTexture: If true, the alpha channel of the texture is used to draw the image. */ virtual void draw2DImageBatch(const video::ITexture* texture, const core::position2d& pos, const core::array >& sourceRects, const core::array& indices, s32 kerningWidth = 0, const core::rect* clipRect = 0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false); //! Draws a set of 2d images, using a color and the alpha channel of the texture. /** All drawings are clipped against clipRect (if != 0). The subtextures are defined by the array of sourceRects and are positioned using the array of positions. \param texture Texture to be drawn. \param pos Array of upper left 2d destinations where the images will be drawn. \param sourceRects Source rectangles of the image. \param clipRect Pointer to rectangle on the screen where the images are clipped to. If this pointer is 0 then the image is not clipped. \param color Color with which the image is drawn. Note that the alpha component is used. If alpha is other than 255, the image will be transparent. \param useAlphaChannelOfTexture: If true, the alpha channel of the texture is used to draw the image. */ virtual void draw2DImageBatch(const video::ITexture* texture, const core::array >& positions, const core::array >& sourceRects, const core::rect* clipRect=0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false); //! 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. virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect = 0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false); //! Draws a part of the texture into the rectangle. virtual void draw2DImage(const video::ITexture* texture, const core::rect& destRect, const core::rect& sourceRect, const core::rect* clipRect = 0, const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false); //! Draws a 2d rectangle virtual void draw2DRectangle(SColor color, const core::rect& pos, const core::rect* clip = 0); //! Draws a 2d rectangle with a gradient. virtual void draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip = 0); //! Draws the outline of a 2d rectangle virtual void draw2DRectangleOutline(const core::recti& pos, SColor color=SColor(255,255,255,255)); //! Draws a 2d line. virtual void draw2DLine(const core::position2d& start, const core::position2d& end, SColor color=SColor(255,255,255,255)); //! Draws a pixel virtual void drawPixel(u32 x, u32 y, const SColor & color); //! Draws a non filled concyclic reqular 2d polyon. virtual void draw2DPolygon(core::position2d center, f32 radius, video::SColor Color, s32 vertexCount); virtual void setFog(SColor color=SColor(0,255,255,255), E_FOG_TYPE fogType=EFT_FOG_LINEAR, f32 start=50.0f, f32 end=100.0f, f32 density=0.01f, bool pixelFog=false, bool rangeFog=false); virtual void getFog(SColor& color, E_FOG_TYPE& fogType, f32& start, f32& end, f32& density, bool& pixelFog, bool& rangeFog); //! get color format of the current color buffer virtual ECOLOR_FORMAT getColorFormat() const; //! get screen size virtual const core::dimension2d& getScreenSize() const; //! get render target size virtual const core::dimension2d& getCurrentRenderTargetSize() const; // get current frames per second value virtual s32 getFPS() const; //! returns amount of primitives (mostly triangles) were drawn in the last frame. //! very useful method for statistics. virtual u32 getPrimitiveCountDrawn( u32 param = 0 ) const; //! deletes all dynamic lights there are virtual void deleteAllDynamicLights(); //! adds a dynamic light, returning an index to the light //! \param light: the light data to use to create the light //! \return An index to the light, or -1 if an error occurs virtual s32 addDynamicLight(const SLight& light); //! Turns a dynamic light on or off //! \param lightIndex: the index returned by addDynamicLight //! \param turnOn: true to turn the light on, false to turn it off virtual void turnLightOn(s32 lightIndex, bool turnOn); //! returns the maximal amount of dynamic lights the device can handle virtual u32 getMaximalDynamicLightAmount() const; //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8 //! driver, it would return "Direct3D8.1". virtual const wchar_t* getName() const; //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. virtual void setAmbientLight(const SColorf& color); //! Adds an external image loader to the engine. virtual void addExternalImageLoader(IImageLoader* loader); //! Adds an external image writer to the engine. virtual void addExternalImageWriter(IImageWriter* writer); //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do //! this: Frist, draw all geometry. Then use this method, to draw the shadow //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. virtual void drawStencilShadowVolume(const core::array& triangles, bool zfail=true, u32 debugDataVisible=0); //! Fills the stencil shadow with color. After the shadow volume has been drawn //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this //! to draw the color of the shadow. virtual void drawStencilShadow(bool clearStencilBuffer=false, video::SColor leftUpEdge = video::SColor(0,0,0,0), video::SColor rightUpEdge = video::SColor(0,0,0,0), video::SColor leftDownEdge = video::SColor(0,0,0,0), video::SColor rightDownEdge = video::SColor(0,0,0,0)); //! Returns current amount of dynamic lights set //! \return Current amount of dynamic lights set virtual u32 getDynamicLightCount() const; //! Returns light data which was previously set with IVideDriver::addDynamicLight(). //! \param idx: Zero based index of the light. Must be greater than 0 and smaller //! than IVideoDriver()::getDynamicLightCount. //! \return Light data. virtual const SLight& getDynamicLight(u32 idx) const; //! Removes a texture from the texture cache and deletes it, freeing lot of //! memory. virtual void removeTexture(ITexture* texture); //! Removes all texture from the texture cache and deletes them, freeing lot of //! memory. virtual void removeAllTextures(); //! Creates a render target texture. virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! Creates an 1bit alpha channel of the texture based of an color key. virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor color, bool zeroTexels) const; //! Creates an 1bit alpha channel of the texture based of an color key position. virtual void makeColorKeyTexture(video::ITexture* texture, core::position2d colorKeyPixelPos, bool zeroTexels) const; //! Creates a normal map from a height map texture. //! \param amplitude: Constant value by which the height information is multiplied. virtual void makeNormalMapTexture(video::ITexture* texture, f32 amplitude=1.0f) const; //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. virtual u32 getMaximalPrimitiveCount() const; //! Enables or disables a texture creation flag. virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled); //! Returns if a texture creation flag is enabled or disabled. virtual bool getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const; //! Creates a software image from a file. virtual IImage* createImageFromFile(const io::path& filename); //! Creates a software image from a file. virtual IImage* createImageFromFile(io::IReadFile* file); //! Creates a software image from a byte array. /** \param useForeignMemory: If true, the image will use the data pointer directly and own it from now on, which means it will also try to delete [] the data when the image will be destructed. If false, the memory will by copied. */ virtual IImage* createImageFromData(ECOLOR_FORMAT format, const core::dimension2d& size, void *data, bool ownForeignMemory=true, bool deleteForeignMemory = true); //! Creates an empty software image. virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d& size); //! Creates a software image from another image. virtual IImage* createImage(ECOLOR_FORMAT format, IImage *imageToCopy); //! Creates a software image from part of another image. virtual IImage* createImage(IImage* imageToCopy, const core::position2d& pos, const core::dimension2d& size); //! Creates a software image from part of a texture. virtual IImage* createImage(ITexture* texture, const core::position2d& pos, const core::dimension2d& size); //! Draws a mesh buffer virtual void drawMeshBuffer(const scene::IMeshBuffer* mb); //! Draws the normals of a mesh buffer virtual void drawMeshBufferNormals(const scene::IMeshBuffer* mb, f32 length=10.f, SColor color=0xffffffff); protected: struct SHWBufferLink { SHWBufferLink(const scene::IMeshBuffer *_MeshBuffer) :MeshBuffer(_MeshBuffer), ChangedID_Vertex(0),ChangedID_Index(0),LastUsed(0), Mapped_Vertex(scene::EHM_NEVER),Mapped_Index(scene::EHM_NEVER) { if (MeshBuffer) MeshBuffer->grab(); } virtual ~SHWBufferLink() { if (MeshBuffer) MeshBuffer->drop(); } const scene::IMeshBuffer *MeshBuffer; u32 ChangedID_Vertex; u32 ChangedID_Index; u32 LastUsed; scene::E_HARDWARE_MAPPING Mapped_Vertex; scene::E_HARDWARE_MAPPING Mapped_Index; }; //! Gets hardware buffer link from a meshbuffer (may create or update buffer) virtual SHWBufferLink *getBufferLink(const scene::IMeshBuffer* mb); //! updates hardware buffer if needed (only some drivers can) virtual bool updateHardwareBuffer(SHWBufferLink *HWBuffer) {return false;} //! Draw hardware buffer (only some drivers can) virtual void drawHardwareBuffer(SHWBufferLink *HWBuffer) {} //! Delete hardware buffer virtual void deleteHardwareBuffer(SHWBufferLink *HWBuffer); //! Create hardware buffer from mesh (only some drivers can) virtual SHWBufferLink *createHardwareBuffer(const scene::IMeshBuffer* mb) {return 0;} public: //! Update all hardware buffers, remove unused ones virtual void updateAllHardwareBuffers(); //! Remove hardware buffer virtual void removeHardwareBuffer(const scene::IMeshBuffer* mb); //! Remove all hardware buffers virtual void removeAllHardwareBuffers(); //! is vbo recommended on this mesh? virtual bool isHardwareBufferRecommend(const scene::IMeshBuffer* mb); //! Create occlusion query. /** Use node for identification and mesh for occlusion test. */ virtual void addOcclusionQuery(scene::ISceneNode* node, const scene::IMesh* mesh=0); //! Remove occlusion query. virtual void removeOcclusionQuery(scene::ISceneNode* node); //! Remove all occlusion queries. virtual void removeAllOcclusionQueries(); //! Run occlusion query. Draws mesh stored in query. /** If the mesh shall not be rendered visible, use overrideMaterial to disable the color and depth buffer. */ virtual void runOcclusionQuery(scene::ISceneNode* node, bool visible=false); //! Run all occlusion queries. Draws all meshes stored in queries. /** If the meshes shall not be rendered visible, use overrideMaterial to disable the color and depth buffer. */ virtual void runAllOcclusionQueries(bool visible=false); //! Update occlusion query. Retrieves results from GPU. /** If the query shall not block, set the flag to false. Update might not occur in this case, though */ virtual void updateOcclusionQuery(scene::ISceneNode* node, bool block=true); //! Update all occlusion queries. Retrieves results from GPU. /** If the query shall not block, set the flag to false. Update might not occur in this case, though */ virtual void updateAllOcclusionQueries(bool block=true); //! Return query result. /** Return value is the number of visible pixels/fragments. The value is a safe approximation, i.e. can be larger than the actual value of pixels. */ virtual u32 getOcclusionQueryResult(scene::ISceneNode* node) const; //! Only used by the engine internally. /** Used to notify the driver that the window was resized. */ virtual void OnResize(const core::dimension2d& size); //! Adds a new material renderer to the video device. virtual s32 addMaterialRenderer(IMaterialRenderer* renderer, const char* name = 0); //! Returns driver and operating system specific data about the IVideoDriver. virtual const SExposedVideoData& getExposedVideoData(); //! Returns type of video driver virtual E_DRIVER_TYPE getDriverType() const; //! Returns the transformation set by setTransform virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const; //! Returns pointer to the IGPUProgrammingServices interface. virtual IGPUProgrammingServices* getGPUProgrammingServices(); //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. virtual s32 addShaderMaterial(const c8* vertexShaderProgram = 0, const c8* pixelShaderProgram = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the //! programs from files. virtual s32 addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram = 0, io::IReadFile* pixelShaderProgram = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the //! programs from files. virtual s32 addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName, const io::path& pixelShaderProgramFileName, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); //! Returns pointer to material renderer or null virtual IMaterialRenderer* getMaterialRenderer(u32 idx); //! Returns amount of currently available material renderers. virtual u32 getMaterialRendererCount() const; //! Returns name of the material renderer virtual const char* getMaterialRendererName(u32 idx) const; //! Adds a new material renderer to the VideoDriver, based on a high level shading //! language. Currently only HLSL in D3D9 is supported. virtual s32 addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName = 0, E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, const c8* pixelShaderProgram = 0, const c8* pixelShaderEntryPointName = 0, E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, const c8* geometryShaderProgram = 0, const c8* geometryShaderEntryPointName = "main", E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0, E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT); //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), //! but tries to load the programs from files. virtual s32 addHighLevelShaderMaterialFromFiles( const io::path& vertexShaderProgramFile, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, const io::path& pixelShaderProgramFile = "", const c8* pixelShaderEntryPointName = "main", E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, const io::path& geometryShaderProgramFileName="", const c8* geometryShaderEntryPointName = "main", E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0, E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT); //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), //! but tries to load the programs from files. virtual s32 addHighLevelShaderMaterialFromFiles( io::IReadFile* vertexShaderProgram, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, io::IReadFile* pixelShaderProgram = 0, const c8* pixelShaderEntryPointName = "main", E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, io::IReadFile* geometryShaderProgram= 0, const c8* geometryShaderEntryPointName = "main", E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0, E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT); //! Returns a pointer to the mesh manipulator. virtual scene::IMeshManipulator* getMeshManipulator(); //! Clears the ZBuffer. virtual void clearZBuffer(); //! Returns an image created from the last rendered frame. virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER); //! Writes the provided image to disk file virtual bool writeImageToFile(IImage* image, const io::path& filename, u32 param = 0); //! Writes the provided image to a file. virtual bool writeImageToFile(IImage* image, io::IWriteFile * file, u32 param = 0); //! Sets the name of a material renderer. virtual void setMaterialRendererName(s32 idx, const char* name); //! Creates material attributes list from a material, usable for serialization and more. virtual io::IAttributes* createAttributesFromMaterial(const video::SMaterial& material, io::SAttributeReadWriteOptions* options=0); //! Fills an SMaterial structure from attributes. virtual void fillMaterialStructureFromAttributes(video::SMaterial& outMaterial, io::IAttributes* attributes); //! looks if the image is already loaded virtual video::ITexture* findTexture(const io::path& filename); //! Set/unset a clipping plane. //! There are at least 6 clipping planes available for the user to set at will. //! \param index: The plane index. Must be between 0 and MaxUserClipPlanes. //! \param plane: The plane itself. //! \param enable: If true, enable the clipping plane else disable it. virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false); //! Enable/disable a clipping plane. //! There are at least 6 clipping planes available for the user to set at will. //! \param index: The plane index. Must be between 0 and MaxUserClipPlanes. //! \param enable: If true, enable the clipping plane else disable it. virtual void enableClipPlane(u32 index, bool enable); //! Returns the graphics card vendor name. virtual core::stringc getVendorInfo() {return "Not available on this driver.";} //! Set the minimum number of vertices for which a hw buffer will be created /** \param count Number of vertices to set as minimum. */ virtual void setMinHardwareBufferVertexCount(u32 count); //! Get the global Material, which might override local materials. /** Depending on the enable flags, values from this Material are used to override those of local materials of some meshbuffer being rendered. */ virtual SOverrideMaterial& getOverrideMaterial(); //! Get the 2d override material for altering its values virtual SMaterial& getMaterial2D(); //! Enable the 2d override material virtual void enableMaterial2D(bool enable=true); //! Only used by the engine internally. virtual void setAllowZWriteOnTransparent(bool flag) { AllowZWriteOnTransparent=flag; } //! Returns the maximum texture size supported. virtual core::dimension2du getMaxTextureSize() const; //! Color conversion convenience function /** Convert an image (as array of pixels) from source to destination array, thereby converting the color format. The pixel size is determined by the color formats. \param sP Pointer to source \param sF Color format of source \param sN Number of pixels to convert, both array must be large enough \param dP Pointer to destination \param dF Color format of destination */ virtual void convertColor(const void* sP, ECOLOR_FORMAT sF, s32 sN, void* dP, ECOLOR_FORMAT dF) const; //! deprecated method virtual ITexture* createRenderTargetTexture(const core::dimension2d& size, const c8* name=0); virtual bool checkDriverReset() {return false;} protected: //! deletes all textures void deleteAllTextures(); //! opens the file and loads it into the surface video::ITexture* loadTextureFromFile(io::IReadFile* file, const io::path& hashName = ""); //! adds a surface, not loaded or created by the Irrlicht Engine void addTexture(video::ITexture* surface); //! Creates a texture from a loaded IImage. virtual ITexture* addTexture(const io::path& name, IImage* image, void* mipmapData=0); //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); //! checks triangle count and print warning if wrong bool checkPrimitiveCount(u32 prmcnt) const; // adds a material renderer and drops it afterwards. To be used for internal creation s32 addAndDropMaterialRenderer(IMaterialRenderer* m); //! deletes all material renderers void deleteMaterialRenders(); // prints renderer version void printVersion(); //! normal map lookup 32 bit version inline f32 nml32(int x, int y, int pitch, int height, s32 *p) const { if (x < 0) x = pitch-1; if (x >= pitch) x = 0; if (y < 0) y = height-1; if (y >= height) y = 0; return (f32)(((p[(y * pitch) + x])>>16) & 0xff); } //! normal map lookup 16 bit version inline f32 nml16(int x, int y, int pitch, int height, s16 *p) const { if (x < 0) x = pitch-1; if (x >= pitch) x = 0; if (y < 0) y = height-1; if (y >= height) y = 0; return (f32) getAverage ( p[(y * pitch) + x] ); } struct SSurface { video::ITexture* Surface; bool operator < (const SSurface& other) const { return Surface->getName() < other.Surface->getName(); } }; struct SMaterialRenderer { core::stringc Name; IMaterialRenderer* Renderer; }; struct SDummyTexture : public ITexture { SDummyTexture(const io::path& name) : ITexture(name), size(0,0) {}; virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0) { return 0; }; virtual void unlock(){} virtual const core::dimension2d& getOriginalSize() const { return size; } virtual const core::dimension2d& getSize() const { return size; } virtual E_DRIVER_TYPE getDriverType() const { return video::EDT_NULL; } virtual ECOLOR_FORMAT getColorFormat() const { return video::ECF_A1R5G5B5; }; virtual u32 getPitch() const { return 0; } virtual void regenerateMipMapLevels(void* mipmapData=0) {}; core::dimension2d size; }; core::array Textures; struct SOccQuery { SOccQuery(scene::ISceneNode* node, const scene::IMesh* mesh=0) : Node(node), Mesh(mesh), PID(0), Result(~0), Run(~0) { if (Node) Node->grab(); if (Mesh) Mesh->grab(); } SOccQuery(const SOccQuery& other) : Node(other.Node), Mesh(other.Mesh), PID(other.PID), Result(other.Result), Run(other.Run) { if (Node) Node->grab(); if (Mesh) Mesh->grab(); } ~SOccQuery() { if (Node) Node->drop(); if (Mesh) Mesh->drop(); } SOccQuery& operator=(const SOccQuery& other) { Node=other.Node; Mesh=other.Mesh; PID=other.PID; Result=other.Result; Run=other.Run; if (Node) Node->grab(); if (Mesh) Mesh->grab(); return *this; } bool operator==(const SOccQuery& other) const { return other.Node==Node; } scene::ISceneNode* Node; const scene::IMesh* Mesh; union { void* PID; unsigned int UID; }; u32 Result; u32 Run; }; core::array OcclusionQueries; core::array SurfaceLoader; core::array SurfaceWriter; core::array Lights; core::array MaterialRenderers; //core::array HWBufferLinks; core::map< const scene::IMeshBuffer* , SHWBufferLink* > HWBufferMap; io::IFileSystem* FileSystem; //! mesh manipulator scene::IMeshManipulator* MeshManipulator; core::rect ViewPort; core::dimension2d ScreenSize; core::matrix4 TransformationMatrix; CFPSCounter FPSCounter; u32 PrimitivesDrawn; u32 MinVertexCountForVBO; u32 TextureCreationFlags; f32 FogStart; f32 FogEnd; f32 FogDensity; SColor FogColor; SExposedVideoData ExposedData; io::IAttributes* DriverAttributes; SOverrideMaterial OverrideMaterial; SMaterial OverrideMaterial2D; SMaterial InitMaterial2D; bool OverrideMaterial2DEnabled; E_FOG_TYPE FogType; bool PixelFog; bool RangeFog; bool AllowZWriteOnTransparent; bool FeatureEnabled[video::EVDF_COUNT]; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CNullDriver.cpp0000644000000000000000000020705712574354552020045 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CNullDriver.h" #include "os.h" #include "CImage.h" #include "CAttributes.h" #include "IReadFile.h" #include "IWriteFile.h" #include "IImageLoader.h" #include "IImageWriter.h" #include "IMaterialRenderer.h" #include "IAnimatedMeshSceneNode.h" #include "CMeshManipulator.h" #include "CColorConverter.h" #include "IAttributeExchangingObject.h" namespace irr { namespace video { //! creates a loader which is able to load windows bitmaps IImageLoader* createImageLoaderBMP(); //! creates a loader which is able to load jpeg images IImageLoader* createImageLoaderJPG(); //! creates a loader which is able to load targa images IImageLoader* createImageLoaderTGA(); //! creates a loader which is able to load psd images IImageLoader* createImageLoaderPSD(); //! creates a loader which is able to load dds images IImageLoader* createImageLoaderDDS(); //! creates a loader which is able to load pcx images IImageLoader* createImageLoaderPCX(); //! creates a loader which is able to load png images IImageLoader* createImageLoaderPNG(); //! creates a loader which is able to load WAL images IImageLoader* createImageLoaderWAL(); //! creates a loader which is able to load halflife images IImageLoader* createImageLoaderHalfLife(); //! creates a loader which is able to load lmp images IImageLoader* createImageLoaderLMP(); //! creates a loader which is able to load ppm/pgm/pbm images IImageLoader* createImageLoaderPPM(); //! creates a loader which is able to load rgb images IImageLoader* createImageLoaderRGB(); //! creates a writer which is able to save bmp images IImageWriter* createImageWriterBMP(); //! creates a writer which is able to save jpg images IImageWriter* createImageWriterJPG(); //! creates a writer which is able to save tga images IImageWriter* createImageWriterTGA(); //! creates a writer which is able to save psd images IImageWriter* createImageWriterPSD(); //! creates a writer which is able to save pcx images IImageWriter* createImageWriterPCX(); //! creates a writer which is able to save png images IImageWriter* createImageWriterPNG(); //! creates a writer which is able to save ppm images IImageWriter* createImageWriterPPM(); //! constructor CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize) : FileSystem(io), MeshManipulator(0), ViewPort(0,0,0,0), ScreenSize(screenSize), PrimitivesDrawn(0), MinVertexCountForVBO(500), TextureCreationFlags(0), OverrideMaterial2DEnabled(false), AllowZWriteOnTransparent(false) { #ifdef _DEBUG setDebugName("CNullDriver"); #endif DriverAttributes = new io::CAttributes(); DriverAttributes->addInt("MaxTextures", _IRR_MATERIAL_MAX_TEXTURES_); DriverAttributes->addInt("MaxSupportedTextures", _IRR_MATERIAL_MAX_TEXTURES_); DriverAttributes->addInt("MaxLights", getMaximalDynamicLightAmount()); DriverAttributes->addInt("MaxAnisotropy", 1); // DriverAttributes->addInt("MaxUserClipPlanes", 0); // DriverAttributes->addInt("MaxAuxBuffers", 0); DriverAttributes->addInt("MaxMultipleRenderTargets", 1); DriverAttributes->addInt("MaxIndices", -1); DriverAttributes->addInt("MaxTextureSize", -1); // DriverAttributes->addInt("MaxGeometryVerticesOut", 0); // DriverAttributes->addFloat("MaxTextureLODBias", 0.f); DriverAttributes->addInt("Version", 1); // DriverAttributes->addInt("ShaderLanguageVersion", 0); // DriverAttributes->addInt("AntiAlias", 0); setFog(); setTextureCreationFlag(ETCF_ALWAYS_32_BIT, true); setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true); ViewPort = core::rect(core::position2d(0,0), core::dimension2di(screenSize)); // create manipulator MeshManipulator = new scene::CMeshManipulator(); if (FileSystem) FileSystem->grab(); // create surface loader #ifdef _IRR_COMPILE_WITH_WAL_LOADER_ SurfaceLoader.push_back(video::createImageLoaderHalfLife()); SurfaceLoader.push_back(video::createImageLoaderWAL()); #endif #ifdef _IRR_COMPILE_WITH_LMP_LOADER_ SurfaceLoader.push_back(video::createImageLoaderLMP()); #endif #ifdef _IRR_COMPILE_WITH_PPM_LOADER_ SurfaceLoader.push_back(video::createImageLoaderPPM()); #endif #ifdef _IRR_COMPILE_WITH_RGB_LOADER_ SurfaceLoader.push_back(video::createImageLoaderRGB()); #endif #ifdef _IRR_COMPILE_WITH_PSD_LOADER_ SurfaceLoader.push_back(video::createImageLoaderPSD()); #endif #ifdef _IRR_COMPILE_WITH_DDS_LOADER_ SurfaceLoader.push_back(video::createImageLoaderDDS()); #endif #ifdef _IRR_COMPILE_WITH_PCX_LOADER_ SurfaceLoader.push_back(video::createImageLoaderPCX()); #endif #ifdef _IRR_COMPILE_WITH_TGA_LOADER_ SurfaceLoader.push_back(video::createImageLoaderTGA()); #endif #ifdef _IRR_COMPILE_WITH_PNG_LOADER_ SurfaceLoader.push_back(video::createImageLoaderPNG()); #endif #ifdef _IRR_COMPILE_WITH_JPG_LOADER_ SurfaceLoader.push_back(video::createImageLoaderJPG()); #endif #ifdef _IRR_COMPILE_WITH_BMP_LOADER_ SurfaceLoader.push_back(video::createImageLoaderBMP()); #endif #ifdef _IRR_COMPILE_WITH_PPM_WRITER_ SurfaceWriter.push_back(video::createImageWriterPPM()); #endif #ifdef _IRR_COMPILE_WITH_PCX_WRITER_ SurfaceWriter.push_back(video::createImageWriterPCX()); #endif #ifdef _IRR_COMPILE_WITH_PSD_WRITER_ SurfaceWriter.push_back(video::createImageWriterPSD()); #endif #ifdef _IRR_COMPILE_WITH_TGA_WRITER_ SurfaceWriter.push_back(video::createImageWriterTGA()); #endif #ifdef _IRR_COMPILE_WITH_JPG_WRITER_ SurfaceWriter.push_back(video::createImageWriterJPG()); #endif #ifdef _IRR_COMPILE_WITH_PNG_WRITER_ SurfaceWriter.push_back(video::createImageWriterPNG()); #endif #ifdef _IRR_COMPILE_WITH_BMP_WRITER_ SurfaceWriter.push_back(video::createImageWriterBMP()); #endif // set ExposedData to 0 memset(&ExposedData, 0, sizeof(ExposedData)); for (u32 i=0; idrop(); if (FileSystem) FileSystem->drop(); if (MeshManipulator) MeshManipulator->drop(); deleteAllTextures(); u32 i; for (i=0; idrop(); for (i=0; idrop(); // delete material renderers deleteMaterialRenders(); // delete hardware mesh buffers removeAllHardwareBuffers(); } //! Adds an external surface loader to the engine. void CNullDriver::addExternalImageLoader(IImageLoader* loader) { if (!loader) return; loader->grab(); SurfaceLoader.push_back(loader); } //! Adds an external surface writer to the engine. void CNullDriver::addExternalImageWriter(IImageWriter* writer) { if (!writer) return; writer->grab(); SurfaceWriter.push_back(writer); } //! Retrieve the number of image loaders u32 CNullDriver::getImageLoaderCount() const { return SurfaceLoader.size(); } //! Retrieve the given image loader IImageLoader* CNullDriver::getImageLoader(u32 n) { if (n < SurfaceLoader.size()) return SurfaceLoader[n]; return 0; } //! Retrieve the number of image writers u32 CNullDriver::getImageWriterCount() const { return SurfaceWriter.size(); } //! Retrieve the given image writer IImageWriter* CNullDriver::getImageWriter(u32 n) { if (n < SurfaceWriter.size()) return SurfaceWriter[n]; return 0; } //! deletes all textures void CNullDriver::deleteAllTextures() { // we need to remove previously set textures which might otherwise be kept in the // last set material member. Could be optimized to reduce state changes. setMaterial(SMaterial()); for (u32 i=0; idrop(); Textures.clear(); } //! applications must call this method before performing any rendering. returns false if failed. bool CNullDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, const SExposedVideoData& videoData, core::rect* sourceRect) { core::clearFPUException(); PrimitivesDrawn = 0; return true; } //! applications must call this method after performing any rendering. returns false if failed. bool CNullDriver::endScene() { FPSCounter.registerFrame(os::Timer::getRealTime(), PrimitivesDrawn); updateAllHardwareBuffers(); updateAllOcclusionQueries(); return true; } //! Disable a feature of the driver. void CNullDriver::disableFeature(E_VIDEO_DRIVER_FEATURE feature, bool flag) { FeatureEnabled[feature]=!flag; } //! queries the features of the driver, returns true if feature is available bool CNullDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const { return false; } //! Get attributes of the actual video driver const io::IAttributes& CNullDriver::getDriverAttributes() const { return *DriverAttributes; } //! sets transformation void CNullDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) { } //! Returns the transformation set by setTransform const core::matrix4& CNullDriver::getTransform(E_TRANSFORMATION_STATE state) const { return TransformationMatrix; } //! sets a material void CNullDriver::setMaterial(const SMaterial& material) { } //! Removes a texture from the texture cache and deletes it, freeing lot of //! memory. void CNullDriver::removeTexture(ITexture* texture) { if (!texture) return; for (u32 i=0; idrop(); Textures.erase(i); } } } //! Removes all texture from the texture cache and deletes them, freeing lot of //! memory. void CNullDriver::removeAllTextures() { setMaterial ( SMaterial() ); deleteAllTextures(); } //! Returns a texture by index ITexture* CNullDriver::getTextureByIndex(u32 i) { if ( i < Textures.size() ) return Textures[i].Surface; return 0; } //! Returns amount of textures currently loaded u32 CNullDriver::getTextureCount() const { return Textures.size(); } //! Renames a texture void CNullDriver::renameTexture(ITexture* texture, const io::path& newName) { // we can do a const_cast here safely, the name of the ITexture interface // is just readonly to prevent the user changing the texture name without invoking // this method, because the textures will need resorting afterwards io::SNamedPath& name = const_cast(texture->getName()); name.setPath(newName); Textures.sort(); } //! loads a Texture ITexture* CNullDriver::getTexture(const io::path& filename) { // Identify textures by their absolute filenames if possible. const io::path absolutePath = FileSystem->getAbsolutePath(filename); ITexture* texture = findTexture(absolutePath); if (texture) return texture; // Then try the raw filename, which might be in an Archive texture = findTexture(filename); if (texture) return texture; // Now try to open the file using the complete path. io::IReadFile* file = FileSystem->createAndOpenFile(absolutePath); if (!file) { // Try to open it using the raw filename. file = FileSystem->createAndOpenFile(filename); } if (file) { // Re-check name for actual archive names texture = findTexture(file->getFileName()); if (texture) { file->drop(); return texture; } texture = loadTextureFromFile(file); file->drop(); if (texture) { addTexture(texture); texture->drop(); // drop it because we created it, one grab too much } else os::Printer::log("Could not load texture", filename, ELL_ERROR); return texture; } else { os::Printer::log("Could not open file of texture", filename, ELL_WARNING); return 0; } } //! loads a Texture ITexture* CNullDriver::getTexture(io::IReadFile* file) { ITexture* texture = 0; if (file) { texture = findTexture(file->getFileName()); if (texture) return texture; texture = loadTextureFromFile(file); if (texture) { addTexture(texture); texture->drop(); // drop it because we created it, one grab too much } if (!texture) os::Printer::log("Could not load texture", file->getFileName(), ELL_WARNING); } return texture; } //! opens the file and loads it into the surface video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const io::path& hashName ) { ITexture* texture = 0; IImage* image = createImageFromFile(file); if (image) { // create texture from surface texture = createDeviceDependentTexture(image, hashName.size() ? hashName : file->getFileName() ); os::Printer::log("Loaded texture", file->getFileName()); image->drop(); } return texture; } //! adds a surface, not loaded or created by the Irrlicht Engine void CNullDriver::addTexture(video::ITexture* texture) { if (texture) { SSurface s; s.Surface = texture; texture->grab(); Textures.push_back(s); // the new texture is now at the end of the texture list. when searching for // the next new texture, the texture array will be sorted and the index of this texture // will be changed. to let the order be more consistent to the user, sort // the textures now already although this isn't necessary: Textures.sort(); } } //! looks if the image is already loaded video::ITexture* CNullDriver::findTexture(const io::path& filename) { SSurface s; SDummyTexture dummy(filename); s.Surface = &dummy; s32 index = Textures.binary_search(s); if (index != -1) return Textures[index].Surface; return 0; } //! Creates a texture from a loaded IImage. ITexture* CNullDriver::addTexture(const io::path& name, IImage* image, void* mipmapData) { if ( 0 == name.size() || !image) return 0; ITexture* t = createDeviceDependentTexture(image, name, mipmapData); if (t) { addTexture(t); t->drop(); } return t; } //! creates a Texture ITexture* CNullDriver::addTexture(const core::dimension2d& size, const io::path& name, ECOLOR_FORMAT format) { if(IImage::isRenderTargetOnlyFormat(format)) { os::Printer::log("Could not create ITexture, format only supported for render target textures.", ELL_WARNING); return 0; } if ( 0 == name.size () ) return 0; IImage* image = new CImage(format, size); ITexture* t = createDeviceDependentTexture(image, name); image->drop(); addTexture(t); if (t) t->drop(); return t; } //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES ITexture* CNullDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) { return new SDummyTexture(name); } //! set or reset special render targets bool CNullDriver::setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget, bool clearZBuffer, SColor color) { if (ERT_FRAME_BUFFER==target) return setRenderTarget(0,clearTarget, clearZBuffer, color); else return false; } //! sets a render target bool CNullDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, bool clearZBuffer, SColor color) { return false; } //! Sets multiple render targets bool CNullDriver::setRenderTarget(const core::array& texture, bool clearBackBuffer, bool clearZBuffer, SColor color) { return false; } //! sets a viewport void CNullDriver::setViewPort(const core::rect& area) { } //! gets the area of the current viewport const core::rect& CNullDriver::getViewPort() const { return ViewPort; } //! draws a vertex primitive list 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) { if ((iType==EIT_16BIT) && (vertexCount>65536)) os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur."); PrimitivesDrawn += primitiveCount; } //! draws a vertex primitive list in 2d 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) { if ((iType==EIT_16BIT) && (vertexCount>65536)) os::Printer::log("Too many vertices for 16bit index type, render artifacts may occur."); PrimitivesDrawn += primitiveCount; } //! Draws a 3d line. void CNullDriver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color) { } //! Draws a 3d triangle. void CNullDriver::draw3DTriangle(const core::triangle3df& triangle, SColor color) { S3DVertex vertices[3]; vertices[0].Pos=triangle.pointA; vertices[0].Color=color; vertices[0].Normal=triangle.getNormal().normalize(); vertices[0].TCoords.set(0.f,0.f); vertices[1].Pos=triangle.pointB; vertices[1].Color=color; vertices[1].Normal=vertices[0].Normal; vertices[1].TCoords.set(0.5f,1.f); vertices[2].Pos=triangle.pointC; vertices[2].Color=color; vertices[2].Normal=vertices[0].Normal; vertices[2].TCoords.set(1.f,0.f); const u16 indexList[] = {0,1,2}; drawVertexPrimitiveList(vertices, 3, indexList, 1, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT); } //! Draws a 3d axis aligned box. void CNullDriver::draw3DBox(const core::aabbox3d& box, SColor color) { core::vector3df edges[8]; box.getEdges(edges); // TODO: optimize into one big drawIndexPrimitive call. draw3DLine(edges[5], edges[1], color); draw3DLine(edges[1], edges[3], color); draw3DLine(edges[3], edges[7], color); draw3DLine(edges[7], edges[5], color); draw3DLine(edges[0], edges[2], color); draw3DLine(edges[2], edges[6], color); draw3DLine(edges[6], edges[4], color); draw3DLine(edges[4], edges[0], color); draw3DLine(edges[1], edges[0], color); draw3DLine(edges[3], edges[2], color); draw3DLine(edges[7], edges[6], color); draw3DLine(edges[5], edges[4], color); } //! draws an 2d image void CNullDriver::draw2DImage(const video::ITexture* texture, const core::position2d& destPos) { if (!texture) return; draw2DImage(texture,destPos, core::rect(core::position2d(0,0), core::dimension2di(texture->getOriginalSize()))); } //! draws a set of 2d images, using a color and the alpha channel of the //! texture if desired. The images are drawn beginning at pos and concatenated //! in one line. All drawings are clipped against clipRect (if != 0). //! The subtextures are defined by the array of sourceRects and are chosen //! by the indices given. void CNullDriver::draw2DImageBatch(const video::ITexture* texture, const core::position2d& pos, const core::array >& sourceRects, const core::array& indices, s32 kerningWidth, const core::rect* clipRect, SColor color, bool useAlphaChannelOfTexture) { core::position2d target(pos); for (u32 i=0; i >& positions, const core::array >& sourceRects, const core::rect* clipRect, SColor color, bool useAlphaChannelOfTexture) { const irr::u32 drawCount = core::min_(positions.size(), sourceRects.size()); for (u32 i=0; i& destRect, const core::rect& sourceRect, const core::rect* clipRect, const video::SColor* const colors, bool useAlphaChannelOfTexture) { if (destRect.isValid()) draw2DImage(texture, core::position2d(destRect.UpperLeftCorner), sourceRect, clipRect, colors?colors[0]:video::SColor(0xffffffff), useAlphaChannelOfTexture); } //! 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. void CNullDriver::draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect, SColor color, bool useAlphaChannelOfTexture) { } //! Draws the outline of a 2d rectangle void CNullDriver::draw2DRectangleOutline(const core::recti& pos, SColor color) { draw2DLine(pos.UpperLeftCorner, core::position2di(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y), color); draw2DLine(core::position2di(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y), pos.LowerRightCorner, color); draw2DLine(pos.LowerRightCorner, core::position2di(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y), color); draw2DLine(core::position2di(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y), pos.UpperLeftCorner, color); } //! Draw a 2d rectangle void CNullDriver::draw2DRectangle(SColor color, const core::rect& pos, const core::rect* clip) { draw2DRectangle(pos, color, color, color, color, clip); } //! Draws a 2d rectangle with a gradient. void CNullDriver::draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip) { } //! Draws a 2d line. void CNullDriver::draw2DLine(const core::position2d& start, const core::position2d& end, SColor color) { } //! Draws a pixel void CNullDriver::drawPixel(u32 x, u32 y, const SColor & color) { } //! Draws a non filled concyclic regular 2d polyon. void CNullDriver::draw2DPolygon(core::position2d center, f32 radius, video::SColor color, s32 count) { if (count < 2) return; core::position2d first; core::position2d a,b; for (s32 j=0; j((s32)(sin(p)*radius), (s32)(cos(p)*radius)); if (j==0) first = a; else draw2DLine(a, b, color); } draw2DLine(a, first, color); } //! returns color format ECOLOR_FORMAT CNullDriver::getColorFormat() const { return ECF_R5G6B5; } //! returns screen size const core::dimension2d& CNullDriver::getScreenSize() const { return ScreenSize; } //! returns the current render target size, //! or the screen size if render targets are not implemented const core::dimension2d& CNullDriver::getCurrentRenderTargetSize() const { return ScreenSize; } // returns current frames per second value s32 CNullDriver::getFPS() const { return FPSCounter.getFPS(); } //! returns amount of primitives (mostly triangles) were drawn in the last frame. //! very useful method for statistics. u32 CNullDriver::getPrimitiveCountDrawn( u32 param ) const { return (0 == param) ? FPSCounter.getPrimitive() : (1 == param) ? FPSCounter.getPrimitiveAverage() : FPSCounter.getPrimitiveTotal(); } //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. void CNullDriver::setAmbientLight(const SColorf& color) { } //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8 //! driver, it would return "Direct3D8". const wchar_t* CNullDriver::getName() const { return L"Irrlicht NullDevice"; } //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do //! this: Frist, draw all geometry. Then use this method, to draw the shadow //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. void CNullDriver::drawStencilShadowVolume(const core::array& triangles, bool zfail, u32 debugDataVisible) { } //! Fills the stencil shadow with color. After the shadow volume has been drawn //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this //! to draw the color of the shadow. void CNullDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge, video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge) { } //! deletes all dynamic lights there are void CNullDriver::deleteAllDynamicLights() { Lights.set_used(0); } //! adds a dynamic light s32 CNullDriver::addDynamicLight(const SLight& light) { Lights.push_back(light); return Lights.size() - 1; } //! Turns a dynamic light on or off //! \param lightIndex: the index returned by addDynamicLight //! \param turnOn: true to turn the light on, false to turn it off void CNullDriver::turnLightOn(s32 lightIndex, bool turnOn) { // Do nothing } //! returns the maximal amount of dynamic lights the device can handle u32 CNullDriver::getMaximalDynamicLightAmount() const { return 0; } //! Returns current amount of dynamic lights set //! \return Current amount of dynamic lights set u32 CNullDriver::getDynamicLightCount() const { return Lights.size(); } //! Returns light data which was previously set by IVideoDriver::addDynamicLight(). //! \param idx: Zero based index of the light. Must be greater than 0 and smaller //! than IVideoDriver()::getDynamicLightCount. //! \return Light data. const SLight& CNullDriver::getDynamicLight(u32 idx) const { if ( idx < Lights.size() ) return Lights[idx]; else return *((SLight*)0); } //! Creates a boolean alpha channel of the texture based of an color key. void CNullDriver::makeColorKeyTexture(video::ITexture* texture, video::SColor color, bool zeroTexels) const { if (!texture) return; if (texture->getColorFormat() != ECF_A1R5G5B5 && texture->getColorFormat() != ECF_A8R8G8B8 ) { os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR); return; } if (texture->getColorFormat() == ECF_A1R5G5B5) { u16 *p = (u16*)texture->lock(); if (!p) { os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR); return; } const core::dimension2d dim = texture->getSize(); const u32 pitch = texture->getPitch() / 2; // color with alpha disabled (i.e. fully transparent) const u16 refZeroAlpha = (0x7fff & color.toA1R5G5B5()); const u32 pixels = pitch * dim.Height; for (u32 pixel = 0; pixel < pixels; ++ pixel) { // If the color matches the reference color, ignoring alphas, // set the alpha to zero. if(((*p) & 0x7fff) == refZeroAlpha) { if(zeroTexels) (*p) = 0; else (*p) = refZeroAlpha; } ++p; } texture->unlock(); } else { u32 *p = (u32*)texture->lock(); if (!p) { os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR); return; } core::dimension2d dim = texture->getSize(); u32 pitch = texture->getPitch() / 4; // color with alpha disabled (fully transparent) const u32 refZeroAlpha = 0x00ffffff & color.color; const u32 pixels = pitch * dim.Height; for (u32 pixel = 0; pixel < pixels; ++ pixel) { // If the color matches the reference color, ignoring alphas, // set the alpha to zero. if(((*p) & 0x00ffffff) == refZeroAlpha) { if(zeroTexels) (*p) = 0; else (*p) = refZeroAlpha; } ++p; } texture->unlock(); } texture->regenerateMipMapLevels(); } //! Creates an boolean alpha channel of the texture based of an color key position. void CNullDriver::makeColorKeyTexture(video::ITexture* texture, core::position2d colorKeyPixelPos, bool zeroTexels) const { if (!texture) return; if (texture->getColorFormat() != ECF_A1R5G5B5 && texture->getColorFormat() != ECF_A8R8G8B8 ) { os::Printer::log("Error: Unsupported texture color format for making color key channel.", ELL_ERROR); return; } SColor colorKey; if (texture->getColorFormat() == ECF_A1R5G5B5) { u16 *p = (u16*)texture->lock(ETLM_READ_ONLY); if (!p) { os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR); return; } u32 pitch = texture->getPitch() / 2; const u16 key16Bit = 0x7fff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X]; colorKey = video::A1R5G5B5toA8R8G8B8(key16Bit); } else { u32 *p = (u32*)texture->lock(ETLM_READ_ONLY); if (!p) { os::Printer::log("Could not lock texture for making color key channel.", ELL_ERROR); return; } u32 pitch = texture->getPitch() / 4; colorKey = 0x00ffffff & p[colorKeyPixelPos.Y*pitch + colorKeyPixelPos.X]; } texture->unlock(); makeColorKeyTexture(texture, colorKey, zeroTexels); } //! Creates a normal map from a height map texture. //! \param amplitude: Constant value by which the height information is multiplied. void CNullDriver::makeNormalMapTexture(video::ITexture* texture, f32 amplitude) const { if (!texture) return; if (texture->getColorFormat() != ECF_A1R5G5B5 && texture->getColorFormat() != ECF_A8R8G8B8 ) { os::Printer::log("Error: Unsupported texture color format for making normal map.", ELL_ERROR); return; } core::dimension2d dim = texture->getSize(); amplitude = amplitude / 255.0f; f32 vh = dim.Height / (f32)dim.Width; f32 hh = dim.Width / (f32)dim.Height; if (texture->getColorFormat() == ECF_A8R8G8B8) { // ECF_A8R8G8B8 version s32 *p = (s32*)texture->lock(); if (!p) { os::Printer::log("Could not lock texture for making normal map.", ELL_ERROR); return; } // copy texture u32 pitch = texture->getPitch() / 4; s32* in = new s32[dim.Height * pitch]; memcpy(in, p, dim.Height * pitch * 4); for (s32 x=0; x < s32(pitch); ++x) for (s32 y=0; y < s32(dim.Height); ++y) { // TODO: this could be optimized really a lot core::vector3df h1((x-1)*hh, nml32(x-1, y, pitch, dim.Height, in)*amplitude, y*vh); core::vector3df h2((x+1)*hh, nml32(x+1, y, pitch, dim.Height, in)*amplitude, y*vh); //core::vector3df v1(x*hh, nml32(x, y-1, pitch, dim.Height, in)*amplitude, (y-1)*vh); //core::vector3df v2(x*hh, nml32(x, y+1, pitch, dim.Height, in)*amplitude, (y+1)*vh); core::vector3df v1(x*hh, nml32(x, y+1, pitch, dim.Height, in)*amplitude, (y-1)*vh); core::vector3df v2(x*hh, nml32(x, y-1, pitch, dim.Height, in)*amplitude, (y+1)*vh); core::vector3df v = v1-v2; core::vector3df h = h1-h2; core::vector3df n = v.crossProduct(h); n.normalize(); n *= 0.5f; n += core::vector3df(0.5f,0.5f,0.5f); // now between 0 and 1 n *= 255.0f; s32 height = (s32)nml32(x, y, pitch, dim.Height, in); p[y*pitch + x] = video::SColor( height, // store height in alpha (s32)n.X, (s32)n.Z, (s32)n.Y).color; } delete [] in; texture->unlock(); } else { // ECF_A1R5G5B5 version s16 *p = (s16*)texture->lock(); if (!p) { os::Printer::log("Could not lock texture for making normal map.", ELL_ERROR); return; } u32 pitch = texture->getPitch() / 2; // copy texture s16* in = new s16[dim.Height * pitch]; memcpy(in, p, dim.Height * pitch * 2); for (s32 x=0; x < s32(pitch); ++x) for (s32 y=0; y < s32(dim.Height); ++y) { // TODO: this could be optimized really a lot core::vector3df h1((x-1)*hh, nml16(x-1, y, pitch, dim.Height, in)*amplitude, y*vh); core::vector3df h2((x+1)*hh, nml16(x+1, y, pitch, dim.Height, in)*amplitude, y*vh); core::vector3df v1(x*hh, nml16(x, y-1, pitch, dim.Height, in)*amplitude, (y-1)*vh); core::vector3df v2(x*hh, nml16(x, y+1, pitch, dim.Height, in)*amplitude, (y+1)*vh); core::vector3df v = v1-v2; core::vector3df h = h1-h2; core::vector3df n = v.crossProduct(h); n.normalize(); n *= 0.5f; n += core::vector3df(0.5f,0.5f,0.5f); // now between 0 and 1 n *= 255.0f; p[y*pitch + x] = video::RGBA16((u32)n.X, (u32)n.Z, (u32)n.Y); } delete [] in; texture->unlock(); } texture->regenerateMipMapLevels(); } //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. u32 CNullDriver::getMaximalPrimitiveCount() const { return 0xFFFFFFFF; } //! checks triangle count and print warning if wrong bool CNullDriver::checkPrimitiveCount(u32 prmCount) const { const u32 m = getMaximalPrimitiveCount(); if (prmCount > m) { char tmp[1024]; sprintf(tmp,"Could not draw triangles, too many primitives(%u), maxium is %u.", prmCount, m); os::Printer::log(tmp, ELL_ERROR); return false; } return true; } //! Enables or disables a texture creation flag. void CNullDriver::setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled) { if (enabled && ((flag == ETCF_ALWAYS_16_BIT) || (flag == ETCF_ALWAYS_32_BIT) || (flag == ETCF_OPTIMIZED_FOR_QUALITY) || (flag == ETCF_OPTIMIZED_FOR_SPEED))) { // disable other formats setTextureCreationFlag(ETCF_ALWAYS_16_BIT, false); setTextureCreationFlag(ETCF_ALWAYS_32_BIT, false); setTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY, false); setTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED, false); } // set flag TextureCreationFlags = (TextureCreationFlags & (~flag)) | ((((u32)!enabled)-1) & flag); } //! Returns if a texture creation flag is enabled or disabled. bool CNullDriver::getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const { return (TextureCreationFlags & flag)!=0; } //! Creates a software image from a file. IImage* CNullDriver::createImageFromFile(const io::path& filename) { if (!filename.size()) return 0; IImage* image = 0; io::IReadFile* file = FileSystem->createAndOpenFile(filename); if (file) { image = createImageFromFile(file); file->drop(); } else os::Printer::log("Could not open file of image", filename, ELL_WARNING); return image; } //! Creates a software image from a file. IImage* CNullDriver::createImageFromFile(io::IReadFile* file) { if (!file) return 0; IImage* image = 0; s32 i; // try to load file based on file extension for (i=SurfaceLoader.size()-1; i>=0; --i) { if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName())) { // reset file position which might have changed due to previous loadImage calls file->seek(0); image = SurfaceLoader[i]->loadImage(file); if (image) return image; } } // try to load file based on what is in it for (i=SurfaceLoader.size()-1; i>=0; --i) { // dito file->seek(0); if (SurfaceLoader[i]->isALoadableFileFormat(file)) { file->seek(0); image = SurfaceLoader[i]->loadImage(file); if (image) return image; } } return 0; // failed to load } //! Writes the provided image to disk file bool CNullDriver::writeImageToFile(IImage* image, const io::path& filename,u32 param) { io::IWriteFile* file = FileSystem->createAndWriteFile(filename); if(!file) return false; bool result = writeImageToFile(image, file, param); file->drop(); return result; } //! Writes the provided image to a file. bool CNullDriver::writeImageToFile(IImage* image, io::IWriteFile * file, u32 param) { if(!file) return false; for (s32 i=SurfaceWriter.size()-1; i>=0; --i) { if (SurfaceWriter[i]->isAWriteableFileExtension(file->getFileName())) { bool written = SurfaceWriter[i]->writeImage(file, image, param); if (written) return true; } } return false; // failed to write } //! Creates a software image from a byte array. IImage* CNullDriver::createImageFromData(ECOLOR_FORMAT format, const core::dimension2d& size, void *data, bool ownForeignMemory, bool deleteMemory) { if(IImage::isRenderTargetOnlyFormat(format)) { os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING); return 0; } return new CImage(format, size, data, ownForeignMemory, deleteMemory); } //! Creates an empty software image. IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2d& size) { if(IImage::isRenderTargetOnlyFormat(format)) { os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING); return 0; } return new CImage(format, size); } //! Creates a software image from another image. IImage* CNullDriver::createImage(ECOLOR_FORMAT format, IImage *imageToCopy) { os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING); if(IImage::isRenderTargetOnlyFormat(format)) { os::Printer::log("Could not create IImage, format only supported for render target textures.", ELL_WARNING); return 0; } CImage* tmp = new CImage(format, imageToCopy->getDimension()); imageToCopy->copyTo(tmp); return tmp; } //! Creates a software image from part of another image. IImage* CNullDriver::createImage(IImage* imageToCopy, const core::position2d& pos, const core::dimension2d& size) { os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING); CImage* tmp = new CImage(imageToCopy->getColorFormat(), imageToCopy->getDimension()); imageToCopy->copyTo(tmp, core::position2di(0,0), core::recti(pos,size)); return tmp; } //! Creates a software image from part of a texture. IImage* CNullDriver::createImage(ITexture* texture, const core::position2d& pos, const core::dimension2d& size) { if ((pos==core::position2di(0,0)) && (size == texture->getSize())) { IImage* image = new CImage(texture->getColorFormat(), size, texture->lock(ETLM_READ_ONLY), false); texture->unlock(); return image; } else { // make sure to avoid buffer overruns // make the vector a separate variable for g++ 3.x const core::vector2d leftUpper(core::clamp(static_cast(pos.X), 0u, texture->getSize().Width), core::clamp(static_cast(pos.Y), 0u, texture->getSize().Height)); const core::rect clamped(leftUpper, core::dimension2du(core::clamp(static_cast(size.Width), 0u, texture->getSize().Width), core::clamp(static_cast(size.Height), 0u, texture->getSize().Height))); if (!clamped.isValid()) return 0; u8* src = static_cast(texture->lock(ETLM_READ_ONLY)); if (!src) return 0; IImage* image = new CImage(texture->getColorFormat(), clamped.getSize()); u8* dst = static_cast(image->lock()); src += clamped.UpperLeftCorner.Y * texture->getPitch() + image->getBytesPerPixel() * clamped.UpperLeftCorner.X; for (u32 i=0; igetColorFormat(), clamped.getWidth(), dst, image->getColorFormat()); src += texture->getPitch(); dst += image->getPitch(); } image->unlock(); texture->unlock(); return image; } } //! Sets the fog mode. void CNullDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog) { FogColor = color; FogType = fogType; FogStart = start; FogEnd = end; FogDensity = density; PixelFog = pixelFog; RangeFog = rangeFog; } //! Gets the fog mode. void CNullDriver::getFog(SColor& color, E_FOG_TYPE& fogType, f32& start, f32& end, f32& density, bool& pixelFog, bool& rangeFog) { color = FogColor; fogType = FogType; start = FogStart; end = FogEnd; density = FogDensity; pixelFog = PixelFog; rangeFog = RangeFog; } //! Draws a mesh buffer void CNullDriver::drawMeshBuffer(const scene::IMeshBuffer* mb) { if (!mb) return; //IVertexBuffer and IIndexBuffer later SHWBufferLink *HWBuffer=getBufferLink(mb); if (HWBuffer) drawHardwareBuffer(HWBuffer); else drawVertexPrimitiveList(mb->getVertices(), mb->getVertexCount(), mb->getIndices(), mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType()); } //! Draws the normals of a mesh buffer void CNullDriver::drawMeshBufferNormals(const scene::IMeshBuffer* mb, f32 length, SColor color) { const u32 count = mb->getVertexCount(); const bool normalize = mb->getMaterial().NormalizeNormals; for (u32 i=0; i < count; ++i) { core::vector3df normalizedNormal = mb->getNormal(i); if (normalize) normalizedNormal.normalize(); const core::vector3df& pos = mb->getPosition(i); draw3DLine(pos, pos + (normalizedNormal * length), color); } } CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IMeshBuffer* mb) { if (!mb || !isHardwareBufferRecommend(mb)) return 0; //search for hardware links core::map< const scene::IMeshBuffer*,SHWBufferLink* >::Node* node = HWBufferMap.find(mb); if (node) return node->getValue(); return createHardwareBuffer(mb); //no hardware links, and mesh wants one, create it } //! Update all hardware buffers, remove unused ones void CNullDriver::updateAllHardwareBuffers() { core::map::ParentFirstIterator Iterator=HWBufferMap.getParentFirstIterator(); for (;!Iterator.atEnd();Iterator++) { SHWBufferLink *Link=Iterator.getNode()->getValue(); Link->LastUsed++; if (Link->LastUsed>20000) { deleteHardwareBuffer(Link); // todo: needs better fix Iterator = HWBufferMap.getParentFirstIterator(); } } } void CNullDriver::deleteHardwareBuffer(SHWBufferLink *HWBuffer) { if (!HWBuffer) return; HWBufferMap.remove(HWBuffer->MeshBuffer); delete HWBuffer; } //! Remove hardware buffer void CNullDriver::removeHardwareBuffer(const scene::IMeshBuffer* mb) { core::map::Node* node = HWBufferMap.find(mb); if (node) deleteHardwareBuffer(node->getValue()); } //! Remove all hardware buffers void CNullDriver::removeAllHardwareBuffers() { while (HWBufferMap.size()) deleteHardwareBuffer(HWBufferMap.getRoot()->getValue()); } bool CNullDriver::isHardwareBufferRecommend(const scene::IMeshBuffer* mb) { if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER)) return false; if (mb->getVertexCount()getType() != scene::ESNT_MESH) && (node->getType() != scene::ESNT_ANIMATED_MESH)) return; else if (node->getType() == scene::ESNT_MESH) mesh = static_cast(node)->getMesh(); else mesh = static_cast(node)->getMesh()->getMesh(0); if (!mesh) return; } //search for query s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if (index != -1) { if (OcclusionQueries[index].Mesh != mesh) { OcclusionQueries[index].Mesh->drop(); OcclusionQueries[index].Mesh = mesh; mesh->grab(); } } else { OcclusionQueries.push_back(SOccQuery(node, mesh)); node->setAutomaticCulling(node->getAutomaticCulling() | scene::EAC_OCC_QUERY); } } //! Remove occlusion query. void CNullDriver::removeOcclusionQuery(scene::ISceneNode* node) { //search for query s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if (index != -1) { node->setAutomaticCulling(node->getAutomaticCulling() & ~scene::EAC_OCC_QUERY); OcclusionQueries.erase(index); } } //! Remove all occlusion queries. void CNullDriver::removeAllOcclusionQueries() { for (s32 i=OcclusionQueries.size()-1; i>=0; --i) { removeOcclusionQuery(OcclusionQueries[i].Node); } } //! Run occlusion query. Draws mesh stored in query. /** If the mesh shall be rendered visible, use flag to enable the proper material setting. */ void CNullDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible) { if(!node) return; s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if (index==-1) return; OcclusionQueries[index].Run=0; if (!visible) { SMaterial mat; mat.Lighting=false; mat.AntiAliasing=0; mat.ColorMask=ECP_NONE; mat.GouraudShading=false; mat.ZWriteEnable=false; setMaterial(mat); } setTransform(video::ETS_WORLD, node->getAbsoluteTransformation()); const scene::IMesh* mesh = OcclusionQueries[index].Mesh; for (u32 i=0; igetMeshBufferCount(); ++i) { if (visible) setMaterial(mesh->getMeshBuffer(i)->getMaterial()); drawMeshBuffer(mesh->getMeshBuffer(i)); } } //! Run all occlusion queries. Draws all meshes stored in queries. /** If the meshes shall not be rendered visible, use overrideMaterial to disable the color and depth buffer. */ void CNullDriver::runAllOcclusionQueries(bool visible) { for (u32 i=0; i1000) removeOcclusionQuery(OcclusionQueries[i].Node); } } //! Return query result. /** Return value is the number of visible pixels/fragments. The value is a safe approximation, i.e. can be larger then the actual value of pixels. */ u32 CNullDriver::getOcclusionQueryResult(scene::ISceneNode* node) const { return ~0; } //! Only used by the internal engine. Used to notify the driver that //! the window was resized. void CNullDriver::OnResize(const core::dimension2d& size) { if (ViewPort.getWidth() == (s32)ScreenSize.Width && ViewPort.getHeight() == (s32)ScreenSize.Height) ViewPort = core::rect(core::position2d(0,0), core::dimension2di(size)); ScreenSize = size; } // adds a material renderer and drops it afterwards. To be used for internal creation s32 CNullDriver::addAndDropMaterialRenderer(IMaterialRenderer* m) { s32 i = addMaterialRenderer(m); if (m) m->drop(); return i; } //! Adds a new material renderer to the video device. s32 CNullDriver::addMaterialRenderer(IMaterialRenderer* renderer, const char* name) { if (!renderer) return -1; SMaterialRenderer r; r.Renderer = renderer; r.Name = name; if (name == 0 && (MaterialRenderers.size() < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 )) { // set name of built in renderer so that we don't have to implement name // setting in all available renderers. r.Name = sBuiltInMaterialTypeNames[MaterialRenderers.size()]; } MaterialRenderers.push_back(r); renderer->grab(); return MaterialRenderers.size()-1; } //! Sets the name of a material renderer. void CNullDriver::setMaterialRendererName(s32 idx, const char* name) { if (idx < s32(sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 || idx >= (s32)MaterialRenderers.size()) return; MaterialRenderers[idx].Name = name; } //! Creates material attributes list from a material, usable for serialization and more. io::IAttributes* CNullDriver::createAttributesFromMaterial(const video::SMaterial& material, io::SAttributeReadWriteOptions* options) { io::CAttributes* attr = new io::CAttributes(this); attr->addEnum("Type", material.MaterialType, sBuiltInMaterialTypeNames); attr->addColor("Ambient", material.AmbientColor); attr->addColor("Diffuse", material.DiffuseColor); attr->addColor("Emissive", material.EmissiveColor); attr->addColor("Specular", material.SpecularColor); attr->addFloat("Shininess", material.Shininess); attr->addFloat("Param1", material.MaterialTypeParam); attr->addFloat("Param2", material.MaterialTypeParam2); core::stringc prefix="Texture"; u32 i; for (i=0; iFlags&io::EARWF_USE_RELATIVE_PATHS) && options->Filename && material.getTexture(i)) { io::path path = FileSystem->getRelativeFilename( FileSystem->getAbsolutePath(material.getTexture(i)->getName()), options->Filename); attr->addTexture((prefix+core::stringc(i+1)).c_str(), material.getTexture(i), path); } else attr->addTexture((prefix+core::stringc(i+1)).c_str(), material.getTexture(i)); } attr->addBool("Wireframe", material.Wireframe); attr->addBool("GouraudShading", material.GouraudShading); attr->addBool("Lighting", material.Lighting); attr->addBool("ZWriteEnable", material.ZWriteEnable); attr->addInt("ZBuffer", material.ZBuffer); attr->addBool("BackfaceCulling", material.BackfaceCulling); attr->addBool("FrontfaceCulling", material.FrontfaceCulling); attr->addBool("FogEnable", material.FogEnable); attr->addBool("NormalizeNormals", material.NormalizeNormals); attr->addBool("UseMipMaps", material.UseMipMaps); attr->addInt("AntiAliasing", material.AntiAliasing); attr->addInt("ColorMask", material.ColorMask); attr->addInt("ColorMaterial", material.ColorMaterial); attr->addInt("PolygonOffsetFactor", material.PolygonOffsetFactor); attr->addEnum("PolygonOffsetDirection", material.PolygonOffsetDirection, video::PolygonOffsetDirectionNames); prefix = "BilinearFilter"; for (i=0; iaddBool((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].BilinearFilter); prefix = "TrilinearFilter"; for (i=0; iaddBool((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TrilinearFilter); prefix = "AnisotropicFilter"; for (i=0; iaddInt((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].AnisotropicFilter); prefix="TextureWrapU"; for (i=0; iaddEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrapU, aTextureClampNames); prefix="TextureWrapV"; for (i=0; iaddEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrapV, aTextureClampNames); prefix="LODBias"; for (i=0; iaddInt((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].LODBias); return attr; } //! Fills an SMaterial structure from attributes. void CNullDriver::fillMaterialStructureFromAttributes(video::SMaterial& outMaterial, io::IAttributes* attr) { outMaterial.MaterialType = video::EMT_SOLID; core::stringc name = attr->getAttributeAsString("Type"); u32 i; for ( i=0; i < MaterialRenderers.size(); ++i) if ( name == MaterialRenderers[i].Name ) { outMaterial.MaterialType = (video::E_MATERIAL_TYPE)i; break; } outMaterial.AmbientColor = attr->getAttributeAsColor("Ambient"); outMaterial.DiffuseColor = attr->getAttributeAsColor("Diffuse"); outMaterial.EmissiveColor = attr->getAttributeAsColor("Emissive"); outMaterial.SpecularColor = attr->getAttributeAsColor("Specular"); outMaterial.Shininess = attr->getAttributeAsFloat("Shininess"); outMaterial.MaterialTypeParam = attr->getAttributeAsFloat("Param1"); outMaterial.MaterialTypeParam2 = attr->getAttributeAsFloat("Param2"); core::stringc prefix="Texture"; for (i=0; igetAttributeAsTexture((prefix+core::stringc(i+1)).c_str())); outMaterial.Wireframe = attr->getAttributeAsBool("Wireframe"); outMaterial.GouraudShading = attr->getAttributeAsBool("GouraudShading"); outMaterial.Lighting = attr->getAttributeAsBool("Lighting"); outMaterial.ZWriteEnable = attr->getAttributeAsBool("ZWriteEnable"); outMaterial.ZBuffer = (u8)attr->getAttributeAsInt("ZBuffer"); outMaterial.BackfaceCulling = attr->getAttributeAsBool("BackfaceCulling"); outMaterial.FrontfaceCulling = attr->getAttributeAsBool("FrontfaceCulling"); outMaterial.FogEnable = attr->getAttributeAsBool("FogEnable"); outMaterial.NormalizeNormals = attr->getAttributeAsBool("NormalizeNormals"); if (attr->existsAttribute("UseMipMaps")) // legacy outMaterial.UseMipMaps = attr->getAttributeAsBool("UseMipMaps"); else outMaterial.UseMipMaps = true; // default 0 is ok outMaterial.AntiAliasing = attr->getAttributeAsInt("AntiAliasing"); if (attr->existsAttribute("ColorMask")) outMaterial.ColorMask = attr->getAttributeAsInt("ColorMask"); if (attr->existsAttribute("ColorMaterial")) outMaterial.ColorMaterial = attr->getAttributeAsInt("ColorMaterial"); if (attr->existsAttribute("PolygonOffsetFactor")) outMaterial.PolygonOffsetFactor = attr->getAttributeAsInt("PolygonOffsetFactor"); if (attr->existsAttribute("PolygonOffsetDirection")) outMaterial.PolygonOffsetDirection = (video::E_POLYGON_OFFSET)attr->getAttributeAsEnumeration("PolygonOffsetDirection", video::PolygonOffsetDirectionNames); prefix = "BilinearFilter"; if (attr->existsAttribute(prefix.c_str())) // legacy outMaterial.setFlag(EMF_BILINEAR_FILTER, attr->getAttributeAsBool(prefix.c_str())); else for (i=0; igetAttributeAsBool((prefix+core::stringc(i+1)).c_str()); prefix = "TrilinearFilter"; if (attr->existsAttribute(prefix.c_str())) // legacy outMaterial.setFlag(EMF_TRILINEAR_FILTER, attr->getAttributeAsBool(prefix.c_str())); else for (i=0; igetAttributeAsBool((prefix+core::stringc(i+1)).c_str()); prefix = "AnisotropicFilter"; if (attr->existsAttribute(prefix.c_str())) // legacy outMaterial.setFlag(EMF_ANISOTROPIC_FILTER, attr->getAttributeAsBool(prefix.c_str())); else for (i=0; igetAttributeAsInt((prefix+core::stringc(i+1)).c_str()); prefix = "TextureWrap"; if (attr->existsAttribute(prefix.c_str())) // legacy { for (i=0; igetAttributeAsEnumeration((prefix+core::stringc(i+1)).c_str(), aTextureClampNames); outMaterial.TextureLayer[i].TextureWrapV = outMaterial.TextureLayer[i].TextureWrapU; } } else { for (i=0; igetAttributeAsEnumeration((prefix+"U"+core::stringc(i+1)).c_str(), aTextureClampNames); outMaterial.TextureLayer[i].TextureWrapV = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+"V"+core::stringc(i+1)).c_str(), aTextureClampNames); } } // default 0 is ok prefix="LODBias"; for (i=0; igetAttributeAsInt((prefix+core::stringc(i+1)).c_str()); } //! Returns driver and operating system specific data about the IVideoDriver. const SExposedVideoData& CNullDriver::getExposedVideoData() { return ExposedData; } //! Returns type of video driver E_DRIVER_TYPE CNullDriver::getDriverType() const { return EDT_NULL; } //! deletes all material renderers void CNullDriver::deleteMaterialRenders() { // delete material renderers for (u32 i=0; idrop(); MaterialRenderers.clear(); } //! Returns pointer to material renderer or null IMaterialRenderer* CNullDriver::getMaterialRenderer(u32 idx) { if ( idx < MaterialRenderers.size() ) return MaterialRenderers[idx].Renderer; else return 0; } //! Returns amount of currently available material renderers. u32 CNullDriver::getMaterialRendererCount() const { return MaterialRenderers.size(); } //! Returns name of the material renderer const char* CNullDriver::getMaterialRendererName(u32 idx) const { if ( idx < MaterialRenderers.size() ) return MaterialRenderers[idx].Name.c_str(); return 0; } //! Returns pointer to the IGPUProgrammingServices interface. IGPUProgrammingServices* CNullDriver::getGPUProgrammingServices() { return this; } //! Adds a new material renderer to the VideoDriver, based on a high level shading language. s32 CNullDriver::addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, const c8* geometryShaderProgram, const c8* geometryShaderEntryPointName, E_GEOMETRY_SHADER_TYPE gsCompileTarget, scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 verticesOut, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData, E_GPU_SHADING_LANGUAGE shadingLang) { os::Printer::log("High level shader materials not available (yet) in this driver, sorry"); return -1; } //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), //! but tries to load the programs from files. s32 CNullDriver::addHighLevelShaderMaterialFromFiles( const io::path& vertexShaderProgramFileName, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, const io::path& pixelShaderProgramFileName, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, const io::path& geometryShaderProgramFileName, const c8* geometryShaderEntryPointName, E_GEOMETRY_SHADER_TYPE gsCompileTarget, scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 verticesOut, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData, E_GPU_SHADING_LANGUAGE shadingLang) { io::IReadFile* vsfile = 0; io::IReadFile* psfile = 0; io::IReadFile* gsfile = 0; if (vertexShaderProgramFileName.size() ) { vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName); if (!vsfile) { os::Printer::log("Could not open vertex shader program file", vertexShaderProgramFileName, ELL_WARNING); } } if (pixelShaderProgramFileName.size() ) { psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName); if (!psfile) { os::Printer::log("Could not open pixel shader program file", pixelShaderProgramFileName, ELL_WARNING); } } if (geometryShaderProgramFileName.size() ) { gsfile = FileSystem->createAndOpenFile(geometryShaderProgramFileName); if (!gsfile) { os::Printer::log("Could not open geometry shader program file", geometryShaderProgramFileName, ELL_WARNING); } } s32 result = addHighLevelShaderMaterialFromFiles( vsfile, vertexShaderEntryPointName, vsCompileTarget, psfile, pixelShaderEntryPointName, psCompileTarget, gsfile, geometryShaderEntryPointName, gsCompileTarget, inType, outType, verticesOut, callback, baseMaterial, userData, shadingLang); if (psfile) psfile->drop(); if (vsfile) vsfile->drop(); if (gsfile) gsfile->drop(); return result; } //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), //! but tries to load the programs from files. s32 CNullDriver::addHighLevelShaderMaterialFromFiles( io::IReadFile* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, io::IReadFile* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, io::IReadFile* geometryShaderProgram, const c8* geometryShaderEntryPointName, E_GEOMETRY_SHADER_TYPE gsCompileTarget, scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 verticesOut, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData, E_GPU_SHADING_LANGUAGE shadingLang) { c8* vs = 0; c8* ps = 0; c8* gs = 0; if (vertexShaderProgram) { const long size = vertexShaderProgram->getSize(); if (size) { vs = new c8[size+1]; vertexShaderProgram->read(vs, size); vs[size] = 0; } } if (pixelShaderProgram) { const long size = pixelShaderProgram->getSize(); if (size) { // if both handles are the same we must reset the file if (pixelShaderProgram==vertexShaderProgram) pixelShaderProgram->seek(0); ps = new c8[size+1]; pixelShaderProgram->read(ps, size); ps[size] = 0; } } if (geometryShaderProgram) { const long size = geometryShaderProgram->getSize(); if (size) { // if both handles are the same we must reset the file if ((geometryShaderProgram==vertexShaderProgram) || (geometryShaderProgram==pixelShaderProgram)) geometryShaderProgram->seek(0); gs = new c8[size+1]; geometryShaderProgram->read(gs, size); gs[size] = 0; } } s32 result = this->addHighLevelShaderMaterial( vs, vertexShaderEntryPointName, vsCompileTarget, ps, pixelShaderEntryPointName, psCompileTarget, gs, geometryShaderEntryPointName, gsCompileTarget, inType, outType, verticesOut, callback, baseMaterial, userData, shadingLang); delete [] vs; delete [] ps; delete [] gs; return result; } //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. s32 CNullDriver::addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) { os::Printer::log("Shader materials not implemented yet in this driver, sorry."); return -1; } //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the //! programs from files. s32 CNullDriver::addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram, io::IReadFile* pixelShaderProgram, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) { c8* vs = 0; c8* ps = 0; if (vertexShaderProgram) { const long size = vertexShaderProgram->getSize(); if (size) { vs = new c8[size+1]; vertexShaderProgram->read(vs, size); vs[size] = 0; } } if (pixelShaderProgram) { const long size = pixelShaderProgram->getSize(); if (size) { ps = new c8[size+1]; pixelShaderProgram->read(ps, size); ps[size] = 0; } } s32 result = addShaderMaterial(vs, ps, callback, baseMaterial, userData); delete [] vs; delete [] ps; return result; } //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the //! programs from files. s32 CNullDriver::addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName, const io::path& pixelShaderProgramFileName, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) { io::IReadFile* vsfile = 0; io::IReadFile* psfile = 0; if (vertexShaderProgramFileName.size()) { vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName); if (!vsfile) { os::Printer::log("Could not open vertex shader program file", vertexShaderProgramFileName, ELL_WARNING); return -1; } } if (pixelShaderProgramFileName.size()) { psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName); if (!psfile) { os::Printer::log("Could not open pixel shader program file", pixelShaderProgramFileName, ELL_WARNING); if (vsfile) vsfile->drop(); return -1; } } s32 result = addShaderMaterialFromFiles(vsfile, psfile, callback, baseMaterial, userData); if (psfile) psfile->drop(); if (vsfile) vsfile->drop(); return result; } //! Creates a render target texture. ITexture* CNullDriver::addRenderTargetTexture(const core::dimension2d& size, const io::path&name, const ECOLOR_FORMAT format) { return 0; } //! Clears the ZBuffer. void CNullDriver::clearZBuffer() { } //! Returns a pointer to the mesh manipulator. scene::IMeshManipulator* CNullDriver::getMeshManipulator() { return MeshManipulator; } //! Returns an image created from the last rendered frame. IImage* CNullDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target) { return 0; } // prints renderer version void CNullDriver::printVersion() { core::stringw namePrint = L"Using renderer: "; namePrint += getName(); os::Printer::log(namePrint.c_str(), ELL_INFORMATION); } //! creates a video driver IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize) { CNullDriver* nullDriver = new CNullDriver(io, screenSize); // create empty material renderers for(u32 i=0; sBuiltInMaterialTypeNames[i]; ++i) { IMaterialRenderer* imr = new IMaterialRenderer(); nullDriver->addMaterialRenderer(imr); imr->drop(); } return nullDriver; } //! Set/unset a clipping plane. //! There are at least 6 clipping planes available for the user to set at will. //! \param index: The plane index. Must be between 0 and MaxUserClipPlanes. //! \param plane: The plane itself. //! \param enable: If true, enable the clipping plane else disable it. bool CNullDriver::setClipPlane(u32 index, const core::plane3df& plane, bool enable) { return false; } //! Enable/disable a clipping plane. void CNullDriver::enableClipPlane(u32 index, bool enable) { // not necessary } ITexture* CNullDriver::createRenderTargetTexture(const core::dimension2d& size, const c8* name) { os::Printer::log("createRenderTargetTexture is deprecated, use addRenderTargetTexture instead"); ITexture* tex = addRenderTargetTexture(size, name); tex->grab(); return tex; } void CNullDriver::setMinHardwareBufferVertexCount(u32 count) { MinVertexCountForVBO = count; } SOverrideMaterial& CNullDriver::getOverrideMaterial() { return OverrideMaterial; } //! Get the 2d override material for altering its values SMaterial& CNullDriver::getMaterial2D() { return OverrideMaterial2D; } //! Enable the 2d override material void CNullDriver::enableMaterial2D(bool enable) { OverrideMaterial2DEnabled=enable; } core::dimension2du CNullDriver::getMaxTextureSize() const { return core::dimension2du(0x10000,0x10000); // maybe large enough } //! Color conversion convenience function /** Convert an image (as array of pixels) from source to destination array, thereby converting the color format. The pixel size is determined by the color formats. \param sP Pointer to source \param sF Color format of source \param sN Number of pixels to convert, both array must be large enough \param dP Pointer to destination \param dF Color format of destination */ void CNullDriver::convertColor(const void* sP, ECOLOR_FORMAT sF, s32 sN, void* dP, ECOLOR_FORMAT dF) const { video::CColorConverter::convert_viaFormat(sP, sF, sN, dP, dF); } } // end namespace } // end namespace irrlicht-1.8.3/source/Irrlicht/CNPKReader.h0000644000000000000000000000710112574354552017163 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // Copyright (C) 2009-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_NPK_READER_H_INCLUDED__ #define __C_NPK_READER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ #include "IReferenceCounted.h" #include "IReadFile.h" #include "irrArray.h" #include "irrString.h" #include "IFileSystem.h" #include "CFileList.h" namespace irr { namespace io { namespace { //! File header containing location and size of the table of contents struct SNPKHeader { // Don't change the order of these fields! They must match the order stored on disk. c8 Tag[4]; u32 Length; u32 Offset; }; //! An entry in the NPK file's table of contents. struct SNPKFileEntry { core::stringc Name; u32 Offset; u32 Length; }; } // end namespace //! Archiveloader capable of loading Nebula Device 2 NPK Archives class CArchiveLoaderNPK : public IArchiveLoader { public: //! Constructor CArchiveLoaderNPK(io::IFileSystem* fs); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".zip") virtual bool isALoadableFileFormat(const io::path& filename) const; //! Check if the file might be loaded by this class /** Check might look into the file. \param file File handle to check. \return True if file seems to be loadable. */ virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! Check to see if the loader can create archives of this type. /** Check based on the archive type. \param fileType The archive type to check. \return True if the archile loader supports this type, false if not */ virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const; //! Creates an archive from the filename /** \param file File handle to check. \return Pointer to newly created archive, or 0 upon error. */ virtual IFileArchive* createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const; //! creates/loads an archive from the file. //! \return Pointer to the created archive. Returns 0 if loading failed. virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; //! Returns the type of archive created by this loader virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_NPK; } private: io::IFileSystem* FileSystem; }; //! reads from NPK class CNPKReader : public virtual IFileArchive, virtual CFileList { public: CNPKReader(IReadFile* file, bool ignoreCase, bool ignorePaths); virtual ~CNPKReader(); // file archive methods //! return the id of the file Archive virtual const io::path& getArchiveName() const { return File->getFileName(); } //! opens a file by file name virtual IReadFile* createAndOpenFile(const io::path& filename); //! opens a file by index virtual IReadFile* createAndOpenFile(u32 index); //! returns the list of files virtual const IFileList* getFileList() const; //! get the class Type virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_NPK; } private: //! scans for a local header, returns false if the header is invalid bool scanLocalHeader(); void readString(core::stringc& name); IReadFile* File; }; } // end namespace io } // end namespace irr #endif // __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ #endif // __C_NPK_READER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CNPKReader.cpp0000644000000000000000000001412312574354552017520 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // Copyright (C) 2009-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // Based on the NPK reader from Irrlicht #include "CNPKReader.h" #ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ #include "os.h" #include "coreutil.h" #ifdef _DEBUG #define IRR_DEBUG_NPK_READER #endif namespace irr { namespace io { namespace { bool isHeaderValid(const SNPKHeader& header) { const c8* const tag = header.Tag; return tag[0] == '0' && tag[1] == 'K' && tag[2] == 'P' && tag[3] == 'N'; } } // end namespace //! Constructor CArchiveLoaderNPK::CArchiveLoaderNPK( io::IFileSystem* fs) : FileSystem(fs) { #ifdef _DEBUG setDebugName("CArchiveLoaderNPK"); #endif } //! returns true if the file maybe is able to be loaded by this class bool CArchiveLoaderNPK::isALoadableFileFormat(const io::path& filename) const { return core::hasFileExtension(filename, "npk"); } //! Check to see if the loader can create archives of this type. bool CArchiveLoaderNPK::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const { return fileType == EFAT_NPK; } //! Creates an archive from the filename /** \param file File handle to check. \return Pointer to newly created archive, or 0 upon error. */ IFileArchive* CArchiveLoaderNPK::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const { IFileArchive *archive = 0; io::IReadFile* file = FileSystem->createAndOpenFile(filename); if (file) { archive = createArchive(file, ignoreCase, ignorePaths); file->drop (); } return archive; } //! creates/loads an archive from the file. //! \return Pointer to the created archive. Returns 0 if loading failed. IFileArchive* CArchiveLoaderNPK::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const { IFileArchive *archive = 0; if ( file ) { file->seek ( 0 ); archive = new CNPKReader(file, ignoreCase, ignorePaths); } return archive; } //! Check if the file might be loaded by this class /** Check might look into the file. \param file File handle to check. \return True if file seems to be loadable. */ bool CArchiveLoaderNPK::isALoadableFileFormat(io::IReadFile* file) const { SNPKHeader header; file->read(&header, sizeof(header)); return isHeaderValid(header); } /*! NPK Reader */ CNPKReader::CNPKReader(IReadFile* file, bool ignoreCase, bool ignorePaths) : CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file) { #ifdef _DEBUG setDebugName("CNPKReader"); #endif if (File) { File->grab(); if (scanLocalHeader()) sort(); else os::Printer::log("Failed to load NPK archive."); } } CNPKReader::~CNPKReader() { if (File) File->drop(); } const IFileList* CNPKReader::getFileList() const { return this; } bool CNPKReader::scanLocalHeader() { SNPKHeader header; // Read and validate the header File->read(&header, sizeof(header)); if (!isHeaderValid(header)) return false; // Seek to the table of contents #ifdef __BIG_ENDIAN__ header.Offset = os::Byteswap::byteswap(header.Offset); header.Length = os::Byteswap::byteswap(header.Length); #endif header.Offset += 8; core::stringc dirName; bool inTOC=true; // Loop through each entry in the table of contents while (inTOC && (File->getPos() < File->getSize())) { // read an entry char tag[4]={0}; SNPKFileEntry entry; File->read(tag, 4); const int numTag = MAKE_IRR_ID(tag[3],tag[2],tag[1],tag[0]); int size; bool isDir=true; switch (numTag) { case MAKE_IRR_ID('D','I','R','_'): { File->read(&size, 4); readString(entry.Name); entry.Length=0; entry.Offset=0; #ifdef IRR_DEBUG_NPK_READER os::Printer::log("Dir", entry.Name); #endif } break; case MAKE_IRR_ID('F','I','L','E'): { File->read(&size, 4); File->read(&entry.Offset, 4); File->read(&entry.Length, 4); readString(entry.Name); isDir=false; #ifdef IRR_DEBUG_NPK_READER os::Printer::log("File", entry.Name); #endif #ifdef __BIG_ENDIAN__ entry.Offset = os::Byteswap::byteswap(entry.Offset); entry.Length = os::Byteswap::byteswap(entry.Length); #endif } break; case MAKE_IRR_ID('D','E','N','D'): { File->read(&size, 4); entry.Name=""; entry.Length=0; entry.Offset=0; const s32 pos = dirName.findLast('/', dirName.size()-2); if (pos==-1) dirName=""; else dirName=dirName.subString(0, pos); #ifdef IRR_DEBUG_NPK_READER os::Printer::log("Dirend", dirName); #endif } break; default: inTOC=false; } // skip root dir if (isDir) { if (!entry.Name.size() || (entry.Name==".") || (entry.Name=="")) continue; dirName += entry.Name; dirName += "/"; } #ifdef IRR_DEBUG_NPK_READER os::Printer::log("Name", entry.Name); #endif addItem((isDir?dirName:dirName+entry.Name), entry.Offset+header.Offset, entry.Length, isDir); } return true; } //! opens a file by file name IReadFile* CNPKReader::createAndOpenFile(const io::path& filename) { s32 index = findFile(filename, false); if (index != -1) return createAndOpenFile(index); return 0; } //! opens a file by index IReadFile* CNPKReader::createAndOpenFile(u32 index) { if (index >= Files.size() ) return 0; const SFileListEntry &entry = Files[index]; return createLimitReadFile( entry.FullName, File, entry.Offset, entry.Size ); } void CNPKReader::readString(core::stringc& name) { short stringSize; char buf[256]; File->read(&stringSize, 2); #ifdef __BIG_ENDIAN__ stringSize = os::Byteswap::byteswap(stringSize); #endif name.reserve(stringSize); while(stringSize) { const short next = core::min_(stringSize, (short)255); File->read(buf,next); buf[next]=0; name.append(buf); stringSize -= next; } } } // end namespace io } // end namespace irr #endif // __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ irrlicht-1.8.3/source/Irrlicht/CMY3DMeshFileLoader.h0000644000000000000000000000731512574354552020677 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // This file was originally written by ZDimitor. // I (Nikolaus Gebhardt) did some few changes to this: // - replaced logging calls to their os:: counterparts // - removed some logging calls // - removed setTexture path and replaced it with the directory of the mesh // - added EAMT_MY3D file type // - fixed a memory leak when decompressing RLE data. // - cleaned multi character constant problems with gcc // - removed octree child scene node generation because irrlicht is now able to draw // scene nodes with transparent and sold materials in them at the same time. (see changes.txt) // Thanks a lot to ZDimitor for his work on this and that he gave me // his permission to add it into Irrlicht. //-------------------------------------------------------------------------------- // This tool created by ZDimitor everyone can use it as wants //-------------------------------------------------------------------------------- #ifndef __CMY3D_MESH_FILE_LOADER_H_INCLUDED__ #define __CMY3D_MESH_FILE_LOADER_H_INCLUDED__ #ifdef _MSC_VER #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #endif #include "IMeshLoader.h" #include "SMesh.h" #include "SMeshBufferLightMap.h" #include "IFileSystem.h" #include "IVideoDriver.h" #include "irrString.h" #include "ISceneManager.h" namespace irr { namespace scene { // byte-align structures #include "irrpack.h" struct SMyColor { SMyColor () {;} SMyColor (s32 __R, s32 __G, s32 __B, s32 __A) : R(__R), G(__G), B(__B), A(__A) {} s32 R, G, B, A; } PACK_STRUCT; // material header struct SMyMaterialHeader { c8 Name[256]; // material name u32 Index; SMyColor AmbientColor; SMyColor DiffuseColor; SMyColor EmissiveColor; SMyColor SpecularColor; f32 Shininess; f32 Transparency; u32 TextureCount; // texture count } PACK_STRUCT; // Default alignment #include "irrunpack.h" class CMY3DMeshFileLoader : public IMeshLoader { public: CMY3DMeshFileLoader(ISceneManager *scmgr, io::IFileSystem* fs); virtual ~CMY3DMeshFileLoader(); virtual bool isALoadableFileExtension(const io::path& filename) const; virtual IAnimatedMesh* createMesh(io::IReadFile* file); //! getting access to the nodes (with transparent material), creating //! while loading .my3d file const core::array& getChildNodes() const; private: video::ITexture* readEmbeddedLightmap(io::IReadFile* file, char* namebuf); scene::ISceneManager* SceneManager; io::IFileSystem* FileSystem; struct SMyMaterialEntry { SMyMaterialEntry () : Texture1FileName("null"), Texture2FileName("null"), Texture1(0), Texture2(0), MaterialType(video::EMT_SOLID) {} SMyMaterialHeader Header; core::stringc Texture1FileName; core::stringc Texture2FileName; video::ITexture *Texture1; video::ITexture *Texture2; video::E_MATERIAL_TYPE MaterialType; }; struct SMyMeshBufferEntry { SMyMeshBufferEntry() : MaterialIndex(-1), MeshBuffer(0) {} SMyMeshBufferEntry(s32 mi, SMeshBufferLightMap* mb) : MaterialIndex(mi), MeshBuffer(mb) {} s32 MaterialIndex; SMeshBufferLightMap* MeshBuffer; }; SMyMaterialEntry* getMaterialEntryByIndex (u32 matInd); SMeshBufferLightMap* getMeshBufferByMaterialIndex(u32 matInd); core::array MaterialEntry; core::array MeshBufferEntry; core::array ChildNodes; }; } // end namespace scene } // end namespace irr #endif // __CMY3D_MESH_FILE_LOADER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CMY3DMeshFileLoader.cpp0000644000000000000000000006175412574354552021241 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // This file was originally written by ZDimitor. //----------------------------------------------------------------------------- // This tool created by ZDimitor everyone can use it as wants //----------------------------------------------------------------------------- #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_MY3D_LOADER_ #include "CMY3DMeshFileLoader.h" #include "SAnimatedMesh.h" #include "SMeshBuffer.h" #include "IReadFile.h" #include "IAttributes.h" #include "CMY3DHelper.h" #include "os.h" // v3.15 - May 16, 2005 namespace irr { namespace scene { static const u32 MY3D_ID = 0x4d593344; static const u16 MY3D_VER = 0x0003; static const u16 MY3D_SCENE_HEADER_ID = 0x1000; static const u16 MY3D_MAT_LIST_ID = 0x2000; static const u16 MY3D_MAT_HEADER_ID = 0x2100; static const u16 MY3D_TEX_FNAME_ID = 0x2101; static const u16 MY3D_TEXDATA_HEADER_ID = 0x2501; static const u16 MY3D_TEXDATA_RLE_HEADER_ID = 0x2502; static const u16 MY3D_MESH_LIST_ID = 0x3000; static const u16 MY3D_MESH_HEADER_ID = 0x3100; static const u16 MY3D_VERTS_ID = 0x3101; static const u16 MY3D_FACES_ID = 0x3102; static const u16 MY3D_TVERTS_ID = 0x3103; static const u16 MY3D_TFACES_ID = 0x3104; static const u16 MY3D_FILE_END_ID = 0xFFFF; static const unsigned long MY3D_TEXDATA_COMPR_NONE_ID = 0x4e4f4e45; static const unsigned long MY3D_TEXDATA_COMPR_SIMPLE_ID = 0x53494d50; static const unsigned long MY3D_TEXDATA_COMPR_RLE_ID = 0x20524c45; static const unsigned long MY3D_PIXEL_FORMAT_24 = 0x5f32345f; static const unsigned long MY3D_PIXEL_FORMAT_16 = 0x5f31365f; CMY3DMeshFileLoader::CMY3DMeshFileLoader(ISceneManager* scmgr, io::IFileSystem* fs) : SceneManager(scmgr), FileSystem(fs) { #ifdef _DEBUG setDebugName("CMY3DMeshFileLoader"); #endif if (FileSystem) FileSystem->grab(); } CMY3DMeshFileLoader::~CMY3DMeshFileLoader() { if (FileSystem) FileSystem->drop(); } bool CMY3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "my3d" ); } IAnimatedMesh* CMY3DMeshFileLoader::createMesh(io::IReadFile* file) { MaterialEntry.clear(); MeshBufferEntry.clear(); ChildNodes.clear(); // working directory (from which we load the scene) core::stringc filepath = FileSystem->getFileDir(file->getFileName()); if (filepath==".") filepath=""; else filepath.append("/"); // read file into memory SMyFileHeader fileHeader; file->read(&fileHeader, sizeof(SMyFileHeader)); #ifdef __BIG_ENDIAN__ fileHeader.MyId = os::Byteswap::byteswap(fileHeader.MyId); fileHeader.Ver = os::Byteswap::byteswap(fileHeader.Ver); #endif if (fileHeader.MyId!=MY3D_ID || fileHeader.Ver!=MY3D_VER) { os::Printer::log("Bad MY3D file header, loading failed!", ELL_ERROR); return 0; } u16 id; file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_SCENE_HEADER_ID) { os::Printer::log("Cannot find MY3D_SCENE_HEADER_ID, loading failed!", ELL_ERROR); return 0; } SMySceneHeader sceneHeader; file->read(&sceneHeader, sizeof(SMySceneHeader)); #ifdef __BIG_ENDIAN__ sceneHeader.MaterialCount = os::Byteswap::byteswap(sceneHeader.MaterialCount); sceneHeader.MeshCount = os::Byteswap::byteswap(sceneHeader.MeshCount); #endif file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_MAT_LIST_ID) { os::Printer::log("Can not find MY3D_MAT_LIST_ID, loading failed!", ELL_ERROR); return 0; } core::stringc texturePath = SceneManager->getParameters()->getAttributeAsString(MY3D_TEXTURE_PATH); file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif c8 namebuf[256]; for (s32 m=0; mread(&(me.Header), sizeof(SMyMaterialHeader)); // read next identificator file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif bool gotLightMap=false, gotMainMap=false; for (u32 t=0; tread(namebuf, 256); else { me.Texture2 = readEmbeddedLightmap(file, namebuf); if (!me.Texture2) return 0; gotLightMap = true; } const core::stringc name(namebuf); const s32 pos = name.findLast('.'); const core::stringc LightingMapStr = "LightingMap"; const s32 ls = LightingMapStr.size(); const bool isSubString = (LightingMapStr == name.subString(core::max_(0, (pos - ls)), ls)); if ((isSubString || (name[pos-1]=='m' && name[pos-2]=='l' && name[pos-3]=='_')) && !gotLightMap) { const bool oldMipMapState = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); me.Texture2FileName = texturePath.size() ? texturePath : filepath; me.Texture2FileName.append("Lightmaps/"); me.Texture2FileName.append(name); if (name.size()) me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName); me.MaterialType = video::EMT_LIGHTMAP_M2; gotLightMap = true; SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); } else if (!gotLightMap && gotMainMap) { me.Texture2FileName = texturePath.size() ? texturePath : filepath; me.Texture2FileName.append(name); if (name.size()) me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName); me.MaterialType = video::EMT_REFLECTION_2_LAYER; } else if (!gotMainMap && !gotLightMap) { me.Texture1FileName = filepath; me.Texture1FileName.append(name); if (name.size()) me.Texture1 = SceneManager->getVideoDriver()->getTexture(me.Texture1FileName); gotMainMap = true; me.MaterialType = video::EMT_SOLID; } else if (gotLightMap) { me.MaterialType = video::EMT_LIGHTMAP_M2; } file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif } // override material types based on their names if (!strncmp(me.Header.Name, "AlphaChannel-", 13)) me.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; else if (!strncmp(me.Header.Name, "SphereMap-", 10)) me.MaterialType = video::EMT_SPHERE_MAP; } // loading meshes if (id!=MY3D_MESH_LIST_ID) { os::Printer::log("Can not find MY3D_MESH_LIST_ID, loading failed!", ELL_ERROR); return 0; } file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif for (s32 mesh_id=0; mesh_idread(&meshHeader, sizeof(SMyMeshHeader)); core::array Vertex; core::array Face; core::array TVertex1, TVertex2; core::array TFace1, TFace2; s32 vertsNum=0; s32 facesNum=0; // vertices file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_VERTS_ID) { os::Printer::log("Can not find MY3D_VERTS_ID, loading failed!", ELL_ERROR); return 0; } file->read(&vertsNum, sizeof(vertsNum)); Vertex.set_used(vertsNum); file->read(Vertex.pointer(), sizeof(SMyVertex)*vertsNum); // faces file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_FACES_ID) { os::Printer::log("Can not find MY3D_FACES_ID, loading failed!", ELL_ERROR); return 0; } file->read(&facesNum, sizeof(facesNum)); Face.set_used(facesNum); file->read(Face.pointer(), sizeof(SMyFace)*facesNum); // reading texture channels for (s32 tex=0; tex<(s32)meshHeader.TChannelCnt; tex++) { // Max 2 texture channels allowed (but in format .my3d can be more) s32 tVertsNum=0, tFacesNum=0; // reading texture coords file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_TVERTS_ID) { core::stringc msg="Can not find MY3D_TVERTS_ID ("; msg.append(core::stringc(tex)); msg.append("texture channel), loading failed!"); os::Printer::log(msg.c_str(), ELL_ERROR); return 0; } file->read(&tVertsNum, sizeof(tVertsNum)); if (tex==0) { // 1st texture channel TVertex1.set_used(tVertsNum); file->read(TVertex1.pointer(), sizeof(SMyTVertex)*tVertsNum); } else if (tex==1) { // 2nd texture channel TVertex2.set_used(tVertsNum); file->read(TVertex2.pointer(), sizeof(SMyTVertex)*tVertsNum); } else { // skip other texture channels file->seek(file->getPos()+sizeof(SMyTVertex)*tVertsNum); } // reading texture faces file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_TFACES_ID) { core::stringc msg="Can not find MY3D_TFACES_ID ("; msg.append(core::stringc(tex)); msg.append("texture channel), loading failed!"); os::Printer::log(msg.c_str(), ELL_ERROR); return 0; } file->read(&tFacesNum, sizeof(tFacesNum)); if (tex==0) { // 1st texture channel TFace1.set_used(tFacesNum); file->read(TFace1.pointer(), sizeof(SMyFace)*tFacesNum); } else if (tex==1) { // 2nd texture channel TFace2.set_used(tFacesNum); file->read(TFace2.pointer(), sizeof(SMyFace)*tFacesNum); } else { // skip other texture channels file->seek(file->getPos()+sizeof(SMyFace)*tFacesNum); } } // trying to find material SMyMaterialEntry* matEnt = getMaterialEntryByIndex(meshHeader.MatIndex); // creating geometry for the mesh // trying to find mesh buffer for this material SMeshBufferLightMap* buffer = getMeshBufferByMaterialIndex(meshHeader.MatIndex); if (!buffer || (buffer->Vertices.size()+vertsNum) > SceneManager->getVideoDriver()->getMaximalPrimitiveCount()) { // creating new mesh buffer for this material buffer = new scene::SMeshBufferLightMap(); buffer->Material.MaterialType = video::EMT_LIGHTMAP_M2; // EMT_LIGHTMAP_M4 also possible buffer->Material.Wireframe = false; buffer->Material.Lighting = false; if (matEnt) { buffer->Material.MaterialType = matEnt->MaterialType; if (buffer->Material.MaterialType == video::EMT_REFLECTION_2_LAYER) { buffer->Material.Lighting = true; buffer->Material.setTexture(1, matEnt->Texture1); buffer->Material.setTexture(0, matEnt->Texture2); } else { buffer->Material.setTexture(0, matEnt->Texture1); buffer->Material.setTexture(1, matEnt->Texture2); } if (buffer->Material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL) { buffer->Material.BackfaceCulling = true; buffer->Material.Lighting = true; } else if (buffer->Material.MaterialType == video::EMT_SPHERE_MAP) { buffer->Material.Lighting = true; } buffer->Material.AmbientColor = video::SColor( matEnt->Header.AmbientColor.A, matEnt->Header.AmbientColor.R, matEnt->Header.AmbientColor.G, matEnt->Header.AmbientColor.B ); buffer->Material.DiffuseColor = video::SColor( matEnt->Header.DiffuseColor.A, matEnt->Header.DiffuseColor.R, matEnt->Header.DiffuseColor.G, matEnt->Header.DiffuseColor.B ); buffer->Material.EmissiveColor = video::SColor( matEnt->Header.EmissiveColor.A, matEnt->Header.EmissiveColor.R, matEnt->Header.EmissiveColor.G, matEnt->Header.EmissiveColor.B ); buffer->Material.SpecularColor = video::SColor( matEnt->Header.SpecularColor.A, matEnt->Header.SpecularColor.R, matEnt->Header.SpecularColor.G, matEnt->Header.SpecularColor.B ); } else { buffer->Material.setTexture(0, 0); buffer->Material.setTexture(1, 0); buffer->Material.AmbientColor = video::SColor(255, 255, 255, 255); buffer->Material.DiffuseColor = video::SColor(255, 255, 255, 255); buffer->Material.EmissiveColor = video::SColor(0, 0, 0, 0); buffer->Material.SpecularColor = video::SColor(0, 0, 0, 0); } if (matEnt && matEnt->Header.Transparency!=0) { if (buffer->Material.MaterialType == video::EMT_REFLECTION_2_LAYER ) { buffer->Material.MaterialType = video::EMT_TRANSPARENT_REFLECTION_2_LAYER; buffer->Material.Lighting = true; buffer->Material.BackfaceCulling = true; } else { buffer->Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; buffer->Material.Lighting = false; buffer->Material.BackfaceCulling = false; } } else if ( !buffer->Material.getTexture(1) && buffer->Material.MaterialType != video::EMT_TRANSPARENT_ALPHA_CHANNEL && buffer->Material.MaterialType != video::EMT_SPHERE_MAP) { buffer->Material.MaterialType = video::EMT_SOLID; buffer->Material.Lighting = true; } MeshBufferEntry.push_back( SMyMeshBufferEntry(meshHeader.MatIndex, buffer)); } video::S3DVertex2TCoords VertexA, VertexB, VertexC; // vertices (A, B, C) color video::SColor vert_color; if (matEnt && (buffer->Material.MaterialType == video::EMT_TRANSPARENT_VERTEX_ALPHA || buffer->Material.MaterialType == video::EMT_TRANSPARENT_REFLECTION_2_LAYER)) { video::SColor color( matEnt->Header.DiffuseColor.A, matEnt->Header.DiffuseColor.R, matEnt->Header.DiffuseColor.G, matEnt->Header.DiffuseColor.B); vert_color = color.getInterpolated(video::SColor(0,0,0,0), 1-matEnt->Header.Transparency); } else { vert_color = buffer->Material.DiffuseColor; } VertexA.Color = VertexB.Color = VertexC.Color = vert_color; if (buffer->Material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL) { buffer->Indices.reallocate(buffer->Indices.size()+6*facesNum); buffer->Vertices.reallocate(buffer->Vertices.size()+6*facesNum); } else { buffer->Indices.reallocate(buffer->Indices.size()+3*facesNum); buffer->Vertices.reallocate(buffer->Vertices.size()+3*facesNum); } for (int f=0; f0) { VertexA.TCoords.X = TVertex1[TFace1[f].C].TCoord.X; VertexA.TCoords.Y = TVertex1[TFace1[f].C].TCoord.Y; } if (meshHeader.TChannelCnt>1) { VertexA.TCoords2.X = TVertex2[TFace2[f].C].TCoord.X; VertexA.TCoords2.Y = TVertex2[TFace2[f].C].TCoord.Y; } // vertex B VertexB.Pos.X = Vertex[Face[f].B].Coord.X; VertexB.Pos.Y = Vertex[Face[f].B].Coord.Y; VertexB.Pos.Z = Vertex[Face[f].B].Coord.Z; VertexB.Normal.X = Vertex[Face[f].B].Normal.X; VertexB.Normal.Y = Vertex[Face[f].B].Normal.Y; VertexB.Normal.Z = Vertex[Face[f].B].Normal.Z; if (meshHeader.TChannelCnt>0) { VertexB.TCoords.X = TVertex1[TFace1[f].B].TCoord.X; VertexB.TCoords.Y = TVertex1[TFace1[f].B].TCoord.Y; } if (meshHeader.TChannelCnt>1) { VertexB.TCoords2.X = TVertex2[TFace2[f].B].TCoord.X; VertexB.TCoords2.Y = TVertex2[TFace2[f].B].TCoord.Y; } // vertex C VertexC.Pos.X = Vertex[Face[f].A].Coord.X; VertexC.Pos.Y = Vertex[Face[f].A].Coord.Y; VertexC.Pos.Z = Vertex[Face[f].A].Coord.Z; VertexC.Normal.X = Vertex[Face[f].A].Normal.X; VertexC.Normal.Y = Vertex[Face[f].A].Normal.Y; VertexC.Normal.Z = Vertex[Face[f].A].Normal.Z; if (meshHeader.TChannelCnt>0) { VertexC.TCoords.X = TVertex1[TFace1[f].A].TCoord.X; VertexC.TCoords.Y = TVertex1[TFace1[f].A].TCoord.Y; } if (meshHeader.TChannelCnt>1) { VertexC.TCoords2.X = TVertex2[TFace2[f].A].TCoord.X; VertexC.TCoords2.Y = TVertex2[TFace2[f].A].TCoord.Y; } // store 3d data in mesh buffer buffer->Indices.push_back(buffer->Vertices.size()); buffer->Vertices.push_back(VertexA); buffer->Indices.push_back(buffer->Vertices.size()); buffer->Vertices.push_back(VertexB); buffer->Indices.push_back(buffer->Vertices.size()); buffer->Vertices.push_back(VertexC); //***************************************************************** // !!!!!! W A R N I N G !!!!!!! //***************************************************************** // For materials with alpha channel we duplicate all faces. // This has be done for proper lighting calculation of the back faces. // So you must remember this while you creating your models !!!!! //***************************************************************** // !!!!!! W A R N I N G !!!!!!! //***************************************************************** if (buffer->Material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL) { VertexA.Normal = core::vector3df(-VertexA.Normal.X, -VertexA.Normal.Y, -VertexA.Normal.Z); VertexB.Normal = core::vector3df(-VertexB.Normal.X, -VertexB.Normal.Y, -VertexB.Normal.Z); VertexC.Normal = core::vector3df(-VertexC.Normal.X, -VertexC.Normal.Y, -VertexC.Normal.Z); buffer->Indices.push_back(buffer->Vertices.size()); buffer->Vertices.push_back(VertexC); buffer->Indices.push_back(buffer->Vertices.size()); buffer->Vertices.push_back(VertexB); buffer->Indices.push_back(buffer->Vertices.size()); buffer->Vertices.push_back(VertexA); } } file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif } // creating mesh SMesh* mesh = new SMesh(); for (u32 num=0; numaddMeshBuffer(buffer); buffer->recalculateBoundingBox(); buffer->drop(); } mesh->recalculateBoundingBox(); if (id != MY3D_FILE_END_ID) os::Printer::log("Loading finished, but can not find MY3D_FILE_END_ID token.", ELL_WARNING); SAnimatedMesh* am = new SAnimatedMesh(); am->addMesh(mesh); mesh->drop(); am->recalculateBoundingBox(); return am; } video::ITexture* CMY3DMeshFileLoader::readEmbeddedLightmap(io::IReadFile* file, char* namebuf) { static int LightMapIndex=0; u16 id; file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_TEXDATA_HEADER_ID) { os::Printer::log("Can not find MY3D_TEXDATA_HEADER_ID, loading failed!", ELL_ERROR); return 0; } SMyTexDataHeader texDataHeader; file->read(&texDataHeader, sizeof(SMyTexDataHeader)); strcpy(texDataHeader.Name, namebuf); char LightMapName[255]; sprintf(LightMapName,"My3D.Lightmap.%d",++LightMapIndex); core::stringc pixFormatStr; if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24) pixFormatStr = "24bit,"; else if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_16) pixFormatStr = "16bit,"; else { core::stringc msg="Unknown format of image data ("; msg.append(LightMapName); msg.append("), loading failed!"); os::Printer::log(msg.c_str(), ELL_ERROR); return 0; } if (texDataHeader.ComprMode != MY3D_TEXDATA_COMPR_NONE_ID && texDataHeader.ComprMode != MY3D_TEXDATA_COMPR_RLE_ID && texDataHeader.ComprMode != MY3D_TEXDATA_COMPR_SIMPLE_ID ) { os::Printer::log("Unknown method of compression image data, loading failed!", ELL_ERROR); return 0; } const u32 num_pixels = texDataHeader.Width*texDataHeader.Height; void* data = 0; if (texDataHeader.ComprMode==MY3D_TEXDATA_COMPR_NONE_ID) { // none compressed image data if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24) { data = (void*) new SMyPixelColor24[num_pixels]; file->read(data, sizeof(SMyPixelColor24)*num_pixels); } else { data = (void*) new SMyPixelColor16[num_pixels]; file->read(data, sizeof(SMyPixelColor16)*num_pixels); } } else if (texDataHeader.ComprMode==MY3D_TEXDATA_COMPR_RLE_ID) { // read RLE header identificator file->read(&id, sizeof(id)); #ifdef __BIG_ENDIAN__ id = os::Byteswap::byteswap(id); #endif if (id!=MY3D_TEXDATA_RLE_HEADER_ID) { os::Printer::log("Can not find MY3D_TEXDATA_RLE_HEADER_ID, loading failed!", ELL_ERROR); return 0; } // read RLE header SMyRLEHeader rleHeader; file->read(&rleHeader, sizeof(SMyRLEHeader)); //allocate memory for input and output buffers void *input_buffer = (void*) new unsigned char[rleHeader.nEncodedBytes]; void *output_buffer = (void*) new unsigned char[rleHeader.nDecodedBytes]; // read encoded data file->read(input_buffer, rleHeader.nEncodedBytes); // decode data data = 0;//(void*) new unsigned char[rleHeader.nDecodedBytes]; s32 decodedBytes = core::rle_decode( (unsigned char*)input_buffer, rleHeader.nEncodedBytes, (unsigned char*)output_buffer, rleHeader.nDecodedBytes); if (decodedBytes!=(s32)rleHeader.nDecodedBytes) { os::Printer::log("Error extracting data from RLE compression, loading failed!", ELL_ERROR); return 0; } // free input buffer delete [] (unsigned char*)input_buffer; // here decoded data data = output_buffer; } else if (texDataHeader.ComprMode==MY3D_TEXDATA_COMPR_SIMPLE_ID) { // simple compressed image data if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24) data = (void*) new SMyPixelColor24[num_pixels]; else data = (void*) new SMyPixelColor16[num_pixels]; u32 nReadedPixels=0, nToRead=0; while (true) { file->read(&nToRead, sizeof(nToRead)); if ((nReadedPixels+nToRead) > num_pixels) break; if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24) { SMyPixelColor24 col24; file->read(&col24, sizeof(SMyPixelColor24)); for (u32 p=0; pread(&col16, sizeof(SMyPixelColor16)); for (u32 p=0; p= num_pixels) break; } if (nReadedPixels != num_pixels) { os::Printer::log("Image data seems to be corrupted, loading failed!", ELL_ERROR); return 0; } } //! Creates a software image from a byte array. video::IImage* light_img = 0; if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24) { // 24 bit lightmap format light_img = SceneManager->getVideoDriver()->createImageFromData( video::ECF_R8G8B8, core::dimension2d(texDataHeader.Width, texDataHeader.Height), data, true); } else { // 16 bit lightmap format light_img = SceneManager->getVideoDriver()->createImageFromData( video::ECF_A1R5G5B5, core::dimension2d(texDataHeader.Width, texDataHeader.Height), data, true); } const bool oldMipMapState = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); video::ITexture* lmtex = SceneManager->getVideoDriver()->addTexture(LightMapName, light_img); SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); light_img->drop(); return lmtex; } CMY3DMeshFileLoader::SMyMaterialEntry* CMY3DMeshFileLoader::getMaterialEntryByIndex(u32 matInd) { for (u32 m=0; m& CMY3DMeshFileLoader::getChildNodes() const { return ChildNodes; } } // end namespace scnene } // end namespace irr #endif // _IRR_COMPILE_WITH_MY3D_LOADER_ irrlicht-1.8.3/source/Irrlicht/CMY3DHelper.h0000644000000000000000000003316712574354552017277 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // This file was originally written by ZDimitor. //---------------------------------------------------------------------- // somefuncs.h - part of the My3D Tools // // This tool was created by Zhuck Dmitry (ZDimitor). // Everyone can use it as wants ( i'll be happy if it helps to someone :) ). //---------------------------------------------------------------------- //********************************************************************** // some useful functions //********************************************************************** #ifndef __C_MY3D_HELPER_H_INCLUDED__ #define __C_MY3D_HELPER_H_INCLUDED__ #include namespace irr { namespace scene { //********************************************************************** // MY3D stuff //********************************************************************** // byte-align structures #include "irrpack.h" struct SMyVector3 { SMyVector3 () {;} SMyVector3 (f32 __X, f32 __Y, f32 __Z) : X(__X), Y(__Y), Z(__Z) {} f32 X, Y, Z; } PACK_STRUCT; struct SMyVector2 { SMyVector2 () {;} SMyVector2(f32 __X, f32 __Y) : X(__X), Y(__Y) {} f32 X, Y; } PACK_STRUCT; struct SMyVertex { SMyVertex () {;} SMyVertex (SMyVector3 _Coord, SMyColor _Color, SMyVector3 _Normal) :Coord(_Coord), Color(_Color), Normal(_Normal) {;} SMyVector3 Coord; SMyColor Color; SMyVector3 Normal; } PACK_STRUCT; struct SMyTVertex { SMyTVertex () {;} SMyTVertex (SMyVector2 _TCoord) : TCoord(_TCoord) {;} SMyVector2 TCoord; } PACK_STRUCT; struct SMyFace { SMyFace() {;} SMyFace(u32 __A, u32 __B, u32 __C) : A(__A), B(__B), C(__C) {} u32 A, B, C; } PACK_STRUCT; // file header (6 bytes) struct SMyFileHeader { u32 MyId; // MY3D u16 Ver; // Version } PACK_STRUCT; // scene header struct SMySceneHeader { SMyColor BackgrColor; // background color SMyColor AmbientColor; // ambient color s32 MaterialCount; // material count s32 MeshCount; // mesh count } PACK_STRUCT; // mesh header struct SMyMeshHeader { c8 Name[256]; // material name u32 MatIndex; // index of the mesh material u32 TChannelCnt; // mesh mapping channels count } PACK_STRUCT; // texture data header struct SMyTexDataHeader { c8 Name[256]; // texture name u32 ComprMode; //compression mode u32 PixelFormat; u32 Width; // image width u32 Height; // image height } PACK_STRUCT; // pixel color 24bit (R8G8B8) struct SMyPixelColor24 { SMyPixelColor24() {;} SMyPixelColor24(u8 __r, u8 __g, u8 __b) : r(__r), g(__g), b(__b) {} u8 r, g, b; } PACK_STRUCT; // pixel color 16bit (A1R5G5B5) struct SMyPixelColor16 { SMyPixelColor16() {;} SMyPixelColor16(s16 _argb): argb(_argb) {;} SMyPixelColor16(u8 r, u8 g, u8 b) { argb = ((r&0x1F)<<10) | ((g&0x1F)<<5) | (b&0x1F); } s16 argb; } PACK_STRUCT; // RLE Header struct SMyRLEHeader { SMyRLEHeader() {} u32 nEncodedBytes; u32 nDecodedBytes; } PACK_STRUCT; // Default alignment #include "irrunpack.h" } // end namespace } // end namespace //----------------------------------------------------------------------------- namespace irr { namespace core { //-----------------RLE stuff----------------------------------------- int rle_encode ( unsigned char *in_buf, int in_buf_size, unsigned char *out_buf, int out_buf_size ); unsigned long process_comp( unsigned char *buf, int buf_size, unsigned char *out_buf, int out_buf_size ); void process_uncomp( unsigned char, unsigned char *out_buf, int out_buf_size ); void flush_outbuf( unsigned char *out_buf, int out_buf_size ); unsigned long get_byte ( unsigned char *ch, unsigned char *in_buf, int in_buf_size, unsigned char *out_buf, int out_buf_size ); void put_byte( unsigned char ch, unsigned char *out_buf, int out_buf_size ); //----------------------------------------------------------- const unsigned long LIMIT = 1; // was #define LIMIT 1 const unsigned long NON_MATCH = 2; // was: #define NON_MATCH 2 const unsigned long EOD_FOUND = 3; // was: #define EOD_FOUND 3 const unsigned long EOD = 0x00454f44; // was: #define EOD 'EOD' //----------------------------------------------------------- // number of decoded bytes static int nDecodedBytes=0; // number of coded bytes static int nCodedBytes=0; // number of read bytes static int nReadedBytes=0; // table used to look for sequences of repeating bytes static unsigned char tmpbuf[4]; // we use subscripts 1 - 3 static int tmpbuf_cnt; // output buffer for non-compressed output data static unsigned char outbuf[128]; static int outbuf_cnt; //----------------------------------------------------------- int rle_encode ( unsigned char *in_buf, int in_buf_size, unsigned char *out_buf, int out_buf_size ) { unsigned long ret_code; unsigned char ch; nCodedBytes=0; nReadedBytes=0; tmpbuf_cnt = 0; // no. of char's in tmpbuf outbuf_cnt = 0; // no. of char's in outbuf while (1) { if (get_byte(&ch, in_buf, in_buf_size, out_buf, out_buf_size) == (int)EOD) // read next byte into ch break; tmpbuf[++tmpbuf_cnt] = (unsigned char) ch; if (tmpbuf_cnt == 3) { // see if all 3 match each other if ((tmpbuf[1] == tmpbuf[2]) && (tmpbuf[2] == tmpbuf[3])) { // they do - add compression // this will process all bytes in input file until // a non-match occurs, or 128 bytes are processed, // or we find eod */ ret_code = process_comp(in_buf, in_buf_size, out_buf, out_buf_size); if (ret_code == (int)EOD_FOUND) break; // stop compressing if (ret_code == (int)NON_MATCH) tmpbuf_cnt=1; /* save the char that didn't match */ else // we just compressed the max. of 128 bytes tmpbuf_cnt=0; /* start over for next chunk */ } else { // we know the first byte doesn't match 2 or more // others, so just send it out as uncompressed. */ process_uncomp(tmpbuf[1], out_buf, out_buf_size); // see if the last 2 bytes in the buffer match if (tmpbuf[2] == tmpbuf[3]) { // move byte 3 to position 1 and pretend we just // have 2 bytes -- note that the first byte was // already sent to output */ tmpbuf[1]=tmpbuf[3]; tmpbuf_cnt=2; } else { // send byte 2 and keep byte 3 - it may match the // next byte. Move byte 3 to position 1 and set // count to 1. Note that the first byte was // already sent to output process_uncomp(tmpbuf[2], out_buf, out_buf_size); tmpbuf[1]=tmpbuf[3]; tmpbuf_cnt=1; } } } } // end while flush_outbuf(out_buf, out_buf_size); return nCodedBytes; } //------------------------------------------------------------------ // This flushes any non-compressed data not yet sent, then it processes // repeating bytes until > 128, or EOD, or non-match. // return values: LIMIT, EOD_FOUND, NON_MATCH // Prior to ANY return, it writes out the 2 byte compressed code. // If a NON_MATCH was found, this returns with the non-matching char // residing in tmpbuf[0]. // Inputs: tmpbuf[0], input file // Outputs: tmpbuf[0] (sometimes), output file, and return code //------------------------------------------------------------------ unsigned long process_comp( unsigned char *buf, int buf_size, unsigned char *out_buf, int out_buf_size) { // we start out with 3 repeating bytes register int len = 3; unsigned char ch; // we're starting a repeating chunk - end the non-repeaters flush_outbuf(out_buf, out_buf_size); while (get_byte(&ch, buf, buf_size, out_buf, out_buf_size) != (int)EOD) { if (ch != tmpbuf[1]) { // send no. of repeated bytes to be encoded put_byte((unsigned char)((--len) | 0x80), out_buf, out_buf_size); // send the byte's value being repeated put_byte((unsigned char)tmpbuf[1], out_buf, out_buf_size); /* save the non-matching character just read */ tmpbuf[1]=(unsigned char) ch; return NON_MATCH; } /* we know the new byte is part of the repeating seq */ len++; if (len == 128) { // send no. of repeated bytes to be encoded put_byte((unsigned char)((--len) | 0x80), out_buf, out_buf_size); // send the byte's value being repeated put_byte((unsigned char)tmpbuf[1], out_buf, out_buf_size); return LIMIT; } } // end while // if flow comes here, we just read an EOD // send no. of repeated bytes to be encoded put_byte((unsigned char)((--len) | 0x80), out_buf, out_buf_size); // send the byte's value being repeated put_byte((unsigned char)tmpbuf[1], out_buf, out_buf_size); return EOD_FOUND; } //---------------------------------------------------------------- // This adds 1 non-repeating byte to outbuf. If outbuf becomes full // with 128 bytes, it flushes outbuf. // There are no return codes and no bytes are read from the input. //---------------------------------------------------------------- void process_uncomp( unsigned char char1, unsigned char *out_buf, int out_buf_size ) { outbuf[outbuf_cnt++] = char1; if (outbuf_cnt == 128) flush_outbuf(out_buf, out_buf_size); } //----------------------------------------------------------- // This flushes any non-compressed data not yet sent. // On exit, outbuf_cnt will equal zero. //----------------------------------------------------------- void flush_outbuf(unsigned char *out_buf, int out_buf_size) { register int pos=0; if(!outbuf_cnt) return; // nothing to do */ // send no. of unencoded bytes to be sent put_byte((unsigned char)(outbuf_cnt - 1), out_buf, out_buf_size); for ( ; outbuf_cnt; outbuf_cnt--) put_byte((unsigned char)outbuf[pos++], out_buf, out_buf_size); } //--------------------------------------------------- void put_byte(unsigned char ch, unsigned char *out_buf, int out_buf_size) { if (nCodedBytes<=(out_buf_size-1)) { out_buf[nCodedBytes++]=ch; out_buf[nCodedBytes]=0; } } //--------------------------------------------------- // This reads the next byte into ch. It returns EOD // at end-of-data //--------------------------------------------------- unsigned long get_byte( unsigned char *ch, unsigned char *in_buf, int in_buf_size, unsigned char *out_buf, int out_buf_size ) { if (nReadedBytes>=in_buf_size) { // there are either 0, 1, or 2 char's to write before we quit if (tmpbuf_cnt == 1) process_uncomp(tmpbuf[1], out_buf, out_buf_size); else { if (tmpbuf_cnt == 2) { process_uncomp(tmpbuf[1], out_buf, out_buf_size); process_uncomp(tmpbuf[2], out_buf, out_buf_size); } } nReadedBytes =0; return EOD; } (*ch) = (unsigned char)in_buf[nReadedBytes++]; return 0; } //----------------------------------------------------------- int rle_decode ( unsigned char *in_buf, int in_buf_size, unsigned char *out_buf, int out_buf_size ) { nDecodedBytes=0; nReadedBytes=0; int ch, i; while (1) { if (nReadedBytes>=in_buf_size) break; else ch=in_buf[nReadedBytes]; nReadedBytes++; if (ch > 127) { i = ch - 127; // i is the number of repetitions // get the byte to be repeated if (nReadedBytes>=in_buf_size) break; else ch=in_buf[nReadedBytes]; nReadedBytes++; // uncompress a chunk for ( ; i ; i--) { if (nDecodedBytes=in_buf_size) break; else ch=in_buf[nReadedBytes]; nReadedBytes++; if (nDecodedBytes VertexIds; u16 MaterialIdx; }; //! Constructor CMS3DMeshFileLoader::CMS3DMeshFileLoader(video::IVideoDriver *driver) : Driver(driver), AnimatedMesh(0) { #ifdef _DEBUG setDebugName("CMS3DMeshFileLoader"); #endif } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool CMS3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "ms3d" ); } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* CMS3DMeshFileLoader::createMesh(io::IReadFile* file) { if (!file) return 0; AnimatedMesh = new CSkinnedMesh(); if ( load(file) ) { AnimatedMesh->finalize(); } else { AnimatedMesh->drop(); AnimatedMesh = 0; } return AnimatedMesh; } //! loads a milkshape file bool CMS3DMeshFileLoader::load(io::IReadFile* file) { if (!file) return false; // find file size const long fileSize = file->getSize(); // read whole file u8* buffer = new u8[fileSize]; s32 read = file->read(buffer, fileSize); if (read != fileSize) { delete [] buffer; os::Printer::log("Could not read full file. Loading failed", file->getFileName(), ELL_ERROR); return false; } // read header const u8 *pPtr = (u8*)((void*)buffer); MS3DHeader *pHeader = (MS3DHeader*)pPtr; pPtr += sizeof(MS3DHeader); if ( strncmp( pHeader->ID, "MS3D000000", 10 ) != 0 ) { delete [] buffer; os::Printer::log("Not a valid Milkshape3D Model File. Loading failed", file->getFileName(), ELL_ERROR); return false; } #ifdef __BIG_ENDIAN__ pHeader->Version = os::Byteswap::byteswap(pHeader->Version); #endif if ( pHeader->Version < 3 || pHeader->Version > 4 ) { delete [] buffer; os::Printer::log("Only Milkshape3D version 3 and 4 (1.3 to 1.8) is supported. Loading failed", file->getFileName(), ELL_ERROR); return false; } #ifdef _IRR_DEBUG_MS3D_LOADER_ os::Printer::log("Loaded header version", core::stringc(pHeader->Version).c_str()); #endif // get pointers to data // vertices u16 numVertices = *(u16*)pPtr; #ifdef __BIG_ENDIAN__ numVertices = os::Byteswap::byteswap(numVertices); #endif #ifdef _IRR_DEBUG_MS3D_LOADER_ os::Printer::log("Load vertices", core::stringc(numVertices).c_str()); #endif pPtr += sizeof(u16); MS3DVertex *vertices = (MS3DVertex*)pPtr; pPtr += sizeof(MS3DVertex) * numVertices; if (pPtr > buffer+fileSize) { delete [] buffer; os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); return false; } for (u16 tmp=0; tmp buffer+fileSize) { delete [] buffer; os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); return false; } for (u16 tmp=0; tmp groups; groups.reallocate(numGroups); //store groups u32 i; for (i=0; i buffer+fileSize) { delete [] buffer; os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); return false; } } // load materials u16 numMaterials = *(u16*)pPtr; #ifdef __BIG_ENDIAN__ numMaterials = os::Byteswap::byteswap(numMaterials); #endif #ifdef _IRR_DEBUG_MS3D_LOADER_ os::Printer::log("Load Materials", core::stringc(numMaterials).c_str()); #endif pPtr += sizeof(u16); if(numMaterials == 0) { // if there are no materials, add at least one buffer AnimatedMesh->addMeshBuffer(); } for (i=0; iAmbient[j] = os::Byteswap::byteswap(material->Ambient[j]); for (u16 j=0; j<4; ++j) material->Diffuse[j] = os::Byteswap::byteswap(material->Diffuse[j]); for (u16 j=0; j<4; ++j) material->Specular[j] = os::Byteswap::byteswap(material->Specular[j]); for (u16 j=0; j<4; ++j) material->Emissive[j] = os::Byteswap::byteswap(material->Emissive[j]); material->Shininess = os::Byteswap::byteswap(material->Shininess); material->Transparency = os::Byteswap::byteswap(material->Transparency); #endif pPtr += sizeof(MS3DMaterial); if (pPtr > buffer+fileSize) { delete [] buffer; os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); return false; } scene::SSkinMeshBuffer *tmpBuffer = AnimatedMesh->addMeshBuffer(); tmpBuffer->Material.MaterialType = video::EMT_SOLID; tmpBuffer->Material.AmbientColor = video::SColorf(material->Ambient[0], material->Ambient[1], material->Ambient[2], material->Ambient[3]).toSColor (); tmpBuffer->Material.DiffuseColor = video::SColorf(material->Diffuse[0], material->Diffuse[1], material->Diffuse[2], material->Diffuse[3]).toSColor (); tmpBuffer->Material.EmissiveColor = video::SColorf(material->Emissive[0], material->Emissive[1], material->Emissive[2], material->Emissive[3]).toSColor (); tmpBuffer->Material.SpecularColor = video::SColorf(material->Specular[0], material->Specular[1], material->Specular[2], material->Specular[3]).toSColor (); tmpBuffer->Material.Shininess = material->Shininess; core::stringc TexturePath(material->Texture); if (TexturePath.trim()!="") { TexturePath=stripPathFromString(file->getFileName(),true) + stripPathFromString(TexturePath,false); tmpBuffer->Material.setTexture(0, Driver->getTexture(TexturePath)); } core::stringc AlphamapPath=(const c8*)material->Alphamap; if (AlphamapPath.trim()!="") { AlphamapPath=stripPathFromString(file->getFileName(),true) + stripPathFromString(AlphamapPath,false); tmpBuffer->Material.setTexture(2, Driver->getTexture(AlphamapPath)); } } // animation time f32 framesPerSecond = *(float*)pPtr; #ifdef __BIG_ENDIAN__ framesPerSecond = os::Byteswap::byteswap(framesPerSecond); #endif #ifdef _IRR_DEBUG_MS3D_LOADER_ os::Printer::log("FPS", core::stringc(framesPerSecond).c_str()); #endif pPtr += sizeof(float) * 2; // fps and current time if (framesPerSecond<1.f) framesPerSecond=1.f; AnimatedMesh->setAnimationSpeed(framesPerSecond); // ignore, calculated inside SkinnedMesh // s32 frameCount = *(int*)pPtr; #ifdef __BIG_ENDIAN__ // frameCount = os::Byteswap::byteswap(frameCount); #endif pPtr += sizeof(int); u16 jointCount = *(u16*)pPtr; #ifdef __BIG_ENDIAN__ jointCount = os::Byteswap::byteswap(jointCount); #endif #ifdef _IRR_DEBUG_MS3D_LOADER_ os::Printer::log("Joints", core::stringc(jointCount).c_str()); #endif pPtr += sizeof(u16); if (pPtr > buffer+fileSize) { delete [] buffer; os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); return false; } core::array parentNames; parentNames.reallocate(jointCount); // load joints for (i=0; iRotation[j] = os::Byteswap::byteswap(pJoint->Rotation[j]); for (j=0; j<3; ++j) pJoint->Translation[j] = os::Byteswap::byteswap(pJoint->Translation[j]); pJoint->NumRotationKeyframes= os::Byteswap::byteswap(pJoint->NumRotationKeyframes); pJoint->NumTranslationKeyframes = os::Byteswap::byteswap(pJoint->NumTranslationKeyframes); #endif pPtr += sizeof(MS3DJoint); if (pPtr > buffer+fileSize) { delete [] buffer; os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); return false; } ISkinnedMesh::SJoint *jnt = AnimatedMesh->addJoint(); jnt->Name = pJoint->Name; #ifdef _IRR_DEBUG_MS3D_LOADER_ os::Printer::log("Joint", jnt->Name.c_str()); os::Printer::log("Rotation keyframes", core::stringc(pJoint->NumRotationKeyframes).c_str()); os::Printer::log("Translation keyframes", core::stringc(pJoint->NumTranslationKeyframes).c_str()); #endif jnt->LocalMatrix.makeIdentity(); jnt->LocalMatrix.setRotationRadians( core::vector3df(pJoint->Rotation[0], pJoint->Rotation[1], pJoint->Rotation[2]) ); // convert right-handed to left-handed jnt->LocalMatrix[2]=-jnt->LocalMatrix[2]; jnt->LocalMatrix[6]=-jnt->LocalMatrix[6]; jnt->LocalMatrix[8]=-jnt->LocalMatrix[8]; jnt->LocalMatrix[9]=-jnt->LocalMatrix[9]; jnt->LocalMatrix.setTranslation( core::vector3df(pJoint->Translation[0], pJoint->Translation[1], -pJoint->Translation[2]) ); jnt->Animatedposition.set(jnt->LocalMatrix.getTranslation()); jnt->Animatedrotation.set(jnt->LocalMatrix.getRotationDegrees()); parentNames.push_back( (c8*)pJoint->ParentName ); /*if (pJoint->NumRotationKeyframes || pJoint->NumTranslationKeyframes) HasAnimation = true; */ // get rotation keyframes const u16 numRotationKeyframes = pJoint->NumRotationKeyframes; for (j=0; j < numRotationKeyframes; ++j) { MS3DKeyframe* kf = (MS3DKeyframe*)pPtr; #ifdef __BIG_ENDIAN__ kf->Time = os::Byteswap::byteswap(kf->Time); for (u32 l=0; l<3; ++l) kf->Parameter[l] = os::Byteswap::byteswap(kf->Parameter[l]); #endif pPtr += sizeof(MS3DKeyframe); if (pPtr > buffer+fileSize) { delete [] buffer; os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); return false; } ISkinnedMesh::SRotationKey *k=AnimatedMesh->addRotationKey(jnt); k->frame = kf->Time * framesPerSecond-1; core::matrix4 tmpMatrix; tmpMatrix.setRotationRadians( core::vector3df(kf->Parameter[0], kf->Parameter[1], kf->Parameter[2]) ); // convert right-handed to left-handed tmpMatrix[2]=-tmpMatrix[2]; tmpMatrix[6]=-tmpMatrix[6]; tmpMatrix[8]=-tmpMatrix[8]; tmpMatrix[9]=-tmpMatrix[9]; tmpMatrix=jnt->LocalMatrix*tmpMatrix; // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched from tmpMatrix to tmpMatrix.getTransposed() for downward compatibility. // Not tested so far if this was correct or wrong before quaternion fix! k->rotation = core::quaternion(tmpMatrix.getTransposed()); } // get translation keyframes const u16 numTranslationKeyframes = pJoint->NumTranslationKeyframes; for (j=0; jTime = os::Byteswap::byteswap(kf->Time); for (u32 l=0; l<3; ++l) kf->Parameter[l] = os::Byteswap::byteswap(kf->Parameter[l]); #endif pPtr += sizeof(MS3DKeyframe); if (pPtr > buffer+fileSize) { delete [] buffer; os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); return false; } ISkinnedMesh::SPositionKey *k=AnimatedMesh->addPositionKey(jnt); k->frame = kf->Time * framesPerSecond-1; k->position = core::vector3df (kf->Parameter[0]+pJoint->Translation[0], kf->Parameter[1]+pJoint->Translation[1], -kf->Parameter[2]-pJoint->Translation[2]); } } core::array vertexWeights; f32 weightFactor=0; if (jointCount && (pHeader->Version == 4) && (pPtr < buffer+fileSize)) { s32 subVersion = *(s32*)pPtr; // comment subVersion, always 1 #ifdef __BIG_ENDIAN__ subVersion = os::Byteswap::byteswap(subVersion); #endif pPtr += sizeof(s32); for (u32 j=0; j<4; ++j) // four comment groups { #ifdef _IRR_DEBUG_MS3D_LOADER_ os::Printer::log("Skipping comment group", core::stringc(j+1).c_str()); #endif u32 numComments = *(u32*)pPtr; #ifdef __BIG_ENDIAN__ numComments = os::Byteswap::byteswap(numComments); #endif pPtr += sizeof(u32); for (i=0; i buffer+fileSize) { delete [] buffer; os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); return false; } } if (pPtr < buffer+fileSize) { subVersion = *(s32*)pPtr; // vertex subVersion, 1 or 2 #ifdef __BIG_ENDIAN__ subVersion = os::Byteswap::byteswap(subVersion); #endif if (subVersion==1) weightFactor=1.f/255.f; else weightFactor=1.f/100.f; pPtr += sizeof(s32); #ifdef _IRR_DEBUG_MS3D_LOADER_ os::Printer::log("Reading vertex weights"); #endif // read vertex weights, ignoring data 'extra' from 1.8.2 vertexWeights.reallocate(numVertices); const char offset = (subVersion==1)?6:10; for (i=0; i buffer+fileSize) { delete [] buffer; os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); return false; } } if (pPtr < buffer+fileSize) { subVersion = *(s32*)pPtr; // joint subVersion, 1 or 2 #ifdef __BIG_ENDIAN__ subVersion = os::Byteswap::byteswap(subVersion); #endif pPtr += sizeof(s32); // skip joint colors #ifdef _IRR_DEBUG_MS3D_LOADER_ os::Printer::log("Skip joint color"); #endif pPtr += 3*sizeof(float)*jointCount; if (pPtr > buffer+fileSize) { delete [] buffer; os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); return false; } } if (pPtr < buffer+fileSize) { subVersion = *(s32*)pPtr; // model subVersion, 1 or 2 #ifdef __BIG_ENDIAN__ subVersion = os::Byteswap::byteswap(subVersion); #endif pPtr += sizeof(s32); #ifdef _IRR_DEBUG_MS3D_LOADER_ os::Printer::log("Skip model extra information"); #endif // now the model extra information would follow // we also skip this for now } } //find parent of every joint for (u32 jointnum=0; jointnumgetAllJoints().size(); ++jointnum) { for (u32 j2=0; j2getAllJoints().size(); ++j2) { if (jointnum != j2 && parentNames[jointnum] == AnimatedMesh->getAllJoints()[j2]->Name ) { AnimatedMesh->getAllJoints()[j2]->Children.push_back(AnimatedMesh->getAllJoints()[jointnum]); break; } } } // create vertices and indices, attach them to the joints. video::S3DVertex v; core::array *Vertices; core::array Indices; for (i=0; igetMeshBuffers()[tmp]->Vertices_Standard; for (s32 j = 2; j!=-1; --j) { const u32 vertidx = triangles[i].VertexIndices[j]; v.TCoords.X = triangles[i].S[j]; v.TCoords.Y = triangles[i].T[j]; v.Normal.X = triangles[i].VertexNormals[j][0]; v.Normal.Y = triangles[i].VertexNormals[j][1]; v.Normal.Z = triangles[i].VertexNormals[j][2]; if(triangles[i].GroupIndex < groups.size() && groups[triangles[i].GroupIndex].MaterialIdx < AnimatedMesh->getMeshBuffers().size()) v.Color = AnimatedMesh->getMeshBuffers()[groups[triangles[i].GroupIndex].MaterialIdx]->Material.DiffuseColor; else v.Color.set(255,255,255,255); v.Pos.X = vertices[vertidx].Vertex[0]; v.Pos.Y = vertices[vertidx].Vertex[1]; v.Pos.Z = vertices[vertidx].Vertex[2]; // check if we already have this vertex in our vertex array s32 index = -1; for (u32 iV = 0; iV < Vertices->size(); ++iV) { if (v == (*Vertices)[iV]) { index = (s32)iV; break; } } if (index == -1) { index = Vertices->size(); const u32 matidx = groups[triangles[i].GroupIndex].MaterialIdx; if (vertexWeights.size()==0) { const s32 boneid = vertices[vertidx].BoneID; if ((u32)boneid < AnimatedMesh->getAllJoints().size()) { ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); w->buffer_id = matidx; w->strength = 1.0f; w->vertex_id = index; } } else if (jointCount) // new weights from 1.8.x { f32 sum = 1.0f; s32 boneid = vertices[vertidx].BoneID; if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[0] != 0)) { ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); w->buffer_id = matidx; sum -= (w->strength = vertexWeights[vertidx].weights[0]*weightFactor); w->vertex_id = index; } boneid = vertexWeights[vertidx].boneIds[0]; if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[1] != 0)) { ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); w->buffer_id = matidx; sum -= (w->strength = vertexWeights[vertidx].weights[1]*weightFactor); w->vertex_id = index; } boneid = vertexWeights[vertidx].boneIds[1]; if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[2] != 0)) { ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); w->buffer_id = matidx; sum -= (w->strength = vertexWeights[vertidx].weights[2]*weightFactor); w->vertex_id = index; } boneid = vertexWeights[vertidx].boneIds[2]; if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (sum > 0.f)) { ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); w->buffer_id = matidx; w->strength = sum; w->vertex_id = index; } // fallback, if no bone chosen. Seems to be an error in the specs boneid = vertices[vertidx].BoneID; if ((sum == 1.f) && ((u32)boneid < AnimatedMesh->getAllJoints().size())) { ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); w->buffer_id = matidx; w->strength = 1.f; w->vertex_id = index; } } Vertices->push_back(v); } Indices.push_back(index); } } //create groups s32 iIndex = -1; for (i=0; i= AnimatedMesh->getMeshBuffers().size()) grp.MaterialIdx = 0; core::array& indices = AnimatedMesh->getMeshBuffers()[grp.MaterialIdx]->Indices; for (u32 k=0; k < grp.VertexIds.size(); ++k) for (u32 l=0; l<3; ++l) indices.push_back(Indices[++iIndex]); } delete [] buffer; return true; } core::stringc CMS3DMeshFileLoader::stripPathFromString(const core::stringc& inString, bool returnPath) const { s32 slashIndex=inString.findLast('/'); // forward slash s32 backSlash=inString.findLast('\\'); // back slash if (backSlash>slashIndex) slashIndex=backSlash; if (slashIndex==-1)//no slashes found { if (returnPath) return core::stringc(); //no path to return else return inString; } if (returnPath) return inString.subString(0, slashIndex + 1); else return inString.subString(slashIndex+1, inString.size() - (slashIndex+1)); } } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CMountPointReader.h0000644000000000000000000000531312574354552020652 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_MOUNT_READER_H_INCLUDED__ #define __C_MOUNT_READER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ #include "IFileSystem.h" #include "CFileList.h" namespace irr { namespace io { //! Archiveloader capable of loading MountPoint Archives class CArchiveLoaderMount : public IArchiveLoader { public: //! Constructor CArchiveLoaderMount(io::IFileSystem* fs); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".zip") virtual bool isALoadableFileFormat(const io::path& filename) const; //! Check if the file might be loaded by this class /** Check might look into the file. \param file File handle to check. \return True if file seems to be loadable. */ virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! Check to see if the loader can create archives of this type. /** Check based on the archive type. \param fileType The archive type to check. \return True if the archile loader supports this type, false if not */ virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const; //! Creates an archive from the filename /** \param file File handle to check. \return Pointer to newly created archive, or 0 upon error. */ virtual IFileArchive* createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const; //! creates/loads an archive from the file. //! \return Pointer to the created archive. Returns 0 if loading failed. virtual IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; private: io::IFileSystem* FileSystem; }; //! A File Archive which uses a mountpoint class CMountPointReader : public virtual IFileArchive, virtual CFileList { public: //! Constructor CMountPointReader(IFileSystem *parent, const io::path& basename, bool ignoreCase, bool ignorePaths); //! opens a file by index virtual IReadFile* createAndOpenFile(u32 index); //! opens a file by file name virtual IReadFile* createAndOpenFile(const io::path& filename); //! returns the list of files virtual const IFileList* getFileList() const; //! get the class Type virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_FOLDER; } private: core::array RealFileNames; IFileSystem *Parent; void buildDirectory(); }; } // io } // irr #endif // __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ #endif // __C_MOUNT_READER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CMountPointReader.cpp0000644000000000000000000001042212574354552021202 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CMountPointReader.h" #ifdef __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ #include "CReadFile.h" #include "os.h" namespace irr { namespace io { //! Constructor CArchiveLoaderMount::CArchiveLoaderMount( io::IFileSystem* fs) : FileSystem(fs) { #ifdef _DEBUG setDebugName("CArchiveLoaderMount"); #endif } //! returns true if the file maybe is able to be loaded by this class bool CArchiveLoaderMount::isALoadableFileFormat(const io::path& filename) const { io::path fname(filename); deletePathFromFilename(fname); if (!fname.size()) return true; IFileList* list = FileSystem->createFileList(); bool ret = false; if (list) { // check if name is found as directory if (list->findFile(filename, true)) ret=true; list->drop(); } return ret; } //! Check to see if the loader can create archives of this type. bool CArchiveLoaderMount::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const { return fileType == EFAT_FOLDER; } //! Check if the file might be loaded by this class bool CArchiveLoaderMount::isALoadableFileFormat(io::IReadFile* file) const { return false; } //! Creates an archive from the filename IFileArchive* CArchiveLoaderMount::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const { IFileArchive *archive = 0; EFileSystemType current = FileSystem->setFileListSystem(FILESYSTEM_NATIVE); const io::path save = FileSystem->getWorkingDirectory(); io::path fullPath = FileSystem->getAbsolutePath(filename); FileSystem->flattenFilename(fullPath); if (FileSystem->changeWorkingDirectoryTo(fullPath)) { archive = new CMountPointReader(FileSystem, fullPath, ignoreCase, ignorePaths); } FileSystem->changeWorkingDirectoryTo(save); FileSystem->setFileListSystem(current); return archive; } //! creates/loads an archive from the file. //! \return Pointer to the created archive. Returns 0 if loading failed. IFileArchive* CArchiveLoaderMount::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const { return 0; } //! compatible Folder Architecture CMountPointReader::CMountPointReader(IFileSystem * parent, const io::path& basename, bool ignoreCase, bool ignorePaths) : CFileList(basename, ignoreCase, ignorePaths), Parent(parent) { //! ensure CFileList path ends in a slash if (Path.lastChar() != '/' ) Path.append('/'); const io::path& work = Parent->getWorkingDirectory(); Parent->changeWorkingDirectoryTo(basename); buildDirectory(); Parent->changeWorkingDirectoryTo(work); sort(); } //! returns the list of files const IFileList* CMountPointReader::getFileList() const { return this; } void CMountPointReader::buildDirectory() { IFileList * list = Parent->createFileList(); if (!list) return; const u32 size = list->getFileCount(); for (u32 i=0; i < size; ++i) { io::path full = list->getFullFileName(i); full = full.subString(Path.size(), full.size() - Path.size()); if (!list->isDirectory(i)) { addItem(full, list->getFileOffset(i), list->getFileSize(i), false, RealFileNames.size()); RealFileNames.push_back(list->getFullFileName(i)); } else { const io::path rel = list->getFileName(i); RealFileNames.push_back(list->getFullFileName(i)); io::path pwd = Parent->getWorkingDirectory(); if (pwd.lastChar() != '/') pwd.append('/'); pwd.append(rel); if ( rel != "." && rel != ".." ) { addItem(full, 0, 0, true, 0); Parent->changeWorkingDirectoryTo(pwd); buildDirectory(); Parent->changeWorkingDirectoryTo(".."); } } } list->drop(); } //! opens a file by index IReadFile* CMountPointReader::createAndOpenFile(u32 index) { if (index >= Files.size()) return 0; return createReadFile(RealFileNames[Files[index].ID]); } //! opens a file by file name IReadFile* CMountPointReader::createAndOpenFile(const io::path& filename) { s32 index = findFile(filename, false); if (index != -1) return createAndOpenFile(index); else return 0; } } // io } // irr #endif // __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ irrlicht-1.8.3/source/Irrlicht/CMetaTriangleSelector.h0000644000000000000000000000464512574354552021477 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_META_TRIANGLE_SELECTOR_H_INCLUDED__ #define __C_META_TRIANGLE_SELECTOR_H_INCLUDED__ #include "IMetaTriangleSelector.h" #include "irrArray.h" namespace irr { namespace scene { //! Interface for making multiple triangle selectors work as one big selector. class CMetaTriangleSelector : public IMetaTriangleSelector { public: //! constructor CMetaTriangleSelector(); //! destructor virtual ~CMetaTriangleSelector(); //! Get amount of all available triangles in this selector virtual s32 getTriangleCount() const; //! Gets all triangles. virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::matrix4* transform=0) const; //! Gets all triangles which lie within a specific bounding box. virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::aabbox3d& box, const core::matrix4* transform=0) const; //! Gets all triangles which have or may have contact with a 3d line. virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform=0) const; //! Adds a triangle selector to the collection of triangle selectors //! in this metaTriangleSelector. virtual void addTriangleSelector(ITriangleSelector* toAdd); //! Removes a specific triangle selector which was added before from the collection. virtual bool removeTriangleSelector(ITriangleSelector* toRemove); //! Removes all triangle selectors from the collection. virtual void removeAllTriangleSelectors(); //! Get the scene node associated with a given triangle. virtual ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const; // Get the number of TriangleSelectors that are part of this one virtual u32 getSelectorCount() const; // Get the TriangleSelector based on index based on getSelectorCount virtual ITriangleSelector* getSelector(u32 index); // Get the TriangleSelector based on index based on getSelectorCount virtual const ITriangleSelector* getSelector(u32 index) const; private: core::array TriangleSelectors; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CMetaTriangleSelector.cpp0000644000000000000000000001113412574354552022021 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CMetaTriangleSelector.h" namespace irr { namespace scene { //! constructor CMetaTriangleSelector::CMetaTriangleSelector() { #ifdef _DEBUG setDebugName("CMetaTriangleSelector"); #endif } //! destructor CMetaTriangleSelector::~CMetaTriangleSelector() { removeAllTriangleSelectors(); } //! Returns amount of all available triangles in this selector s32 CMetaTriangleSelector::getTriangleCount() const { s32 count = 0; for (u32 i=0; igetTriangleCount(); return count; } //! Gets all triangles. void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::matrix4* transform) const { s32 outWritten = 0; for (u32 i=0; igetTriangles(triangles + outWritten, arraySize - outWritten, t, transform); outWritten += t; if (outWritten==arraySize) break; } outTriangleCount = outWritten; } //! Gets all triangles which lie within a specific bounding box. void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::aabbox3d& box, const core::matrix4* transform) const { s32 outWritten = 0; for (u32 i=0; igetTriangles(triangles + outWritten, arraySize - outWritten, t, box, transform); outWritten += t; if (outWritten==arraySize) break; } outTriangleCount = outWritten; } //! Gets all triangles which have or may have contact with a 3d line. void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform) const { s32 outWritten = 0; for (u32 i=0; igetTriangles(triangles + outWritten, arraySize - outWritten, t, line, transform); outWritten += t; if (outWritten==arraySize) break; } outTriangleCount = outWritten; } //! Adds a triangle selector to the collection of triangle selectors //! in this metaTriangleSelector. void CMetaTriangleSelector::addTriangleSelector(ITriangleSelector* toAdd) { if (!toAdd) return; TriangleSelectors.push_back(toAdd); toAdd->grab(); } //! Removes a specific triangle selector which was added before from the collection. bool CMetaTriangleSelector::removeTriangleSelector(ITriangleSelector* toRemove) { for (u32 i=0; idrop(); TriangleSelectors.erase(i); return true; } } return false; } //! Removes all triangle selectors from the collection. void CMetaTriangleSelector::removeAllTriangleSelectors() { for (u32 i=0; idrop(); TriangleSelectors.clear(); } //! Return the scene node associated with a given triangle. ISceneNode* CMetaTriangleSelector::getSceneNodeForTriangle(u32 triangleIndex) const { u32 totalTriangles = 0; for (u32 i=0; igetTriangleCount(); if(totalTriangles > triangleIndex) return TriangleSelectors[i]->getSceneNodeForTriangle(0); } // For lack of anything more sensible, return the first selector. return TriangleSelectors[0]->getSceneNodeForTriangle(0); } /* Return the number of TriangleSelectors that are inside this one, Only useful for MetaTriangleSelector others return 1 */ u32 CMetaTriangleSelector::getSelectorCount() const { return TriangleSelectors.size(); } /* Returns the TriangleSelector based on index based on getSelectorCount Only useful for MetaTriangleSelector others return 'this' */ ITriangleSelector* CMetaTriangleSelector::getSelector(u32 index) { if (index >= TriangleSelectors.size()) return 0; return TriangleSelectors[index]; } /* Returns the TriangleSelector based on index based on getSelectorCount Only useful for MetaTriangleSelector others return 'this' */ const ITriangleSelector* CMetaTriangleSelector::getSelector(u32 index) const { if (index >= TriangleSelectors.size()) return 0; return TriangleSelectors[index]; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CMeshSceneNode.h0000644000000000000000000000657012574354552020101 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_MESH_SCENE_NODE_H_INCLUDED__ #define __C_MESH_SCENE_NODE_H_INCLUDED__ #include "IMeshSceneNode.h" #include "IMesh.h" namespace irr { namespace scene { class CMeshSceneNode : public IMeshSceneNode { public: //! constructor CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); //! destructor virtual ~CMeshSceneNode(); //! frame virtual void OnRegisterSceneNode(); //! renders the node. virtual void render(); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. virtual video::SMaterial& getMaterial(u32 i); //! returns amount of materials used by this scene node. virtual u32 getMaterialCount() const; //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_MESH; } //! Sets a new mesh virtual void setMesh(IMesh* mesh); //! Returns the current mesh virtual IMesh* getMesh(void) { return Mesh; } //! Creates shadow volume scene node as child of this node //! and returns a pointer to it. virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh, s32 id, bool zfailmethod=true, f32 infinity=10000.0f); //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. /* In this way it is possible to change the materials a mesh causing all mesh scene nodes referencing this mesh to change too. */ virtual void setReadOnlyMaterials(bool readonly); //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style virtual bool isReadOnlyMaterials() const; //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. virtual bool removeChild(ISceneNode* child); protected: void copyMaterials(); core::array Materials; core::aabbox3d Box; video::SMaterial ReadOnlyMaterial; IMesh* Mesh; IShadowVolumeSceneNode* Shadow; s32 PassCount; bool ReadOnlyMaterials; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CMeshSceneNode.cpp0000644000000000000000000002706612574354552020437 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CMeshSceneNode.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "S3DVertex.h" #include "ICameraSceneNode.h" #include "IMeshCache.h" #include "IAnimatedMesh.h" #include "IMaterialRenderer.h" #include "IFileSystem.h" #include "CShadowVolumeSceneNode.h" namespace irr { namespace scene { //! constructor CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) : IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), Shadow(0), PassCount(0), ReadOnlyMaterials(false) { #ifdef _DEBUG setDebugName("CMeshSceneNode"); #endif setMesh(mesh); } //! destructor CMeshSceneNode::~CMeshSceneNode() { if (Shadow) Shadow->drop(); if (Mesh) Mesh->drop(); } //! frame void CMeshSceneNode::OnRegisterSceneNode() { if (IsVisible) { // because this node supports rendering of mixed mode meshes consisting of // transparent and solid material at the same time, we need to go through all // materials, check of what type they are and register this node for the right // render pass according to that. video::IVideoDriver* driver = SceneManager->getVideoDriver(); PassCount = 0; int transparentCount = 0; int solidCount = 0; // count transparent and solid materials in this scene node if (ReadOnlyMaterials && Mesh) { // count mesh materials for (u32 i=0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); video::IMaterialRenderer* rnd = mb ? driver->getMaterialRenderer(mb->getMaterial().MaterialType) : 0; if (rnd && rnd->isTransparent()) ++transparentCount; else ++solidCount; if (solidCount && transparentCount) break; } } else { // count copied materials for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); if (rnd && rnd->isTransparent()) ++transparentCount; else ++solidCount; if (solidCount && transparentCount) break; } } // register according to material types counted if (solidCount) SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); if (transparentCount) SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); ISceneNode::OnRegisterSceneNode(); } } //! renders the node. void CMeshSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); if (!Mesh || !driver) return; bool isTransparentPass = SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; ++PassCount; driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); Box = Mesh->getBoundingBox(); if (Shadow && PassCount==1) Shadow->updateShadowVolumes(); // for debug purposes only: bool renderMeshes = true; video::SMaterial mat; if (DebugDataVisible && PassCount==1) { // overwrite half transparency if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY) { for (u32 g=0; ggetMeshBufferCount(); ++g) { mat = Materials[g]; mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; driver->setMaterial(mat); driver->drawMeshBuffer(Mesh->getMeshBuffer(g)); } renderMeshes = false; } } // render original meshes if (renderMeshes) { for (u32 i=0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); if (mb) { const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; video::IMaterialRenderer* rnd = driver->getMaterialRenderer(material.MaterialType); bool transparent = (rnd && rnd->isTransparent()); // only render transparent buffer if this is the transparent render pass // and solid only in solid pass if (transparent == isTransparentPass) { driver->setMaterial(material); driver->drawMeshBuffer(mb); } } } } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); // for debug purposes only: if (DebugDataVisible && PassCount==1) { video::SMaterial m; m.Lighting = false; m.AntiAliasing=0; driver->setMaterial(m); if (DebugDataVisible & scene::EDS_BBOX) { driver->draw3DBox(Box, video::SColor(255,255,255,255)); } if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) { for (u32 g=0; ggetMeshBufferCount(); ++g) { driver->draw3DBox( Mesh->getMeshBuffer(g)->getBoundingBox(), video::SColor(255,190,128,128)); } } if (DebugDataVisible & scene::EDS_NORMALS) { // draw normals const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); const u32 count = Mesh->getMeshBufferCount(); for (u32 i=0; i != count; ++i) { driver->drawMeshBufferNormals(Mesh->getMeshBuffer(i), debugNormalLength, debugNormalColor); } } // show mesh if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) { m.Wireframe = true; driver->setMaterial(m); for (u32 g=0; ggetMeshBufferCount(); ++g) { driver->drawMeshBuffer(Mesh->getMeshBuffer(g)); } } } } //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. bool CMeshSceneNode::removeChild(ISceneNode* child) { if (child && Shadow == child) { Shadow->drop(); Shadow = 0; } return ISceneNode::removeChild(child); } //! returns the axis aligned bounding box of this node const core::aabbox3d& CMeshSceneNode::getBoundingBox() const { return Mesh ? Mesh->getBoundingBox() : Box; } //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hierarchy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. video::SMaterial& CMeshSceneNode::getMaterial(u32 i) { if (Mesh && ReadOnlyMaterials && igetMeshBufferCount()) { ReadOnlyMaterial = Mesh->getMeshBuffer(i)->getMaterial(); return ReadOnlyMaterial; } if (i >= Materials.size()) return ISceneNode::getMaterial(i); return Materials[i]; } //! returns amount of materials used by this scene node. u32 CMeshSceneNode::getMaterialCount() const { if (Mesh && ReadOnlyMaterials) return Mesh->getMeshBufferCount(); return Materials.size(); } //! Sets a new mesh void CMeshSceneNode::setMesh(IMesh* mesh) { if (mesh) { mesh->grab(); if (Mesh) Mesh->drop(); Mesh = mesh; copyMaterials(); } } //! Creates shadow volume scene node as child of this node //! and returns a pointer to it. IShadowVolumeSceneNode* CMeshSceneNode::addShadowVolumeSceneNode( const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity) { if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) return 0; if (!shadowMesh) shadowMesh = Mesh; // if null is given, use the mesh of node if (Shadow) Shadow->drop(); Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity); return Shadow; } void CMeshSceneNode::copyMaterials() { Materials.clear(); if (Mesh) { video::SMaterial mat; for (u32 i=0; igetMeshBufferCount(); ++i) { IMeshBuffer* mb = Mesh->getMeshBuffer(i); if (mb) mat = mb->getMaterial(); Materials.push_back(mat); } } } //! Writes attributes of the scene node. void CMeshSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { IMeshSceneNode::serializeAttributes(out, options); if (options && (options->Flags&io::EARWF_USE_RELATIVE_PATHS) && options->Filename) { const io::path path = SceneManager->getFileSystem()->getRelativeFilename( SceneManager->getFileSystem()->getAbsolutePath(SceneManager->getMeshCache()->getMeshName(Mesh).getPath()), options->Filename); out->addString("Mesh", path.c_str()); } else out->addString("Mesh", SceneManager->getMeshCache()->getMeshName(Mesh).getPath().c_str()); out->addBool("ReadOnlyMaterials", ReadOnlyMaterials); } //! Reads attributes of the scene node. void CMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { io::path oldMeshStr = SceneManager->getMeshCache()->getMeshName(Mesh); io::path newMeshStr = in->getAttributeAsString("Mesh"); ReadOnlyMaterials = in->getAttributeAsBool("ReadOnlyMaterials"); if (newMeshStr != "" && oldMeshStr != newMeshStr) { IMesh* newMesh = 0; IAnimatedMesh* newAnimatedMesh = SceneManager->getMesh(newMeshStr.c_str()); if (newAnimatedMesh) newMesh = newAnimatedMesh->getMesh(0); if (newMesh) setMesh(newMesh); } // optional attribute to assign the hint to the whole mesh if (in->existsAttribute("HardwareMappingHint") && in->existsAttribute("HardwareMappingBufferType")) { scene::E_HARDWARE_MAPPING mapping = scene::EHM_NEVER; scene::E_BUFFER_TYPE bufferType = scene::EBT_NONE; core::stringc smapping = in->getAttributeAsString("HardwareMappingHint"); if (smapping.equals_ignore_case("static")) mapping = scene::EHM_STATIC; else if (smapping.equals_ignore_case("dynamic")) mapping = scene::EHM_DYNAMIC; else if (smapping.equals_ignore_case("stream")) mapping = scene::EHM_STREAM; core::stringc sbufferType = in->getAttributeAsString("HardwareMappingBufferType"); if (sbufferType.equals_ignore_case("vertex")) bufferType = scene::EBT_VERTEX; else if (sbufferType.equals_ignore_case("index")) bufferType = scene::EBT_INDEX; else if (sbufferType.equals_ignore_case("vertexindex")) bufferType = scene::EBT_VERTEX_AND_INDEX; IMesh* mesh = getMesh(); if (mesh) mesh->setHardwareMappingHint(mapping, bufferType); } IMeshSceneNode::deserializeAttributes(in, options); } //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. /* In this way it is possible to change the materials a mesh causing all mesh scene nodes referencing this mesh to change too. */ void CMeshSceneNode::setReadOnlyMaterials(bool readonly) { ReadOnlyMaterials = readonly; } //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style bool CMeshSceneNode::isReadOnlyMaterials() const { return ReadOnlyMaterials; } //! Creates a clone of this scene node and its children. ISceneNode* CMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CMeshSceneNode* nb = new CMeshSceneNode(Mesh, newParent, newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale); nb->cloneMembers(this, newManager); nb->ReadOnlyMaterials = ReadOnlyMaterials; nb->Materials = Materials; nb->Shadow = Shadow; if ( nb->Shadow ) nb->Shadow->grab(); if (newParent) nb->drop(); return nb; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CMeshManipulator.h0000644000000000000000000001050212574354552020517 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_MESH_MANIPULATOR_H_INCLUDED__ #define __C_MESH_MANIPULATOR_H_INCLUDED__ #include "IMeshManipulator.h" namespace irr { namespace scene { //! An interface for easy manipulation of meshes. /** Scale, set alpha value, flip surfaces, and so on. This exists for fixing problems with wrong imported or exported meshes quickly after loading. It is not intended for doing mesh modifications and/or animations during runtime. */ class CMeshManipulator : public IMeshManipulator { public: //! Flips the direction of surfaces. /** Changes backfacing triangles to frontfacing triangles and vice versa. \param mesh: Mesh on which the operation is performed. */ virtual void flipSurfaces(scene::IMesh* mesh) const; //! Recalculates all normals of the mesh. /** \param mesh: Mesh on which the operation is performed. \param smooth: Whether to use smoothed normals. */ virtual void recalculateNormals(scene::IMesh* mesh, bool smooth = false, bool angleWeighted = false) const; //! Recalculates all normals of the mesh buffer. /** \param buffer: Mesh buffer on which the operation is performed. \param smooth: Whether to use smoothed normals. */ virtual void recalculateNormals(IMeshBuffer* buffer, bool smooth = false, bool angleWeighted = false) const; //! Clones a static IMesh into a modifiable SMesh. virtual SMesh* createMeshCopy(scene::IMesh* mesh) const; //! Creates a planar texture mapping on the mesh /** \param mesh: Mesh on which the operation is performed. \param resolution: resolution of the planar mapping. This is the value specifying which is the relation between world space and texture coordinate space. */ virtual void makePlanarTextureMapping(scene::IMesh* mesh, f32 resolution=0.001f) const; //! Creates a planar texture mapping on the meshbuffer virtual void makePlanarTextureMapping(scene::IMeshBuffer* meshbuffer, f32 resolution=0.001f) const; //! Creates a planar texture mapping on the meshbuffer void makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const; //! Creates a planar texture mapping on the mesh void makePlanarTextureMapping(scene::IMesh* mesh, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const; //! Recalculates tangents, requires a tangent mesh buffer virtual void recalculateTangents(IMeshBuffer* buffer, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false) const; //! Recalculates tangents, requires a tangent mesh virtual void recalculateTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false) const; //! Creates a copy of the mesh, which will only consist of S3DVertexTangents vertices. virtual IMesh* createMeshWithTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false, bool recalculateTangents=true) const; //! Creates a copy of the mesh, which will only consist of S3D2TCoords vertices. virtual IMesh* createMeshWith2TCoords(IMesh* mesh) const; //! Creates a copy of the mesh, which will only consist of S3DVertex vertices. virtual IMesh* createMeshWith1TCoords(IMesh* mesh) const; //! Creates a copy of the mesh, which will only consist of unique triangles, i.e. no vertices are shared. virtual IMesh* createMeshUniquePrimitives(IMesh* mesh) const; //! Creates a copy of the mesh, which will have all duplicated vertices removed, i.e. maximal amount of vertices are shared via indexing. virtual IMesh* createMeshWelded(IMesh *mesh, f32 tolerance=core::ROUNDING_ERROR_f32) const; //! Returns amount of polygons in mesh. virtual s32 getPolyCount(scene::IMesh* mesh) const; //! Returns amount of polygons in mesh. virtual s32 getPolyCount(scene::IAnimatedMesh* mesh) const; //! create a new AnimatedMesh and adds the mesh to it virtual IAnimatedMesh * createAnimatedMesh(scene::IMesh* mesh,scene::E_ANIMATED_MESH_TYPE type) const; //! create a mesh optimized for the vertex cache virtual IMesh* createForsythOptimizedMesh(const scene::IMesh *mesh) const; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CMeshManipulator.cpp0000644000000000000000000013236012574354552021061 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CMeshManipulator.h" #include "SMesh.h" #include "CMeshBuffer.h" #include "SAnimatedMesh.h" #include "os.h" #include "irrMap.h" namespace irr { namespace scene { static inline core::vector3df getAngleWeight(const core::vector3df& v1, const core::vector3df& v2, const core::vector3df& v3) { // Calculate this triangle's weight for each of its three vertices // start by calculating the lengths of its sides const f32 a = v2.getDistanceFromSQ(v3); const f32 asqrt = sqrtf(a); const f32 b = v1.getDistanceFromSQ(v3); const f32 bsqrt = sqrtf(b); const f32 c = v1.getDistanceFromSQ(v2); const f32 csqrt = sqrtf(c); // use them to find the angle at each vertex return core::vector3df( acosf((b + c - a) / (2.f * bsqrt * csqrt)), acosf((-b + c + a) / (2.f * asqrt * csqrt)), acosf((b - c + a) / (2.f * bsqrt * asqrt))); } //! Flips the direction of surfaces. Changes backfacing triangles to frontfacing //! triangles and vice versa. //! \param mesh: Mesh on which the operation is performed. void CMeshManipulator::flipSurfaces(scene::IMesh* mesh) const { if (!mesh) return; const u32 bcount = mesh->getMeshBufferCount(); for (u32 b=0; bgetMeshBuffer(b); const u32 idxcnt = buffer->getIndexCount(); if (buffer->getIndexType() == video::EIT_16BIT) { u16* idx = buffer->getIndices(); for (u32 i=0; i(buffer->getIndices()); for (u32 i=0; i void recalculateNormalsT(IMeshBuffer* buffer, bool smooth, bool angleWeighted) { const u32 vtxcnt = buffer->getVertexCount(); const u32 idxcnt = buffer->getIndexCount(); const T* idx = reinterpret_cast(buffer->getIndices()); if (!smooth) { for (u32 i=0; igetPosition(idx[i+0]); const core::vector3df& v2 = buffer->getPosition(idx[i+1]); const core::vector3df& v3 = buffer->getPosition(idx[i+2]); const core::vector3df normal = core::plane3d(v1, v2, v3).Normal; buffer->getNormal(idx[i+0]) = normal; buffer->getNormal(idx[i+1]) = normal; buffer->getNormal(idx[i+2]) = normal; } } else { u32 i; for ( i = 0; i!= vtxcnt; ++i ) buffer->getNormal(i).set(0.f, 0.f, 0.f); for ( i=0; igetPosition(idx[i+0]); const core::vector3df& v2 = buffer->getPosition(idx[i+1]); const core::vector3df& v3 = buffer->getPosition(idx[i+2]); const core::vector3df normal = core::plane3d(v1, v2, v3).Normal; core::vector3df weight(1.f,1.f,1.f); if (angleWeighted) weight = irr::scene::getAngleWeight(v1,v2,v3); // writing irr::scene:: necessary for borland buffer->getNormal(idx[i+0]) += weight.X*normal; buffer->getNormal(idx[i+1]) += weight.Y*normal; buffer->getNormal(idx[i+2]) += weight.Z*normal; } for ( i = 0; i!= vtxcnt; ++i ) buffer->getNormal(i).normalize(); } } } //! Recalculates all normals of the mesh buffer. /** \param buffer: Mesh buffer on which the operation is performed. */ void CMeshManipulator::recalculateNormals(IMeshBuffer* buffer, bool smooth, bool angleWeighted) const { if (!buffer) return; if (buffer->getIndexType()==video::EIT_16BIT) recalculateNormalsT(buffer, smooth, angleWeighted); else recalculateNormalsT(buffer, smooth, angleWeighted); } //! Recalculates all normals of the mesh. //! \param mesh: Mesh on which the operation is performed. void CMeshManipulator::recalculateNormals(scene::IMesh* mesh, bool smooth, bool angleWeighted) const { if (!mesh) return; const u32 bcount = mesh->getMeshBufferCount(); for ( u32 b=0; bgetMeshBuffer(b), smooth, angleWeighted); } namespace { void calculateTangents( core::vector3df& normal, core::vector3df& tangent, core::vector3df& binormal, const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords { // choose one of them: //#define USE_NVIDIA_GLH_VERSION // use version used by nvidia in glh headers #define USE_IRR_VERSION #ifdef USE_IRR_VERSION core::vector3df v1 = vt1 - vt2; core::vector3df v2 = vt3 - vt1; normal = v2.crossProduct(v1); normal.normalize(); // binormal f32 deltaX1 = tc1.X - tc2.X; f32 deltaX2 = tc3.X - tc1.X; binormal = (v1 * deltaX2) - (v2 * deltaX1); binormal.normalize(); // tangent f32 deltaY1 = tc1.Y - tc2.Y; f32 deltaY2 = tc3.Y - tc1.Y; tangent = (v1 * deltaY2) - (v2 * deltaY1); tangent.normalize(); // adjust core::vector3df txb = tangent.crossProduct(binormal); if (txb.dotProduct(normal) < 0.0f) { tangent *= -1.0f; binormal *= -1.0f; } #endif // USE_IRR_VERSION #ifdef USE_NVIDIA_GLH_VERSION tangent.set(0,0,0); binormal.set(0,0,0); core::vector3df v1(vt2.X - vt1.X, tc2.X - tc1.X, tc2.Y - tc1.Y); core::vector3df v2(vt3.X - vt1.X, tc3.X - tc1.X, tc3.Y - tc1.Y); core::vector3df txb = v1.crossProduct(v2); if ( !core::iszero ( txb.X ) ) { tangent.X = -txb.Y / txb.X; binormal.X = -txb.Z / txb.X; } v1.X = vt2.Y - vt1.Y; v2.X = vt3.Y - vt1.Y; txb = v1.crossProduct(v2); if ( !core::iszero ( txb.X ) ) { tangent.Y = -txb.Y / txb.X; binormal.Y = -txb.Z / txb.X; } v1.X = vt2.Z - vt1.Z; v2.X = vt3.Z - vt1.Z; txb = v1.crossProduct(v2); if ( !core::iszero ( txb.X ) ) { tangent.Z = -txb.Y / txb.X; binormal.Z = -txb.Z / txb.X; } tangent.normalize(); binormal.normalize(); normal = tangent.crossProduct(binormal); normal.normalize(); binormal = tangent.crossProduct(normal); binormal.normalize(); core::plane3d pl(vt1, vt2, vt3); if(normal.dotProduct(pl.Normal) < 0.0f ) normal *= -1.0f; #endif // USE_NVIDIA_GLH_VERSION } //! Recalculates tangents for a tangent mesh buffer template void recalculateTangentsT(IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted) { if (!buffer || (buffer->getVertexType()!= video::EVT_TANGENTS)) return; const u32 vtxCnt = buffer->getVertexCount(); const u32 idxCnt = buffer->getIndexCount(); T* idx = reinterpret_cast(buffer->getIndices()); video::S3DVertexTangents* v = (video::S3DVertexTangents*)buffer->getVertices(); if (smooth) { u32 i; for ( i = 0; i!= vtxCnt; ++i ) { if (recalculateNormals) v[i].Normal.set( 0.f, 0.f, 0.f ); v[i].Tangent.set( 0.f, 0.f, 0.f ); v[i].Binormal.set( 0.f, 0.f, 0.f ); } //Each vertex gets the sum of the tangents and binormals from the faces around it for ( i=0; igetVertexType() == video::EVT_TANGENTS)) { if (buffer->getIndexType() == video::EIT_16BIT) recalculateTangentsT(buffer, recalculateNormals, smooth, angleWeighted); else recalculateTangentsT(buffer, recalculateNormals, smooth, angleWeighted); } } //! Recalculates tangents for all tangent mesh buffers void CMeshManipulator::recalculateTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted) const { if (!mesh) return; const u32 meshBufferCount = mesh->getMeshBufferCount(); for (u32 b=0; bgetMeshBuffer(b), recalculateNormals, smooth, angleWeighted); } } namespace { //! Creates a planar texture mapping on the meshbuffer template void makePlanarTextureMappingT(scene::IMeshBuffer* buffer, f32 resolution) { u32 idxcnt = buffer->getIndexCount(); T* idx = reinterpret_cast(buffer->getIndices()); for (u32 i=0; igetPosition(idx[i+0]), buffer->getPosition(idx[i+1]), buffer->getPosition(idx[i+2])); p.Normal.X = fabsf(p.Normal.X); p.Normal.Y = fabsf(p.Normal.Y); p.Normal.Z = fabsf(p.Normal.Z); // calculate planar mapping worldspace coordinates if (p.Normal.X > p.Normal.Y && p.Normal.X > p.Normal.Z) { for (u32 o=0; o!=3; ++o) { buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).Y * resolution; buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Z * resolution; } } else if (p.Normal.Y > p.Normal.X && p.Normal.Y > p.Normal.Z) { for (u32 o=0; o!=3; ++o) { buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).X * resolution; buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Z * resolution; } } else { for (u32 o=0; o!=3; ++o) { buffer->getTCoords(idx[i+o]).X = buffer->getPosition(idx[i+o]).X * resolution; buffer->getTCoords(idx[i+o]).Y = buffer->getPosition(idx[i+o]).Y * resolution; } } } } } //! Creates a planar texture mapping on the meshbuffer void CMeshManipulator::makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolution) const { if (!buffer) return; if (buffer->getIndexType()==video::EIT_16BIT) makePlanarTextureMappingT(buffer, resolution); else makePlanarTextureMappingT(buffer, resolution); } //! Creates a planar texture mapping on the mesh void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resolution) const { if (!mesh) return; const u32 bcount = mesh->getMeshBufferCount(); for ( u32 b=0; bgetMeshBuffer(b), resolution); } } namespace { //! Creates a planar texture mapping on the meshbuffer template void makePlanarTextureMappingT(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) { u32 idxcnt = buffer->getIndexCount(); T* idx = reinterpret_cast(buffer->getIndices()); for (u32 i=0; igetTCoords(idx[i+o]).X = 0.5f+(buffer->getPosition(idx[i+o]).Z + offset.Z) * resolutionS; buffer->getTCoords(idx[i+o]).Y = 0.5f-(buffer->getPosition(idx[i+o]).Y + offset.Y) * resolutionT; } } else if (axis==1) { for (u32 o=0; o!=3; ++o) { buffer->getTCoords(idx[i+o]).X = 0.5f+(buffer->getPosition(idx[i+o]).X + offset.X) * resolutionS; buffer->getTCoords(idx[i+o]).Y = 1.f-(buffer->getPosition(idx[i+o]).Z + offset.Z) * resolutionT; } } else if (axis==2) { for (u32 o=0; o!=3; ++o) { buffer->getTCoords(idx[i+o]).X = 0.5f+(buffer->getPosition(idx[i+o]).X + offset.X) * resolutionS; buffer->getTCoords(idx[i+o]).Y = 0.5f-(buffer->getPosition(idx[i+o]).Y + offset.Y) * resolutionT; } } } } } //! Creates a planar texture mapping on the meshbuffer void CMeshManipulator::makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const { if (!buffer) return; if (buffer->getIndexType()==video::EIT_16BIT) makePlanarTextureMappingT(buffer, resolutionS, resolutionT, axis, offset); else makePlanarTextureMappingT(buffer, resolutionS, resolutionT, axis, offset); } //! Creates a planar texture mapping on the mesh void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const { if (!mesh) return; const u32 bcount = mesh->getMeshBufferCount(); for ( u32 b=0; bgetMeshBuffer(b), resolutionS, resolutionT, axis, offset); } } //! Clones a static IMesh into a modifyable SMesh. // not yet 32bit SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const { if (!mesh) return 0; SMesh* clone = new SMesh(); const u32 meshBufferCount = mesh->getMeshBufferCount(); for ( u32 b=0; bgetMeshBuffer(b); switch(mb->getVertexType()) { case video::EVT_STANDARD: { SMeshBuffer* buffer = new SMeshBuffer(); buffer->Material = mb->getMaterial(); const u32 vcount = mb->getVertexCount(); buffer->Vertices.reallocate(vcount); video::S3DVertex* vertices = (video::S3DVertex*)mb->getVertices(); for (u32 i=0; i < vcount; ++i) buffer->Vertices.push_back(vertices[i]); const u32 icount = mb->getIndexCount(); buffer->Indices.reallocate(icount); const u16* indices = mb->getIndices(); for (u32 i=0; i < icount; ++i) buffer->Indices.push_back(indices[i]); clone->addMeshBuffer(buffer); buffer->drop(); } break; case video::EVT_2TCOORDS: { SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); buffer->Material = mb->getMaterial(); const u32 vcount = mb->getVertexCount(); buffer->Vertices.reallocate(vcount); video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)mb->getVertices(); for (u32 i=0; i < vcount; ++i) buffer->Vertices.push_back(vertices[i]); const u32 icount = mb->getIndexCount(); buffer->Indices.reallocate(icount); const u16* indices = mb->getIndices(); for (u32 i=0; i < icount; ++i) buffer->Indices.push_back(indices[i]); clone->addMeshBuffer(buffer); buffer->drop(); } break; case video::EVT_TANGENTS: { SMeshBufferTangents* buffer = new SMeshBufferTangents(); buffer->Material = mb->getMaterial(); const u32 vcount = mb->getVertexCount(); buffer->Vertices.reallocate(vcount); video::S3DVertexTangents* vertices = (video::S3DVertexTangents*)mb->getVertices(); for (u32 i=0; i < vcount; ++i) buffer->Vertices.push_back(vertices[i]); const u32 icount = mb->getIndexCount(); buffer->Indices.reallocate(icount); const u16* indices = mb->getIndices(); for (u32 i=0; i < icount; ++i) buffer->Indices.push_back(indices[i]); clone->addMeshBuffer(buffer); buffer->drop(); } break; }// end switch }// end for all mesh buffers clone->BoundingBox = mesh->getBoundingBox(); return clone; } //! Creates a copy of the mesh, which will only consist of unique primitives // not yet 32bit IMesh* CMeshManipulator::createMeshUniquePrimitives(IMesh* mesh) const { if (!mesh) return 0; SMesh* clone = new SMesh(); const u32 meshBufferCount = mesh->getMeshBufferCount(); for ( u32 b=0; bgetMeshBuffer(b); const s32 idxCnt = mb->getIndexCount(); const u16* idx = mb->getIndices(); switch(mb->getVertexType()) { case video::EVT_STANDARD: { SMeshBuffer* buffer = new SMeshBuffer(); buffer->Material = mb->getMaterial(); video::S3DVertex* v = (video::S3DVertex*)mb->getVertices(); buffer->Vertices.reallocate(idxCnt); buffer->Indices.reallocate(idxCnt); for (s32 i=0; iVertices.push_back( v[idx[i + 0 ]] ); buffer->Vertices.push_back( v[idx[i + 1 ]] ); buffer->Vertices.push_back( v[idx[i + 2 ]] ); buffer->Indices.push_back( i + 0 ); buffer->Indices.push_back( i + 1 ); buffer->Indices.push_back( i + 2 ); } buffer->setBoundingBox(mb->getBoundingBox()); clone->addMeshBuffer(buffer); buffer->drop(); } break; case video::EVT_2TCOORDS: { SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); buffer->Material = mb->getMaterial(); video::S3DVertex2TCoords* v = (video::S3DVertex2TCoords*)mb->getVertices(); buffer->Vertices.reallocate(idxCnt); buffer->Indices.reallocate(idxCnt); for (s32 i=0; iVertices.push_back( v[idx[i + 0 ]] ); buffer->Vertices.push_back( v[idx[i + 1 ]] ); buffer->Vertices.push_back( v[idx[i + 2 ]] ); buffer->Indices.push_back( i + 0 ); buffer->Indices.push_back( i + 1 ); buffer->Indices.push_back( i + 2 ); } buffer->setBoundingBox(mb->getBoundingBox()); clone->addMeshBuffer(buffer); buffer->drop(); } break; case video::EVT_TANGENTS: { SMeshBufferTangents* buffer = new SMeshBufferTangents(); buffer->Material = mb->getMaterial(); video::S3DVertexTangents* v = (video::S3DVertexTangents*)mb->getVertices(); buffer->Vertices.reallocate(idxCnt); buffer->Indices.reallocate(idxCnt); for (s32 i=0; iVertices.push_back( v[idx[i + 0 ]] ); buffer->Vertices.push_back( v[idx[i + 1 ]] ); buffer->Vertices.push_back( v[idx[i + 2 ]] ); buffer->Indices.push_back( i + 0 ); buffer->Indices.push_back( i + 1 ); buffer->Indices.push_back( i + 2 ); } buffer->setBoundingBox(mb->getBoundingBox()); clone->addMeshBuffer(buffer); buffer->drop(); } break; }// end switch }// end for all mesh buffers clone->BoundingBox = mesh->getBoundingBox(); return clone; } //! Creates a copy of a mesh, which will have identical vertices welded together // not yet 32bit IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const { SMesh* clone = new SMesh(); clone->BoundingBox = mesh->getBoundingBox(); core::array redirects; for (u32 b=0; bgetMeshBufferCount(); ++b) { const IMeshBuffer* const mb = mesh->getMeshBuffer(b); // reset redirect list redirects.set_used(mb->getVertexCount()); const u16* indices = 0; u32 indexCount = 0; core::array* outIdx = 0; switch(mb->getVertexType()) { case video::EVT_STANDARD: { SMeshBuffer* buffer = new SMeshBuffer(); buffer->BoundingBox = mb->getBoundingBox(); buffer->Material = mb->getMaterial(); clone->addMeshBuffer(buffer); buffer->drop(); video::S3DVertex* v = (video::S3DVertex*)mb->getVertices(); u32 vertexCount = mb->getVertexCount(); indices = mb->getIndices(); indexCount = mb->getIndexCount(); outIdx = &buffer->Indices; buffer->Vertices.reallocate(vertexCount); for (u32 i=0; i < vertexCount; ++i) { bool found = false; for (u32 j=0; j < i; ++j) { if ( v[i].Pos.equals( v[j].Pos, tolerance) && v[i].Normal.equals( v[j].Normal, tolerance) && v[i].TCoords.equals( v[j].TCoords ) && (v[i].Color == v[j].Color) ) { redirects[i] = redirects[j]; found = true; break; } } if (!found) { redirects[i] = buffer->Vertices.size(); buffer->Vertices.push_back(v[i]); } } break; } case video::EVT_2TCOORDS: { SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); buffer->BoundingBox = mb->getBoundingBox(); buffer->Material = mb->getMaterial(); clone->addMeshBuffer(buffer); buffer->drop(); video::S3DVertex2TCoords* v = (video::S3DVertex2TCoords*)mb->getVertices(); u32 vertexCount = mb->getVertexCount(); indices = mb->getIndices(); indexCount = mb->getIndexCount(); outIdx = &buffer->Indices; buffer->Vertices.reallocate(vertexCount); for (u32 i=0; i < vertexCount; ++i) { bool found = false; for (u32 j=0; j < i; ++j) { if ( v[i].Pos.equals( v[j].Pos, tolerance) && v[i].Normal.equals( v[j].Normal, tolerance) && v[i].TCoords.equals( v[j].TCoords ) && v[i].TCoords2.equals( v[j].TCoords2 ) && (v[i].Color == v[j].Color) ) { redirects[i] = redirects[j]; found = true; break; } } if (!found) { redirects[i] = buffer->Vertices.size(); buffer->Vertices.push_back(v[i]); } } break; } case video::EVT_TANGENTS: { SMeshBufferTangents* buffer = new SMeshBufferTangents(); buffer->BoundingBox = mb->getBoundingBox(); buffer->Material = mb->getMaterial(); clone->addMeshBuffer(buffer); buffer->drop(); video::S3DVertexTangents* v = (video::S3DVertexTangents*)mb->getVertices(); u32 vertexCount = mb->getVertexCount(); indices = mb->getIndices(); indexCount = mb->getIndexCount(); outIdx = &buffer->Indices; buffer->Vertices.reallocate(vertexCount); for (u32 i=0; i < vertexCount; ++i) { bool found = false; for (u32 j=0; j < i; ++j) { if ( v[i].Pos.equals( v[j].Pos, tolerance) && v[i].Normal.equals( v[j].Normal, tolerance) && v[i].TCoords.equals( v[j].TCoords ) && v[i].Tangent.equals( v[j].Tangent, tolerance ) && v[i].Binormal.equals( v[j].Binormal, tolerance ) && (v[i].Color == v[j].Color) ) { redirects[i] = redirects[j]; found = true; break; } } if (!found) { redirects[i] = buffer->Vertices.size(); buffer->Vertices.push_back(v[i]); } } break; } default: os::Printer::log("Cannot create welded mesh, vertex type unsupported", ELL_ERROR); break; } // write the buffer's index list core::array &Indices = *outIdx; Indices.set_used(indexCount); for (u32 i=0; igetMeshBufferCount(); for (u32 b=0; bgetMeshBuffer(b); const u32 idxCnt = original->getIndexCount(); const u16* idx = original->getIndices(); SMeshBufferTangents* buffer = new SMeshBufferTangents(); buffer->Material = original->getMaterial(); buffer->Vertices.reallocate(idxCnt); buffer->Indices.reallocate(idxCnt); core::map vertMap; int vertLocation; // copy vertices const video::E_VERTEX_TYPE vType = original->getVertexType(); video::S3DVertexTangents vNew; for (u32 i=0; igetVertices(); vNew = video::S3DVertexTangents( v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); } break; case video::EVT_2TCOORDS: { const video::S3DVertex2TCoords* v = (const video::S3DVertex2TCoords*)original->getVertices(); vNew = video::S3DVertexTangents( v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); } break; case video::EVT_TANGENTS: { const video::S3DVertexTangents* v = (const video::S3DVertexTangents*)original->getVertices(); vNew = v[idx[i]]; } break; } core::map::Node* n = vertMap.find(vNew); if (n) { vertLocation = n->getValue(); } else { vertLocation = buffer->Vertices.size(); buffer->Vertices.push_back(vNew); vertMap.insert(vNew, vertLocation); } // create new indices buffer->Indices.push_back(vertLocation); } buffer->recalculateBoundingBox(); // add new buffer clone->addMeshBuffer(buffer); buffer->drop(); } clone->recalculateBoundingBox(); if (calculateTangents) recalculateTangents(clone, recalculateNormals, smooth, angleWeighted); return clone; } //! Creates a copy of the mesh, which will only consist of S3DVertex2TCoords vertices. // not yet 32bit IMesh* CMeshManipulator::createMeshWith2TCoords(IMesh* mesh) const { if (!mesh) return 0; // copy mesh and fill data into SMeshBufferLightMap SMesh* clone = new SMesh(); const u32 meshBufferCount = mesh->getMeshBufferCount(); for (u32 b=0; bgetMeshBuffer(b); const u32 idxCnt = original->getIndexCount(); const u16* idx = original->getIndices(); SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); buffer->Material = original->getMaterial(); buffer->Vertices.reallocate(idxCnt); buffer->Indices.reallocate(idxCnt); core::map vertMap; int vertLocation; // copy vertices const video::E_VERTEX_TYPE vType = original->getVertexType(); video::S3DVertex2TCoords vNew; for (u32 i=0; igetVertices(); vNew = video::S3DVertex2TCoords( v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords); } break; case video::EVT_2TCOORDS: { const video::S3DVertex2TCoords* v = (const video::S3DVertex2TCoords*)original->getVertices(); vNew = v[idx[i]]; } break; case video::EVT_TANGENTS: { const video::S3DVertexTangents* v = (const video::S3DVertexTangents*)original->getVertices(); vNew = video::S3DVertex2TCoords( v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords, v[idx[i]].TCoords); } break; } core::map::Node* n = vertMap.find(vNew); if (n) { vertLocation = n->getValue(); } else { vertLocation = buffer->Vertices.size(); buffer->Vertices.push_back(vNew); vertMap.insert(vNew, vertLocation); } // create new indices buffer->Indices.push_back(vertLocation); } buffer->recalculateBoundingBox(); // add new buffer clone->addMeshBuffer(buffer); buffer->drop(); } clone->recalculateBoundingBox(); return clone; } //! Creates a copy of the mesh, which will only consist of S3DVertex vertices. // not yet 32bit IMesh* CMeshManipulator::createMeshWith1TCoords(IMesh* mesh) const { if (!mesh) return 0; // copy mesh and fill data into SMeshBuffer SMesh* clone = new SMesh(); const u32 meshBufferCount = mesh->getMeshBufferCount(); for (u32 b=0; bgetMeshBuffer(b); const u32 idxCnt = original->getIndexCount(); const u16* idx = original->getIndices(); SMeshBuffer* buffer = new SMeshBuffer(); buffer->Material = original->getMaterial(); buffer->Vertices.reallocate(idxCnt); buffer->Indices.reallocate(idxCnt); core::map vertMap; int vertLocation; // copy vertices const video::E_VERTEX_TYPE vType = original->getVertexType(); video::S3DVertex vNew; for (u32 i=0; igetVertices(); vNew = v[idx[i]]; } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* v = (video::S3DVertex2TCoords*)original->getVertices(); vNew = video::S3DVertex( v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* v = (video::S3DVertexTangents*)original->getVertices(); vNew = video::S3DVertex( v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); } break; } core::map::Node* n = vertMap.find(vNew); if (n) { vertLocation = n->getValue(); } else { vertLocation = buffer->Vertices.size(); buffer->Vertices.push_back(vNew); vertMap.insert(vNew, vertLocation); } // create new indices buffer->Indices.push_back(vertLocation); } buffer->recalculateBoundingBox(); // add new buffer clone->addMeshBuffer(buffer); buffer->drop(); } clone->recalculateBoundingBox(); return clone; } //! Returns amount of polygons in mesh. s32 CMeshManipulator::getPolyCount(scene::IMesh* mesh) const { if (!mesh) return 0; s32 trianglecount = 0; for (u32 g=0; ggetMeshBufferCount(); ++g) trianglecount += mesh->getMeshBuffer(g)->getIndexCount() / 3; return trianglecount; } //! Returns amount of polygons in mesh. s32 CMeshManipulator::getPolyCount(scene::IAnimatedMesh* mesh) const { if (mesh && mesh->getFrameCount() != 0) return getPolyCount(mesh->getMesh(0)); return 0; } //! create a new AnimatedMesh and adds the mesh to it IAnimatedMesh * CMeshManipulator::createAnimatedMesh(scene::IMesh* mesh, scene::E_ANIMATED_MESH_TYPE type) const { return new SAnimatedMesh(mesh, type); } namespace { struct vcache { core::array tris; float score; s16 cachepos; u16 NumActiveTris; }; struct tcache { u16 ind[3]; float score; bool drawn; }; const u16 cachesize = 32; float FindVertexScore(vcache *v) { const float CacheDecayPower = 1.5f; const float LastTriScore = 0.75f; const float ValenceBoostScale = 2.0f; const float ValenceBoostPower = 0.5f; const float MaxSizeVertexCache = 32.0f; if (v->NumActiveTris == 0) { // No tri needs this vertex! return -1.0f; } float Score = 0.0f; int CachePosition = v->cachepos; if (CachePosition < 0) { // Vertex is not in FIFO cache - no score. } else { if (CachePosition < 3) { // This vertex was used in the last triangle, // so it has a fixed score. Score = LastTriScore; } else { // Points for being high in the cache. const float Scaler = 1.0f / (MaxSizeVertexCache - 3); Score = 1.0f - (CachePosition - 3) * Scaler; Score = powf(Score, CacheDecayPower); } } // Bonus points for having a low number of tris still to // use the vert, so we get rid of lone verts quickly. float ValenceBoost = powf(v->NumActiveTris, -ValenceBoostPower); Score += ValenceBoostScale * ValenceBoost; return Score; } /* A specialized LRU cache for the Forsyth algorithm. */ class f_lru { public: f_lru(vcache *v, tcache *t): vc(v), tc(t) { for (u16 i = 0; i < cachesize; i++) { cache[i] = -1; } } // Adds this vertex index and returns the highest-scoring triangle index u32 add(u16 vert, bool updatetris = false) { bool found = false; // Mark existing pos as empty for (u16 i = 0; i < cachesize; i++) { if (cache[i] == vert) { // Move everything down for (u16 j = i; j; j--) { cache[j] = cache[j - 1]; } found = true; break; } } if (!found) { if (cache[cachesize-1] != -1) vc[cache[cachesize-1]].cachepos = -1; // Move everything down for (u16 i = cachesize - 1; i; i--) { cache[i] = cache[i - 1]; } } cache[0] = vert; u32 highest = 0; float hiscore = 0; if (updatetris) { // Update cache positions for (u16 i = 0; i < cachesize; i++) { if (cache[i] == -1) break; vc[cache[i]].cachepos = i; vc[cache[i]].score = FindVertexScore(&vc[cache[i]]); } // Update triangle scores for (u16 i = 0; i < cachesize; i++) { if (cache[i] == -1) break; const u16 trisize = vc[cache[i]].tris.size(); for (u16 t = 0; t < trisize; t++) { tcache *tri = &tc[vc[cache[i]].tris[t]]; tri->score = vc[tri->ind[0]].score + vc[tri->ind[1]].score + vc[tri->ind[2]].score; if (tri->score > hiscore) { hiscore = tri->score; highest = vc[cache[i]].tris[t]; } } } } return highest; } private: s32 cache[cachesize]; vcache *vc; tcache *tc; }; } // end anonymous namespace /** Vertex cache optimization according to the Forsyth paper: http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html The function is thread-safe (read: you can optimize several meshes in different threads) \param mesh Source mesh for the operation. */ IMesh* CMeshManipulator::createForsythOptimizedMesh(const IMesh *mesh) const { if (!mesh) return 0; SMesh *newmesh = new SMesh(); newmesh->BoundingBox = mesh->getBoundingBox(); const u32 mbcount = mesh->getMeshBufferCount(); for (u32 b = 0; b < mbcount; ++b) { const IMeshBuffer *mb = mesh->getMeshBuffer(b); if (mb->getIndexType() != video::EIT_16BIT) { os::Printer::log("Cannot optimize a mesh with 32bit indices", ELL_ERROR); newmesh->drop(); return 0; } const u32 icount = mb->getIndexCount(); const u32 tcount = icount / 3; const u32 vcount = mb->getVertexCount(); const u16 *ind = mb->getIndices(); vcache *vc = new vcache[vcount]; tcache *tc = new tcache[tcount]; f_lru lru(vc, tc); // init for (u16 i = 0; i < vcount; i++) { vc[i].score = 0; vc[i].cachepos = -1; vc[i].NumActiveTris = 0; } // First pass: count how many times a vert is used for (u32 i = 0; i < icount; i += 3) { vc[ind[i]].NumActiveTris++; vc[ind[i + 1]].NumActiveTris++; vc[ind[i + 2]].NumActiveTris++; const u32 tri_ind = i/3; tc[tri_ind].ind[0] = ind[i]; tc[tri_ind].ind[1] = ind[i + 1]; tc[tri_ind].ind[2] = ind[i + 2]; } // Second pass: list of each triangle for (u32 i = 0; i < tcount; i++) { vc[tc[i].ind[0]].tris.push_back(i); vc[tc[i].ind[1]].tris.push_back(i); vc[tc[i].ind[2]].tris.push_back(i); tc[i].drawn = false; } // Give initial scores for (u16 i = 0; i < vcount; i++) { vc[i].score = FindVertexScore(&vc[i]); } for (u32 i = 0; i < tcount; i++) { tc[i].score = vc[tc[i].ind[0]].score + vc[tc[i].ind[1]].score + vc[tc[i].ind[2]].score; } switch(mb->getVertexType()) { case video::EVT_STANDARD: { video::S3DVertex *v = (video::S3DVertex *) mb->getVertices(); SMeshBuffer *buf = new SMeshBuffer(); buf->Material = mb->getMaterial(); buf->Vertices.reallocate(vcount); buf->Indices.reallocate(icount); core::map sind; // search index for fast operation typedef core::map::Node snode; // Main algorithm u32 highest = 0; u32 drawcalls = 0; for (;;) { if (tc[highest].drawn) { bool found = false; float hiscore = 0; for (u32 t = 0; t < tcount; t++) { if (!tc[t].drawn) { if (tc[t].score > hiscore) { highest = t; hiscore = tc[t].score; found = true; } } } if (!found) break; } // Output the best triangle u16 newind = buf->Vertices.size(); snode *s = sind.find(v[tc[highest].ind[0]]); if (!s) { buf->Vertices.push_back(v[tc[highest].ind[0]]); buf->Indices.push_back(newind); sind.insert(v[tc[highest].ind[0]], newind); newind++; } else { buf->Indices.push_back(s->getValue()); } s = sind.find(v[tc[highest].ind[1]]); if (!s) { buf->Vertices.push_back(v[tc[highest].ind[1]]); buf->Indices.push_back(newind); sind.insert(v[tc[highest].ind[1]], newind); newind++; } else { buf->Indices.push_back(s->getValue()); } s = sind.find(v[tc[highest].ind[2]]); if (!s) { buf->Vertices.push_back(v[tc[highest].ind[2]]); buf->Indices.push_back(newind); sind.insert(v[tc[highest].ind[2]], newind); } else { buf->Indices.push_back(s->getValue()); } vc[tc[highest].ind[0]].NumActiveTris--; vc[tc[highest].ind[1]].NumActiveTris--; vc[tc[highest].ind[2]].NumActiveTris--; tc[highest].drawn = true; for (u16 j = 0; j < 3; j++) { vcache *vert = &vc[tc[highest].ind[j]]; for (u16 t = 0; t < vert->tris.size(); t++) { if (highest == vert->tris[t]) { vert->tris.erase(t); break; } } } lru.add(tc[highest].ind[0]); lru.add(tc[highest].ind[1]); highest = lru.add(tc[highest].ind[2], true); drawcalls++; } buf->setBoundingBox(mb->getBoundingBox()); newmesh->addMeshBuffer(buf); buf->drop(); } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords *v = (video::S3DVertex2TCoords *) mb->getVertices(); SMeshBufferLightMap *buf = new SMeshBufferLightMap(); buf->Material = mb->getMaterial(); buf->Vertices.reallocate(vcount); buf->Indices.reallocate(icount); core::map sind; // search index for fast operation typedef core::map::Node snode; // Main algorithm u32 highest = 0; u32 drawcalls = 0; for (;;) { if (tc[highest].drawn) { bool found = false; float hiscore = 0; for (u32 t = 0; t < tcount; t++) { if (!tc[t].drawn) { if (tc[t].score > hiscore) { highest = t; hiscore = tc[t].score; found = true; } } } if (!found) break; } // Output the best triangle u16 newind = buf->Vertices.size(); snode *s = sind.find(v[tc[highest].ind[0]]); if (!s) { buf->Vertices.push_back(v[tc[highest].ind[0]]); buf->Indices.push_back(newind); sind.insert(v[tc[highest].ind[0]], newind); newind++; } else { buf->Indices.push_back(s->getValue()); } s = sind.find(v[tc[highest].ind[1]]); if (!s) { buf->Vertices.push_back(v[tc[highest].ind[1]]); buf->Indices.push_back(newind); sind.insert(v[tc[highest].ind[1]], newind); newind++; } else { buf->Indices.push_back(s->getValue()); } s = sind.find(v[tc[highest].ind[2]]); if (!s) { buf->Vertices.push_back(v[tc[highest].ind[2]]); buf->Indices.push_back(newind); sind.insert(v[tc[highest].ind[2]], newind); } else { buf->Indices.push_back(s->getValue()); } vc[tc[highest].ind[0]].NumActiveTris--; vc[tc[highest].ind[1]].NumActiveTris--; vc[tc[highest].ind[2]].NumActiveTris--; tc[highest].drawn = true; for (u16 j = 0; j < 3; j++) { vcache *vert = &vc[tc[highest].ind[j]]; for (u16 t = 0; t < vert->tris.size(); t++) { if (highest == vert->tris[t]) { vert->tris.erase(t); break; } } } lru.add(tc[highest].ind[0]); lru.add(tc[highest].ind[1]); highest = lru.add(tc[highest].ind[2]); drawcalls++; } buf->setBoundingBox(mb->getBoundingBox()); newmesh->addMeshBuffer(buf); buf->drop(); } break; case video::EVT_TANGENTS: { video::S3DVertexTangents *v = (video::S3DVertexTangents *) mb->getVertices(); SMeshBufferTangents *buf = new SMeshBufferTangents(); buf->Material = mb->getMaterial(); buf->Vertices.reallocate(vcount); buf->Indices.reallocate(icount); core::map sind; // search index for fast operation typedef core::map::Node snode; // Main algorithm u32 highest = 0; u32 drawcalls = 0; for (;;) { if (tc[highest].drawn) { bool found = false; float hiscore = 0; for (u32 t = 0; t < tcount; t++) { if (!tc[t].drawn) { if (tc[t].score > hiscore) { highest = t; hiscore = tc[t].score; found = true; } } } if (!found) break; } // Output the best triangle u16 newind = buf->Vertices.size(); snode *s = sind.find(v[tc[highest].ind[0]]); if (!s) { buf->Vertices.push_back(v[tc[highest].ind[0]]); buf->Indices.push_back(newind); sind.insert(v[tc[highest].ind[0]], newind); newind++; } else { buf->Indices.push_back(s->getValue()); } s = sind.find(v[tc[highest].ind[1]]); if (!s) { buf->Vertices.push_back(v[tc[highest].ind[1]]); buf->Indices.push_back(newind); sind.insert(v[tc[highest].ind[1]], newind); newind++; } else { buf->Indices.push_back(s->getValue()); } s = sind.find(v[tc[highest].ind[2]]); if (!s) { buf->Vertices.push_back(v[tc[highest].ind[2]]); buf->Indices.push_back(newind); sind.insert(v[tc[highest].ind[2]], newind); } else { buf->Indices.push_back(s->getValue()); } vc[tc[highest].ind[0]].NumActiveTris--; vc[tc[highest].ind[1]].NumActiveTris--; vc[tc[highest].ind[2]].NumActiveTris--; tc[highest].drawn = true; for (u16 j = 0; j < 3; j++) { vcache *vert = &vc[tc[highest].ind[j]]; for (u16 t = 0; t < vert->tris.size(); t++) { if (highest == vert->tris[t]) { vert->tris.erase(t); break; } } } lru.add(tc[highest].ind[0]); lru.add(tc[highest].ind[1]); highest = lru.add(tc[highest].ind[2]); drawcalls++; } buf->setBoundingBox(mb->getBoundingBox()); newmesh->addMeshBuffer(buf); buf->drop(); } break; } delete [] vc; delete [] tc; } // for each meshbuffer return newmesh; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CMeshCache.h0000644000000000000000000001117312574354552017234 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_MESH_CACHE_H_INCLUDED__ #define __C_MESH_CACHE_H_INCLUDED__ #include "IMeshCache.h" #include "irrArray.h" namespace irr { namespace scene { class CMeshCache : public IMeshCache { public: virtual ~CMeshCache(); //! Adds a mesh to the internal list of loaded meshes. /** Usually, ISceneManager::getMesh() is called to load a mesh from file. That method searches the list of loaded meshes if a mesh has already been loaded and returns a pointer to if it is in that list and already in memory. Otherwise it loads the mesh. With IMeshCache::addMesh(), it is possible to pretend that a mesh already has been loaded. This method can be used for example by mesh loaders who need to load more than one mesh with one call. They can add additional meshes with this method to the scene manager. The COLLADA loader for example uses this method. \param filename: Filename of the mesh. When called ISceneManager::getMesh() with this parameter, the method will return the mesh parameter given with this method. \param mesh: Pointer to a mesh which will now be referenced by this name. */ virtual void addMesh(const io::path& filename, IAnimatedMesh* mesh); //! Removes a mesh from the cache. /** After loading a mesh with getMesh(), the mesh can be removed from the cache using this method, freeing a lot of memory. */ virtual void removeMesh(const IMesh* const mesh); //! Returns amount of loaded meshes in the cache. /** You can load new meshes into the cache using getMesh() and addMesh(). If you ever need to access the internal mesh cache, you can do this using removeMesh(), getMeshNumber(), getMeshByIndex() and getMeshFilename() */ virtual u32 getMeshCount() const; //! Returns current index number of the mesh, and -1 if it is not in the cache. virtual s32 getMeshIndex(const IMesh* const mesh) const; //! Returns a mesh based on its index number. /** \param index: Index of the mesh, number between 0 and getMeshCount()-1. Note that this number is only valid until a new mesh is loaded or removed * \return Returns pointer to the mesh or 0 if there is none with this number. */ virtual IAnimatedMesh* getMeshByIndex(u32 index); //! Returns a mesh based on its name. /** \param name Name of the mesh. Usually a filename. \return Pointer to the mesh or 0 if there is none with this number. */ virtual IAnimatedMesh* getMeshByName(const io::path& name); //! Get the name of a loaded mesh, based on its index. /** \param index: Index of the mesh, number between 0 and getMeshCount()-1. \return The name if mesh was found and has a name, else the path is empty. */ virtual const io::SNamedPath& getMeshName(u32 index) const; //! Get the name of a loaded mesh, if there is any. /** \param mesh Pointer to mesh to query. \return The name if mesh was found and has a name, else the path is empty. */ virtual const io::SNamedPath& getMeshName(const IMesh* const mesh) const; //! Renames a loaded mesh. /** Note that renaming meshes might change the ordering of the meshes, and so the index of the meshes as returned by getMeshIndex() or taken by some methods will change. \param index The index of the mesh in the cache. \param name New name for the mesh. \return True if mesh was renamed. */ virtual bool renameMesh(u32 index, const io::path& name); //! Renames a loaded mesh. /** Note that renaming meshes might change the ordering of the meshes, and so the index of the meshes as returned by getMeshIndex() or taken by some methods will change. \param mesh Mesh to be renamed. \param name New name for the mesh. \return True if mesh was renamed. */ virtual bool renameMesh(const IMesh* const mesh, const io::path& name); //! returns if a mesh already was loaded virtual bool isMeshLoaded(const io::path& name); //! Clears the whole mesh cache, removing all meshes. virtual void clear(); //! Clears all meshes that are held in the mesh cache but not used anywhere else. virtual void clearUnusedMeshes(); protected: struct MeshEntry { MeshEntry ( const io::path& name ) : NamedPath ( name ) { } io::SNamedPath NamedPath; IAnimatedMesh* Mesh; bool operator < (const MeshEntry& other) const { return (NamedPath < other.NamedPath); } }; //! loaded meshes core::array Meshes; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CMeshCache.cpp0000644000000000000000000000672512574354552017576 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CMeshCache.h" #include "IAnimatedMesh.h" #include "IMesh.h" namespace irr { namespace scene { static const io::SNamedPath emptyNamedPath; CMeshCache::~CMeshCache() { clear(); } //! adds a mesh to the list void CMeshCache::addMesh(const io::path& filename, IAnimatedMesh* mesh) { mesh->grab(); MeshEntry e ( filename ); e.Mesh = mesh; Meshes.push_back(e); } //! Removes a mesh from the cache. void CMeshCache::removeMesh(const IMesh* const mesh) { if ( !mesh ) return; for (u32 i=0; igetMesh(0) == mesh)) { Meshes[i].Mesh->drop(); Meshes.erase(i); return; } } } //! Returns amount of loaded meshes u32 CMeshCache::getMeshCount() const { return Meshes.size(); } //! Returns current number of the mesh s32 CMeshCache::getMeshIndex(const IMesh* const mesh) const { for (u32 i=0; igetMesh(0) == mesh)) return (s32)i; } return -1; } //! Returns a mesh based on its index number IAnimatedMesh* CMeshCache::getMeshByIndex(u32 number) { if (number >= Meshes.size()) return 0; return Meshes[number].Mesh; } //! Returns a mesh based on its name. IAnimatedMesh* CMeshCache::getMeshByName(const io::path& name) { MeshEntry e ( name ); s32 id = Meshes.binary_search(e); return (id != -1) ? Meshes[id].Mesh : 0; } //! Get the name of a loaded mesh, based on its index. const io::SNamedPath& CMeshCache::getMeshName(u32 index) const { if (index >= Meshes.size()) return emptyNamedPath; return Meshes[index].NamedPath; } //! Get the name of a loaded mesh, if there is any. const io::SNamedPath& CMeshCache::getMeshName(const IMesh* const mesh) const { if (!mesh) return emptyNamedPath; for (u32 i=0; igetMesh(0) == mesh)) return Meshes[i].NamedPath; } return emptyNamedPath; } //! Renames a loaded mesh. bool CMeshCache::renameMesh(u32 index, const io::path& name) { if (index >= Meshes.size()) return false; Meshes[index].NamedPath.setPath(name); Meshes.sort(); return true; } //! Renames a loaded mesh. bool CMeshCache::renameMesh(const IMesh* const mesh, const io::path& name) { for (u32 i=0; igetMesh(0) == mesh)) { Meshes[i].NamedPath.setPath(name); Meshes.sort(); return true; } } return false; } //! returns if a mesh already was loaded bool CMeshCache::isMeshLoaded(const io::path& name) { return getMeshByName(name) != 0; } //! Clears the whole mesh cache, removing all meshes. void CMeshCache::clear() { for (u32 i=0; idrop(); Meshes.clear(); } //! Clears all meshes that are held in the mesh cache but not used anywhere else. void CMeshCache::clearUnusedMeshes() { for (u32 i=0; igetReferenceCount() == 1) { Meshes[i].Mesh->drop(); Meshes.erase(i); --i; } } } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CMemoryFile.h0000644000000000000000000000254212574354552017464 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_MEMORY_READ_FILE_H_INCLUDED__ #define __C_MEMORY_READ_FILE_H_INCLUDED__ #include "IReadFile.h" #include "IWriteFile.h" #include "irrString.h" namespace irr { namespace io { /*! Class for reading and writing from memory. */ class CMemoryFile : public IReadFile, public IWriteFile { public: //! Constructor CMemoryFile(void* memory, long len, const io::path& fileName, bool deleteMemoryWhenDropped); //! Destructor virtual ~CMemoryFile(); //! returns how much was read virtual s32 read(void* buffer, u32 sizeToRead); //! returns how much was written virtual s32 write(const void* buffer, u32 sizeToWrite); //! changes position in file, returns true if successful virtual bool seek(long finalPos, bool relativeMovement = false); //! returns size of file virtual long getSize() const; //! returns where in the file we are. virtual long getPos() const; //! returns name of file virtual const io::path& getFileName() const; private: void *Buffer; long Len; long Pos; io::path Filename; bool deleteMemoryWhenDropped; }; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CMemoryFile.cpp0000644000000000000000000000433212574354552020016 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CMemoryFile.h" #include "irrString.h" namespace irr { namespace io { CMemoryFile::CMemoryFile(void* memory, long len, const io::path& fileName, bool d) : Buffer(memory), Len(len), Pos(0), Filename(fileName), deleteMemoryWhenDropped(d) { #ifdef _DEBUG setDebugName("CMemoryFile"); #endif } CMemoryFile::~CMemoryFile() { if (deleteMemoryWhenDropped) delete [] (c8*)Buffer; } //! returns how much was read s32 CMemoryFile::read(void* buffer, u32 sizeToRead) { s32 amount = static_cast(sizeToRead); if (Pos + amount > Len) amount -= Pos + amount - Len; if (amount <= 0) return 0; c8* p = (c8*)Buffer; memcpy(buffer, p + Pos, amount); Pos += amount; return amount; } //! returns how much was written s32 CMemoryFile::write(const void* buffer, u32 sizeToWrite) { s32 amount = static_cast(sizeToWrite); if (Pos + amount > Len) amount -= Pos + amount - Len; if (amount <= 0) return 0; c8* p = (c8*)Buffer; memcpy(p + Pos, buffer, amount); Pos += amount; return amount; } //! changes position in file, returns true if successful //! if relativeMovement==true, the pos is changed relative to current pos, //! otherwise from begin of file bool CMemoryFile::seek(long finalPos, bool relativeMovement) { if (relativeMovement) { if (Pos + finalPos > Len) return false; Pos += finalPos; } else { if (finalPos > Len) return false; Pos = finalPos; } return true; } //! returns size of file long CMemoryFile::getSize() const { return Len; } //! returns where in the file we are. long CMemoryFile::getPos() const { return Pos; } //! returns name of file const io::path& CMemoryFile::getFileName() const { return Filename; } IReadFile* createMemoryReadFile(void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped) { CMemoryFile* file = new CMemoryFile(memory, size, fileName, deleteMemoryWhenDropped); return file; } } // end namespace io } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CMD3MeshFileLoader.h0000644000000000000000000000245212574354552020543 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_MD3_MESH_FILE_LOADER_H_INCLUDED__ #define __C_MD3_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "IFileSystem.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "IQ3Shader.h" namespace irr { namespace scene { //! Meshloader capable of loading md3 files. class CMD3MeshFileLoader : public IMeshLoader { public: //! Constructor CMD3MeshFileLoader( scene::ISceneManager* smgr ); //! destructor virtual ~CMD3MeshFileLoader(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: scene::ISceneManager* SceneManager; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CMD3MeshFileLoader.cpp0000644000000000000000000000226312574354552021076 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_MD3_LOADER_ #include "CMD3MeshFileLoader.h" #include "CAnimatedMeshMD3.h" #include "irrString.h" namespace irr { namespace scene { //! Constructor CMD3MeshFileLoader::CMD3MeshFileLoader( scene::ISceneManager* smgr) : SceneManager(smgr) { } //! destructor CMD3MeshFileLoader::~CMD3MeshFileLoader() { } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool CMD3MeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "md3" ); } IAnimatedMesh* CMD3MeshFileLoader::createMesh(io::IReadFile* file) { CAnimatedMeshMD3 * mesh = new CAnimatedMeshMD3(); if ( mesh->loadModelFile ( 0, file, SceneManager->getFileSystem(), SceneManager->getVideoDriver() ) ) return mesh; mesh->drop (); return 0; } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_MD3_LOADER_ irrlicht-1.8.3/source/Irrlicht/CMD2MeshFileLoader.h0000644000000000000000000000234012574354552020536 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_MD2_MESH_FILE_LOADER_H_INCLUDED__ #define __C_MD2_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" namespace irr { namespace scene { class CAnimatedMeshMD2; //! Meshloader capable of loading MD2 files class CMD2MeshFileLoader : public IMeshLoader { public: //! Constructor CMD2MeshFileLoader(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: //! Loads the file data into the mesh bool loadFile(io::IReadFile* file, CAnimatedMeshMD2* mesh); }; } // end namespace scene } // end namespace irr #endif // __C_MD2_MESH_LOADER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CMD2MeshFileLoader.cpp0000644000000000000000000002644112574354552021101 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_MD2_LOADER_ #include "CMD2MeshFileLoader.h" #include "CAnimatedMeshMD2.h" #include "os.h" namespace irr { namespace scene { // structs needed to load the md2-format const s32 MD2_MAGIC_NUMBER = 844121161; const s32 MD2_VERSION = 8; const s32 MD2_MAX_VERTS = 2048; // byte-align structures #include "irrpack.h" struct SMD2Header { s32 magic; // four character code "IDP2" s32 version; // must be 8 s32 skinWidth; // width of the texture s32 skinHeight; // height of the texture s32 frameSize; // size in bytes of an animation frame s32 numSkins; // number of textures s32 numVertices; // total number of vertices s32 numTexcoords; // number of vertices with texture coords s32 numTriangles; // number of triangles s32 numGlCommands; // number of opengl commands (triangle strip or triangle fan) s32 numFrames; // animation keyframe count s32 offsetSkins; // offset in bytes to 64 character skin names s32 offsetTexcoords; // offset in bytes to texture coordinate list s32 offsetTriangles; // offset in bytes to triangle list s32 offsetFrames; // offset in bytes to frame list s32 offsetGlCommands;// offset in bytes to opengl commands s32 offsetEnd; // offset in bytes to end of file } PACK_STRUCT; struct SMD2Vertex { u8 vertex[3]; // [0] = X, [1] = Z, [2] = Y u8 lightNormalIndex; // index in the normal table } PACK_STRUCT; struct SMD2Frame { f32 scale[3]; // first scale the vertex position f32 translate[3]; // then translate the position c8 name[16]; // the name of the animation that this key belongs to SMD2Vertex vertices[1]; // vertex 1 of SMD2Header.numVertices } PACK_STRUCT; struct SMD2Triangle { u16 vertexIndices[3]; u16 textureIndices[3]; } PACK_STRUCT; struct SMD2TextureCoordinate { s16 s; s16 t; } PACK_STRUCT; struct SMD2GLCommand { f32 s, t; s32 vertexIndex; } PACK_STRUCT; // Default alignment #include "irrunpack.h" //! Constructor CMD2MeshFileLoader::CMD2MeshFileLoader() { #ifdef _DEBUG setDebugName("CMD2MeshFileLoader"); #endif } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool CMD2MeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "md2" ); } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* CMD2MeshFileLoader::createMesh(io::IReadFile* file) { IAnimatedMesh* msh = new CAnimatedMeshMD2(); if (msh) { if (loadFile(file, (CAnimatedMeshMD2*)msh) ) return msh; msh->drop(); } return 0; } //! loads an md2 file bool CMD2MeshFileLoader::loadFile(io::IReadFile* file, CAnimatedMeshMD2* mesh) { if (!file) return false; SMD2Header header; file->read(&header, sizeof(SMD2Header)); #ifdef __BIG_ENDIAN__ header.magic = os::Byteswap::byteswap(header.magic); header.version = os::Byteswap::byteswap(header.version); header.skinWidth = os::Byteswap::byteswap(header.skinWidth); header.skinHeight = os::Byteswap::byteswap(header.skinHeight); header.frameSize = os::Byteswap::byteswap(header.frameSize); header.numSkins = os::Byteswap::byteswap(header.numSkins); header.numVertices = os::Byteswap::byteswap(header.numVertices); header.numTexcoords = os::Byteswap::byteswap(header.numTexcoords); header.numTriangles = os::Byteswap::byteswap(header.numTriangles); header.numGlCommands = os::Byteswap::byteswap(header.numGlCommands); header.numFrames = os::Byteswap::byteswap(header.numFrames); header.offsetSkins = os::Byteswap::byteswap(header.offsetSkins); header.offsetTexcoords = os::Byteswap::byteswap(header.offsetTexcoords); header.offsetTriangles = os::Byteswap::byteswap(header.offsetTriangles); header.offsetFrames = os::Byteswap::byteswap(header.offsetFrames); header.offsetGlCommands = os::Byteswap::byteswap(header.offsetGlCommands); header.offsetEnd = os::Byteswap::byteswap(header.offsetEnd); #endif if (header.magic != MD2_MAGIC_NUMBER || header.version != MD2_VERSION) { os::Printer::log("MD2 Loader: Wrong file header", file->getFileName(), ELL_WARNING); return false; } // // prepare mesh and allocate memory // mesh->FrameCount = header.numFrames; // create keyframes mesh->FrameTransforms.set_used(header.numFrames); // create vertex arrays for each keyframe if (mesh->FrameList) delete [] mesh->FrameList; mesh->FrameList = new core::array[header.numFrames]; // allocate space in vertex arrays s32 i; for (i=0; iFrameList[i].reallocate(header.numVertices); // allocate interpolation buffer vertices mesh->InterpolationBuffer->Vertices.set_used(header.numTriangles*3); // populate triangles mesh->InterpolationBuffer->Indices.reallocate(header.numTriangles*3); const s32 count = header.numTriangles*3; for (i=0; iInterpolationBuffer->Indices.push_back(i); mesh->InterpolationBuffer->Indices.push_back(i+1); mesh->InterpolationBuffer->Indices.push_back(i+2); } // // read texture coordinates // file->seek(header.offsetTexcoords); SMD2TextureCoordinate* textureCoords = new SMD2TextureCoordinate[header.numTexcoords]; if (!file->read(textureCoords, sizeof(SMD2TextureCoordinate)*header.numTexcoords)) { delete[] textureCoords; os::Printer::log("MD2 Loader: Error reading TextureCoords.", file->getFileName(), ELL_ERROR); return false; } #ifdef __BIG_ENDIAN__ for (i=0; iseek(header.offsetTriangles); SMD2Triangle *triangles = new SMD2Triangle[header.numTriangles]; if (!file->read(triangles, header.numTriangles *sizeof(SMD2Triangle))) { delete[] triangles; delete[] textureCoords; os::Printer::log("MD2 Loader: Error reading triangles.", file->getFileName(), ELL_ERROR); return false; } #ifdef __BIG_ENDIAN__ for (i=0; iseek(header.offsetFrames); for (i = 0; iread(frame, header.frameSize); #ifdef __BIG_ENDIAN__ frame->scale[0] = os::Byteswap::byteswap(frame->scale[0]); frame->scale[1] = os::Byteswap::byteswap(frame->scale[1]); frame->scale[2] = os::Byteswap::byteswap(frame->scale[2]); frame->translate[0] = os::Byteswap::byteswap(frame->translate[0]); frame->translate[1] = os::Byteswap::byteswap(frame->translate[1]); frame->translate[2] = os::Byteswap::byteswap(frame->translate[2]); #endif // // store frame data // CAnimatedMeshMD2::SAnimationData adata; adata.begin = i; adata.end = i; adata.fps = 7; // Add new named animation if necessary if (frame->name[0]) { // get animation name for (s32 s = 0; s < 16 && frame->name[s]!=0 && (frame->name[s] < '0' || frame->name[s] > '9'); ++s) { adata.name += frame->name[s]; } // Does this keyframe have the same animation name as the current animation? if (!mesh->AnimationData.empty() && mesh->AnimationData[mesh->AnimationData.size()-1].name == adata.name) { // Increase the length of the animation ++mesh->AnimationData[mesh->AnimationData.size() - 1].end; } else { // Add the new animation mesh->AnimationData.push_back(adata); } } // save keyframe scale and translation mesh->FrameTransforms[i].scale.X = frame->scale[0]; mesh->FrameTransforms[i].scale.Z = frame->scale[1]; mesh->FrameTransforms[i].scale.Y = frame->scale[2]; mesh->FrameTransforms[i].translate.X = frame->translate[0]; mesh->FrameTransforms[i].translate.Z = frame->translate[1]; mesh->FrameTransforms[i].translate.Y = frame->translate[2]; // add vertices for (s32 j=0; jvertices[num].vertex[0]; v.Pos.Z = frame->vertices[num].vertex[1]; v.Pos.Y = frame->vertices[num].vertex[2]; v.NormalIdx = frame->vertices[num].lightNormalIndex; mesh->FrameList[i].push_back(v); } } // calculate bounding boxes if (header.numVertices) { core::aabbox3d box; core::vector3df pos; pos.X = f32(mesh->FrameList[i] [0].Pos.X) * mesh->FrameTransforms[i].scale.X + mesh->FrameTransforms[i].translate.X; pos.Y = f32(mesh->FrameList[i] [0].Pos.Y) * mesh->FrameTransforms[i].scale.Y + mesh->FrameTransforms[i].translate.Y; pos.Z = f32(mesh->FrameList[i] [0].Pos.Z) * mesh->FrameTransforms[i].scale.Z + mesh->FrameTransforms[i].translate.Z; box.reset(pos); for (s32 j=1; jFrameList[i] [j].Pos.X) * mesh->FrameTransforms[i].scale.X + mesh->FrameTransforms[i].translate.X; pos.Y = f32(mesh->FrameList[i] [j].Pos.Y) * mesh->FrameTransforms[i].scale.Y + mesh->FrameTransforms[i].translate.Y; pos.Z = f32(mesh->FrameList[i] [j].Pos.Z) * mesh->FrameTransforms[i].scale.Z + mesh->FrameTransforms[i].translate.Z; box.addInternalPoint(pos); } mesh->BoxList.push_back(box); } } // populate interpolation buffer with texture coordinates and colors if (header.numFrames) { f32 dmaxs = 1.0f/(header.skinWidth); f32 dmaxt = 1.0f/(header.skinHeight); for (s32 t=0; tInterpolationBuffer->Vertices[t*3 + n].TCoords.X = (textureCoords[triangles[t].textureIndices[n]].s + 0.5f) * dmaxs; mesh->InterpolationBuffer->Vertices[t*3 + n].TCoords.Y = (textureCoords[triangles[t].textureIndices[n]].t + 0.5f) * dmaxt; mesh->InterpolationBuffer->Vertices[t*3 + n].Color = video::SColor(255,255,255,255); } } } // clean up delete [] triangles; delete [] textureCoords; // init buffer with start frame. mesh->getMesh(0); return true; } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_MD2_LOADER_ irrlicht-1.8.3/source/Irrlicht/CLWOMeshFileLoader.h0000644000000000000000000000460212574354552020620 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_LWO_MESH_FILE_LOADER_H_INCLUDED__ #define __C_LWO_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "SMeshBuffer.h" #include "irrString.h" namespace irr { namespace io { class IReadFile; class IFileSystem; } // end namespace io namespace scene { struct SMesh; class ISceneManager; //! Meshloader capable of loading Lightwave 3D meshes. class CLWOMeshFileLoader : public IMeshLoader { public: //! Constructor CLWOMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs); //! destructor virtual ~CLWOMeshFileLoader(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IUnknown::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: struct tLWOMaterial; bool readFileHeader(); bool readChunks(); void readObj1(u32 size); void readTagMapping(u32 size); void readVertexMapping(u32 size); void readDiscVertexMapping (u32 size); void readObj2(u32 size); void readMat(u32 size); u32 readString(core::stringc& name, u32 size=0); u32 readVec(core::vector3df& vec); u32 readVX(u32& num); u32 readColor(video::SColor& color); video::ITexture* loadTexture(const core::stringc& file); scene::ISceneManager* SceneManager; io::IFileSystem* FileSystem; io::IReadFile* File; SMesh* Mesh; core::array Points; core::array > Indices; core::array UvName; core::array > UvIndex; core::array DUvName; core::array > VmPolyPointsIndex; core::array > VmCoordsIndex; core::array MaterialMapping; core::array > TCoords; core::array Materials; core::array Images; u8 FormatVersion; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CLWOMeshFileLoader.cpp0000644000000000000000000015546112574354552021165 0ustar rootroot// Copyright (C) 2007-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CLWOMeshFileLoader.h" #include "os.h" #include "SAnimatedMesh.h" #include "SMesh.h" #include "IReadFile.h" #include "ISceneManager.h" #include "IFileSystem.h" #include "IVideoDriver.h" #include "IMeshManipulator.h" namespace irr { namespace scene { #ifdef _DEBUG #define LWO_READER_DEBUG #endif #define charsToUIntD(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d) inline unsigned int charsToUInt(const char *str) { return (str[0] << 24) | (str[1] << 16) | (str[2] << 8) | str[3]; } struct tLWOTextureInfo { tLWOTextureInfo() : UVTag(0), DUVTag(0), Flags(0), WidthWrap(2), HeightWrap(2), OpacType(0), Color(0xffffffff), Value(0.0f), AntiAliasing(1.0f), Opacity(1.0f), Axis(255), Projection(0), Active(false) {} core::stringc Type; core::stringc Map; core::stringc AlphaMap; core::stringc UVname; u16 UVTag; u16 DUVTag; u16 Flags; u16 WidthWrap; u16 HeightWrap; u16 OpacType; u16 IParam[3]; core::vector3df Size; core::vector3df Center; core::vector3df Falloff; core::vector3df Velocity; video::SColor Color; f32 Value; f32 AntiAliasing; f32 Opacity; f32 FParam[3]; u8 Axis; u8 Projection; bool Active; }; struct CLWOMeshFileLoader::tLWOMaterial { tLWOMaterial() : Meshbuffer(0), TagType(0), Flags(0), ReflMode(3), TranspMode(3), Glow(0), AlphaMode(2), Luminance(0.0f), Diffuse(1.0f), Specular(0.0f), Reflection(0.0f), Transparency(0.0f), Translucency(0.0f), Sharpness(0.0f), ReflSeamAngle(0.0f), ReflBlur(0.0f), RefrIndex(1.0f), TranspBlur(0.0f), SmoothingAngle(0.0f), EdgeTransparency(0.0f), HighlightColor(0.0f), ColorFilter(0.0f), AdditiveTransparency(0.0f), GlowIntensity(0.0f), GlowSize(0.0f), AlphaValue(0.0f), VertexColorIntensity(0.0f), VertexColor() {} core::stringc Name; scene::SMeshBuffer *Meshbuffer; core::stringc ReflMap; u16 TagType; u16 Flags; u16 ReflMode; u16 TranspMode; u16 Glow; u16 AlphaMode; f32 Luminance; f32 Diffuse; f32 Specular; f32 Reflection; f32 Transparency; f32 Translucency; f32 Sharpness; f32 ReflSeamAngle; f32 ReflBlur; f32 RefrIndex; f32 TranspBlur; f32 SmoothingAngle; f32 EdgeTransparency; f32 HighlightColor; f32 ColorFilter; f32 AdditiveTransparency; f32 GlowIntensity; f32 GlowSize; f32 AlphaValue; f32 VertexColorIntensity; video::SColorf VertexColor; u32 Envelope[23]; tLWOTextureInfo Texture[7]; }; struct tLWOLayerInfo { u16 Number; u16 Parent; u16 Flags; bool Active; core::stringc Name; core::vector3df Pivot; }; //! Constructor CLWOMeshFileLoader::CLWOMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) : SceneManager(smgr), FileSystem(fs), File(0), Mesh(0) { #ifdef _DEBUG setDebugName("CLWOMeshFileLoader"); #endif } //! destructor CLWOMeshFileLoader::~CLWOMeshFileLoader() { if (Mesh) Mesh->drop(); } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool CLWOMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension(filename, "lwo"); } //! creates/loads an animated mesh from the file. IAnimatedMesh* CLWOMeshFileLoader::createMesh(io::IReadFile* file) { File = file; if (Mesh) Mesh->drop(); Mesh = new SMesh(); if (!readFileHeader()) return 0; if (!readChunks()) return 0; #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: Creating geometry."); os::Printer::log("LWO loader: Assigning UV maps."); #endif u32 i; for (i=0; iTexture[j].UVname.size()) { for (uvTag=0; uvTagTexture[j].UVname == UvName[uvTag]) { Materials[i]->Texture[j].UVTag=uvTag; break; } } for (uvTag=0; uvTagTexture[j].UVname == DUvName[uvTag]) { Materials[i]->Texture[j].DUVTag=uvTag; break; } } } } } #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: Creating polys."); #endif // create actual geometry for lwo2 if (FormatVersion==2) { core::array vertexCount; vertexCount.reallocate(Materials.size()); for (i=0; iMeshbuffer->Vertices.reallocate(vertexCount[i]); Materials[i]->Meshbuffer->Indices.reallocate(vertexCount[i]); } } // create actual geometry for lwo2 for (u32 polyIndex=0; polyIndexMeshbuffer; const core::array& poly = Indices[polyIndex]; const u32 polySize=poly.size(); const u16 uvTag = Materials[tag]->Texture[0].UVTag; const u16 duvTag = Materials[tag]->Texture[0].DUVTag; video::S3DVertex vertex; vertex.Color=0xffffffff; const u32 vertCount=mb->Vertices.size(); for (u32 i=0; iVertices.push_back(vertex); } // triangulate as trifan if (polySize>2) { for (u32 i=1; iIndices.push_back(vertCount); mb->Indices.push_back(vertCount+i); mb->Indices.push_back(vertCount+i+1); } } } #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: Fixing meshbuffers."); #endif for (u32 i=0; iName); os::Printer::log("LWO loader: Vertex count", core::stringc(Materials[i]->Meshbuffer->Vertices.size())); #endif if (!Materials[i]->Meshbuffer->Vertices.size()) { Materials[i]->Meshbuffer->drop(); delete Materials[i]; continue; } for (u32 j=0; jMeshbuffer->Vertices.size(); ++j) Materials[i]->Meshbuffer->Vertices[j].Color=Materials[i]->Meshbuffer->Material.DiffuseColor; Materials[i]->Meshbuffer->recalculateBoundingBox(); // load textures video::SMaterial& irrMat=Materials[i]->Meshbuffer->Material; if (Materials[i]->Texture[0].Map != "") // diffuse irrMat.setTexture(0,loadTexture(Materials[i]->Texture[0].Map)); if (Materials[i]->Texture[3].Map != "") // reflection { #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading reflection texture."); #endif video::ITexture* reflTexture = loadTexture(Materials[i]->Texture[3].Map); if (reflTexture && irrMat.getTexture(0)) irrMat.setTexture(1, irrMat.getTexture(0)); irrMat.setTexture(0, reflTexture); irrMat.MaterialType=video::EMT_REFLECTION_2_LAYER; } if (Materials[i]->Texture[4].Map != "") // transparency { #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading transparency texture."); #endif video::ITexture* transTexture = loadTexture(Materials[i]->Texture[4].Map); if (transTexture && irrMat.getTexture(0)) irrMat.setTexture(1, irrMat.getTexture(0)); irrMat.setTexture(0, transTexture); irrMat.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR; } if (Materials[i]->Texture[6].Map != "") // bump { #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading bump texture."); #endif const u8 pos = irrMat.getTexture(0)?1:0; irrMat.setTexture(pos, loadTexture(Materials[i]->Texture[6].Map)); if (irrMat.getTexture(pos)) { // SceneManager->getVideoDriver()->makeNormalMapTexture(irrMat.getTexture(1)); // irrMat.MaterialType=video::EMT_NORMAL_MAP_SOLID; } } // cope with planar mapping texture coords if (Materials[i]->Texture[0].Projection != 5) { if (FormatVersion!=2) { if (Materials[i]->Texture[0].Flags&1) Materials[i]->Texture[0].Axis=0; else if (Materials[i]->Texture[0].Flags&2) Materials[i]->Texture[0].Axis=1; else if (Materials[i]->Texture[0].Flags&4) Materials[i]->Texture[0].Axis=2; } // if no axis given choose the dominant one else if (Materials[i]->Texture[0].Axis>2) { if (Materials[i]->Meshbuffer->getBoundingBox().getExtent().YMeshbuffer->getBoundingBox().getExtent().X) { if (Materials[i]->Meshbuffer->getBoundingBox().getExtent().YMeshbuffer->getBoundingBox().getExtent().Z) Materials[i]->Texture[0].Axis=1; else Materials[i]->Texture[0].Axis=2; } else { if (Materials[i]->Meshbuffer->getBoundingBox().getExtent().XMeshbuffer->getBoundingBox().getExtent().Z) Materials[i]->Texture[0].Axis=0; else Materials[i]->Texture[0].Axis=2; } } // get the resolution for this axis f32 resolutionS = core::reciprocal(Materials[i]->Texture[0].Size.Z); f32 resolutionT = core::reciprocal(Materials[i]->Texture[0].Size.Y); if (Materials[i]->Texture[0].Axis==1) { resolutionS = core::reciprocal(Materials[i]->Texture[0].Size.X); resolutionT = core::reciprocal(Materials[i]->Texture[0].Size.Z); } else if (Materials[i]->Texture[0].Axis==2) { resolutionS = core::reciprocal(Materials[i]->Texture[0].Size.X); resolutionT = core::reciprocal(Materials[i]->Texture[0].Size.Y); } // use the two-way planar mapping SceneManager->getMeshManipulator()->makePlanarTextureMapping(Materials[i]->Meshbuffer, resolutionS, resolutionT, Materials[i]->Texture[0].Axis, Materials[i]->Texture[0].Center); } // add bump maps if (Materials[i]->Meshbuffer->Material.MaterialType==video::EMT_NORMAL_MAP_SOLID) { SMesh* tmpmesh = new SMesh(); tmpmesh->addMeshBuffer(Materials[i]->Meshbuffer); SceneManager->getMeshManipulator()->createMeshWithTangents(tmpmesh, true, true); Mesh->addMeshBuffer(tmpmesh->getMeshBuffer(0)); tmpmesh->getMeshBuffer(0)->drop(); tmpmesh->drop(); } else { SceneManager->getMeshManipulator()->recalculateNormals(Materials[i]->Meshbuffer); Mesh->addMeshBuffer(Materials[i]->Meshbuffer); } Materials[i]->Meshbuffer->drop(); // clear the material array elements delete Materials[i]; } Mesh->recalculateBoundingBox(); SAnimatedMesh* am = new SAnimatedMesh(); am->Type = EAMT_3DS; am->addMesh(Mesh); am->recalculateBoundingBox(); Mesh->drop(); Mesh = 0; Points.clear(); Indices.clear(); MaterialMapping.clear(); TCoords.clear(); Materials.clear(); Images.clear(); VmPolyPointsIndex.clear(); VmCoordsIndex.clear(); UvIndex.clear(); UvName.clear(); return am; } bool CLWOMeshFileLoader::readChunks() { s32 lastPos; u32 size; unsigned int uiType; char type[5]; type[4]=0; tLWOLayerInfo layer; while(File->getPos()getSize()) { File->read(&type, 4); //Convert 4-char string to 4-byte integer //Makes it possible to do a switch statement uiType = charsToUInt(type); File->read(&size, 4); #ifndef __BIG_ENDIAN__ size=os::Byteswap::byteswap(size); #endif lastPos=File->getPos(); switch(uiType) { case charsToUIntD('L','A','Y','R'): { #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading layer."); #endif u16 tmp16; File->read(&tmp16, 2); // number File->read(&tmp16, 2); // flags size -= 4; #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif if (((FormatVersion==1)&&(tmp16!=1)) || ((FormatVersion==2)&&(tmp16&1))) layer.Active=false; else layer.Active=true; if (FormatVersion==2) size -= readVec(layer.Pivot); size -= readString(layer.Name); if (size) { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif layer.Parent = tmp16; } } break; case charsToUIntD('P','N','T','S'): { #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading points."); #endif core::vector3df vec; Points.clear(); const u32 tmpsize = size/12; Points.reallocate(tmpsize); for (u32 i=0; iName=""; mat->Meshbuffer=new scene::SMeshBuffer(); size -= readString(mat->Name); if (FormatVersion!=2) mat->TagType = 1; // format 2 has more types Materials.push_back(mat); } } break; case charsToUIntD('P','T','A','G'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading tag mapping."); #endif readTagMapping(size); break; case charsToUIntD('V','M','A','D'): // discontinuous vertex mapping, i.e. additional texcoords #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading Vertex mapping VMAD."); #endif readDiscVertexMapping(size); // case charsToUIntD('V','M','P','A'): // case charsToUIntD('E','N','V','L'): break; case charsToUIntD('C','L','I','P'): { #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading clips."); #endif u32 index; u16 subsize; File->read(&index, 4); #ifndef __BIG_ENDIAN__ index=os::Byteswap::byteswap(index); #endif size -= 4; while (size != 0) { File->read(&type, 4); File->read(&subsize, 2); #ifndef __BIG_ENDIAN__ subsize=os::Byteswap::byteswap(subsize); #endif size -= 6; if (strncmp(type, "STIL", 4)) { File->seek(subsize, true); size -= subsize; continue; } core::stringc path; size -= readString(path, subsize); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loaded clip", path.c_str()); #endif Images.push_back(path); } } break; case charsToUIntD('S','U','R','F'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading material."); #endif readMat(size); break; case charsToUIntD('B','B','O','X'): { #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading bbox."); #endif // not stored core::vector3df vec; for (u32 i=0; i<2; ++i) readVec(vec); size -= 24; } break; case charsToUIntD('D','E','S','C'): case charsToUIntD('T','E','X','T'): { core::stringc text; size -= readString(text, size); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader text", text); #endif } break; // not needed case charsToUIntD('I','C','O','N'): // not yet supported case charsToUIntD('P','C','H','S'): case charsToUIntD('C','R','V','S'): default: #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: skipping ", type); #endif //Go to next chunk File->seek(lastPos + size, false); break; } } return true; } void CLWOMeshFileLoader::readObj1(u32 size) { u32 pos; u16 numVerts, vertIndex; s16 material; video::S3DVertex vertex; vertex.Color=0xffffffff; while (size!=0) { File->read(&numVerts, 2); #ifndef __BIG_ENDIAN__ numVerts=os::Byteswap::byteswap(numVerts); #endif pos=File->getPos(); // skip forward to material number File->seek(2*numVerts, true); File->read(&material, 2); #ifndef __BIG_ENDIAN__ material=os::Byteswap::byteswap(material); #endif size -=2*numVerts+4; // detail meshes ? scene::SMeshBuffer *mb; if (material<0) mb=Materials[-material-1]->Meshbuffer; else mb=Materials[material-1]->Meshbuffer; // back to vertex list start File->seek(pos, false); const u16 vertCount=mb->Vertices.size(); for (u16 i=0; iread(&vertIndex, 2); #ifndef __BIG_ENDIAN__ vertIndex=os::Byteswap::byteswap(vertIndex); #endif vertex.Pos=Points[vertIndex]; mb->Vertices.push_back(vertex); } for (u16 i=1; iIndices.push_back(vertCount); mb->Indices.push_back(vertCount+i); mb->Indices.push_back(vertCount+i+1); } // skip material number and detail surface count // detail surface can be read just as a normal one now if (material<0) File->read(&material, 2); File->read(&material, 2); } } void CLWOMeshFileLoader::readVertexMapping(u32 size) { char type[5]={0}; u16 dimension; core::stringc name; File->read(&type, 4); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: Vertex map type", type); #endif File->read(&dimension,2); #ifndef __BIG_ENDIAN__ dimension=os::Byteswap::byteswap(dimension); #endif size -= 6; size -= readString(name); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: Vertex map", name.c_str()); #endif if (strncmp(type, "TXUV", 4)) // also support RGB, RGBA, WGHT, ... { File->seek(size, true); return; } UvName.push_back(name); TCoords.push_back(core::array()); core::array& UvCoords=TCoords.getLast(); UvCoords.reallocate(Points.size()); UvIndex.push_back(core::array()); core::array& UvPointsArray=UvIndex.getLast(); UvPointsArray.reallocate(Points.size()); u32 index; core::vector2df tcoord; while (size) { size -= readVX(index); File->read(&tcoord.X, 4); File->read(&tcoord.Y, 4); size -= 8; #ifndef __BIG_ENDIAN__ index=os::Byteswap::byteswap(index); tcoord.X=os::Byteswap::byteswap(tcoord.X); tcoord.Y=os::Byteswap::byteswap(tcoord.Y); #endif UvCoords.push_back(tcoord); UvPointsArray.push_back(index); } #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: UvCoords", core::stringc(UvCoords.size())); #endif } void CLWOMeshFileLoader::readDiscVertexMapping(u32 size) { char type[5]={0}; u16 dimension; core::stringc name; File->read(&type, 4); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: Discontinuous vertex map type", type); #endif File->read(&dimension,2); #ifndef __BIG_ENDIAN__ dimension=os::Byteswap::byteswap(dimension); #endif size -= 6; size -= readString(name); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: Discontinuous vertex map", name.c_str()); #endif if (strncmp(type, "TXUV", 4)) { File->seek(size, true); return; } DUvName.push_back(name); VmPolyPointsIndex.push_back(core::array()); core::array& VmPolyPoints=VmPolyPointsIndex.getLast(); VmCoordsIndex.push_back(core::array()); core::array& VmCoords=VmCoordsIndex.getLast(); u32 vmpolys; u32 vmpoints; core::vector2df vmcoords; while (size) { size-=readVX(vmpoints); size-=readVX(vmpolys); File->read(&vmcoords.X, 4); File->read(&vmcoords.Y, 4); size -= 8; #ifndef __BIG_ENDIAN__ vmpoints=os::Byteswap::byteswap(vmpoints); vmpolys=os::Byteswap::byteswap(vmpolys); vmcoords.X=os::Byteswap::byteswap(vmcoords.X); vmcoords.Y=os::Byteswap::byteswap(vmcoords.Y); #endif VmCoords.push_back(vmcoords); VmPolyPoints.push_back(vmpolys); VmPolyPoints.push_back(vmpoints); } #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: VmCoords", core::stringc(VmCoords.size())); #endif } void CLWOMeshFileLoader::readTagMapping(u32 size) { char type[5]; type[4]=0; File->read(&type, 4); size -= 4; if ((strncmp(type, "SURF", 4))||(Indices.size()==0)) { File->seek(size, true); return; } while (size!=0) { u16 tag; u32 polyIndex; size-=readVX(polyIndex); File->read(&tag, 2); #ifndef __BIG_ENDIAN__ tag=os::Byteswap::byteswap(tag); #endif size -= 2; MaterialMapping[polyIndex]=tag; Materials[tag]->TagType=1; } } void CLWOMeshFileLoader::readObj2(u32 size) { char type[5]; type[4]=0; File->read(&type, 4); size -= 4; Indices.clear(); if (strncmp(type, "FACE", 4)) // also possible are splines, subdivision patches, metaballs, and bones { File->seek(size, true); return; } u16 numVerts=0; while (size!=0) { File->read(&numVerts, 2); #ifndef __BIG_ENDIAN__ numVerts=os::Byteswap::byteswap(numVerts); #endif // mask out flags numVerts &= 0x03FF; size -= 2; Indices.push_back(core::array()); u32 vertIndex; core::array& polyArray = Indices.getLast(); polyArray.reallocate(numVerts); for (u16 i=0; iTagType==1) && (Materials[i]->Name==name)) { mat=Materials[i]; break; } } if (!mat) { File->seek(size, true); return; } if (FormatVersion==2) size -= readString(name); video::SMaterial& irrMat=mat->Meshbuffer->Material; u8 currTexture=0; while (size!=0) { char type[5]; type[4]=0; u32 uiType; u32 tmp32; u16 subsize, tmp16; f32 tmpf32; File->read(&type, 4); //Convert 4-char string to 4-byte integer //Makes it possible to do a switch statement uiType = charsToUInt(type); File->read(&subsize, 2); #ifndef __BIG_ENDIAN__ subsize=os::Byteswap::byteswap(subsize); #endif size -= 6; switch (uiType) { case charsToUIntD('C','O','L','R'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading Ambient color."); #endif { s32 colSize = readColor(irrMat.DiffuseColor); irrMat.AmbientColor=irrMat.DiffuseColor; size -= colSize; subsize -= colSize; if (FormatVersion==2) size -= readVX(mat->Envelope[0]); } break; case charsToUIntD('D','I','F','F'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading Diffuse color."); #endif { if (FormatVersion==2) { File->read(&mat->Diffuse, 4); #ifndef __BIG_ENDIAN__ mat->Diffuse=os::Byteswap::byteswap(mat->Diffuse); #endif size -= 4; subsize -= 4; size -= readVX(mat->Envelope[1]); } else { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif mat->Diffuse=tmp16/256.0f; size -= 2; subsize -= 2; } } break; case charsToUIntD('V','D','I','F'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading Diffuse color."); #endif { File->read(&mat->Diffuse, 4); #ifndef __BIG_ENDIAN__ mat->Diffuse=os::Byteswap::byteswap(mat->Diffuse); #endif size -= 4; } break; case charsToUIntD('L','U','M','I'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading luminance."); #endif { if (FormatVersion==2) { File->read(&mat->Luminance, 4); #ifndef __BIG_ENDIAN__ mat->Luminance=os::Byteswap::byteswap(mat->Luminance); #endif size -= 4; subsize -= 4; size -= readVX(mat->Envelope[2]); } else { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif mat->Luminance=tmp16/256.0f; size -= 2; subsize -= 2; } } break; case charsToUIntD('V','L','U','M'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading luminance."); #endif { File->read(&mat->Luminance, 4); #ifndef __BIG_ENDIAN__ mat->Luminance=os::Byteswap::byteswap(mat->Luminance); #endif size -= 4; } break; case charsToUIntD('S','P','E','C'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading specular."); #endif { if (FormatVersion==2) { File->read(&mat->Specular, 4); #ifndef __BIG_ENDIAN__ mat->Specular=os::Byteswap::byteswap(mat->Specular); #endif size -= 4; subsize -= 4; size -= readVX(mat->Envelope[3]); } else { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif mat->Specular=tmp16/256.0f;; size -= 2; subsize -= 2; } } break; case charsToUIntD('V','S','P','C'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading specular."); #endif { File->read(&mat->Specular, 4); #ifndef __BIG_ENDIAN__ mat->Specular=os::Byteswap::byteswap(mat->Specular); #endif size -= 4; } break; case charsToUIntD('R','E','F','L'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading reflection."); #endif { if (FormatVersion==2) { File->read(&mat->Reflection, 4); #ifndef __BIG_ENDIAN__ mat->Reflection=os::Byteswap::byteswap(mat->Reflection); #endif size -= 4; subsize -= 4; size -= readVX(mat->Envelope[4]); } else { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif mat->Reflection=tmp16/256.0f; size -= 2; subsize -= 2; } } break; case charsToUIntD('V','R','F','L'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading reflection."); #endif { File->read(&mat->Reflection, 4); #ifndef __BIG_ENDIAN__ mat->Reflection=os::Byteswap::byteswap(mat->Reflection); #endif size -= 4; } break; case charsToUIntD('T','R','A','N'): { if (FormatVersion==2) { File->read(&mat->Transparency, 4); #ifndef __BIG_ENDIAN__ mat->Transparency=os::Byteswap::byteswap(mat->Transparency); #endif size -= 4; subsize -= 4; size -= readVX(mat->Envelope[5]); } else { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif mat->Transparency=tmp16/256.0f; size -= 2; subsize -= 2; } #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading transparency", core::stringc(mat->Transparency).c_str()); #endif } break; case charsToUIntD('V','T','R','N'): { File->read(&mat->Transparency, 4); #ifndef __BIG_ENDIAN__ mat->Transparency=os::Byteswap::byteswap(mat->Transparency); #endif size -= 4; } #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading transparency", core::stringc(mat->Transparency).c_str()); #endif break; case charsToUIntD('T','R','N','L'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading translucency."); #endif { File->read(&mat->Translucency, 4); #ifndef __BIG_ENDIAN__ mat->Translucency=os::Byteswap::byteswap(mat->Translucency); #endif size -= 4; subsize -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[6]); } break; case charsToUIntD('G','L','O','S'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading glossy."); #endif { if (FormatVersion == 2) { File->read(&irrMat.Shininess, 4); #ifndef __BIG_ENDIAN__ irrMat.Shininess=os::Byteswap::byteswap(irrMat.Shininess); #endif size -= 4; subsize -= 4; size -= readVX(mat->Envelope[7]); } else { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif irrMat.Shininess=tmp16/16.f; size -= 2; subsize -= 2; } } break; case charsToUIntD('S','H','R','P'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading sharpness."); #endif { File->read(&mat->Sharpness, 4); #ifndef __BIG_ENDIAN__ mat->Sharpness=os::Byteswap::byteswap(mat->Sharpness); #endif size -= 4; subsize -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[8]); } break; case charsToUIntD('B','U','M','P'): case charsToUIntD('T','A','M','P'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading bumpiness."); #endif { File->read(&tmpf32, 4); #ifndef __BIG_ENDIAN__ tmpf32=os::Byteswap::byteswap(tmpf32); #endif if (currTexture==6) irrMat.MaterialTypeParam=tmpf32; size -= 4; subsize -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[9]); } break; case charsToUIntD('S','I','D','E'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading backface culled."); #endif { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif if (tmp16==1) irrMat.BackfaceCulling=true; else if (tmp16==3) irrMat.BackfaceCulling=false; size -= 2; } break; case charsToUIntD('S','M','A','N'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading smoothing angle."); #endif { File->read(&mat->SmoothingAngle, 4); #ifndef __BIG_ENDIAN__ mat->SmoothingAngle=os::Byteswap::byteswap(mat->SmoothingAngle); #endif size -= 4; } break; case charsToUIntD('R','F','O','P'): case charsToUIntD('R','F','L','T'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading reflection mode."); #endif { File->read(&mat->ReflMode, 2); #ifndef __BIG_ENDIAN__ mat->ReflMode=os::Byteswap::byteswap(mat->ReflMode); #endif size -= 2; } break; case charsToUIntD('R','I','M','G'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading reflection map."); #endif { if (FormatVersion==2) { size -= readVX(tmp32); if (tmp32) mat->ReflMap=Images[tmp32-1]; } else size -= readString(mat->ReflMap, size); } break; case charsToUIntD('R','S','A','N'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading reflection seam angle."); #endif { File->read(&mat->ReflSeamAngle, 4); #ifndef __BIG_ENDIAN__ mat->ReflSeamAngle=os::Byteswap::byteswap(mat->ReflSeamAngle); #endif size -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[10]); } break; case charsToUIntD('R','B','L','R'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading reflection blur."); #endif { File->read(&mat->ReflBlur, 4); #ifndef __BIG_ENDIAN__ mat->ReflBlur=os::Byteswap::byteswap(mat->ReflBlur); #endif size -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[11]); } break; case charsToUIntD('R','I','N','D'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading refraction index."); #endif { File->read(&mat->RefrIndex, 4); #ifndef __BIG_ENDIAN__ mat->RefrIndex=os::Byteswap::byteswap(mat->RefrIndex); #endif size -= 4; subsize -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[12]); } break; case charsToUIntD('T','R','O','P'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading refraction options."); #endif { File->read(&mat->TranspMode, 2); #ifndef __BIG_ENDIAN__ mat->TranspMode=os::Byteswap::byteswap(mat->TranspMode); #endif size -= 2; } break; case charsToUIntD('T','I','M','G'): { if (FormatVersion==2) { #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading refraction map."); #endif size -= readVX(tmp32); #ifndef __BIG_ENDIAN__ tmp32=os::Byteswap::byteswap(tmp32); #endif if (tmp32) mat->Texture[currTexture].Map=Images[tmp32-1]; } else { size -= readString(mat->Texture[currTexture].Map, size); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading image", mat->Texture[currTexture].Map.c_str()); #endif } } break; case charsToUIntD('T','B','L','R'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading transparency blur."); #endif { File->read(&mat->TranspBlur, 4); #ifndef __BIG_ENDIAN__ mat->TranspBlur=os::Byteswap::byteswap(mat->TranspBlur); #endif size -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[13]); } break; case charsToUIntD('C','L','R','H'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading highlight color."); #endif { File->read(&mat->HighlightColor, 4); #ifndef __BIG_ENDIAN__ mat->HighlightColor=os::Byteswap::byteswap(mat->HighlightColor); #endif size -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[14]); } break; case charsToUIntD('C','L','R','F'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading color filter."); #endif { File->read(&mat->ColorFilter, 4); #ifndef __BIG_ENDIAN__ mat->ColorFilter=os::Byteswap::byteswap(mat->ColorFilter); #endif size -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[15]); } break; case charsToUIntD('A','D','T','R'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading additive transparency."); #endif { File->read(&mat->AdditiveTransparency, 4); #ifndef __BIG_ENDIAN__ mat->AdditiveTransparency=os::Byteswap::byteswap(mat->AdditiveTransparency); #endif size -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[16]); } break; case charsToUIntD('G','L','O','W'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading glow."); #endif { if (FormatVersion==0) { File->read(&mat->GlowIntensity, 4); #ifndef __BIG_ENDIAN__ mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity); #endif size -= 4; } else { File->read(&mat->Glow, 2); #ifndef __BIG_ENDIAN__ mat->Glow=os::Byteswap::byteswap(mat->Glow); #endif size -= 2; File->read(&mat->GlowIntensity, 4); #ifndef __BIG_ENDIAN__ mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity); #endif size -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[17]); File->read(&mat->GlowSize, 4); #ifndef __BIG_ENDIAN__ mat->GlowSize=os::Byteswap::byteswap(mat->GlowSize); #endif size -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[18]); } } break; case charsToUIntD('G','V','A','L'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading glow intensity."); #endif { File->read(&mat->GlowIntensity, 4); #ifndef __BIG_ENDIAN__ mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity); #endif size -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[17]); } break; case charsToUIntD('L','I','N','E'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading isWireframe."); #endif { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif if (tmp16&1) irrMat.Wireframe=true; size -= 2; if (size!=0) { File->read(&irrMat.Thickness, 4); #ifndef __BIG_ENDIAN__ irrMat.Thickness=os::Byteswap::byteswap(irrMat.Thickness); #endif size -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[19]); } if (size!=0) { video::SColor lineColor; size -= readColor(lineColor); if (FormatVersion==2) size -= readVX(mat->Envelope[20]); } } break; case charsToUIntD('A','L','P','H'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading alpha mode."); #endif { File->read(&mat->AlphaMode, 2); #ifndef __BIG_ENDIAN__ mat->AlphaMode=os::Byteswap::byteswap(mat->AlphaMode); #endif size -= 2; File->read(&mat->AlphaValue, 4); #ifndef __BIG_ENDIAN__ mat->AlphaValue=os::Byteswap::byteswap(mat->AlphaValue); #endif size -= 4; } break; case charsToUIntD('V','C','O','L'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading vertex color."); #endif { File->read(&mat->VertexColorIntensity, 4); #ifndef __BIG_ENDIAN__ mat->VertexColorIntensity=os::Byteswap::byteswap(mat->VertexColorIntensity); #endif size -= 4; if (FormatVersion==2) size -= readVX(mat->Envelope[21]); File->read(&tmp32, 4); // skip type size -= 4; core::stringc tmpname; size -= readString(tmpname, size); // mat->VertexColor = getColorVMAP(tmpname); } break; case charsToUIntD('F','L','A','G'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading flag."); #endif { File->read(&mat->Flags, 2); #ifndef __BIG_ENDIAN__ mat->Flags=os::Byteswap::byteswap(mat->Flags); #endif if (mat->Flags&1) mat->Luminance=1.0f; if (mat->Flags&256) irrMat.BackfaceCulling=false; size -= 2; } break; case charsToUIntD('E','D','G','E'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading edge."); #endif { File->read(&mat->EdgeTransparency, 4); #ifndef __BIG_ENDIAN__ mat->EdgeTransparency=os::Byteswap::byteswap(mat->EdgeTransparency); #endif size -= 4; } break; case charsToUIntD('C','T','E','X'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading ctex."); #endif currTexture=0; size -= readString(mat->Texture[currTexture].Type, size); break; case charsToUIntD('D','T','E','X'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading dtex."); #endif currTexture=1; size -= readString(mat->Texture[currTexture].Type, size); break; case charsToUIntD('S','T','E','X'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading stex."); #endif currTexture=2; size -= readString(mat->Texture[currTexture].Type, size); break; case charsToUIntD('R','T','E','X'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading rtex."); #endif currTexture=3; size -= readString(mat->Texture[currTexture].Type, size); break; case charsToUIntD('T','T','E','X'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading ttex."); #endif currTexture=4; size -= readString(mat->Texture[currTexture].Type, size); break; case charsToUIntD('L','T','E','X'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading ltex."); #endif currTexture=5; size -= readString(mat->Texture[currTexture].Type, size); break; case charsToUIntD('B','T','E','X'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading btex."); #endif currTexture=6; size -= readString(mat->Texture[currTexture].Type, size); break; case charsToUIntD('T','A','L','P'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading alpha map."); #endif size -= readString(mat->Texture[currTexture].AlphaMap, size); break; case charsToUIntD('T','F','L','G'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture flag."); #endif { File->read(&mat->Texture[currTexture].Flags, 2); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].Flags=os::Byteswap::byteswap(mat->Texture[currTexture].Flags); #endif size -= 2; } break; case charsToUIntD('E','N','A','B'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading isEnabled."); #endif { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif mat->Texture[currTexture].Active=(tmp16!=0); size -= 2; } break; case charsToUIntD('W','R','A','P'): case charsToUIntD('T','W','R','P'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture wrap."); #endif { File->read(&mat->Texture[currTexture].WidthWrap, 2); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].WidthWrap=os::Byteswap::byteswap(mat->Texture[currTexture].WidthWrap); #endif File->read(&mat->Texture[currTexture].HeightWrap, 2); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].HeightWrap=os::Byteswap::byteswap(mat->Texture[currTexture].HeightWrap); #endif size -= 4; } break; case charsToUIntD('T','V','E','L'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture velocity."); #endif size -= readVec(mat->Texture[currTexture].Velocity); break; case charsToUIntD('T','C','L','R'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture color."); #endif size -= readColor(mat->Texture[currTexture].Color); break; case charsToUIntD('A','A','S','T'): case charsToUIntD('T','A','A','S'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture antialias."); #endif { tmp16=0; if (FormatVersion==2) { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif size -= 2; } File->read(&mat->Texture[currTexture].AntiAliasing, 4); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].AntiAliasing=os::Byteswap::byteswap(mat->Texture[currTexture].AntiAliasing); #endif if (tmp16 & ~0x01) mat->Texture[currTexture].AntiAliasing=0.0f; // disabled size -= 4; } break; case charsToUIntD('T','O','P','C'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture opacity."); #endif { File->read(&mat->Texture[currTexture].Opacity, 4); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].Opacity=os::Byteswap::byteswap(mat->Texture[currTexture].Opacity); #endif size -= 4; } break; case charsToUIntD('O','P','A','C'): { #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture opacity and type."); #endif File->read(&mat->Texture[currTexture].OpacType, 2); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].OpacType=os::Byteswap::byteswap(mat->Texture[currTexture].OpacType); #endif File->read(&mat->Texture[currTexture].Opacity, 4); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].Opacity=os::Byteswap::byteswap(mat->Texture[currTexture].Opacity); #endif size -= 6; subsize -= 6; if (FormatVersion==2) size -= readVX(mat->Envelope[22]); } break; case charsToUIntD('A','X','I','S'): { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif mat->Texture[currTexture].Axis=(u8)tmp16; size -= 2; #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading axis value", core::stringc(tmp16).c_str()); #endif } break; case charsToUIntD('T','M','A','P'): // empty separation chunk break; case charsToUIntD('T','C','T','R'): case charsToUIntD('C','N','T','R'): { core::vector3df& center=mat->Texture[currTexture].Center; size -= readVec(center); if (FormatVersion==2) size -= readVX(mat->Envelope[22]); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture center", (core::stringc(center.X)+" "+core::stringc(center.Y)+" "+core::stringc(center.Z)).c_str()); #endif } break; case charsToUIntD('T','S','I','Z'): case charsToUIntD('S','I','Z','E'): { core::vector3df& tsize=mat->Texture[currTexture].Size; size -= readVec(tsize); if (FormatVersion==2) size -= readVX(mat->Envelope[22]); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture size", (core::stringc(tsize.X)+" "+core::stringc(tsize.Y)+" "+core::stringc(tsize.Z)).c_str()); #endif } break; case charsToUIntD('R','O','T','A'): { core::vector3df rotation; size -= readVec(rotation); if (FormatVersion==2) size -= readVX(mat->Envelope[22]); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture rotation", (core::stringc(rotation.X)+" "+core::stringc(rotation.Y)+" "+core::stringc(rotation.Z)).c_str()); #endif } break; case charsToUIntD('O','R','E','F'): { core::stringc tmpname; size -= readString(tmpname); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: texture reference object", tmpname.c_str()); #endif } break; case charsToUIntD('T','F','A','L'): case charsToUIntD('F','A','L','L'): { if (FormatVersion==2) { u16 tmp16; File->read(&tmp16, 2); size -= 2; #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif } core::vector3df& falloff=mat->Texture[currTexture].Falloff; size -= readVec(falloff); if (FormatVersion==2) size -= readVX(mat->Envelope[22]); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture falloff"); #endif } break; case charsToUIntD('C','S','Y','S'): { u16 tmp16; File->read(&tmp16, 2); size -= 2; #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: texture coordinate system", tmp16==0?"object coords":"world coords"); #endif } break; case charsToUIntD('T','V','A','L'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture value."); #endif { File->read(&tmp16, 2); #ifndef __BIG_ENDIAN__ tmp16=os::Byteswap::byteswap(tmp16); #endif mat->Texture[currTexture].Value=tmp16/256.0f; size -= 2; } break; case charsToUIntD('T','F','P','0'): case charsToUIntD('T','S','P','0'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture param 0."); #endif { File->read(&mat->Texture[currTexture].FParam[0], 4); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].FParam[0]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[0]); #endif size -= 4; } break; case charsToUIntD('T','F','P','1'): case charsToUIntD('T','S','P','1'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture param 1."); #endif { File->read(&mat->Texture[currTexture].FParam[1], 4); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].FParam[1]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[1]); #endif size -= 4; } break; case charsToUIntD('T','F','P','2'): case charsToUIntD('T','S','P','2'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture param 2."); #endif { File->read(&mat->Texture[currTexture].FParam[2], 4); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].FParam[2]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[2]); #endif size -= 4; } break; case charsToUIntD('T','F','R','Q'): case charsToUIntD('T','I','P','0'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture iparam 0."); #endif { File->read(&mat->Texture[currTexture].IParam[0], 2); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].IParam[0]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[0]); #endif size -= 2; } break; case charsToUIntD('T','I','P','1'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture param 1."); #endif { File->read(&mat->Texture[currTexture].IParam[1], 2); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].IParam[1]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[1]); #endif size -= 2; } break; case charsToUIntD('T','I','P','2'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading texture param 2."); #endif { File->read(&mat->Texture[currTexture].IParam[2], 2); #ifndef __BIG_ENDIAN__ mat->Texture[currTexture].IParam[2]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[2]); #endif size -= 2; } break; case charsToUIntD('V','M','A','P'): { size -= readString(mat->Texture[currTexture].UVname); #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading material vmap binding",mat->Texture[currTexture].UVname.c_str()); #endif } break; case charsToUIntD('B','L','O','K'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading blok."); #endif { core::stringc ordinal; File->read(&type, 4); File->read(&subsize, 2); #ifndef __BIG_ENDIAN__ subsize=os::Byteswap::byteswap(subsize); #endif size -= 6; size -= readString(ordinal, size); } break; case charsToUIntD('C','H','A','N'): { File->read(&type, 4); size -= 4; if (!strncmp(type, "COLR", 4)) currTexture=0; else if (!strncmp(type, "DIFF", 4)) currTexture=1; else if (!strncmp(type, "LUMI", 4)) currTexture=5; else if (!strncmp(type, "SPEC", 4)) currTexture=2; else if (!strncmp(type, "REFL", 4)) currTexture=3; else if (!strncmp(type, "TRAN", 4)) currTexture=4; else if (!strncmp(type, "BUMP", 4)) currTexture=6; } #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading channel ", type); #endif break; case charsToUIntD('I','M','A','G'): #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading channel map."); #endif { u16 index; File->read(&index, 2); #ifndef __BIG_ENDIAN__ index=os::Byteswap::byteswap(index); #endif size -= 2; if (index) mat->Texture[currTexture].Map=Images[index-1]; } break; case charsToUIntD('P','R','O','J'): // define the projection type #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: loading channel projection type."); #endif { u16 index; File->read(&index, 2); #ifndef __BIG_ENDIAN__ index=os::Byteswap::byteswap(index); #endif size -= 2; #ifdef LWO_READER_DEBUG if (index != 5) os::Printer::log("LWO loader: wrong channel projection type", core::stringc(index).c_str()); #endif mat->Texture[currTexture].Projection=(u8)index; } break; case charsToUIntD('W','R','P','W'): // for cylindrical and spherical projections case charsToUIntD('W','R','P','H'): // for cylindrical and spherical projections default: { #ifdef LWO_READER_DEBUG os::Printer::log("LWO loader: skipping ", core::stringc((char*)&uiType, 4)); #endif File->seek(subsize, true); size -= subsize; } } } if (mat->Transparency != 0.f) { irrMat.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR; } } u32 CLWOMeshFileLoader::readColor(video::SColor& color) { if (FormatVersion!=2) { u8 colorComponent; File->read(&colorComponent, 1); color.setRed(colorComponent); File->read(&colorComponent, 1); color.setGreen(colorComponent); File->read(&colorComponent, 1); color.setBlue(colorComponent); // unknown value File->read(&colorComponent, 1); return 4; } else { video::SColorf col; File->read(&col.r, 4); #ifndef __BIG_ENDIAN__ col.r=os::Byteswap::byteswap(col.r); #endif File->read(&col.g, 4); #ifndef __BIG_ENDIAN__ col.g=os::Byteswap::byteswap(col.g); #endif File->read(&col.b, 4); #ifndef __BIG_ENDIAN__ col.b=os::Byteswap::byteswap(col.b); #endif color=col.toSColor(); return 12; } } u32 CLWOMeshFileLoader::readString(core::stringc& name, u32 size) { c8 c; name=""; if (size) name.reserve(size); File->read(&c, 1); while (c) { name.append(c); File->read(&c, 1); } // read extra 0 upon odd file position if (File->getPos() & 0x1) { File->read(&c, 1); return (name.size()+2); } return (name.size()+1); } u32 CLWOMeshFileLoader::readVec(core::vector3df& vec) { File->read(&vec.X, 4); #ifndef __BIG_ENDIAN__ vec.X=os::Byteswap::byteswap(vec.X); #endif File->read(&vec.Y, 4); #ifndef __BIG_ENDIAN__ vec.Y=os::Byteswap::byteswap(vec.Y); #endif File->read(&vec.Z, 4); #ifndef __BIG_ENDIAN__ vec.Z=os::Byteswap::byteswap(vec.Z); #endif return 12; } u32 CLWOMeshFileLoader::readVX(u32& num) { u16 tmpIndex; File->read(&tmpIndex, 2); #ifndef __BIG_ENDIAN__ tmpIndex=os::Byteswap::byteswap(tmpIndex); #endif num=tmpIndex; if (num >= 0xFF00) { File->read(&tmpIndex, 2); #ifndef __BIG_ENDIAN__ tmpIndex=os::Byteswap::byteswap(tmpIndex); #endif num=((num << 16)|tmpIndex) & ~0xFF000000; return 4; } return 2; } bool CLWOMeshFileLoader::readFileHeader() { u32 Id; File->read(&Id, 4); #ifndef __BIG_ENDIAN__ Id=os::Byteswap::byteswap(Id); #endif if (Id != 0x464f524d) // FORM return false; //skip the file length File->read(&Id, 4); File->read(&Id, 4); #ifndef __BIG_ENDIAN__ Id=os::Byteswap::byteswap(Id); #endif // Currently supported: LWOB, LWLO, LWO2 switch (Id) { case 0x4c574f42: FormatVersion = 0; // LWOB break; case 0x4c574c4f: FormatVersion = 1; // LWLO break; case 0x4c574f32: FormatVersion = 2; // LWO2 break; default: return false; // unsupported } return true; } video::ITexture* CLWOMeshFileLoader::loadTexture(const core::stringc& file) { video::IVideoDriver* driver = SceneManager->getVideoDriver(); if (FileSystem->existFile(file)) return driver->getTexture(file); core::stringc strippedName=FileSystem->getFileBasename(file); if (FileSystem->existFile(strippedName)) return driver->getTexture(strippedName); core::stringc newpath = FileSystem->getFileDir(File->getFileName()); newpath.append("/"); newpath.append(strippedName); if (FileSystem->existFile(newpath)) return driver->getTexture(newpath); os::Printer::log("Could not load texture", file.c_str(), ELL_WARNING); return 0; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CLogger.h0000644000000000000000000000267612574354552016643 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_LOGGER_H_INCLUDED__ #define __C_LOGGER_H_INCLUDED__ #include "ILogger.h" #include "os.h" #include "irrString.h" #include "IEventReceiver.h" namespace irr { //! Class for logging messages, warnings and errors to stdout class CLogger : public ILogger { public: CLogger(IEventReceiver* r); //! Returns the current set log level. virtual ELOG_LEVEL getLogLevel() const; //! Sets a new log level. virtual void setLogLevel(ELOG_LEVEL ll); virtual void setLogLevel(ELOG_LEVEL ll); //! Prints out a text into the log virtual void log(const c8* text, ELOG_LEVEL ll=ELL_INFORMATION); //! Prints out a text into the log virtual void log(const wchar_t* text, ELOG_LEVEL ll=ELL_INFORMATION); //! Prints out a text into the log virtual void log(const c8* text, const c8* hint, ELOG_LEVEL ll=ELL_INFORMATION); //! Prints out a text into the log virtual void log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION); //! Prints out a text into the log virtual void log(const wchar_t* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION); //! Sets a new event receiver void setReceiver(IEventReceiver* r); private: ELOG_LEVEL LogLevel; IEventReceiver* Receiver; }; } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/CLogger.cpp0000644000000000000000000000365212574354552017171 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CLogger.h" namespace irr { CLogger::CLogger(IEventReceiver* r) : LogLevel(ELL_INFORMATION), Receiver(r) { #ifdef _DEBUG setDebugName("CLogger"); #endif } //! Returns the current set log level. ELOG_LEVEL CLogger::getLogLevel() const { return LogLevel; } //! Sets a new log level. void CLogger::setLogLevel(ELOG_LEVEL ll) { LogLevel = ll; } //! Prints out a text into the log void CLogger::log(const c8* text, ELOG_LEVEL ll) { if (ll < LogLevel) return; if (Receiver) { SEvent event; event.EventType = EET_LOG_TEXT_EVENT; event.LogEvent.Text = text; event.LogEvent.Level = ll; if (Receiver->OnEvent(event)) return; } os::Printer::print(text); } //! Prints out a text into the log void CLogger::log(const c8* text, const c8* hint, ELOG_LEVEL ll) { if (ll < LogLevel) return; core::stringc s = text; s += ": "; s += hint; log (s.c_str(), ll); } //! Prints out a text into the log void CLogger::log(const wchar_t* text, ELOG_LEVEL ll) { if (ll < LogLevel) return; core::stringc s = text; log(s.c_str(), ll); } //! Prints out a text into the log void CLogger::log(const wchar_t* text, const wchar_t* hint, ELOG_LEVEL ll) { if (ll < LogLevel) return; core::stringc s1 = text; core::stringc s2 = hint; log(s1.c_str(), s2.c_str(), ll); } //! Prints out a text into the log void CLogger::log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll) { if (ll < LogLevel) return; core::stringc s2 = hint; log( text, s2.c_str(), ll); } //! Sets a new event receiver void CLogger::setReceiver(IEventReceiver* r) { Receiver = r; } } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CLMTSMeshFileLoader.h0000644000000000000000000000441712574354552020742 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // I (Nikolaus Gebhardt) did some few changes to Jonas Petersen's original loader: // - removed setTexturePath() and replaced with the ISceneManager::getStringParameter()-stuff. // - added EAMT_LMTS enumeration value // Thanks a lot to Jonas Petersen for his work // on this and that he gave me his permission to add it into Irrlicht. /* CLMTSMeshFileLoader.h LMTSMeshFileLoader Written by Jonas Petersen (a.k.a. jox) Version 1.5 - 15 March 2005 */ #if !defined(__C_LMTS_MESH_FILE_LOADER_H_INCLUDED__) #define __C_LMTS_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "SMesh.h" #include "IFileSystem.h" #include "IVideoDriver.h" namespace irr { namespace scene { class CLMTSMeshFileLoader : public IMeshLoader { public: CLMTSMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver, io::IAttributes* parameters); virtual ~CLMTSMeshFileLoader(); virtual bool isALoadableFileExtension(const io::path& filename) const; virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: void constructMesh(SMesh* mesh); void loadTextures(SMesh* mesh); void cleanup(); // byte-align structures #include "irrpack.h" struct SLMTSHeader { u32 MagicID; u32 Version; u32 HeaderSize; u16 TextureCount; u16 SubsetCount; u32 TriangleCount; u16 SubsetSize; u16 VertexSize; } PACK_STRUCT; struct SLMTSTextureInfoEntry { c8 Filename[256]; u16 Flags; } PACK_STRUCT; struct SLMTSSubsetInfoEntry { u32 Offset; u32 Count; u16 TextID1; u16 TextID2; } PACK_STRUCT; struct SLMTSTriangleDataEntry { f32 X; f32 Y; f32 Z; f32 U1; f32 V1; f32 U2; f32 V2; } PACK_STRUCT; // Default alignment #include "irrunpack.h" SLMTSHeader Header; SLMTSTextureInfoEntry* Textures; SLMTSSubsetInfoEntry* Subsets; SLMTSTriangleDataEntry* Triangles; io::IAttributes* Parameters; video::IVideoDriver* Driver; io::IFileSystem* FileSystem; bool FlipEndianess; }; } // end namespace scene } // end namespace irr #endif // !defined(__C_LMTS_MESH_FILE_LOADER_H_INCLUDED__) irrlicht-1.8.3/source/Irrlicht/CLMTSMeshFileLoader.cpp0000644000000000000000000002426712574354552021302 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // This file was written by Jonas Petersen and modified by Nikolaus Gebhardt. // See CLMTSMeshFileLoder.h for details. /* CLMTSMeshFileLoader.cpp LMTSMeshFileLoader Written by Jonas Petersen (a.k.a. jox) Version 1.5 - 15 March 2005 Get the latest version here: http://development.mindfloaters.de/ This class allows loading meshes with lightmaps (*.lmts + *.tga files) that were created using Pulsar LMTools by Lord Trancos (http://www.geocities.com/dxlab/index_en.html) Notes: - This version does not support user data in the *.lmts files, but still loads those files (by skipping the extra data). License: -------- It's free. You are encouraged to give me credit if you use it in your software. Version History: ---------------- Version 1.5 - 15 March 2005 - Did a better cleanup. No memory leaks in case of an loading error. - Added "#include " for sprintf. Version 1.4 - 12 March 2005 - Fixed bug in texture and subset loading code that would possibly cause crash. - Fixed memory cleanup to avoid leak when loading more then one mesh - Used the irrlicht Logger instead of cerr to output warnings and errors. For this I had to change the constructor from: CLMTSMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver) to: CLMTSMeshFileLoader(IrrlichtDevice* device) Version 1.3 - 15 February 2005 - Fixed bug that prevented loading more than one different lmts files. - Removed unnecessary "#include ". - Added "std::" in front of "cerr". This was necessary for Visual Studio .NET, I hope it's not disturbing other compilers. - Added warning message when a texture can not be loaded. - Changed the documentation a bit (minor). Version 1.2 - To avoid confusion I skipped version 1.2 because the website was offering version 1.2 even though it was only version 1.1. Sorry about that. Version 1.1 - 29 July 2004 - Added setTexturePath() function - Minor improvements Version 1.0 - 29 July 2004 - Initial release */ ////////////////////////////////////////////////////////////////////// #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_LMTS_LOADER_ #include "SMeshBufferLightMap.h" #include "SAnimatedMesh.h" #include "SMeshBuffer.h" #include "irrString.h" #include "IReadFile.h" #include "IAttributes.h" #include "ISceneManager.h" #include "CLMTSMeshFileLoader.h" #include "os.h" namespace irr { namespace scene { CLMTSMeshFileLoader::CLMTSMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver, io::IAttributes* parameters) : Textures(0), Subsets(0), Triangles(0), Parameters(parameters), Driver(driver), FileSystem(fs), FlipEndianess(false) { #ifdef _DEBUG setDebugName("CLMTSMeshFileLoader"); #endif if (Driver) Driver->grab(); if (FileSystem) FileSystem->grab(); } CLMTSMeshFileLoader::~CLMTSMeshFileLoader() { cleanup(); if (Driver) Driver->drop(); if (FileSystem) FileSystem->drop(); } void CLMTSMeshFileLoader::cleanup() { delete [] Textures; Textures = 0; delete [] Subsets; Subsets = 0; delete [] Triangles; Triangles = 0; } bool CLMTSMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "lmts" ); } IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file) { u32 i; u32 id; // HEADER file->read(&Header, sizeof(SLMTSHeader)); if (Header.MagicID == 0x4C4D5354) { FlipEndianess = true; Header.MagicID = os::Byteswap::byteswap(Header.MagicID); Header.Version = os::Byteswap::byteswap(Header.Version); Header.HeaderSize = os::Byteswap::byteswap(Header.HeaderSize); Header.TextureCount = os::Byteswap::byteswap(Header.TextureCount); Header.SubsetCount = os::Byteswap::byteswap(Header.SubsetCount); Header.TriangleCount = os::Byteswap::byteswap(Header.TriangleCount); Header.SubsetSize = os::Byteswap::byteswap(Header.SubsetSize); Header.VertexSize = os::Byteswap::byteswap(Header.VertexSize); } if (Header.MagicID != 0x53544D4C) { // "LMTS" os::Printer::log("LMTS ERROR: wrong header magic id!", ELL_ERROR); return 0; } //Skip any User Data (arbitrary app specific data) const s32 userSize = Header.HeaderSize - sizeof(SLMTSHeader); if (userSize>0) file->seek(userSize,true); // TEXTURES file->read(&id, sizeof(u32)); if (FlipEndianess) id = os::Byteswap::byteswap(id); if (id != 0x54584554) { // "TEXT" os::Printer::log("LMTS ERROR: wrong texture magic id!", ELL_ERROR); return 0; } Textures = new SLMTSTextureInfoEntry[Header.TextureCount]; file->read(Textures, sizeof(SLMTSTextureInfoEntry)*Header.TextureCount); if (FlipEndianess) { for (i=0; iread(&id, sizeof(u32)); if (FlipEndianess) id = os::Byteswap::byteswap(id); if (id != 0x53425553) // "SUBS" { os::Printer::log("LMTS ERROR: wrong subset magic id!", ELL_ERROR); cleanup(); return 0; } Subsets = new SLMTSSubsetInfoEntry[Header.SubsetCount]; const s32 subsetUserSize = Header.SubsetSize - sizeof(SLMTSSubsetInfoEntry); for (i=0; iread(&Subsets[i], sizeof(SLMTSSubsetInfoEntry)); if (FlipEndianess) { Subsets[i].Offset = os::Byteswap::byteswap(Subsets[i].Offset); Subsets[i].Count = os::Byteswap::byteswap(Subsets[i].Count); Subsets[i].TextID1 = os::Byteswap::byteswap(Subsets[i].TextID1); Subsets[i].TextID2 = os::Byteswap::byteswap(Subsets[i].TextID2); } if (subsetUserSize>0) file->seek(subsetUserSize,true); } // TRIANGLES file->read(&id, sizeof(u32)); if (FlipEndianess) id = os::Byteswap::byteswap(id); if (id != 0x53495254) // "TRIS" { os::Printer::log("LMTS ERROR: wrong triangle magic id!", ELL_ERROR); cleanup(); return 0; } Triangles = new SLMTSTriangleDataEntry[(Header.TriangleCount*3)]; const s32 triUserSize = Header.VertexSize - sizeof(SLMTSTriangleDataEntry); for (i=0; i<(Header.TriangleCount*3); ++i) { file->read(&Triangles[i], sizeof(SLMTSTriangleDataEntry)); if (FlipEndianess) { Triangles[i].X = os::Byteswap::byteswap(Triangles[i].X); Triangles[i].Y = os::Byteswap::byteswap(Triangles[i].Y); Triangles[i].Z = os::Byteswap::byteswap(Triangles[i].Z); Triangles[i].U1 = os::Byteswap::byteswap(Triangles[i].U1); Triangles[i].V1 = os::Byteswap::byteswap(Triangles[i].U2); Triangles[i].U2 = os::Byteswap::byteswap(Triangles[i].V1); Triangles[i].V2 = os::Byteswap::byteswap(Triangles[i].V2); } if (triUserSize>0) file->seek(triUserSize,true); } ///////////////////////////////////////////////////////////////// SMesh* mesh = new SMesh(); constructMesh(mesh); loadTextures(mesh); cleanup(); SAnimatedMesh* am = new SAnimatedMesh(); am->Type = EAMT_LMTS; // not unknown to irrlicht anymore am->addMesh(mesh); am->recalculateBoundingBox(); mesh->drop(); return am; } void CLMTSMeshFileLoader::constructMesh(SMesh* mesh) { for (s32 i=0; iMaterial.MaterialType = video::EMT_LIGHTMAP; meshBuffer->Material.Wireframe = false; meshBuffer->Material.Lighting = false; mesh->addMeshBuffer(meshBuffer); const u32 offs = Subsets[i].Offset * 3; for (u32 sc=0; scgetVertexCount(); for (u32 vu=0; vu<3; ++vu) { const SLMTSTriangleDataEntry& v = Triangles[offs+(3*sc)+vu]; meshBuffer->Vertices.push_back( video::S3DVertex2TCoords( v.X, v.Y, v.Z, video::SColor(255,255,255,255), v.U1, v.V1, v.U2, v.V2)); } const core::vector3df normal = core::plane3df( meshBuffer->Vertices[idx].Pos, meshBuffer->Vertices[idx+1].Pos, meshBuffer->Vertices[idx+2].Pos).Normal; meshBuffer->Vertices[idx].Normal = normal; meshBuffer->Vertices[idx+1].Normal = normal; meshBuffer->Vertices[idx+2].Normal = normal; meshBuffer->Indices.push_back(idx); meshBuffer->Indices.push_back(idx+1); meshBuffer->Indices.push_back(idx+2); } meshBuffer->drop(); } for (u32 j=0; jMeshBuffers.size(); ++j) mesh->MeshBuffers[j]->recalculateBoundingBox(); mesh->recalculateBoundingBox(); } void CLMTSMeshFileLoader::loadTextures(SMesh* mesh) { if (!Driver || !FileSystem) return; // load textures // a little too much space, but won't matter here core::array tex; tex.reallocate(Header.TextureCount); core::array lig; lig.reallocate(Header.TextureCount); core::array id2id; id2id.reallocate(Header.TextureCount); const core::stringc Path = Parameters->getAttributeAsString(LMTS_TEXTURE_PATH); core::stringc s; for (u32 t=0; texistFile(s)) tmptex = Driver->getTexture(s); else os::Printer::log("LMTS WARNING: Texture does not exist", s.c_str(), ELL_WARNING); if (Textures[t].Flags & 0x01) { id2id.push_back(lig.size()); lig.push_back(tmptex); } else { id2id.push_back(tex.size()); tex.push_back(tmptex); } } // attach textures to materials. for (u32 i=0; igetMeshBuffer(i)->getMaterial().setTexture(0, tex[id2id[Subsets[i].TextID1]]); if (Subsets[i].TextID2 < Header.TextureCount && id2id[Subsets[i].TextID2] < lig.size()) mesh->getMeshBuffer(i)->getMaterial().setTexture(1, lig[id2id[Subsets[i].TextID2]]); if (!mesh->getMeshBuffer(i)->getMaterial().getTexture(1)) mesh->getMeshBuffer(i)->getMaterial().MaterialType = video::EMT_SOLID; } } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_LMTS_LOADER_ irrlicht-1.8.3/source/Irrlicht/CLimitReadFile.h0000644000000000000000000000302412574354552020062 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_LIMIT_READ_FILE_H_INCLUDED__ #define __C_LIMIT_READ_FILE_H_INCLUDED__ #include "IReadFile.h" #include "irrString.h" namespace irr { class CUnicodeConverter; namespace io { /*! this is a read file, which is limited to some boundaries, so that it may only start from a certain file position and may only read until a certain file position. This can be useful, for example for reading uncompressed files in an archive (zip, tar). !*/ class CLimitReadFile : public IReadFile { public: CLimitReadFile(IReadFile* alreadyOpenedFile, long pos, long areaSize, const io::path& name); virtual ~CLimitReadFile(); //! returns how much was read virtual s32 read(void* buffer, u32 sizeToRead); //! changes position in file, returns true if successful //! if relativeMovement==true, the pos is changed relative to current pos, //! otherwise from begin of file virtual bool seek(long finalPos, bool relativeMovement = false); //! returns size of file virtual long getSize() const; //! returns where in the file we are. virtual long getPos() const; //! returns name of file virtual const io::path& getFileName() const; private: io::path Filename; long AreaStart; long AreaEnd; long Pos; IReadFile* File; }; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CLimitReadFile.cpp0000644000000000000000000000454212574354552020423 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CLimitReadFile.h" #include "irrString.h" namespace irr { namespace io { CLimitReadFile::CLimitReadFile(IReadFile* alreadyOpenedFile, long pos, long areaSize, const io::path& name) : Filename(name), AreaStart(0), AreaEnd(0), Pos(0), File(alreadyOpenedFile) { #ifdef _DEBUG setDebugName("CLimitReadFile"); #endif if (File) { File->grab(); AreaStart = pos; AreaEnd = AreaStart + areaSize; } } CLimitReadFile::~CLimitReadFile() { if (File) File->drop(); } //! returns how much was read s32 CLimitReadFile::read(void* buffer, u32 sizeToRead) { #if 1 if (0 == File) return 0; s32 r = AreaStart + Pos; s32 toRead = core::s32_min(AreaEnd, r + sizeToRead) - core::s32_max(AreaStart, r); if (toRead < 0) return 0; File->seek(r); r = File->read(buffer, toRead); Pos += r; return r; #else const long pos = File->getPos(); if (pos >= AreaEnd) return 0; if (pos + (long)sizeToRead >= AreaEnd) sizeToRead = AreaEnd - pos; return File->read(buffer, sizeToRead); #endif } //! changes position in file, returns true if successful bool CLimitReadFile::seek(long finalPos, bool relativeMovement) { #if 1 Pos = core::s32_clamp(finalPos + (relativeMovement ? Pos : 0 ), 0, AreaEnd - AreaStart); return true; #else const long pos = File->getPos(); if (relativeMovement) { if (pos + finalPos > AreaEnd) finalPos = AreaEnd - pos; } else { finalPos += AreaStart; if (finalPos > AreaEnd) return false; } return File->seek(finalPos, relativeMovement); #endif } //! returns size of file long CLimitReadFile::getSize() const { return AreaEnd - AreaStart; } //! returns where in the file we are. long CLimitReadFile::getPos() const { #if 1 return Pos; #else return File->getPos() - AreaStart; #endif } //! returns name of file const io::path& CLimitReadFile::getFileName() const { return Filename; } IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize) { return new CLimitReadFile(alreadyOpenedFile, pos, areaSize, fileName); } } // end namespace io } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CLightSceneNode.h0000644000000000000000000000661512574354552020254 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_LIGHT_SCENE_NODE_H_INCLUDED__ #define __C_LIGHT_SCENE_NODE_H_INCLUDED__ #include "ILightSceneNode.h" namespace irr { namespace scene { //! Scene node which is a dynamic light. You can switch the light on and off by //! making it visible or not, and let it be animated by ordinary scene node animators. class CLightSceneNode : public ILightSceneNode { public: //! constructor CLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, video::SColorf color, f32 range); virtual ~CLightSceneNode() { } //! pre render event virtual void OnRegisterSceneNode(); //! render virtual void render(); //! set node light data from light info virtual void setLightData(const video::SLight& light); //! \return Returns the light data. virtual const video::SLight& getLightData() const; //! \return Returns the light data. virtual video::SLight& getLightData(); //! Sets if the node should be visible or not. /** All children of this node won't be visible either, when set to true. \param isVisible If the node shall be visible. */ virtual void setVisible(bool isVisible); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_LIGHT; } //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); //! Sets the light's radius of influence. /** Outside this radius the light won't lighten geometry and cast no shadows. Setting the radius will also influence the attenuation, setting it to (0,1/radius,0). If you want to override this behavior, set the attenuation after the radius. \param radius The new radius. */ virtual void setRadius(f32 radius); //! Gets the light's radius of influence. /** \return The current radius. */ virtual f32 getRadius() const; //! Sets the light type. /** \param type The new type. */ virtual void setLightType(video::E_LIGHT_TYPE type); //! Gets the light type. /** \return The current light type. */ virtual video::E_LIGHT_TYPE getLightType() const; //! Sets whether this light casts shadows. /** Enabling this flag won't automatically cast shadows, the meshes will still need shadow scene nodes attached. But one can enable or disable distinct lights for shadow casting for performance reasons. \param shadow True if this light shall cast shadows. */ virtual void enableCastShadow(bool shadow=true); //! Check whether this light casts shadows. /** \return True if light would cast shadows, else false. */ virtual bool getCastShadow() const; private: video::SLight LightData; core::aabbox3d BBox; s32 DriverLightIndex; bool LightIsOn; void doLightRecalc(); }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CLightSceneNode.cpp0000644000000000000000000001705412574354552020606 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CLightSceneNode.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "ICameraSceneNode.h" #include "os.h" namespace irr { namespace scene { //! constructor CLightSceneNode::CLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, video::SColorf color, f32 radius) : ILightSceneNode(parent, mgr, id, position), DriverLightIndex(-1), LightIsOn(true) { #ifdef _DEBUG setDebugName("CLightSceneNode"); #endif LightData.DiffuseColor = color; // set some useful specular color LightData.SpecularColor = color.getInterpolated(video::SColor(255,255,255,255),0.7f); setRadius(radius); } //! pre render event void CLightSceneNode::OnRegisterSceneNode() { doLightRecalc(); if (IsVisible) SceneManager->registerNodeForRendering(this, ESNRP_LIGHT); ISceneNode::OnRegisterSceneNode(); } //! render void CLightSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); if (!driver) return; if ( DebugDataVisible & scene::EDS_BBOX ) { driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); video::SMaterial m; m.Lighting = false; driver->setMaterial(m); switch ( LightData.Type ) { case video::ELT_POINT: case video::ELT_SPOT: driver->draw3DBox(BBox, LightData.DiffuseColor.toSColor()); break; case video::ELT_DIRECTIONAL: driver->draw3DLine(core::vector3df(0.f, 0.f, 0.f), LightData.Direction * LightData.Radius, LightData.DiffuseColor.toSColor()); break; default: break; } } DriverLightIndex = driver->addDynamicLight(LightData); setVisible(LightIsOn); } //! sets the light data void CLightSceneNode::setLightData(const video::SLight& light) { LightData = light; } //! \return Returns the light data. const video::SLight& CLightSceneNode::getLightData() const { return LightData; } //! \return Returns the light data. video::SLight& CLightSceneNode::getLightData() { return LightData; } void CLightSceneNode::setVisible(bool isVisible) { ISceneNode::setVisible(isVisible); if(DriverLightIndex < 0) return; video::IVideoDriver* driver = SceneManager->getVideoDriver(); if (!driver) return; LightIsOn = isVisible; driver->turnLightOn((u32)DriverLightIndex, LightIsOn); } //! returns the axis aligned bounding box of this node const core::aabbox3d& CLightSceneNode::getBoundingBox() const { return BBox; } //! Sets the light's radius of influence. /** Outside this radius the light won't lighten geometry and cast no shadows. Setting the radius will also influence the attenuation, setting it to (0,1/radius,0). If you want to override this behavior, set the attenuation after the radius. \param radius The new radius. */ void CLightSceneNode::setRadius(f32 radius) { LightData.Radius=radius; LightData.Attenuation.set(0.f, 1.f/radius, 0.f); doLightRecalc(); } //! Gets the light's radius of influence. /** \return The current radius. */ f32 CLightSceneNode::getRadius() const { return LightData.Radius; } //! Sets the light type. /** \param type The new type. */ void CLightSceneNode::setLightType(video::E_LIGHT_TYPE type) { LightData.Type=type; } //! Gets the light type. /** \return The current light type. */ video::E_LIGHT_TYPE CLightSceneNode::getLightType() const { return LightData.Type; } //! Sets whether this light casts shadows. /** Enabling this flag won't automatically cast shadows, the meshes will still need shadow scene nodes attached. But one can enable or disable distinct lights for shadow casting for performance reasons. \param shadow True if this light shall cast shadows. */ void CLightSceneNode::enableCastShadow(bool shadow) { LightData.CastShadows=shadow; } //! Check whether this light casts shadows. /** \return True if light would cast shadows, else false. */ bool CLightSceneNode::getCastShadow() const { return LightData.CastShadows; } void CLightSceneNode::doLightRecalc() { if ((LightData.Type == video::ELT_SPOT) || (LightData.Type == video::ELT_DIRECTIONAL)) { LightData.Direction = core::vector3df(.0f,.0f,1.0f); getAbsoluteTransformation().rotateVect(LightData.Direction); LightData.Direction.normalize(); } if ((LightData.Type == video::ELT_SPOT) || (LightData.Type == video::ELT_POINT)) { const f32 r = LightData.Radius * LightData.Radius * 0.5f; BBox.MaxEdge.set( r, r, r ); BBox.MinEdge.set( -r, -r, -r ); //setAutomaticCulling( scene::EAC_BOX ); setAutomaticCulling( scene::EAC_OFF ); LightData.Position = getAbsolutePosition(); } if (LightData.Type == video::ELT_DIRECTIONAL) { BBox.reset( 0, 0, 0 ); setAutomaticCulling( scene::EAC_OFF ); } } //! Writes attributes of the scene node. void CLightSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { ILightSceneNode::serializeAttributes(out, options); out->addColorf ("AmbientColor", LightData.AmbientColor); out->addColorf ("DiffuseColor", LightData.DiffuseColor); out->addColorf ("SpecularColor", LightData.SpecularColor); out->addVector3d("Attenuation", LightData.Attenuation); out->addFloat ("Radius", LightData.Radius); out->addFloat ("OuterCone", LightData.OuterCone); out->addFloat ("InnerCone", LightData.InnerCone); out->addFloat ("Falloff", LightData.Falloff); out->addBool ("CastShadows", LightData.CastShadows); out->addEnum ("LightType", LightData.Type, video::LightTypeNames); } //! Reads attributes of the scene node. void CLightSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { LightData.AmbientColor = in->getAttributeAsColorf("AmbientColor"); LightData.DiffuseColor = in->getAttributeAsColorf("DiffuseColor"); LightData.SpecularColor = in->getAttributeAsColorf("SpecularColor"); //TODO: clearify Radius and Linear Attenuation #if 0 setRadius ( in->getAttributeAsFloat("Radius") ); #else LightData.Radius = in->getAttributeAsFloat("Radius"); #endif if (in->existsAttribute("Attenuation")) // might not exist in older files LightData.Attenuation = in->getAttributeAsVector3d("Attenuation"); if (in->existsAttribute("OuterCone")) // might not exist in older files LightData.OuterCone = in->getAttributeAsFloat("OuterCone"); if (in->existsAttribute("InnerCone")) // might not exist in older files LightData.InnerCone = in->getAttributeAsFloat("InnerCone"); if (in->existsAttribute("Falloff")) // might not exist in older files LightData.Falloff = in->getAttributeAsFloat("Falloff"); LightData.CastShadows = in->getAttributeAsBool("CastShadows"); LightData.Type = (video::E_LIGHT_TYPE)in->getAttributeAsEnumeration("LightType", video::LightTypeNames); doLightRecalc (); ILightSceneNode::deserializeAttributes(in, options); } //! Creates a clone of this scene node and its children. ISceneNode* CLightSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CLightSceneNode* nb = new CLightSceneNode(newParent, newManager, ID, RelativeTranslation, LightData.DiffuseColor, LightData.Radius); nb->cloneMembers(this, newManager); nb->LightData = LightData; nb->BBox = BBox; if ( newParent ) nb->drop(); return nb; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CIrrMeshWriter.h0000644000000000000000000000302612574354552020160 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_IRR_MESH_WRITER_H_INCLUDED__ #define __IRR_IRR_MESH_WRITER_H_INCLUDED__ #include "IMeshWriter.h" #include "S3DVertex.h" #include "IVideoDriver.h" #include "IFileSystem.h" namespace irr { namespace io { class IXMLWriter; } namespace scene { class IMeshBuffer; //! class to write meshes, implementing a IrrMesh (.irrmesh, .xml) writer /** This writer implementation has been originally developed for irrEdit and then merged out to the Irrlicht Engine */ class CIrrMeshWriter : public IMeshWriter { public: CIrrMeshWriter(video::IVideoDriver* driver, io::IFileSystem* fs); virtual ~CIrrMeshWriter(); //! Returns the type of the mesh writer virtual EMESH_WRITER_TYPE getType() const; //! writes a mesh virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE); protected: void writeBoundingBox(const core::aabbox3df& box); void writeMeshBuffer(const scene::IMeshBuffer* buffer); void writeMaterial(const video::SMaterial& material); core::stringw getVectorAsStringLine(const core::vector3df& v) const; core::stringw getVectorAsStringLine(const core::vector2df& v) const; // member variables: io::IFileSystem* FileSystem; video::IVideoDriver* VideoDriver; io::IXMLWriter* Writer; }; } // end namespace } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/CIrrMeshWriter.cpp0000644000000000000000000001633112574354552020516 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_IRR_WRITER_ #include "CIrrMeshWriter.h" #include "os.h" #include "IWriteFile.h" #include "IXMLWriter.h" #include "IMesh.h" #include "IAttributes.h" namespace irr { namespace scene { CIrrMeshWriter::CIrrMeshWriter(video::IVideoDriver* driver, io::IFileSystem* fs) : FileSystem(fs), VideoDriver(driver), Writer(0) { #ifdef _DEBUG setDebugName("CIrrMeshWriter"); #endif if (VideoDriver) VideoDriver->grab(); if (FileSystem) FileSystem->grab(); } CIrrMeshWriter::~CIrrMeshWriter() { if (VideoDriver) VideoDriver->drop(); if (FileSystem) FileSystem->drop(); } //! Returns the type of the mesh writer EMESH_WRITER_TYPE CIrrMeshWriter::getType() const { return EMWT_IRR_MESH; } //! writes a mesh bool CIrrMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { if (!file) return false; Writer = FileSystem->createXMLWriter(file); if (!Writer) { os::Printer::log("Could not write file", file->getFileName()); return false; } os::Printer::log("Writing mesh", file->getFileName()); // write IRR MESH header Writer->writeXMLHeader(); Writer->writeElement(L"mesh", false, L"xmlns", L"http://irrlicht.sourceforge.net/IRRMESH_09_2007", L"version", L"1.0"); Writer->writeLineBreak(); // add some informational comment. Add a space after and before the comment // tags so that some braindead xml parsers (AS anyone?) are able to parse this too. core::stringw infoComment = L" This file contains a static mesh in the Irrlicht Engine format with "; infoComment += core::stringw(mesh->getMeshBufferCount()); infoComment += L" materials."; Writer->writeComment(infoComment.c_str()); Writer->writeLineBreak(); // write mesh bounding box writeBoundingBox(mesh->getBoundingBox()); Writer->writeLineBreak(); // write mesh buffers for (int i=0; i<(int)mesh->getMeshBufferCount(); ++i) { scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { writeMeshBuffer(buffer); Writer->writeLineBreak(); } } Writer->writeClosingTag(L"mesh"); Writer->drop(); return true; } void CIrrMeshWriter::writeBoundingBox(const core::aabbox3df& box) { Writer->writeElement(L"boundingBox", true, L"minEdge", getVectorAsStringLine(box.MinEdge).c_str(), L"maxEdge", getVectorAsStringLine(box.MaxEdge).c_str()); } core::stringw CIrrMeshWriter::getVectorAsStringLine(const core::vector3df& v) const { core::stringw str; str = core::stringw(v.X); str += L" "; str += core::stringw(v.Y); str += L" "; str += core::stringw(v.Z); return str; } core::stringw CIrrMeshWriter::getVectorAsStringLine(const core::vector2df& v) const { core::stringw str; str = core::stringw(v.X); str += L" "; str += core::stringw(v.Y); return str; } void CIrrMeshWriter::writeMeshBuffer(const scene::IMeshBuffer* buffer) { Writer->writeElement(L"buffer", false); Writer->writeLineBreak(); // write bounding box writeBoundingBox(buffer->getBoundingBox()); Writer->writeLineBreak(); // write material writeMaterial(buffer->getMaterial()); // write vertices const core::stringw vertexTypeStr = video::sBuiltInVertexTypeNames[buffer->getVertexType()]; Writer->writeElement(L"vertices", false, L"type", vertexTypeStr.c_str(), L"vertexCount", core::stringw(buffer->getVertexCount()).c_str()); Writer->writeLineBreak(); u32 vertexCount = buffer->getVertexCount(); switch(buffer->getVertexType()) { case video::EVT_STANDARD: { video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); for (u32 j=0; jwriteText(str.c_str()); Writer->writeLineBreak(); } } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); for (u32 j=0; jwriteText(str.c_str()); Writer->writeLineBreak(); } } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); for (u32 j=0; jwriteText(str.c_str()); Writer->writeLineBreak(); } } break; } Writer->writeClosingTag(L"vertices"); Writer->writeLineBreak(); // write indices Writer->writeElement(L"indices", false, L"indexCount", core::stringw(buffer->getIndexCount()).c_str()); Writer->writeLineBreak(); int indexCount = (int)buffer->getIndexCount(); video::E_INDEX_TYPE iType = buffer->getIndexType(); const u16* idx16 = buffer->getIndices(); const u32* idx32 = (u32*) buffer->getIndices(); const int maxIndicesPerLine = 25; for (int i=0; iwriteText(str.c_str()); } else { core::stringw str((int)idx32[i]); Writer->writeText(str.c_str()); } if (i % maxIndicesPerLine != maxIndicesPerLine) { if (i % maxIndicesPerLine == maxIndicesPerLine-1) Writer->writeLineBreak(); else Writer->writeText(L" "); } } if ((indexCount-1) % maxIndicesPerLine != maxIndicesPerLine-1) Writer->writeLineBreak(); Writer->writeClosingTag(L"indices"); Writer->writeLineBreak(); // close buffer tag Writer->writeClosingTag(L"buffer"); } void CIrrMeshWriter::writeMaterial(const video::SMaterial& material) { // simply use irrlichts built-in attribute serialization capabilities here: io::IAttributes* attributes = VideoDriver->createAttributesFromMaterial(material); if (attributes) { attributes->write(Writer, false, L"material"); attributes->drop(); } } } // end namespace } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/CIrrMeshFileLoader.h0000644000000000000000000000533512574354552020717 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IRR_MESH_FILE_LOADER_H_INCLUDED__ #define __C_IRR_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "IFileSystem.h" #include "IVideoDriver.h" #include "irrString.h" #include "SMesh.h" #include "SMeshBuffer.h" #include "CDynamicMeshBuffer.h" #include "ISceneManager.h" namespace irr { namespace scene { //! Meshloader capable of loading .irrmesh meshes, the Irrlicht Engine mesh format for static meshes class CIrrMeshFileLoader : public IMeshLoader { public: //! Constructor CIrrMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: //! reads a mesh sections and creates a mesh from it IAnimatedMesh* readMesh(io::IXMLReader* reader); //! reads a mesh sections and creates a mesh buffer from it IMeshBuffer* readMeshBuffer(io::IXMLReader* reader); //! skips an (unknown) section in the irrmesh file void skipSection(io::IXMLReader* reader, bool reportSkipping); //! reads a element and stores it in the material section void readMaterial(io::IXMLReader* reader); //! parses a float from a char pointer and moves the pointer to //! the end of the parsed float inline f32 readFloat(const c8** p); //! parses an int from a char pointer and moves the pointer to //! the end of the parsed float inline s32 readInt(const c8** p); //! places pointer to next begin of a token void findNextNoneWhiteSpace(const c8** p); //! places pointer to next begin of a token void skipCurrentNoneWhiteSpace(const c8** p); //! reads floats from inside of xml element until end of xml element void readFloatsInsideElement(io::IXMLReader* reader, f32* floats, u32 count); //! read the mesh buffers void readMeshBuffer(io::IXMLReader* reader, int vertexCount, CDynamicMeshBuffer* sbuffer); //! read indices void readIndices(io::IXMLReader* reader, int indexCount, IIndexBuffer& indices); // member variables scene::ISceneManager* SceneManager; io::IFileSystem* FileSystem; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CIrrMeshFileLoader.cpp0000644000000000000000000003157712574354552021261 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ #include "CIrrMeshFileLoader.h" #include "os.h" #include "IXMLReader.h" #include "SAnimatedMesh.h" #include "fast_atof.h" #include "IReadFile.h" #include "IAttributes.h" #include "IMeshSceneNode.h" #include "CDynamicMeshBuffer.h" #include "SMeshBufferLightMap.h" namespace irr { namespace scene { //! Constructor CIrrMeshFileLoader::CIrrMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) : SceneManager(smgr), FileSystem(fs) { #ifdef _DEBUG setDebugName("CIrrMeshFileLoader"); #endif } //! Returns true if the file maybe is able to be loaded by this class. /** This decision should be based only on the file extension (e.g. ".cob") */ bool CIrrMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "xml", "irrmesh" ); } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* CIrrMeshFileLoader::createMesh(io::IReadFile* file) { io::IXMLReader* reader = FileSystem->createXMLReader(file); if (!reader) return 0; // read until mesh section, skip other parts const core::stringc meshTagName = "mesh"; IAnimatedMesh* mesh = 0; while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { if (meshTagName == reader->getNodeName()) { mesh = readMesh(reader); break; } else skipSection(reader, true); // unknown section } } reader->drop(); return mesh; } //! reads a mesh sections and creates a mesh from it IAnimatedMesh* CIrrMeshFileLoader::readMesh(io::IXMLReader* reader) { SAnimatedMesh* animatedmesh = new SAnimatedMesh(); SMesh* mesh = new SMesh(); animatedmesh->addMesh(mesh); mesh->drop(); core::stringc bbSectionName = "boundingBox"; core::stringc bufferSectionName = "buffer"; core::stringc meshSectionName = "mesh"; if (!reader->isEmptyElement()) while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { const wchar_t* nodeName = reader->getNodeName(); if (bbSectionName == nodeName) { // inside a bounding box, ignore it for now because // we are calculating this anyway ourselves later. } else if (bufferSectionName == nodeName) { // we've got a mesh buffer IMeshBuffer* buffer = readMeshBuffer(reader); if (buffer) { mesh->addMeshBuffer(buffer); buffer->drop(); } } else skipSection(reader, true); // unknown section } // end if node type is element else if (reader->getNodeType() == io::EXN_ELEMENT_END) { if (meshSectionName == reader->getNodeName()) { // end of mesh section reached, cancel out break; } } } // end while reader->read(); mesh->recalculateBoundingBox(); animatedmesh->recalculateBoundingBox(); return animatedmesh; } //! reads a mesh sections and creates a mesh buffer from it IMeshBuffer* CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader) { CDynamicMeshBuffer* buffer = 0; core::stringc verticesSectionName = "vertices"; core::stringc bbSectionName = "boundingBox"; core::stringc materialSectionName = "material"; core::stringc indicesSectionName = "indices"; core::stringc bufferSectionName = "buffer"; bool insideVertexSection = false; bool insideIndexSection = false; int vertexCount = 0; int indexCount = 0; video::SMaterial material; if (!reader->isEmptyElement()) while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { const wchar_t* nodeName = reader->getNodeName(); if (bbSectionName == nodeName) { // inside a bounding box, ignore it for now because // we are calculating this anyway ourselves later. } else if (materialSectionName == nodeName) { //we've got a material io::IAttributes* attributes = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver()); attributes->read(reader, true, L"material"); SceneManager->getVideoDriver()->fillMaterialStructureFromAttributes(material, attributes); attributes->drop(); } else if (verticesSectionName == nodeName) { // vertices section const core::stringc vertexTypeName1 = "standard"; const core::stringc vertexTypeName2 = "2tcoords"; const core::stringc vertexTypeName3 = "tangents"; const wchar_t* vertexType = reader->getAttributeValue(L"type"); vertexCount = reader->getAttributeValueAsInt(L"vertexCount"); insideVertexSection = true; video::E_INDEX_TYPE itype = (vertexCount > 65536)?irr::video::EIT_32BIT:irr::video::EIT_16BIT; if (vertexTypeName1 == vertexType) { buffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, itype); } else if (vertexTypeName2 == vertexType) { buffer = new CDynamicMeshBuffer(irr::video::EVT_2TCOORDS, itype); } else if (vertexTypeName3 == vertexType) { buffer = new CDynamicMeshBuffer(irr::video::EVT_TANGENTS, itype); } buffer->getVertexBuffer().reallocate(vertexCount); buffer->Material = material; } else if (indicesSectionName == nodeName) { // indices section indexCount = reader->getAttributeValueAsInt(L"indexCount"); insideIndexSection = true; } } // end if node type is element else if (reader->getNodeType() == io::EXN_TEXT) { // read vertex data if (insideVertexSection) { readMeshBuffer(reader, vertexCount, buffer); insideVertexSection = false; } // end reading vertex array else if (insideIndexSection) { readIndices(reader, indexCount, buffer->getIndexBuffer()); insideIndexSection = false; } } // end if node type is text else if (reader->getNodeType() == io::EXN_ELEMENT_END) { if (bufferSectionName == reader->getNodeName()) { // end of buffer section reached, cancel out break; } } } // end while reader->read(); if (buffer) buffer->recalculateBoundingBox(); return buffer; } //! read indices void CIrrMeshFileLoader::readIndices(io::IXMLReader* reader, int indexCount, IIndexBuffer& indices) { indices.reallocate(indexCount); core::stringc data = reader->getNodeData(); const c8* p = &data[0]; for (int i=0; igetNodeData(); const c8* p = &data[0]; scene::IVertexBuffer& Vertices = sbuffer->getVertexBuffer(); video::E_VERTEX_TYPE vType = Vertices.getType(); if (sbuffer) { for (int i=0; igetNodeName()).c_str()); #endif // skip if this element is empty anyway. if (reader->isEmptyElement()) return; // read until we've reached the last element in this section u32 tagCounter = 1; while(tagCounter && reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT && !reader->isEmptyElement()) { #ifdef _DEBUG if (reportSkipping) os::Printer::log("irrMesh unknown element:", core::stringc(reader->getNodeName()).c_str()); #endif ++tagCounter; } else if (reader->getNodeType() == io::EXN_ELEMENT_END) --tagCounter; } } //! parses a float from a char pointer and moves the pointer //! to the end of the parsed float inline f32 CIrrMeshFileLoader::readFloat(const c8** p) { f32 ftmp; *p = core::fast_atof_move(*p, ftmp); return ftmp; } //! parses an int from a char pointer and moves the pointer to //! the end of the parsed float inline s32 CIrrMeshFileLoader::readInt(const c8** p) { return (s32)readFloat(p); } //! places pointer to next begin of a token void CIrrMeshFileLoader::skipCurrentNoneWhiteSpace(const c8** start) { const c8* p = *start; while(*p && !(*p==' ' || *p=='\n' || *p=='\r' || *p=='\t')) ++p; // TODO: skip comments *start = p; } //! places pointer to next begin of a token void CIrrMeshFileLoader::findNextNoneWhiteSpace(const c8** start) { const c8* p = *start; while(*p && (*p==' ' || *p=='\n' || *p=='\r' || *p=='\t')) ++p; // TODO: skip comments *start = p; } //! reads floats from inside of xml element until end of xml element void CIrrMeshFileLoader::readFloatsInsideElement(io::IXMLReader* reader, f32* floats, u32 count) { if (reader->isEmptyElement()) return; while(reader->read()) { // TODO: check for comments inside the element // and ignore them. if (reader->getNodeType() == io::EXN_TEXT) { // parse float data core::stringc data = reader->getNodeData(); const c8* p = &data[0]; for (u32 i=0; igetNodeType() == io::EXN_ELEMENT_END) break; // end parsing text } } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_IRR_MESH_LOADER_ irrlicht-1.8.3/source/Irrlicht/CIrrDeviceWinCE.h0000644000000000000000000001712412574354552020160 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IRR_DEVICE_WINCE_H_INCLUDED__ #define __C_IRR_DEVICE_WINCE_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ #include "CIrrDeviceStub.h" #include "IrrlichtDevice.h" #include "IImagePresenter.h" #include #include #include #include #include #include namespace irr { class CIrrDeviceWinCE : public CIrrDeviceStub, video::IImagePresenter { public: //! constructor CIrrDeviceWinCE( const SIrrlichtCreationParameters& params); //! destructor virtual ~CIrrDeviceWinCE(); //! runs the device. Returns false if device wants to be deleted virtual bool run(); //! Cause the device to temporarily pause execution and let other processes to run // This should bring down processor usage without major performance loss for Irrlicht virtual void yield(); //! Pause execution and let other processes to run for a specified amount of time. virtual void sleep(u32 timeMs, bool pauseTimer); //! sets the caption of the window virtual void setWindowCaption(const wchar_t* text); //! returns if window is active. if not, nothing need to be drawn virtual bool isWindowActive() const; //! returns if window has focus virtual bool isWindowFocused() const; //! returns if window is minimized virtual bool isWindowMinimized() const; //! presents a surface in the client area virtual bool present(video::IImage* surface, void* windowId = 0, core::rect* src=0 ); //! notifies the device that it should close itself virtual void closeDevice(); //! \return Returns a pointer to a list with all video modes //! supported by the gfx adapter. video::IVideoModeList* getVideoModeList(); //! Notifies the device, that it has been resized void OnResized(); //! Sets if the window should be resizable in windowed mode. virtual void setResizable(bool resize=false); //! Minimizes the window. virtual void minimizeWindow(); //! Maximizes the window. virtual void maximizeWindow(); //! Restores the window size. virtual void restoreWindow(); //! Get the device type virtual E_DEVICE_TYPE getType() const { return EIDT_WINCE; } //! Implementation of the win32 cursor control class CCursorControl : public gui::ICursorControl { public: CCursorControl(const core::dimension2d& wsize, HWND hwnd, bool fullscreen) : WindowSize(wsize), InvWindowSize(0.0f, 0.0f), HWnd(hwnd), BorderX(0), BorderY(0), UseReferenceRect(false), IsVisible(true) { if (WindowSize.Width!=0) InvWindowSize.Width = 1.0f / WindowSize.Width; if (WindowSize.Height!=0) InvWindowSize.Height = 1.0f / WindowSize.Height; if (!fullscreen) { BorderX = GetSystemMetrics(SM_CXDLGFRAME); BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME); } } //! Changes the visible state of the mouse cursor. virtual void setVisible(bool visible) { IsVisible = visible; } //! Returns if the cursor is currently visible. virtual bool isVisible() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return IsVisible; } //! Sets the new position of the cursor. virtual void setPosition(const core::position2d &pos) { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. virtual void setPosition(f32 x, f32 y) { if (!UseReferenceRect) setPosition(core::round32(x*WindowSize.Width), core::round32(y*WindowSize.Height)); else setPosition(core::round32(x*ReferenceRect.getWidth()), core::round32(y*ReferenceRect.getHeight())); } //! Sets the new position of the cursor. virtual void setPosition(const core::position2d &pos) { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. virtual void setPosition(s32 x, s32 y) { RECT rect; if (UseReferenceRect) { SetCursorPos(ReferenceRect.UpperLeftCorner.X + x, ReferenceRect.UpperLeftCorner.Y + y); } else { if (GetWindowRect(HWnd, &rect)) SetCursorPos(x + rect.left + BorderX, y + rect.top + BorderY); } CursorPos.X = x; CursorPos.Y = y; } //! Returns the current position of the mouse cursor. virtual const core::position2d& getPosition() { updateInternalCursorPosition(); return CursorPos; } //! Returns the current position of the mouse cursor. virtual core::position2d getRelativePosition() { updateInternalCursorPosition(); if (!UseReferenceRect) { return core::position2d(CursorPos.X * InvWindowSize.Width, CursorPos.Y * InvWindowSize.Height); } return core::position2d(CursorPos.X / (f32)ReferenceRect.getWidth(), CursorPos.Y / (f32)ReferenceRect.getHeight()); } //! Sets an absolute reference rect for calculating the cursor position. virtual void setReferenceRect(core::rect* rect=0) { if (rect) { ReferenceRect = *rect; UseReferenceRect = true; // prevent division through zero and uneven sizes if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2) ReferenceRect.LowerRightCorner.Y += 1; if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2) ReferenceRect.LowerRightCorner.X += 1; } else UseReferenceRect = false; } /** Used to notify the cursor that the window was resized. */ virtual void OnResize(const core::dimension2d& size) { WindowSize = size; if (size.Width!=0) InvWindowSize.Width = 1.0f / size.Width; else InvWindowSize.Width = 0.f; if (size.Height!=0) InvWindowSize.Height = 1.0f / size.Height; else InvWindowSize.Height = 0.f; } private: //! Updates the internal cursor position void updateInternalCursorPosition() { POINT p; if (!GetCursorPos(&p)) { DWORD xy = GetMessagePos(); p.x = GET_X_LPARAM(xy); p.y = GET_Y_LPARAM(xy); } if (UseReferenceRect) { CursorPos.X = p.x - ReferenceRect.UpperLeftCorner.X; CursorPos.Y = p.y - ReferenceRect.UpperLeftCorner.Y; } else { RECT rect; if (GetWindowRect(HWnd, &rect)) { CursorPos.X = p.x-rect.left-BorderX; CursorPos.Y = p.y-rect.top-BorderY; } else { // window seems not to be existent, so set cursor to // a negative value CursorPos.X = -1; CursorPos.Y = -1; } } } core::position2d CursorPos; core::dimension2d WindowSize; core::dimension2d InvWindowSize; HWND HWnd; s32 BorderX, BorderY; core::rect ReferenceRect; bool UseReferenceRect; bool IsVisible; }; //! returns the win32 cursor control CCursorControl* getWin32CursorControl(); private: //! create the driver void createDriver(); //! switchs to fullscreen bool switchToFullScreen(); void getWindowsVersion(core::stringc& version); void resizeIfNecessary(); HWND HWnd; CCursorControl* Win32CursorControl; bool ChangedToFullScreen; bool Resized; bool ExternalWindow; }; } // end namespace irr #endif // _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ #endif // __C_IRR_DEVICE_WINCE_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CIrrDeviceWinCE.cpp0000644000000000000000000005445512574354552020523 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ #include "CIrrDeviceWinCE.h" #include "IEventReceiver.h" #include "irrList.h" #include "os.h" #include "CTimer.h" #include "irrString.h" #include "COSOperator.h" #include "dimension2d.h" #include #include "irrlicht.h" #ifdef _MSC_VER #pragma comment (lib, "aygshell.lib") #endif namespace irr { namespace video { #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ IVideoDriver* createDirectX8Driver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, HWND window); #endif #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ IVideoDriver* createDirectX9Driver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, HWND window); #endif #ifdef _IRR_COMPILE_WITH_OPENGL_ IVideoDriver* createOpenGLDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, this); #endif } } // end namespace irr struct SEnvMapper { HWND hWnd; irr::CIrrDeviceWinCE* irrDev; }; irr::core::list EnvMap; SEnvMapper* getEnvMapperFromHWnd(HWND hWnd) { irr::core::list::Iterator it = EnvMap.begin(); for (; it!= EnvMap.end(); ++it) if ((*it).hWnd == hWnd) return &(*it); return 0; } irr::CIrrDeviceWinCE* getDeviceFromHWnd(HWND hWnd) { irr::core::list::Iterator it = EnvMap.begin(); for (; it!= EnvMap.end(); ++it) if ((*it).hWnd == hWnd) return (*it).irrDev; return 0; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { #ifndef WM_MOUSEWHEEL #define WM_MOUSEWHEEL 0x020A #endif #ifndef WHEEL_DELTA #define WHEEL_DELTA 120 #endif irr::CIrrDeviceWinCE* dev = 0; irr::SEvent event; SEnvMapper* envm = 0; //BYTE allKeys[256]; static irr::s32 ClickCount=0; if (GetCapture() != hWnd && ClickCount > 0) ClickCount = 0; switch (message) { case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); } return 0; case WM_ERASEBKGND: return 0; case WM_SETCURSOR: envm = getEnvMapperFromHWnd(hWnd); if (envm && !envm->irrDev->getWin32CursorControl()->isVisible()) { SetCursor(NULL); return 0; } break; case WM_MOUSEWHEEL: event.EventType = irr::EET_MOUSE_INPUT_EVENT; event.MouseInput.Wheel = ((irr::f32)((short)HIWORD(wParam))) / (irr::f32)WHEEL_DELTA; event.MouseInput.Event = irr::EMIE_MOUSE_WHEEL; POINT p; // fixed by jox p.x = 0; p.y = 0; ClientToScreen(hWnd, &p); event.MouseInput.X = LOWORD(lParam) - p.x; event.MouseInput.Y = HIWORD(lParam) - p.y; event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); // left and right mouse buttons event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); // middle and extra buttons if (wParam & MK_MBUTTON) event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); break; case WM_LBUTTONDOWN: ClickCount++; SetCapture(hWnd); event.EventType = irr::EET_MOUSE_INPUT_EVENT; event.MouseInput.Event = irr::EMIE_LMOUSE_PRESSED_DOWN; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); // left and right mouse buttons event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); // middle and extra buttons if (wParam & MK_MBUTTON) event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); return 0; case WM_LBUTTONUP: ClickCount--; if (ClickCount<1) { ClickCount=0; ReleaseCapture(); } event.EventType = irr::EET_MOUSE_INPUT_EVENT; event.MouseInput.Event = irr::EMIE_LMOUSE_LEFT_UP; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); // left and right mouse buttons event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); // middle and extra buttons if (wParam & MK_MBUTTON) event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); return 0; case WM_RBUTTONDOWN: ClickCount++; SetCapture(hWnd); event.EventType = irr::EET_MOUSE_INPUT_EVENT; event.MouseInput.Event = irr::EMIE_RMOUSE_PRESSED_DOWN; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); // left and right mouse buttons event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); // middle and extra buttons if (wParam & MK_MBUTTON) event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); return 0; case WM_RBUTTONUP: ClickCount--; if (ClickCount<1) { ClickCount=0; ReleaseCapture(); } event.EventType = irr::EET_MOUSE_INPUT_EVENT; event.MouseInput.Event = irr::EMIE_RMOUSE_LEFT_UP; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); // left and right mouse buttons event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); // middle and extra buttons if (wParam & MK_MBUTTON) event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); return 0; case WM_MBUTTONDOWN: ClickCount++; SetCapture(hWnd); event.EventType = irr::EET_MOUSE_INPUT_EVENT; event.MouseInput.Event = irr::EMIE_MMOUSE_PRESSED_DOWN; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); // left and right mouse buttons event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); // middle and extra buttons if (wParam & MK_MBUTTON) event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); return 0; case WM_MBUTTONUP: ClickCount--; if (ClickCount<1) { ClickCount=0; ReleaseCapture(); } event.EventType = irr::EET_MOUSE_INPUT_EVENT; event.MouseInput.Event = irr::EMIE_MMOUSE_LEFT_UP; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); // left and right mouse buttons event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); // middle and extra buttons if (wParam & MK_MBUTTON) event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); return 0; case WM_MOUSEMOVE: event.EventType = irr::EET_MOUSE_INPUT_EVENT; event.MouseInput.Event = irr::EMIE_MOUSE_MOVED; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); // left and right mouse buttons event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); // middle and extra buttons if (wParam & MK_MBUTTON) event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); return 0; case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_KEYDOWN: case WM_KEYUP: { event.EventType = irr::EET_KEY_INPUT_EVENT; event.KeyInput.Key = (irr::EKEY_CODE)wParam; event.KeyInput.PressedDown = (message==WM_KEYDOWN || message == WM_SYSKEYDOWN); dev = getDeviceFromHWnd(hWnd); /* WORD KeyAsc=0; GetKeyboardState(allKeys); ToAscii(wParam,lParam,allKeys,&KeyAsc,0); */ // event.KeyInput.Shift = ((allKeys[VK_SHIFT] & 0x80)!=0); // event.KeyInput.Control = ((allKeys[VK_CONTROL] & 0x80)!=0); // event.KeyInput.Char = (KeyAsc & 0x00ff); //KeyAsc >= 0 ? KeyAsc : 0; if (dev) dev->postEventFromUser(event); return 0; } case WM_SIZE: { // resize dev = getDeviceFromHWnd(hWnd); if (dev) dev->OnResized(); } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } namespace irr { //! constructor CIrrDeviceWinCE::CIrrDeviceWinCE(const SIrrlichtCreationParameters& params) : CIrrDeviceStub(params), HWnd(0), Win32CursorControl(0), ChangedToFullScreen(false), Resized(false), ExternalWindow(false) { #ifdef _DEBUG setDebugName("CIrrDeviceWinCE"); #endif core::stringc winversion; getWindowsVersion(winversion); Operator = new COSOperator(winversion); os::Printer::log(winversion.c_str(), ELL_INFORMATION); HINSTANCE hInstance = GetModuleHandle(0); // create the window only if we do not use the null device if (!CreationParams.WindowId && (CreationParams.DriverType != video::EDT_NULL)) { const wchar_t* ClassName = L"CIrrDeviceWinCE"; // Register Class WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = 0; wc.lpszClassName = ClassName; // if there is an icon, load it wc.hIcon = (HICON)LoadImageW(hInstance, L"irrlicht.ico", IMAGE_ICON, 0,0, 0); RegisterClass(&wc); // calculate client size RECT clientSize; clientSize.top = 0; clientSize.left = 0; clientSize.right = CreationParams.WindowSize.Width; clientSize.bottom = CreationParams.WindowSize.Height; DWORD style = WS_POPUP; if (!CreationParams.Fullscreen) style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; AdjustWindowRectEx(&clientSize, style, FALSE, 0); const s32 realWidth = clientSize.right - clientSize.left; const s32 realHeight = clientSize.bottom - clientSize.top; const s32 windowLeft = core::s32_max ( 0, (GetSystemMetrics(SM_CXSCREEN) - realWidth) >> 1 ); const s32 windowTop = core::s32_max ( 0, (GetSystemMetrics(SM_CYSCREEN) - realHeight) >> 1 ); // create window HWnd = CreateWindowW( ClassName, L"", style, windowLeft, windowTop, realWidth, realHeight, NULL, NULL, hInstance, NULL); ShowWindow(HWnd , SW_SHOW); UpdateWindow(HWnd); // fix ugly ATI driver bugs. Thanks to ariaci MoveWindow(HWnd, windowLeft, windowTop, realWidth, realHeight, TRUE); } else if (CreationParams.WindowId) { // attach external window HWnd = static_cast(CreationParams.WindowId); RECT r; GetWindowRect(HWnd, &r); CreationParams.WindowSize.Width = r.right - r.left; CreationParams.WindowSize.Height = r.bottom - r.top; CreationParams.Fullscreen = false; ExternalWindow = true; } // create cursor control Win32CursorControl = new CCursorControl(CreationParams.WindowSize, HWnd, CreationParams.Fullscreen); CursorControl = Win32CursorControl; // create driver createDriver(); if (VideoDriver) createGUIAndScene(); // register environment SEnvMapper em; em.irrDev = this; em.hWnd = HWnd; EnvMap.push_back(em); // set this as active window SetActiveWindow(HWnd); SetForegroundWindow(HWnd); } //! destructor CIrrDeviceWinCE::~CIrrDeviceWinCE() { // unregister environment if (ChangedToFullScreen) SHFullScreen(HWnd, SHFS_SHOWTASKBAR | SHFS_SHOWSTARTICON | SHFS_SHOWSIPBUTTON); irr::core::list::Iterator it = EnvMap.begin(); for (; it!= EnvMap.end(); ++it) if ((*it).hWnd == HWnd) { EnvMap.erase(it); break; } } //! create the driver void CIrrDeviceWinCE::createDriver() { switch(CreationParams.DriverType) { case video::EDT_DIRECT3D8: #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ VideoDriver = video::createDirectX8Driver(CreationParams, FileSystem, HWnd); if (!VideoDriver) { os::Printer::log("Could not create DIRECT3D8 Driver.", ELL_ERROR); } #else os::Printer::log("DIRECT3D8 Driver was not compiled into this dll. Try another one.", ELL_ERROR); #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ break; case video::EDT_DIRECT3D9: #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ VideoDriver = video::createDirectX9Driver(CreationParams, FileSystem, HWnd); if (!VideoDriver) { os::Printer::log("Could not create DIRECT3D9 Driver.", ELL_ERROR); } #else os::Printer::log("DIRECT3D9 Driver was not compiled into this dll. Try another one.", ELL_ERROR); #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ break; case video::EDT_OPENGL: #ifdef _IRR_COMPILE_WITH_OPENGL_ if (CreationParams.Fullscreen) switchToFullScreen(); VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem); if (!VideoDriver) { os::Printer::log("Could not create OpenGL driver.", ELL_ERROR); } #else os::Printer::log("OpenGL driver was not compiled in.", ELL_ERROR); #endif break; case video::EDT_SOFTWARE: #ifdef _IRR_COMPILE_WITH_SOFTWARE_ if (CreationParams.Fullscreen) switchToFullScreen(); VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); #else os::Printer::log("Software driver was not compiled in.", ELL_ERROR); #endif break; case video::EDT_BURNINGSVIDEO: #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ if (CreationParams.Fullscreen) switchToFullScreen(); VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this); #else os::Printer::log("Burning's Video driver was not compiled in.", ELL_ERROR); #endif break; case video::EDT_NULL: // create null driver VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize); break; default: os::Printer::log("Unable to create video driver of unknown type.", ELL_ERROR); break; } } //! runs the device. Returns false if device wants to be deleted bool CIrrDeviceWinCE::run() { os::Timer::tick(); MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); if (ExternalWindow && msg.hwnd == HWnd) WndProc(HWnd, msg.message, msg.wParam, msg.lParam); else DispatchMessage(&msg); if (msg.message == WM_QUIT) Close = true; } if (!Close) resizeIfNecessary(); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return !Close; } //! Pause the current process for the minimum time allowed only to allow other processes to execute void CIrrDeviceWinCE::yield() { Sleep(1); } //! Pause execution and let other processes to run for a specified amount of time. void CIrrDeviceWinCE::sleep(u32 timeMs, bool pauseTimer) { const bool wasStopped = Timer ? Timer->isStopped() : true; if (pauseTimer && !wasStopped) Timer->stop(); Sleep(timeMs); if (pauseTimer && !wasStopped) Timer->start(); } void CIrrDeviceWinCE::resizeIfNecessary() { if (!Resized) return; RECT r; GetClientRect(HWnd, &r); char tmp[255]; if (r.right < 2 || r.bottom < 2) { sprintf(tmp, "Ignoring resize operation to (%ld %ld)", r.right, r.bottom); os::Printer::log(tmp); } else { sprintf(tmp, "Resizing window (%ld %ld)", r.right, r.bottom); os::Printer::log(tmp); getVideoDriver()->OnResize(irr::core::dimension2d(r.right, r.bottom)); getWin32CursorControl()->OnResize(getVideoDriver()->getScreenSize()); } Resized = false; } //! sets the caption of the window void CIrrDeviceWinCE::setWindowCaption(const wchar_t* text) { SetWindowTextW(HWnd, text); } #if !defined(BITMAPV4HEADER) typedef struct { DWORD bV4Size; LONG bV4Width; LONG bV4Height; WORD bV4Planes; WORD bV4BitCount; DWORD bV4V4Compression; DWORD bV4SizeImage; LONG bV4XPelsPerMeter; LONG bV4YPelsPerMeter; DWORD bV4ClrUsed; DWORD bV4ClrImportant; DWORD bV4RedMask; DWORD bV4GreenMask; DWORD bV4BlueMask; DWORD bV4AlphaMask; DWORD bV4CSType; DWORD un[9]; } BITMAPV4HEADER, *PBITMAPV4HEADER; #endif //! presents a surface in the client area bool CIrrDeviceWinCE::present(video::IImage* image, void* windowId, core::rect* src) { HWND hwnd = HWnd; if ( windowId ) hwnd = (HWND)windowId; HDC dc = GetDC(hwnd); if ( dc ) { RECT rect; GetClientRect(hwnd, &rect); const void* memory = (const void *)image->lock(); BITMAPV4HEADER bi; memset (&bi, 0, sizeof(bi)); bi.bV4Size = sizeof(BITMAPINFOHEADER); bi.bV4BitCount = image->getBitsPerPixel(); bi.bV4Planes = 1; bi.bV4Width = image->getDimension().Width; bi.bV4Height = 0 - image->getDimension().Height; bi.bV4V4Compression = BI_BITFIELDS; bi.bV4AlphaMask = image->getAlphaMask (); bi.bV4RedMask = image->getRedMask (); bi.bV4GreenMask = image->getGreenMask(); bi.bV4BlueMask = image->getBlueMask(); int r = 0; if ( src ) { r = StretchDIBits(dc, 0,0, rect.right, rect.bottom, src->UpperLeftCorner.X, src->UpperLeftCorner.Y, src->getWidth(), src->getHeight(), memory, (const BITMAPINFO*)(&bi), DIB_RGB_COLORS, SRCCOPY); } else { r = StretchDIBits(dc, 0,0, rect.right, rect.bottom, 0, 0, image->getDimension().Width, image->getDimension().Height, memory, (const BITMAPINFO*)(&bi), DIB_RGB_COLORS, SRCCOPY); } image->unlock(); ReleaseDC(hwnd, dc); } return true; } //! notifies the device that it should close itself void CIrrDeviceWinCE::closeDevice() { MSG msg; PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE); PostQuitMessage(0); PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE); if (!ExternalWindow) { DestroyWindow(HWnd); const fschar_t* ClassName = __TEXT("CIrrDeviceWin32"); HINSTANCE hInstance = GetModuleHandle(0); UnregisterClass(ClassName, hInstance); } Close=true; } //! returns if window is active. if not, nothing need to be drawn bool CIrrDeviceWinCE::isWindowActive() const { bool ret = (GetActiveWindow() == HWnd); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! returns if window has focus bool CIrrDeviceWinCE::isWindowFocused() const { bool ret = (GetFocus() == HWnd); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! returns if window is minimized bool CIrrDeviceWinCE::isWindowMinimized() const { #if 0 WINDOWPLACEMENT plc; plc.length=sizeof(WINDOWPLACEMENT); bool ret=false; if (GetWindowPlacement(HWnd,&plc)) ret=(plc.showCmd & SW_SHOWMINIMIZED); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; #endif return false; } //! switches to fullscreen bool CIrrDeviceWinCE::switchToFullScreen() { ChangedToFullScreen = SHFullScreen(HWnd, SHFS_HIDESIPBUTTON | SHFS_HIDETASKBAR) != 0; return ChangedToFullScreen; } //! returns the win32 cursor control CIrrDeviceWinCE::CCursorControl* CIrrDeviceWinCE::getWin32CursorControl() { return Win32CursorControl; } //! Return pointer to a list with all video modes supported by the gfx adapter. /** \return Pointer to video modes list */ video::IVideoModeList* CIrrDeviceWinCE::getVideoModeList() { if (!VideoModeList->getVideoModeCount()) { // enumerate video modes. DWORD i=0; DEVMODE mode; memset(&mode, 0, sizeof(mode)); mode.dmSize = sizeof(mode); while (EnumDisplaySettings(NULL, i, &mode)) { VideoModeList->addMode(core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight), mode.dmBitsPerPel); ++i; } if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &mode)) VideoModeList->setDesktop(mode.dmBitsPerPel, core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight)); } return VideoModeList; } void CIrrDeviceWinCE::getWindowsVersion(core::stringc& out) { out = "WinCE"; } //! Notifies the device, that it has been resized void CIrrDeviceWinCE::OnResized() { Resized = true; } //! Sets if the window should be resizable in windowed mode. void CIrrDeviceWinCE::setResizable(bool resize) { if (ExternalWindow || !getVideoDriver() || CreationParams.Fullscreen) return; LONG style = WS_POPUP; if (!resize) style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; else style = WS_THICKFRAME | WS_SYSMENU | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX; if (!SetWindowLong(HWnd, GWL_STYLE, style)) os::Printer::log("Could not change window style."); RECT clientSize; clientSize.top = 0; clientSize.left = 0; clientSize.right = getVideoDriver()->getScreenSize().Width; clientSize.bottom = getVideoDriver()->getScreenSize().Height; AdjustWindowRectEx(&clientSize, style, FALSE, 0); const s32 realWidth = clientSize.right - clientSize.left; const s32 realHeight = clientSize.bottom - clientSize.top; const s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2; const s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2; SetWindowPos(HWnd, HWND_TOP, windowLeft, windowTop, realWidth, realHeight, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_SHOWWINDOW); } //! Minimizes the window. void CIrrDeviceWinCE::minimizeWindow() { // do nothing } //! Maximize window void CIrrDeviceWinCE::maximizeWindow() { // do nothing } //! Restore original window size void CIrrDeviceWinCE::restoreWindow() { // do nothing } } // end namespace #endif // _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ irrlicht-1.8.3/source/Irrlicht/CIrrDeviceWin32.h0000644000000000000000000002717712574354552020126 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IRR_DEVICE_WIN32_H_INCLUDED__ #define __C_IRR_DEVICE_WIN32_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ #include "CIrrDeviceStub.h" #include "IrrlichtDevice.h" #include "IImagePresenter.h" #define WIN32_LEAN_AND_MEAN #if !defined(_IRR_XBOX_PLATFORM_) #include #include // For JOYCAPS #include #endif #if !defined(GET_X_LPARAM) #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) #endif namespace irr { struct SJoystickWin32Control; class CIrrDeviceWin32 : public CIrrDeviceStub, video::IImagePresenter { friend struct SJoystickWin32Control; public: //! constructor CIrrDeviceWin32(const SIrrlichtCreationParameters& params); //! destructor virtual ~CIrrDeviceWin32(); //! runs the device. Returns false if device wants to be deleted virtual bool run(); //! Cause the device to temporarily pause execution and let other processes to run // This should bring down processor usage without major performance loss for Irrlicht virtual void yield(); //! Pause execution and let other processes to run for a specified amount of time. virtual void sleep(u32 timeMs, bool pauseTimer); //! sets the caption of the window virtual void setWindowCaption(const wchar_t* text); //! returns if window is active. if not, nothing need to be drawn virtual bool isWindowActive() const; //! returns if window has focus virtual bool isWindowFocused() const; //! returns if window is minimized virtual bool isWindowMinimized() const; //! presents a surface in the client area virtual bool present(video::IImage* surface, void* windowId=0, core::rect* src=0); //! notifies the device that it should close itself virtual void closeDevice(); //! \return Returns a pointer to a list with all video modes //! supported by the gfx adapter. video::IVideoModeList* getVideoModeList(); //! Notifies the device, that it has been resized void OnResized(); //! Sets if the window should be resizable in windowed mode. virtual void setResizable(bool resize=false); //! Minimizes the window. virtual void minimizeWindow(); //! Maximizes the window. virtual void maximizeWindow(); //! Restores the window size. virtual void restoreWindow(); //! Activate any joysticks, and generate events for them. virtual bool activateJoysticks(core::array & joystickInfo); //! Set the current Gamma Value for the Display virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ); //! Get the current Gamma Value for the Display virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ); //! Remove all messages pending in the system message loop virtual void clearSystemMessages(); //! Get the device type virtual E_DEVICE_TYPE getType() const { return EIDT_WIN32; } //! Compares to the last call of this function to return double and triple clicks. //! \return Returns only 1,2 or 3. A 4th click will start with 1 again. virtual u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ) { // we just have to make it public return CIrrDeviceStub::checkSuccessiveClicks(mouseX, mouseY, inputEvent ); } //! switchs to fullscreen bool switchToFullScreen(bool reset=false); //! Check for and show last Windows API error to help internal debugging. //! Does call GetLastError and on errors formats the errortext and displays it in a messagebox. static void ReportLastWinApiError(); // convert an Irrlicht texture to a windows cursor HCURSOR TextureToCursor(HWND hwnd, irr::video::ITexture * tex, const core::rect& sourceRect, const core::position2d &hotspot); //! Implementation of the win32 cursor control class CCursorControl : public gui::ICursorControl { public: CCursorControl(CIrrDeviceWin32* device, const core::dimension2d& wsize, HWND hwnd, bool fullscreen); ~CCursorControl(); //! Changes the visible state of the mouse cursor. virtual void setVisible(bool visible) { CURSORINFO info; info.cbSize = sizeof(CURSORINFO); BOOL gotCursorInfo = GetCursorInfo(&info); while ( gotCursorInfo ) { #ifdef CURSOR_SUPPRESSED // new flag for Windows 8, where cursor // might be suppressed for touch interface if (info.flags == CURSOR_SUPPRESSED) { visible=false; break; } #endif if ( (visible && info.flags == CURSOR_SHOWING) || // visible (!visible && info.flags == 0 ) ) // hidden { break; } // this only increases an internal // display counter in windows, so it // might have to be called some more const int showResult = ShowCursor(visible); // if result has correct sign we can // stop here as well if (( !visible && showResult < 0 ) || (visible && showResult >= 0)) break; // yes, it really must be set each time info.cbSize = sizeof(CURSORINFO); gotCursorInfo = GetCursorInfo(&info); } IsVisible = visible; } //! Returns if the cursor is currently visible. virtual bool isVisible() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return IsVisible; } //! Sets the new position of the cursor. virtual void setPosition(const core::position2d &pos) { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. virtual void setPosition(f32 x, f32 y) { if (!UseReferenceRect) setPosition(core::round32(x*WindowSize.Width), core::round32(y*WindowSize.Height)); else setPosition(core::round32(x*ReferenceRect.getWidth()), core::round32(y*ReferenceRect.getHeight())); } //! Sets the new position of the cursor. virtual void setPosition(const core::position2d &pos) { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. virtual void setPosition(s32 x, s32 y) { if (UseReferenceRect) { SetCursorPos(ReferenceRect.UpperLeftCorner.X + x, ReferenceRect.UpperLeftCorner.Y + y); } else { RECT rect; if (GetWindowRect(HWnd, &rect)) SetCursorPos(x + rect.left + BorderX, y + rect.top + BorderY); } CursorPos.X = x; CursorPos.Y = y; } //! Returns the current position of the mouse cursor. virtual const core::position2d& getPosition() { updateInternalCursorPosition(); return CursorPos; } //! Returns the current position of the mouse cursor. virtual core::position2d getRelativePosition() { updateInternalCursorPosition(); if (!UseReferenceRect) { return core::position2d(CursorPos.X * InvWindowSize.Width, CursorPos.Y * InvWindowSize.Height); } return core::position2d(CursorPos.X / (f32)ReferenceRect.getWidth(), CursorPos.Y / (f32)ReferenceRect.getHeight()); } //! Sets an absolute reference rect for calculating the cursor position. virtual void setReferenceRect(core::rect* rect=0) { if (rect) { ReferenceRect = *rect; UseReferenceRect = true; // prevent division through zero and uneven sizes if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2) ReferenceRect.LowerRightCorner.Y += 1; if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2) ReferenceRect.LowerRightCorner.X += 1; } else UseReferenceRect = false; } /** Used to notify the cursor that the window was resized. */ virtual void OnResize(const core::dimension2d& size) { WindowSize = size; if (size.Width!=0) InvWindowSize.Width = 1.0f / size.Width; else InvWindowSize.Width = 0.f; if (size.Height!=0) InvWindowSize.Height = 1.0f / size.Height; else InvWindowSize.Height = 0.f; } /** Used to notify the cursor that the window resizable settings changed. */ void updateBorderSize(bool fullscreen, bool resizable) { if (!fullscreen) { if (resizable) { BorderX = GetSystemMetrics(SM_CXSIZEFRAME); BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME); } else { BorderX = GetSystemMetrics(SM_CXDLGFRAME); BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME); } } else { BorderX = BorderY = 0; } } //! Sets the active cursor icon virtual void setActiveIcon(gui::ECURSOR_ICON iconId); //! Gets the currently active icon virtual gui::ECURSOR_ICON getActiveIcon() const { return ActiveIcon; } //! Add a custom sprite as cursor icon. virtual gui::ECURSOR_ICON addIcon(const gui::SCursorSprite& icon); //! replace the given cursor icon. virtual void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon); //! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work. virtual core::dimension2di getSupportedIconSize() const; void update(); private: //! Updates the internal cursor position void updateInternalCursorPosition() { POINT p; if (!GetCursorPos(&p)) { DWORD xy = GetMessagePos(); p.x = GET_X_LPARAM(xy); p.y = GET_Y_LPARAM(xy); } if (UseReferenceRect) { CursorPos.X = p.x - ReferenceRect.UpperLeftCorner.X; CursorPos.Y = p.y - ReferenceRect.UpperLeftCorner.Y; } else { RECT rect; if (GetWindowRect(HWnd, &rect)) { CursorPos.X = p.x-rect.left-BorderX; CursorPos.Y = p.y-rect.top-BorderY; } else { // window seems not to be existent, so set cursor to // a negative value CursorPos.X = -1; CursorPos.Y = -1; } } } CIrrDeviceWin32* Device; core::position2d CursorPos; core::dimension2d WindowSize; core::dimension2d InvWindowSize; HWND HWnd; s32 BorderX, BorderY; core::rect ReferenceRect; bool UseReferenceRect; bool IsVisible; struct CursorFrameW32 { CursorFrameW32() : IconHW(0) {} CursorFrameW32(HCURSOR icon) : IconHW(icon) {} HCURSOR IconHW; // hardware cursor }; struct CursorW32 { CursorW32() {} explicit CursorW32(HCURSOR iconHw, u32 frameTime=0) : FrameTime(frameTime) { Frames.push_back( CursorFrameW32(iconHw) ); } core::array Frames; u32 FrameTime; }; core::array Cursors; gui::ECURSOR_ICON ActiveIcon; u32 ActiveIconStartTime; void initCursors(); }; //! returns the win32 cursor control CCursorControl* getWin32CursorControl(); private: //! create the driver void createDriver(); //! Process system events void handleSystemMessages(); void getWindowsVersion(core::stringc& version); void resizeIfNecessary(); HWND HWnd; bool ChangedToFullScreen; bool Resized; bool ExternalWindow; CCursorControl* Win32CursorControl; DEVMODE DesktopMode; SJoystickWin32Control* JoyControl; }; } // end namespace irr #endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ #endif // __C_IRR_DEVICE_WIN32_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CIrrDeviceWin32.cpp0000644000000000000000000016152712574354552020457 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ #include "CIrrDeviceWin32.h" #include "IEventReceiver.h" #include "irrList.h" #include "os.h" #include "CTimer.h" #include "irrString.h" #include "COSOperator.h" #include "dimension2d.h" #include "IGUISpriteBank.h" #include #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) #ifdef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ #define DIRECTINPUT_VERSION 0x0800 #include #ifdef _MSC_VER #pragma comment(lib, "dinput8.lib") #pragma comment(lib, "dxguid.lib") #endif #else #ifdef _MSC_VER #pragma comment(lib, "winmm.lib") #endif #endif #endif namespace irr { namespace video { #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ IVideoDriver* createDirectX8Driver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, HWND window); #endif #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ IVideoDriver* createDirectX9Driver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, HWND window); #endif #ifdef _IRR_COMPILE_WITH_OPENGL_ IVideoDriver* createOpenGLDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceWin32* device); #endif } } // end namespace irr namespace irr { struct SJoystickWin32Control { CIrrDeviceWin32* Device; #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) && defined(_IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_) IDirectInput8* DirectInputDevice; #endif #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) struct JoystickInfo { u32 Index; #ifdef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ core::stringc Name; GUID guid; LPDIRECTINPUTDEVICE8 lpdijoy; DIDEVCAPS devcaps; u8 axisValid[8]; #else JOYCAPS Caps; #endif }; core::array ActiveJoysticks; #endif SJoystickWin32Control(CIrrDeviceWin32* dev) : Device(dev) { #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) && defined(_IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_) DirectInputDevice=0; if (DI_OK != (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&DirectInputDevice, NULL))) { os::Printer::log("Could not create DirectInput8 Object", ELL_WARNING); return; } #endif } ~SJoystickWin32Control() { #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) && defined(_IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_) for(u32 joystick = 0; joystick < ActiveJoysticks.size(); ++joystick) { LPDIRECTINPUTDEVICE8 dev = ActiveJoysticks[joystick].lpdijoy; if (dev) { dev->Unacquire(); } dev->Release(); } if (DirectInputDevice) DirectInputDevice->Release(); #endif } #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) && defined(_IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_) static BOOL CALLBACK EnumJoysticks(LPCDIDEVICEINSTANCE lpddi, LPVOID cp) { SJoystickWin32Control* p=(SJoystickWin32Control*)cp; p->directInputAddJoystick(lpddi); return DIENUM_CONTINUE; } void directInputAddJoystick(LPCDIDEVICEINSTANCE lpddi) { //Get the GUID of the joystuck const GUID guid = lpddi->guidInstance; JoystickInfo activeJoystick; activeJoystick.Index=ActiveJoysticks.size(); activeJoystick.guid=guid; activeJoystick.Name=lpddi->tszProductName; if (FAILED(DirectInputDevice->CreateDevice(guid, &activeJoystick.lpdijoy, NULL))) { os::Printer::log("Could not create DirectInput device", ELL_WARNING); return; } activeJoystick.devcaps.dwSize=sizeof(activeJoystick.devcaps); if (FAILED(activeJoystick.lpdijoy->GetCapabilities(&activeJoystick.devcaps))) { os::Printer::log("Could not create DirectInput device", ELL_WARNING); return; } if (FAILED(activeJoystick.lpdijoy->SetCooperativeLevel(Device->HWnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE))) { os::Printer::log("Could not set DirectInput device cooperative level", ELL_WARNING); return; } if (FAILED(activeJoystick.lpdijoy->SetDataFormat(&c_dfDIJoystick2))) { os::Printer::log("Could not set DirectInput device data format", ELL_WARNING); return; } if (FAILED(activeJoystick.lpdijoy->Acquire())) { os::Printer::log("Could not set DirectInput cooperative level", ELL_WARNING); return; } DIJOYSTATE2 info; if (FAILED(activeJoystick.lpdijoy->GetDeviceState(sizeof(info),&info))) { os::Printer::log("Could not read DirectInput device state", ELL_WARNING); return; } ZeroMemory(activeJoystick.axisValid,sizeof(activeJoystick.axisValid)); activeJoystick.axisValid[0]= (info.lX!=0) ? 1 : 0; activeJoystick.axisValid[1]= (info.lY!=0) ? 1 : 0; activeJoystick.axisValid[2]= (info.lZ!=0) ? 1 : 0; activeJoystick.axisValid[3]= (info.lRx!=0) ? 1 : 0; activeJoystick.axisValid[4]= (info.lRy!=0) ? 1 : 0; activeJoystick.axisValid[5]= (info.lRz!=0) ? 1 : 0; int caxis=0; for (u8 i=0; i<6; i++) { if (activeJoystick.axisValid[i]) caxis++; } for (u8 i=0; i<(activeJoystick.devcaps.dwAxes)-caxis; i++) { if (i+caxis < 8) activeJoystick.axisValid[i+caxis]=1; } ActiveJoysticks.push_back(activeJoystick); } #endif void pollJoysticks() { #if defined _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ #ifdef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ if(0 == ActiveJoysticks.size()) return; u32 joystick; DIJOYSTATE2 info; for(joystick = 0; joystick < ActiveJoysticks.size(); ++joystick) { // needs to be reset for each joystick // request ALL values and POV as continuous if possible const DIDEVCAPS & caps = ActiveJoysticks[joystick].devcaps; // if no POV is available don't ask for POV values if (!FAILED(ActiveJoysticks[joystick].lpdijoy->GetDeviceState(sizeof(info),&info))) { SEvent event; event.EventType = irr::EET_JOYSTICK_INPUT_EVENT; event.JoystickEvent.Joystick = (u8)joystick; event.JoystickEvent.POV = (u16)info.rgdwPOV[0]; // set to undefined if no POV value was returned or the value // is out of range if ((caps.dwPOVs==0) || (event.JoystickEvent.POV > 35900)) event.JoystickEvent.POV = 65535; for(int axis = 0; axis < SEvent::SJoystickEvent::NUMBER_OF_AXES; ++axis) event.JoystickEvent.Axis[axis] = 0; u16 dxAxis=0; u16 irrAxis=0; while (dxAxis < 6 && irrAxis 0) axisFound=1; if (axisFound) { s32 val=axisValue - 32768; if (val <-32767) val=-32767; if (val > 32767) val=32767; event.JoystickEvent.Axis[irrAxis]=(s16)(val); irrAxis++; } dxAxis++; } u32 buttons=0; BYTE* bytebuttons=info.rgbButtons; for (u16 i=0; i<32; i++) { if (bytebuttons[i] >0) { buttons |= (1 << i); } } event.JoystickEvent.ButtonStates = buttons; (void)Device->postEventFromUser(event); } } #else if (0 == ActiveJoysticks.size()) return; u32 joystick; JOYINFOEX info; for(joystick = 0; joystick < ActiveJoysticks.size(); ++joystick) { // needs to be reset for each joystick // request ALL values and POV as continuous if possible info.dwSize = sizeof(info); info.dwFlags = JOY_RETURNALL|JOY_RETURNPOVCTS; const JOYCAPS & caps = ActiveJoysticks[joystick].Caps; // if no POV is available don't ask for POV values if (!(caps.wCaps & JOYCAPS_HASPOV)) info.dwFlags &= ~(JOY_RETURNPOV|JOY_RETURNPOVCTS); if(JOYERR_NOERROR == joyGetPosEx(ActiveJoysticks[joystick].Index, &info)) { SEvent event; event.EventType = irr::EET_JOYSTICK_INPUT_EVENT; event.JoystickEvent.Joystick = (u8)joystick; event.JoystickEvent.POV = (u16)info.dwPOV; // set to undefined if no POV value was returned or the value // is out of range if (!(info.dwFlags & JOY_RETURNPOV) || (event.JoystickEvent.POV > 35900)) event.JoystickEvent.POV = 65535; for(int axis = 0; axis < SEvent::SJoystickEvent::NUMBER_OF_AXES; ++axis) event.JoystickEvent.Axis[axis] = 0; event.JoystickEvent.ButtonStates = info.dwButtons; switch(caps.wNumAxes) { default: case 6: event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_V] = (s16)((65535 * (info.dwVpos - caps.wVmin)) / (caps.wVmax - caps.wVmin) - 32768); case 5: event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_U] = (s16)((65535 * (info.dwUpos - caps.wUmin)) / (caps.wUmax - caps.wUmin) - 32768); case 4: event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_R] = (s16)((65535 * (info.dwRpos - caps.wRmin)) / (caps.wRmax - caps.wRmin) - 32768); case 3: event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_Z] = (s16)((65535 * (info.dwZpos - caps.wZmin)) / (caps.wZmax - caps.wZmin) - 32768); case 2: event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_Y] = (s16)((65535 * (info.dwYpos - caps.wYmin)) / (caps.wYmax - caps.wYmin) - 32768); case 1: event.JoystickEvent.Axis[SEvent::SJoystickEvent::AXIS_X] = (s16)((65535 * (info.dwXpos - caps.wXmin)) / (caps.wXmax - caps.wXmin) - 32768); } (void)Device->postEventFromUser(event); } } #endif #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ } bool activateJoysticks(core::array & joystickInfo) { #if defined _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ #ifdef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ if (!DirectInputDevice || (DirectInputDevice->EnumDevices(DI8DEVCLASS_GAMECTRL, SJoystickWin32Control::EnumJoysticks, this, DIEDFL_ATTACHEDONLY ))) { os::Printer::log("Could not enum DirectInput8 controllers", ELL_WARNING); return false; } for(u32 joystick = 0; joystick < ActiveJoysticks.size(); ++joystick) { JoystickInfo& activeJoystick = ActiveJoysticks[joystick]; SJoystickInfo info; info.Axes=activeJoystick.devcaps.dwAxes; info.Buttons=activeJoystick.devcaps.dwButtons; info.Name=activeJoystick.Name; info.PovHat = (activeJoystick.devcaps.dwPOVs != 0) ? SJoystickInfo::POV_HAT_PRESENT : SJoystickInfo::POV_HAT_ABSENT; joystickInfo.push_back(info); } return true; #else joystickInfo.clear(); ActiveJoysticks.clear(); const u32 numberOfJoysticks = ::joyGetNumDevs(); JOYINFOEX info; info.dwSize = sizeof(info); info.dwFlags = JOY_RETURNALL; JoystickInfo activeJoystick; SJoystickInfo returnInfo; joystickInfo.reallocate(numberOfJoysticks); ActiveJoysticks.reallocate(numberOfJoysticks); u32 joystick = 0; for(; joystick < numberOfJoysticks; ++joystick) { if(JOYERR_NOERROR == joyGetPosEx(joystick, &info) && JOYERR_NOERROR == joyGetDevCaps(joystick, &activeJoystick.Caps, sizeof(activeJoystick.Caps))) { activeJoystick.Index = joystick; ActiveJoysticks.push_back(activeJoystick); returnInfo.Joystick = (u8)joystick; returnInfo.Axes = activeJoystick.Caps.wNumAxes; returnInfo.Buttons = activeJoystick.Caps.wNumButtons; returnInfo.Name = activeJoystick.Caps.szPname; returnInfo.PovHat = ((activeJoystick.Caps.wCaps & JOYCAPS_HASPOV) == JOYCAPS_HASPOV) ? SJoystickInfo::POV_HAT_PRESENT : SJoystickInfo::POV_HAT_ABSENT; joystickInfo.push_back(returnInfo); } } for(joystick = 0; joystick < joystickInfo.size(); ++joystick) { char logString[256]; (void)sprintf(logString, "Found joystick %d, %d axes, %d buttons '%s'", joystick, joystickInfo[joystick].Axes, joystickInfo[joystick].Buttons, joystickInfo[joystick].Name.c_str()); os::Printer::log(logString, ELL_INFORMATION); } return true; #endif #else return false; #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ } }; } // end namespace irr // Get the codepage from the locale language id // Based on the table from http://www.science.co.il/Language/Locale-Codes.asp?s=decimal static unsigned int LocaleIdToCodepage(unsigned int lcid) { switch ( lcid ) { case 1098: // Telugu case 1095: // Gujarati case 1094: // Punjabi case 1103: // Sanskrit case 1111: // Konkani case 1114: // Syriac case 1099: // Kannada case 1102: // Marathi case 1125: // Divehi case 1067: // Armenian case 1081: // Hindi case 1079: // Georgian case 1097: // Tamil return 0; case 1054: // Thai return 874; case 1041: // Japanese return 932; case 2052: // Chinese (PRC) case 4100: // Chinese (Singapore) return 936; case 1042: // Korean return 949; case 5124: // Chinese (Macau S.A.R.) case 3076: // Chinese (Hong Kong S.A.R.) case 1028: // Chinese (Taiwan) return 950; case 1048: // Romanian case 1060: // Slovenian case 1038: // Hungarian case 1051: // Slovak case 1045: // Polish case 1052: // Albanian case 2074: // Serbian (Latin) case 1050: // Croatian case 1029: // Czech return 1250; case 1104: // Mongolian (Cyrillic) case 1071: // FYRO Macedonian case 2115: // Uzbek (Cyrillic) case 1058: // Ukrainian case 2092: // Azeri (Cyrillic) case 1092: // Tatar case 1087: // Kazakh case 1059: // Belarusian case 1088: // Kyrgyz (Cyrillic) case 1026: // Bulgarian case 3098: // Serbian (Cyrillic) case 1049: // Russian return 1251; case 8201: // English (Jamaica) case 3084: // French (Canada) case 1036: // French (France) case 5132: // French (Luxembourg) case 5129: // English (New Zealand) case 6153: // English (Ireland) case 1043: // Dutch (Netherlands) case 9225: // English (Caribbean) case 4108: // French (Switzerland) case 4105: // English (Canada) case 1110: // Galician case 10249: // English (Belize) case 3079: // German (Austria) case 6156: // French (Monaco) case 12297: // English (Zimbabwe) case 1069: // Basque case 2067: // Dutch (Belgium) case 2060: // French (Belgium) case 1035: // Finnish case 1080: // Faroese case 1031: // German (Germany) case 3081: // English (Australia) case 1033: // English (United States) case 2057: // English (United Kingdom) case 1027: // Catalan case 11273: // English (Trinidad) case 7177: // English (South Africa) case 1030: // Danish case 13321: // English (Philippines) case 15370: // Spanish (Paraguay) case 9226: // Spanish (Colombia) case 5130: // Spanish (Costa Rica) case 7178: // Spanish (Dominican Republic) case 12298: // Spanish (Ecuador) case 17418: // Spanish (El Salvador) case 4106: // Spanish (Guatemala) case 18442: // Spanish (Honduras) case 3082: // Spanish (International Sort) case 13322: // Spanish (Chile) case 19466: // Spanish (Nicaragua) case 2058: // Spanish (Mexico) case 10250: // Spanish (Peru) case 20490: // Spanish (Puerto Rico) case 1034: // Spanish (Traditional Sort) case 14346: // Spanish (Uruguay) case 8202: // Spanish (Venezuela) case 1089: // Swahili case 1053: // Swedish case 2077: // Swedish (Finland) case 5127: // German (Liechtenstein) case 1078: // Afrikaans case 6154: // Spanish (Panama) case 4103: // German (Luxembourg) case 16394: // Spanish (Bolivia) case 2055: // German (Switzerland) case 1039: // Icelandic case 1057: // Indonesian case 1040: // Italian (Italy) case 2064: // Italian (Switzerland) case 2068: // Norwegian (Nynorsk) case 11274: // Spanish (Argentina) case 1046: // Portuguese (Brazil) case 1044: // Norwegian (Bokmal) case 1086: // Malay (Malaysia) case 2110: // Malay (Brunei Darussalam) case 2070: // Portuguese (Portugal) return 1252; case 1032: // Greek return 1253; case 1091: // Uzbek (Latin) case 1068: // Azeri (Latin) case 1055: // Turkish return 1254; case 1037: // Hebrew return 1255; case 5121: // Arabic (Algeria) case 15361: // Arabic (Bahrain) case 9217: // Arabic (Yemen) case 3073: // Arabic (Egypt) case 2049: // Arabic (Iraq) case 11265: // Arabic (Jordan) case 13313: // Arabic (Kuwait) case 12289: // Arabic (Lebanon) case 4097: // Arabic (Libya) case 6145: // Arabic (Morocco) case 8193: // Arabic (Oman) case 16385: // Arabic (Qatar) case 1025: // Arabic (Saudi Arabia) case 10241: // Arabic (Syria) case 14337: // Arabic (U.A.E.) case 1065: // Farsi case 1056: // Urdu case 7169: // Arabic (Tunisia) return 1256; case 1061: // Estonian case 1062: // Latvian case 1063: // Lithuanian return 1257; case 1066: // Vietnamese return 1258; } return 65001; // utf-8 } namespace { struct SEnvMapper { HWND hWnd; irr::CIrrDeviceWin32* irrDev; }; irr::core::list EnvMap; HKL KEYBOARD_INPUT_HKL=0; unsigned int KEYBOARD_INPUT_CODEPAGE = 1252; } SEnvMapper* getEnvMapperFromHWnd(HWND hWnd) { irr::core::list::Iterator it = EnvMap.begin(); for (; it!= EnvMap.end(); ++it) if ((*it).hWnd == hWnd) return &(*it); return 0; } irr::CIrrDeviceWin32* getDeviceFromHWnd(HWND hWnd) { irr::core::list::Iterator it = EnvMap.begin(); for (; it!= EnvMap.end(); ++it) if ((*it).hWnd == hWnd) return (*it).irrDev; return 0; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { #ifndef WM_MOUSEWHEEL #define WM_MOUSEWHEEL 0x020A #endif #ifndef WHEEL_DELTA #define WHEEL_DELTA 120 #endif irr::CIrrDeviceWin32* dev = 0; irr::SEvent event; static irr::s32 ClickCount=0; if (GetCapture() != hWnd && ClickCount > 0) ClickCount = 0; struct messageMap { irr::s32 group; UINT winMessage; irr::s32 irrMessage; }; static messageMap mouseMap[] = { {0, WM_LBUTTONDOWN, irr::EMIE_LMOUSE_PRESSED_DOWN}, {1, WM_LBUTTONUP, irr::EMIE_LMOUSE_LEFT_UP}, {0, WM_RBUTTONDOWN, irr::EMIE_RMOUSE_PRESSED_DOWN}, {1, WM_RBUTTONUP, irr::EMIE_RMOUSE_LEFT_UP}, {0, WM_MBUTTONDOWN, irr::EMIE_MMOUSE_PRESSED_DOWN}, {1, WM_MBUTTONUP, irr::EMIE_MMOUSE_LEFT_UP}, {2, WM_MOUSEMOVE, irr::EMIE_MOUSE_MOVED}, {3, WM_MOUSEWHEEL, irr::EMIE_MOUSE_WHEEL}, {-1, 0, 0} }; // handle grouped events messageMap * m = mouseMap; while ( m->group >=0 && m->winMessage != message ) m += 1; if ( m->group >= 0 ) { if ( m->group == 0 ) // down { ClickCount++; SetCapture(hWnd); } else if ( m->group == 1 ) // up { ClickCount--; if (ClickCount<1) { ClickCount=0; ReleaseCapture(); } } event.EventType = irr::EET_MOUSE_INPUT_EVENT; event.MouseInput.Event = (irr::EMOUSE_INPUT_EVENT) m->irrMessage; event.MouseInput.X = (short)LOWORD(lParam); event.MouseInput.Y = (short)HIWORD(lParam); event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0); event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0); // left and right mouse buttons event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON); // middle and extra buttons if (wParam & MK_MBUTTON) event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE; #if(_WIN32_WINNT >= 0x0500) if (wParam & MK_XBUTTON1) event.MouseInput.ButtonStates |= irr::EMBSM_EXTRA1; if (wParam & MK_XBUTTON2) event.MouseInput.ButtonStates |= irr::EMBSM_EXTRA2; #endif event.MouseInput.Wheel = 0.f; // wheel if ( m->group == 3 ) { POINT p; // fixed by jox p.x = 0; p.y = 0; ClientToScreen(hWnd, &p); event.MouseInput.X -= p.x; event.MouseInput.Y -= p.y; event.MouseInput.Wheel = ((irr::f32)((short)HIWORD(wParam))) / (irr::f32)WHEEL_DELTA; } dev = getDeviceFromHWnd(hWnd); if (dev) { dev->postEventFromUser(event); if ( event.MouseInput.Event >= irr::EMIE_LMOUSE_PRESSED_DOWN && event.MouseInput.Event <= irr::EMIE_MMOUSE_PRESSED_DOWN ) { irr::u32 clicks = dev->checkSuccessiveClicks(event.MouseInput.X, event.MouseInput.Y, event.MouseInput.Event); if ( clicks == 2 ) { event.MouseInput.Event = (irr::EMOUSE_INPUT_EVENT)(irr::EMIE_LMOUSE_DOUBLE_CLICK + event.MouseInput.Event-irr::EMIE_LMOUSE_PRESSED_DOWN); dev->postEventFromUser(event); } else if ( clicks == 3 ) { event.MouseInput.Event = (irr::EMOUSE_INPUT_EVENT)(irr::EMIE_LMOUSE_TRIPLE_CLICK + event.MouseInput.Event-irr::EMIE_LMOUSE_PRESSED_DOWN); dev->postEventFromUser(event); } } } return 0; } switch (message) { case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); } return 0; case WM_ERASEBKGND: return 0; case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_KEYDOWN: case WM_KEYUP: { BYTE allKeys[256]; event.EventType = irr::EET_KEY_INPUT_EVENT; event.KeyInput.Key = (irr::EKEY_CODE)wParam; event.KeyInput.PressedDown = (message==WM_KEYDOWN || message == WM_SYSKEYDOWN); const UINT MY_MAPVK_VSC_TO_VK_EX = 3; // MAPVK_VSC_TO_VK_EX should be in SDK according to MSDN, but isn't in mine. if ( event.KeyInput.Key == irr::KEY_SHIFT ) { // this will fail on systems before windows NT/2000/XP, not sure _what_ will return there instead. event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MY_MAPVK_VSC_TO_VK_EX ); } if ( event.KeyInput.Key == irr::KEY_CONTROL ) { event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MY_MAPVK_VSC_TO_VK_EX ); // some keyboards will just return LEFT for both - left and right keys. So also check extend bit. if (lParam & 0x1000000) event.KeyInput.Key = irr::KEY_RCONTROL; } if ( event.KeyInput.Key == irr::KEY_MENU ) { event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MY_MAPVK_VSC_TO_VK_EX ); if (lParam & 0x1000000) event.KeyInput.Key = irr::KEY_RMENU; } GetKeyboardState(allKeys); event.KeyInput.Shift = ((allKeys[VK_SHIFT] & 0x80)!=0); event.KeyInput.Control = ((allKeys[VK_CONTROL] & 0x80)!=0); // Handle unicode and deadkeys in a way that works since Windows 95 and nt4.0 // Using ToUnicode instead would be shorter, but would to my knowledge not run on 95 and 98. WORD keyChars[2]; UINT scanCode = HIWORD(lParam); int conversionResult = ToAsciiEx(wParam,scanCode,allKeys,keyChars,0,KEYBOARD_INPUT_HKL); if (conversionResult == 1) { WORD unicodeChar; MultiByteToWideChar( KEYBOARD_INPUT_CODEPAGE, MB_PRECOMPOSED, // default (LPCSTR)keyChars, sizeof(keyChars), (WCHAR*)&unicodeChar, 1 ); event.KeyInput.Char = unicodeChar; } else event.KeyInput.Char = 0; // allow composing characters like '@' with Alt Gr on non-US keyboards if ((allKeys[VK_MENU] & 0x80) != 0) event.KeyInput.Control = 0; dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); if (message == WM_SYSKEYDOWN || message == WM_SYSKEYUP) return DefWindowProc(hWnd, message, wParam, lParam); else return 0; } case WM_SIZE: { // resize dev = getDeviceFromHWnd(hWnd); if (dev) dev->OnResized(); } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; case WM_SYSCOMMAND: // prevent screensaver or monitor powersave mode from starting if ((wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER || (wParam & 0xFFF0) == SC_KEYMENU ) return 0; break; case WM_ACTIVATE: // we need to take care for screen changes, e.g. Alt-Tab dev = getDeviceFromHWnd(hWnd); if (dev && dev->isFullscreen()) { if ((wParam&0xFF)==WA_INACTIVE) { // If losing focus we minimize the app to show other one ShowWindow(hWnd,SW_MINIMIZE); // and switch back to default resolution dev->switchToFullScreen(true); } else { // Otherwise we retore the fullscreen Irrlicht app SetForegroundWindow(hWnd); ShowWindow(hWnd, SW_RESTORE); // and set the fullscreen resolution again dev->switchToFullScreen(); } } break; case WM_USER: event.EventType = irr::EET_USER_EVENT; event.UserEvent.UserData1 = (irr::s32)wParam; event.UserEvent.UserData2 = (irr::s32)lParam; dev = getDeviceFromHWnd(hWnd); if (dev) dev->postEventFromUser(event); return 0; case WM_SETCURSOR: // because Windows forgot about that in the meantime dev = getDeviceFromHWnd(hWnd); if (dev) { dev->getCursorControl()->setActiveIcon( dev->getCursorControl()->getActiveIcon() ); dev->getCursorControl()->setVisible( dev->getCursorControl()->isVisible() ); } break; case WM_INPUTLANGCHANGE: // get the new codepage used for keyboard input KEYBOARD_INPUT_HKL = GetKeyboardLayout(0); KEYBOARD_INPUT_CODEPAGE = LocaleIdToCodepage( LOWORD(KEYBOARD_INPUT_HKL) ); return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } namespace irr { //! constructor CIrrDeviceWin32::CIrrDeviceWin32(const SIrrlichtCreationParameters& params) : CIrrDeviceStub(params), HWnd(0), ChangedToFullScreen(false), Resized(false), ExternalWindow(false), Win32CursorControl(0), JoyControl(0) { #ifdef _DEBUG setDebugName("CIrrDeviceWin32"); #endif // get windows version and create OS operator core::stringc winversion; getWindowsVersion(winversion); Operator = new COSOperator(winversion); os::Printer::log(winversion.c_str(), ELL_INFORMATION); // get handle to exe file HINSTANCE hInstance = GetModuleHandle(0); // Store original desktop mode. memset(&DesktopMode, 0, sizeof(DesktopMode)); DesktopMode.dmSize = sizeof(DesktopMode); EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DesktopMode); // create the window if we need to and we do not use the null device if (!CreationParams.WindowId && CreationParams.DriverType != video::EDT_NULL) { const fschar_t* ClassName = __TEXT("CIrrDeviceWin32"); // Register Class WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = NULL; wcex.hCursor = 0; // LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = 0; wcex.lpszClassName = ClassName; wcex.hIconSm = 0; // if there is an icon, load it wcex.hIcon = (HICON)LoadImage(hInstance, __TEXT("irrlicht.ico"), IMAGE_ICON, 0,0, LR_LOADFROMFILE); RegisterClassEx(&wcex); // calculate client size RECT clientSize; clientSize.top = 0; clientSize.left = 0; clientSize.right = CreationParams.WindowSize.Width; clientSize.bottom = CreationParams.WindowSize.Height; DWORD style = WS_POPUP; if (!CreationParams.Fullscreen) style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; AdjustWindowRect(&clientSize, style, FALSE); const s32 realWidth = clientSize.right - clientSize.left; const s32 realHeight = clientSize.bottom - clientSize.top; s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2; s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2; if ( windowLeft < 0 ) windowLeft = 0; if ( windowTop < 0 ) windowTop = 0; // make sure window menus are in screen on creation if (CreationParams.Fullscreen) { windowLeft = 0; windowTop = 0; } // create window HWnd = CreateWindow( ClassName, __TEXT(""), style, windowLeft, windowTop, realWidth, realHeight, NULL, NULL, hInstance, NULL); CreationParams.WindowId = HWnd; // CreationParams.WindowSize.Width = realWidth; // CreationParams.WindowSize.Height = realHeight; ShowWindow(HWnd, SW_SHOWNORMAL); UpdateWindow(HWnd); // fix ugly ATI driver bugs. Thanks to ariaci MoveWindow(HWnd, windowLeft, windowTop, realWidth, realHeight, TRUE); // make sure everything gets updated to the real sizes Resized = true; } else if (CreationParams.WindowId) { // attach external window HWnd = static_cast(CreationParams.WindowId); RECT r; GetWindowRect(HWnd, &r); CreationParams.WindowSize.Width = r.right - r.left; CreationParams.WindowSize.Height = r.bottom - r.top; CreationParams.Fullscreen = false; ExternalWindow = true; } // create cursor control Win32CursorControl = new CCursorControl(this, CreationParams.WindowSize, HWnd, CreationParams.Fullscreen); CursorControl = Win32CursorControl; JoyControl = new SJoystickWin32Control(this); // initialize doubleclicks with system values MouseMultiClicks.DoubleClickTime = GetDoubleClickTime(); // create driver createDriver(); if (VideoDriver) createGUIAndScene(); // register environment SEnvMapper em; em.irrDev = this; em.hWnd = HWnd; EnvMap.push_back(em); // set this as active window if (!ExternalWindow) { SetActiveWindow(HWnd); SetForegroundWindow(HWnd); } // get the codepage used for keyboard input KEYBOARD_INPUT_HKL = GetKeyboardLayout(0); KEYBOARD_INPUT_CODEPAGE = LocaleIdToCodepage( LOWORD(KEYBOARD_INPUT_HKL) ); // inform driver about the window size etc. resizeIfNecessary(); } //! destructor CIrrDeviceWin32::~CIrrDeviceWin32() { delete JoyControl; // unregister environment irr::core::list::Iterator it = EnvMap.begin(); for (; it!= EnvMap.end(); ++it) { if ((*it).hWnd == HWnd) { EnvMap.erase(it); break; } } switchToFullScreen(true); } //! create the driver void CIrrDeviceWin32::createDriver() { switch(CreationParams.DriverType) { case video::EDT_DIRECT3D8: #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ VideoDriver = video::createDirectX8Driver(CreationParams, FileSystem, HWnd); if (!VideoDriver) { os::Printer::log("Could not create DIRECT3D8 Driver.", ELL_ERROR); } #else os::Printer::log("DIRECT3D8 Driver was not compiled into this dll. Try another one.", ELL_ERROR); #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ break; case video::EDT_DIRECT3D9: #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ VideoDriver = video::createDirectX9Driver(CreationParams, FileSystem, HWnd); if (!VideoDriver) { os::Printer::log("Could not create DIRECT3D9 Driver.", ELL_ERROR); } #else os::Printer::log("DIRECT3D9 Driver was not compiled into this dll. Try another one.", ELL_ERROR); #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ break; case video::EDT_OPENGL: #ifdef _IRR_COMPILE_WITH_OPENGL_ switchToFullScreen(); VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem, this); if (!VideoDriver) { os::Printer::log("Could not create OpenGL driver.", ELL_ERROR); } #else os::Printer::log("OpenGL driver was not compiled in.", ELL_ERROR); #endif break; case video::EDT_SOFTWARE: #ifdef _IRR_COMPILE_WITH_SOFTWARE_ switchToFullScreen(); VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); #else os::Printer::log("Software driver was not compiled in.", ELL_ERROR); #endif break; case video::EDT_BURNINGSVIDEO: #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ switchToFullScreen(); VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this); #else os::Printer::log("Burning's Video driver was not compiled in.", ELL_ERROR); #endif break; case video::EDT_NULL: // create null driver VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize); break; default: os::Printer::log("Unable to create video driver of unknown type.", ELL_ERROR); break; } } //! runs the device. Returns false if device wants to be deleted bool CIrrDeviceWin32::run() { os::Timer::tick(); static_cast(CursorControl)->update(); handleSystemMessages(); if (!Close) resizeIfNecessary(); if(!Close && JoyControl) JoyControl->pollJoysticks(); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return !Close; } //! Pause the current process for the minimum time allowed only to allow other processes to execute void CIrrDeviceWin32::yield() { Sleep(1); } //! Pause execution and let other processes to run for a specified amount of time. void CIrrDeviceWin32::sleep(u32 timeMs, bool pauseTimer) { const bool wasStopped = Timer ? Timer->isStopped() : true; if (pauseTimer && !wasStopped) Timer->stop(); Sleep(timeMs); if (pauseTimer && !wasStopped) Timer->start(); } void CIrrDeviceWin32::resizeIfNecessary() { if (!Resized || !getVideoDriver()) return; RECT r; GetClientRect(HWnd, &r); char tmp[255]; if (r.right < 2 || r.bottom < 2) { sprintf(tmp, "Ignoring resize operation to (%ld %ld)", r.right, r.bottom); os::Printer::log(tmp); } else { sprintf(tmp, "Resizing window (%ld %ld)", r.right, r.bottom); os::Printer::log(tmp); getVideoDriver()->OnResize(irr::core::dimension2du((u32)r.right, (u32)r.bottom)); getWin32CursorControl()->OnResize(getVideoDriver()->getScreenSize()); } Resized = false; } //! sets the caption of the window void CIrrDeviceWin32::setWindowCaption(const wchar_t* text) { // We use SendMessage instead of SetText to ensure proper // function even in cases where the HWND was created in a different thread DWORD_PTR dwResult; SendMessageTimeoutW(HWnd, WM_SETTEXT, 0, reinterpret_cast(text), SMTO_ABORTIFHUNG, 2000, &dwResult); } //! presents a surface in the client area bool CIrrDeviceWin32::present(video::IImage* image, void* windowId, core::rect* src) { HWND hwnd = HWnd; if ( windowId ) hwnd = reinterpret_cast(windowId); HDC dc = GetDC(hwnd); if ( dc ) { RECT rect; GetClientRect(hwnd, &rect); const void* memory = (const void *)image->lock(); BITMAPV4HEADER bi; ZeroMemory (&bi, sizeof(bi)); bi.bV4Size = sizeof(BITMAPINFOHEADER); bi.bV4BitCount = (WORD)image->getBitsPerPixel(); bi.bV4Planes = 1; bi.bV4Width = image->getDimension().Width; bi.bV4Height = -((s32)image->getDimension().Height); bi.bV4V4Compression = BI_BITFIELDS; bi.bV4AlphaMask = image->getAlphaMask(); bi.bV4RedMask = image->getRedMask(); bi.bV4GreenMask = image->getGreenMask(); bi.bV4BlueMask = image->getBlueMask(); if ( src ) { StretchDIBits(dc, 0,0, rect.right, rect.bottom, src->UpperLeftCorner.X, src->UpperLeftCorner.Y, src->getWidth(), src->getHeight(), memory, (const BITMAPINFO*)(&bi), DIB_RGB_COLORS, SRCCOPY); } else { StretchDIBits(dc, 0,0, rect.right, rect.bottom, 0, 0, image->getDimension().Width, image->getDimension().Height, memory, (const BITMAPINFO*)(&bi), DIB_RGB_COLORS, SRCCOPY); } image->unlock(); ReleaseDC(hwnd, dc); } return true; } //! notifies the device that it should close itself void CIrrDeviceWin32::closeDevice() { MSG msg; PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE); PostQuitMessage(0); PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE); if (!ExternalWindow) { DestroyWindow(HWnd); const fschar_t* ClassName = __TEXT("CIrrDeviceWin32"); HINSTANCE hInstance = GetModuleHandle(0); UnregisterClass(ClassName, hInstance); } Close=true; } //! returns if window is active. if not, nothing needs to be drawn bool CIrrDeviceWin32::isWindowActive() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return (GetActiveWindow() == HWnd); } //! returns if window has focus bool CIrrDeviceWin32::isWindowFocused() const { bool ret = (GetFocus() == HWnd); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! returns if window is minimized bool CIrrDeviceWin32::isWindowMinimized() const { WINDOWPLACEMENT plc; plc.length=sizeof(WINDOWPLACEMENT); bool ret=false; if (GetWindowPlacement(HWnd,&plc)) ret=(plc.showCmd & SW_SHOWMINIMIZED)!=0; _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! switches to fullscreen bool CIrrDeviceWin32::switchToFullScreen(bool reset) { if (!CreationParams.Fullscreen) return true; if (reset) { if (ChangedToFullScreen) { return (ChangeDisplaySettings(&DesktopMode,0)==DISP_CHANGE_SUCCESSFUL); } else return true; } // use default values from current setting DEVMODE dm; memset(&dm, 0, sizeof(dm)); dm.dmSize = sizeof(dm); EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm); dm.dmPelsWidth = CreationParams.WindowSize.Width; dm.dmPelsHeight = CreationParams.WindowSize.Height; dm.dmBitsPerPel = CreationParams.Bits; dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; LONG res = ChangeDisplaySettings(&dm, CDS_FULLSCREEN); if (res != DISP_CHANGE_SUCCESSFUL) { // try again without forcing display frequency dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; res = ChangeDisplaySettings(&dm, CDS_FULLSCREEN); } bool ret = false; switch(res) { case DISP_CHANGE_SUCCESSFUL: ChangedToFullScreen = true; ret = true; break; case DISP_CHANGE_RESTART: os::Printer::log("Switch to fullscreen: The computer must be restarted in order for the graphics mode to work.", ELL_ERROR); break; case DISP_CHANGE_BADFLAGS: os::Printer::log("Switch to fullscreen: An invalid set of flags was passed in.", ELL_ERROR); break; case DISP_CHANGE_BADPARAM: os::Printer::log("Switch to fullscreen: An invalid parameter was passed in. This can include an invalid flag or combination of flags.", ELL_ERROR); break; case DISP_CHANGE_FAILED: os::Printer::log("Switch to fullscreen: The display driver failed the specified graphics mode.", ELL_ERROR); break; case DISP_CHANGE_BADMODE: os::Printer::log("Switch to fullscreen: The graphics mode is not supported.", ELL_ERROR); break; default: os::Printer::log("An unknown error occured while changing to fullscreen.", ELL_ERROR); break; } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! returns the win32 cursor control CIrrDeviceWin32::CCursorControl* CIrrDeviceWin32::getWin32CursorControl() { return Win32CursorControl; } //! \return Returns a pointer to a list with all video modes supported //! by the gfx adapter. video::IVideoModeList* CIrrDeviceWin32::getVideoModeList() { if (!VideoModeList->getVideoModeCount()) { // enumerate video modes. DWORD i=0; DEVMODE mode; memset(&mode, 0, sizeof(mode)); mode.dmSize = sizeof(mode); while (EnumDisplaySettings(NULL, i, &mode)) { VideoModeList->addMode(core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight), mode.dmBitsPerPel); ++i; } if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &mode)) VideoModeList->setDesktop(mode.dmBitsPerPel, core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight)); } return VideoModeList; } typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD); // Needed for old windows apis // depending on the SDK version and compilers some defines might be available // or not #ifndef PRODUCT_ULTIMATE #define PRODUCT_ULTIMATE 0x00000001 #define PRODUCT_HOME_BASIC 0x00000002 #define PRODUCT_HOME_PREMIUM 0x00000003 #define PRODUCT_ENTERPRISE 0x00000004 #define PRODUCT_HOME_BASIC_N 0x00000005 #define PRODUCT_BUSINESS 0x00000006 #define PRODUCT_STARTER 0x0000000B #endif #ifndef PRODUCT_ULTIMATE_N #define PRODUCT_BUSINESS_N 0x00000010 #define PRODUCT_HOME_PREMIUM_N 0x0000001A #define PRODUCT_ENTERPRISE_N 0x0000001B #define PRODUCT_ULTIMATE_N 0x0000001C #endif #ifndef PRODUCT_STARTER_N #define PRODUCT_STARTER_N 0x0000002F #endif #ifndef PRODUCT_PROFESSIONAL #define PRODUCT_PROFESSIONAL 0x00000030 #define PRODUCT_PROFESSIONAL_N 0x00000031 #endif #ifndef PRODUCT_ULTIMATE_E #define PRODUCT_STARTER_E 0x00000042 #define PRODUCT_HOME_BASIC_E 0x00000043 #define PRODUCT_HOME_PREMIUM_E 0x00000044 #define PRODUCT_PROFESSIONAL_E 0x00000045 #define PRODUCT_ENTERPRISE_E 0x00000046 #define PRODUCT_ULTIMATE_E 0x00000047 #endif void CIrrDeviceWin32::getWindowsVersion(core::stringc& out) { OSVERSIONINFOEX osvi; PGPI pGPI; BOOL bOsVersionInfoEx; ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi); if (!bOsVersionInfoEx) { osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (! GetVersionEx((OSVERSIONINFO *) &osvi)) return; } switch (osvi.dwPlatformId) { case VER_PLATFORM_WIN32_NT: if (osvi.dwMajorVersion <= 4) out.append("Microsoft Windows NT "); else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) out.append("Microsoft Windows 2000 "); else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) out.append("Microsoft Windows XP "); else if (osvi.dwMajorVersion == 6 ) { if (osvi.dwMinorVersion == 0) { if (osvi.wProductType == VER_NT_WORKSTATION) out.append("Microsoft Windows Vista "); else out.append("Microsoft Windows Server 2008 "); } else if (osvi.dwMinorVersion == 1) { if (osvi.wProductType == VER_NT_WORKSTATION) out.append("Microsoft Windows 7 "); else out.append("Microsoft Windows Server 2008 R2 "); } } if (bOsVersionInfoEx) { if (osvi.dwMajorVersion == 6) { DWORD dwType; pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo"); pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType); switch (dwType) { case PRODUCT_ULTIMATE: case PRODUCT_ULTIMATE_E: case PRODUCT_ULTIMATE_N: out.append("Ultimate Edition "); break; case PRODUCT_PROFESSIONAL: case PRODUCT_PROFESSIONAL_E: case PRODUCT_PROFESSIONAL_N: out.append("Professional Edition "); break; case PRODUCT_HOME_BASIC: case PRODUCT_HOME_BASIC_E: case PRODUCT_HOME_BASIC_N: out.append("Home Basic Edition "); break; case PRODUCT_HOME_PREMIUM: case PRODUCT_HOME_PREMIUM_E: case PRODUCT_HOME_PREMIUM_N: out.append("Home Premium Edition "); break; case PRODUCT_ENTERPRISE: case PRODUCT_ENTERPRISE_E: case PRODUCT_ENTERPRISE_N: out.append("Enterprise Edition "); break; case PRODUCT_BUSINESS: case PRODUCT_BUSINESS_N: out.append("Business Edition "); break; case PRODUCT_STARTER: case PRODUCT_STARTER_E: case PRODUCT_STARTER_N: out.append("Starter Edition "); break; } } #ifdef VER_SUITE_ENTERPRISE else if (osvi.wProductType == VER_NT_WORKSTATION) { #ifndef __BORLANDC__ if( osvi.wSuiteMask & VER_SUITE_PERSONAL ) out.append("Personal "); else out.append("Professional "); #endif } else if (osvi.wProductType == VER_NT_SERVER) { if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) out.append("DataCenter Server "); else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) out.append("Advanced Server "); else out.append("Server "); } #endif } else { HKEY hKey; char szProductType[80]; DWORD dwBufLen; RegOpenKeyEx( HKEY_LOCAL_MACHINE, __TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), 0, KEY_QUERY_VALUE, &hKey ); RegQueryValueEx( hKey, __TEXT("ProductType"), NULL, NULL, (LPBYTE) szProductType, &dwBufLen); RegCloseKey( hKey ); if (_strcmpi( "WINNT", szProductType) == 0 ) out.append("Professional "); if (_strcmpi( "LANMANNT", szProductType) == 0) out.append("Server "); if (_strcmpi( "SERVERNT", szProductType) == 0) out.append("Advanced Server "); } // Display version, service pack (if any), and build number. char tmp[255]; if (osvi.dwMajorVersion <= 4 ) { sprintf(tmp, "version %ld.%ld %s (Build %ld)", osvi.dwMajorVersion, osvi.dwMinorVersion, irr::core::stringc(osvi.szCSDVersion).c_str(), osvi.dwBuildNumber & 0xFFFF); } else { sprintf(tmp, "%s (Build %ld)", irr::core::stringc(osvi.szCSDVersion).c_str(), osvi.dwBuildNumber & 0xFFFF); } out.append(tmp); break; case VER_PLATFORM_WIN32_WINDOWS: if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) { out.append("Microsoft Windows 95 "); if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' ) out.append("OSR2 " ); } if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) { out.append("Microsoft Windows 98 "); if ( osvi.szCSDVersion[1] == 'A' ) out.append( "SE " ); } if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) out.append("Microsoft Windows Me "); break; case VER_PLATFORM_WIN32s: out.append("Microsoft Win32s "); break; } } //! Notifies the device, that it has been resized void CIrrDeviceWin32::OnResized() { Resized = true; } //! Sets if the window should be resizable in windowed mode. void CIrrDeviceWin32::setResizable(bool resize) { if (ExternalWindow || !getVideoDriver() || CreationParams.Fullscreen) return; LONG_PTR style = WS_POPUP; if (!resize) style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; else style = WS_THICKFRAME | WS_SYSMENU | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; if (!SetWindowLongPtr(HWnd, GWL_STYLE, style)) os::Printer::log("Could not change window style."); RECT clientSize; clientSize.top = 0; clientSize.left = 0; clientSize.right = getVideoDriver()->getScreenSize().Width; clientSize.bottom = getVideoDriver()->getScreenSize().Height; AdjustWindowRect(&clientSize, style, FALSE); const s32 realWidth = clientSize.right - clientSize.left; const s32 realHeight = clientSize.bottom - clientSize.top; const s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2; const s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2; SetWindowPos(HWnd, HWND_TOP, windowLeft, windowTop, realWidth, realHeight, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_SHOWWINDOW); static_cast(CursorControl)->updateBorderSize(CreationParams.Fullscreen, resize); } //! Minimizes the window. void CIrrDeviceWin32::minimizeWindow() { WINDOWPLACEMENT wndpl; wndpl.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(HWnd, &wndpl); wndpl.showCmd = SW_SHOWMINNOACTIVE; SetWindowPlacement(HWnd, &wndpl); } //! Maximizes the window. void CIrrDeviceWin32::maximizeWindow() { WINDOWPLACEMENT wndpl; wndpl.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(HWnd, &wndpl); wndpl.showCmd = SW_SHOWMAXIMIZED; SetWindowPlacement(HWnd, &wndpl); } //! Restores the window to its original size. void CIrrDeviceWin32::restoreWindow() { WINDOWPLACEMENT wndpl; wndpl.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(HWnd, &wndpl); wndpl.showCmd = SW_SHOWNORMAL; SetWindowPlacement(HWnd, &wndpl); } bool CIrrDeviceWin32::activateJoysticks(core::array & joystickInfo) { if (JoyControl) return JoyControl->activateJoysticks(joystickInfo); else return false; } //! Set the current Gamma Value for the Display bool CIrrDeviceWin32::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) { bool r; u16 ramp[3][256]; calculateGammaRamp( ramp[0], red, brightness, contrast ); calculateGammaRamp( ramp[1], green, brightness, contrast ); calculateGammaRamp( ramp[2], blue, brightness, contrast ); HDC dc = GetDC(0); r = SetDeviceGammaRamp ( dc, ramp ) == TRUE; ReleaseDC(HWnd, dc); return r; } //! Get the current Gamma Value for the Display bool CIrrDeviceWin32::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ) { bool r; u16 ramp[3][256]; HDC dc = GetDC(0); r = GetDeviceGammaRamp ( dc, ramp ) == TRUE; ReleaseDC(HWnd, dc); if ( r ) { calculateGammaFromRamp(red, ramp[0]); calculateGammaFromRamp(green, ramp[1]); calculateGammaFromRamp(blue, ramp[2]); } brightness = 0.f; contrast = 0.f; return r; } //! Process system events void CIrrDeviceWin32::handleSystemMessages() { MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // No message translation because we don't use WM_CHAR and it would conflict with our // deadkey handling. if (ExternalWindow && msg.hwnd == HWnd) WndProc(HWnd, msg.message, msg.wParam, msg.lParam); else DispatchMessage(&msg); if (msg.message == WM_QUIT) Close = true; } } //! Remove all messages pending in the system message loop void CIrrDeviceWin32::clearSystemMessages() { MSG msg; while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) {} while (PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) {} } // shows last error in a messagebox to help internal debugging. void CIrrDeviceWin32::ReportLastWinApiError() { // (based on code from ovidiucucu from http://www.codeguru.com/forum/showthread.php?t=318721) LPCTSTR pszCaption = __TEXT("Windows SDK Error Report"); DWORD dwError = GetLastError(); if(NOERROR == dwError) { MessageBox(NULL, __TEXT("No error"), pszCaption, MB_OK); } else { const DWORD dwFormatControl = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM; LPVOID pTextBuffer = NULL; DWORD dwCount = FormatMessage(dwFormatControl, NULL, dwError, 0, (LPTSTR) &pTextBuffer, 0, NULL); if(0 != dwCount) { MessageBox(NULL, (LPCTSTR)pTextBuffer, pszCaption, MB_OK|MB_ICONERROR); LocalFree(pTextBuffer); } else { MessageBox(NULL, __TEXT("Unknown error"), pszCaption, MB_OK|MB_ICONERROR); } } } // Convert an Irrlicht texture to a Windows cursor // Based on http://www.codeguru.com/cpp/w-p/win32/cursors/article.php/c4529/ HCURSOR CIrrDeviceWin32::TextureToCursor(HWND hwnd, irr::video::ITexture * tex, const core::rect& sourceRect, const core::position2d &hotspot) { // // create the bitmaps needed for cursors from the texture HDC dc = GetDC(hwnd); HDC andDc = CreateCompatibleDC(dc); HDC xorDc = CreateCompatibleDC(dc); HBITMAP andBitmap = CreateCompatibleBitmap(dc, sourceRect.getWidth(), sourceRect.getHeight()); HBITMAP xorBitmap = CreateCompatibleBitmap(dc, sourceRect.getWidth(), sourceRect.getHeight()); HBITMAP oldAndBitmap = (HBITMAP)SelectObject(andDc, andBitmap); HBITMAP oldXorBitmap = (HBITMAP)SelectObject(xorDc, xorBitmap); video::ECOLOR_FORMAT format = tex->getColorFormat(); u32 bytesPerPixel = video::IImage::getBitsPerPixelFromFormat(format) / 8; u32 bytesLeftGap = sourceRect.UpperLeftCorner.X * bytesPerPixel; u32 bytesRightGap = tex->getPitch() - sourceRect.LowerRightCorner.X * bytesPerPixel; const u8* data = (const u8*)tex->lock(video::ETLM_READ_ONLY, 0); data += sourceRect.UpperLeftCorner.Y*tex->getPitch(); for ( s32 y = 0; y < sourceRect.getHeight(); ++y ) { data += bytesLeftGap; for ( s32 x = 0; x < sourceRect.getWidth(); ++x ) { video::SColor pixelCol; pixelCol.setData((const void*)data, format); data += bytesPerPixel; if ( pixelCol.getAlpha() == 0 ) // transparent { SetPixel(andDc, x, y, RGB(255,255,255)); SetPixel(xorDc, x, y, RGB(0,0,0)); } else // color { SetPixel(andDc, x, y, RGB(0,0,0)); SetPixel(xorDc, x, y, RGB(pixelCol.getRed(), pixelCol.getGreen(), pixelCol.getBlue())); } } data += bytesRightGap; } tex->unlock(); SelectObject(andDc, oldAndBitmap); SelectObject(xorDc, oldXorBitmap); DeleteDC(xorDc); DeleteDC(andDc); ReleaseDC(hwnd, dc); // create the cursor ICONINFO iconinfo; iconinfo.fIcon = false; // type is cursor not icon iconinfo.xHotspot = hotspot.X; iconinfo.yHotspot = hotspot.Y; iconinfo.hbmMask = andBitmap; iconinfo.hbmColor = xorBitmap; HCURSOR cursor = CreateIconIndirect(&iconinfo); DeleteObject(andBitmap); DeleteObject(xorBitmap); return cursor; } CIrrDeviceWin32::CCursorControl::CCursorControl(CIrrDeviceWin32* device, const core::dimension2d& wsize, HWND hwnd, bool fullscreen) : Device(device), WindowSize(wsize), InvWindowSize(0.0f, 0.0f), HWnd(hwnd), BorderX(0), BorderY(0), UseReferenceRect(false), IsVisible(true) , ActiveIcon(gui::ECI_NORMAL), ActiveIconStartTime(0) { if (WindowSize.Width!=0) InvWindowSize.Width = 1.0f / WindowSize.Width; if (WindowSize.Height!=0) InvWindowSize.Height = 1.0f / WindowSize.Height; updateBorderSize(fullscreen, false); initCursors(); } CIrrDeviceWin32::CCursorControl::~CCursorControl() { for ( u32 i=0; i < Cursors.size(); ++i ) { for ( u32 f=0; f < Cursors[i].Frames.size(); ++f ) { DestroyCursor(Cursors[i].Frames[f].IconHW); } } } void CIrrDeviceWin32::CCursorControl::initCursors() { Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_ARROW)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_CROSS)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_HAND)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_HELP)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_IBEAM)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_NO)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_WAIT)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZEALL)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENESW)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENWSE)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZENS)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_SIZEWE)) ); Cursors.push_back( CursorW32(LoadCursor(NULL, IDC_UPARROW)) ); } void CIrrDeviceWin32::CCursorControl::update() { if ( !Cursors[ActiveIcon].Frames.empty() && Cursors[ActiveIcon].FrameTime ) { // update animated cursors. This could also be done by X11 in case someone wants to figure that out (this way was just easier to implement) u32 now = Device->getTimer()->getRealTime(); u32 frame = ((now - ActiveIconStartTime) / Cursors[ActiveIcon].FrameTime) % Cursors[ActiveIcon].Frames.size(); SetCursor( Cursors[ActiveIcon].Frames[frame].IconHW ); } } //! Sets the active cursor icon void CIrrDeviceWin32::CCursorControl::setActiveIcon(gui::ECURSOR_ICON iconId) { if ( iconId >= (s32)Cursors.size() ) return; ActiveIcon = iconId; ActiveIconStartTime = Device->getTimer()->getRealTime(); if ( Cursors[ActiveIcon].Frames.size() ) SetCursor( Cursors[ActiveIcon].Frames[0].IconHW ); } //! Add a custom sprite as cursor icon. gui::ECURSOR_ICON CIrrDeviceWin32::CCursorControl::addIcon(const gui::SCursorSprite& icon) { if ( icon.SpriteId >= 0 ) { CursorW32 cW32; cW32.FrameTime = icon.SpriteBank->getSprites()[icon.SpriteId].frameTime; for ( u32 i=0; i < icon.SpriteBank->getSprites()[icon.SpriteId].Frames.size(); ++i ) { irr::u32 texId = icon.SpriteBank->getSprites()[icon.SpriteId].Frames[i].textureNumber; irr::u32 rectId = icon.SpriteBank->getSprites()[icon.SpriteId].Frames[i].rectNumber; irr::core::rect rectIcon = icon.SpriteBank->getPositions()[rectId]; HCURSOR hc = Device->TextureToCursor(HWnd, icon.SpriteBank->getTexture(texId), rectIcon, icon.HotSpot); cW32.Frames.push_back( CursorFrameW32(hc) ); } Cursors.push_back( cW32 ); return (gui::ECURSOR_ICON)(Cursors.size() - 1); } return gui::ECI_NORMAL; } //! replace the given cursor icon. void CIrrDeviceWin32::CCursorControl::changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon) { if ( iconId >= (s32)Cursors.size() ) return; for ( u32 i=0; i < Cursors[iconId].Frames.size(); ++i ) DestroyCursor(Cursors[iconId].Frames[i].IconHW); if ( icon.SpriteId >= 0 ) { CursorW32 cW32; cW32.FrameTime = icon.SpriteBank->getSprites()[icon.SpriteId].frameTime; for ( u32 i=0; i < icon.SpriteBank->getSprites()[icon.SpriteId].Frames.size(); ++i ) { irr::u32 texId = icon.SpriteBank->getSprites()[icon.SpriteId].Frames[i].textureNumber; irr::u32 rectId = icon.SpriteBank->getSprites()[icon.SpriteId].Frames[i].rectNumber; irr::core::rect rectIcon = icon.SpriteBank->getPositions()[rectId]; HCURSOR hc = Device->TextureToCursor(HWnd, icon.SpriteBank->getTexture(texId), rectIcon, icon.HotSpot); cW32.Frames.push_back( CursorFrameW32(hc) ); } Cursors[iconId] = cW32; } } //! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work. core::dimension2di CIrrDeviceWin32::CCursorControl::getSupportedIconSize() const { core::dimension2di result; result.Width = GetSystemMetrics(SM_CXCURSOR); result.Height = GetSystemMetrics(SM_CYCURSOR); return result; } } // end namespace #endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ irrlicht-1.8.3/source/Irrlicht/CIrrDeviceStub.h0000644000000000000000000001364712574354552020136 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IRR_DEVICE_STUB_H_INCLUDED__ #define __C_IRR_DEVICE_STUB_H_INCLUDED__ #include "IrrlichtDevice.h" #include "IImagePresenter.h" #include "SIrrCreationParameters.h" #include "CVideoModeList.h" namespace irr { // lots of prototypes: class ILogger; class CLogger; class IRandomizer; namespace gui { class IGUIEnvironment; IGUIEnvironment* createGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* Driver, IOSOperator* op); } namespace scene { ISceneManager* createSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, gui::ICursorControl* cc, gui::IGUIEnvironment *gui); } namespace io { IFileSystem* createFileSystem(); } namespace video { IVideoDriver* createSoftwareDriver(const core::dimension2d& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter); IVideoDriver* createBurningVideoDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, video::IImagePresenter* presenter); IVideoDriver* createNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize); } //! Stub for an Irrlicht Device implementation class CIrrDeviceStub : public IrrlichtDevice { public: //! constructor CIrrDeviceStub(const SIrrlichtCreationParameters& param); //! destructor virtual ~CIrrDeviceStub(); //! returns the video driver virtual video::IVideoDriver* getVideoDriver(); //! return file system virtual io::IFileSystem* getFileSystem(); //! returns the gui environment virtual gui::IGUIEnvironment* getGUIEnvironment(); //! returns the scene manager virtual scene::ISceneManager* getSceneManager(); //! \return Returns a pointer to the mouse cursor control interface. virtual gui::ICursorControl* getCursorControl(); //! Returns a pointer to a list with all video modes supported by the gfx adapter. virtual video::IVideoModeList* getVideoModeList(); //! Returns a pointer to the ITimer object. With it the current Time can be received. virtual ITimer* getTimer(); //! Returns the version of the engine. virtual const char* getVersion() const; //! send the event to the right receiver virtual bool postEventFromUser(const SEvent& event); //! Sets a new event receiver to receive events virtual void setEventReceiver(IEventReceiver* receiver); //! Returns pointer to the current event receiver. Returns 0 if there is none. virtual IEventReceiver* getEventReceiver(); //! Sets the input receiving scene manager. /** If set to null, the main scene manager (returned by GetSceneManager()) will receive the input */ virtual void setInputReceivingSceneManager(scene::ISceneManager* sceneManager); //! Returns a pointer to the logger. virtual ILogger* getLogger(); //! Provides access to the engine's currently set randomizer. virtual IRandomizer* getRandomizer() const; //! Sets a new randomizer. virtual void setRandomizer(IRandomizer* r); //! Creates a new default randomizer. virtual IRandomizer* createDefaultRandomizer() const; //! Returns the operation system opertator object. virtual IOSOperator* getOSOperator(); //! Checks if the window is running in fullscreen mode. virtual bool isFullscreen() const; //! get color format of the current window virtual video::ECOLOR_FORMAT getColorFormat() const; //! Activate any joysticks, and generate events for them. virtual bool activateJoysticks(core::array & joystickInfo); //! Set the current Gamma Value for the Display virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ); //! Get the current Gamma Value for the Display virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ); //! Set the maximal elapsed time between 2 clicks to generate doubleclicks for the mouse. It also affects tripleclick behavior. //! When set to 0 no double- and tripleclicks will be generated. virtual void setDoubleClickTime( u32 timeMs ); //! Get the maximal elapsed time between 2 clicks to generate double- and tripleclicks for the mouse. virtual u32 getDoubleClickTime() const; //! Remove all messages pending in the system message loop virtual void clearSystemMessages(); protected: void createGUIAndScene(); //! checks version of SDK and prints warning if there might be a problem bool checkVersion(const char* version); //! Compares to the last call of this function to return double and triple clicks. //! \return Returns only 1,2 or 3. A 4th click will start with 1 again. virtual u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ); void calculateGammaRamp ( u16 *ramp, f32 gamma, f32 relativebrightness, f32 relativecontrast ); void calculateGammaFromRamp ( f32 &gamma, const u16 *ramp ); video::IVideoDriver* VideoDriver; gui::IGUIEnvironment* GUIEnvironment; scene::ISceneManager* SceneManager; ITimer* Timer; gui::ICursorControl* CursorControl; IEventReceiver* UserReceiver; CLogger* Logger; IOSOperator* Operator; IRandomizer* Randomizer; io::IFileSystem* FileSystem; scene::ISceneManager* InputReceivingSceneManager; struct SMouseMultiClicks { SMouseMultiClicks() : DoubleClickTime(500), CountSuccessiveClicks(0), LastClickTime(0), LastMouseInputEvent(EMIE_COUNT) {} u32 DoubleClickTime; u32 CountSuccessiveClicks; u32 LastClickTime; core::position2di LastClick; EMOUSE_INPUT_EVENT LastMouseInputEvent; }; SMouseMultiClicks MouseMultiClicks; video::CVideoModeList* VideoModeList; SIrrlichtCreationParameters CreationParams; bool Close; }; } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CIrrDeviceStub.cpp0000644000000000000000000002332512574354552020463 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CIrrDeviceStub.h" #include "ISceneManager.h" #include "IEventReceiver.h" #include "IFileSystem.h" #include "IGUIEnvironment.h" #include "os.h" #include "IrrCompileConfig.h" #include "CTimer.h" #include "CLogger.h" #include "irrString.h" #include "IRandomizer.h" namespace irr { //! constructor CIrrDeviceStub::CIrrDeviceStub(const SIrrlichtCreationParameters& params) : IrrlichtDevice(), VideoDriver(0), GUIEnvironment(0), SceneManager(0), Timer(0), CursorControl(0), UserReceiver(params.EventReceiver), Logger(0), Operator(0), Randomizer(0), FileSystem(0), InputReceivingSceneManager(0), VideoModeList(0), CreationParams(params), Close(false) { Timer = new CTimer(params.UsePerformanceTimer); if (os::Printer::Logger) { os::Printer::Logger->grab(); Logger = (CLogger*)os::Printer::Logger; Logger->setReceiver(UserReceiver); } else { Logger = new CLogger(UserReceiver); os::Printer::Logger = Logger; } Logger->setLogLevel(CreationParams.LoggingLevel); os::Printer::Logger = Logger; Randomizer = createDefaultRandomizer(); FileSystem = io::createFileSystem(); VideoModeList = new video::CVideoModeList(); core::stringc s = "Irrlicht Engine version "; s.append(getVersion()); os::Printer::log(s.c_str(), ELL_INFORMATION); checkVersion(params.SDK_version_do_not_use); } CIrrDeviceStub::~CIrrDeviceStub() { VideoModeList->drop(); FileSystem->drop(); if (GUIEnvironment) GUIEnvironment->drop(); if (VideoDriver) VideoDriver->drop(); if (SceneManager) SceneManager->drop(); if (InputReceivingSceneManager) InputReceivingSceneManager->drop(); if (CursorControl) CursorControl->drop(); if (Operator) Operator->drop(); if (Randomizer) Randomizer->drop(); CursorControl = 0; if (Timer) Timer->drop(); if (Logger->drop()) os::Printer::Logger = 0; } void CIrrDeviceStub::createGUIAndScene() { #ifdef _IRR_COMPILE_WITH_GUI_ // create gui environment GUIEnvironment = gui::createGUIEnvironment(FileSystem, VideoDriver, Operator); #endif // create Scene manager SceneManager = scene::createSceneManager(VideoDriver, FileSystem, CursorControl, GUIEnvironment); setEventReceiver(UserReceiver); } //! returns the video driver video::IVideoDriver* CIrrDeviceStub::getVideoDriver() { return VideoDriver; } //! return file system io::IFileSystem* CIrrDeviceStub::getFileSystem() { return FileSystem; } //! returns the gui environment gui::IGUIEnvironment* CIrrDeviceStub::getGUIEnvironment() { return GUIEnvironment; } //! returns the scene manager scene::ISceneManager* CIrrDeviceStub::getSceneManager() { return SceneManager; } //! \return Returns a pointer to the ITimer object. With it the //! current Time can be received. ITimer* CIrrDeviceStub::getTimer() { return Timer; } //! Returns the version of the engine. const char* CIrrDeviceStub::getVersion() const { return IRRLICHT_SDK_VERSION; } //! \return Returns a pointer to the mouse cursor control interface. gui::ICursorControl* CIrrDeviceStub::getCursorControl() { return CursorControl; } //! \return Returns a pointer to a list with all video modes supported //! by the gfx adapter. video::IVideoModeList* CIrrDeviceStub::getVideoModeList() { return VideoModeList; } //! checks version of sdk and prints warning if there might be a problem bool CIrrDeviceStub::checkVersion(const char* version) { if (strcmp(getVersion(), version)) { core::stringc w; w = "Warning: The library version of the Irrlicht Engine ("; w += getVersion(); w += ") does not match the version the application was compiled with ("; w += version; w += "). This may cause problems."; os::Printer::log(w.c_str(), ELL_WARNING); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } return true; } //! Compares to the last call of this function to return double and triple clicks. u32 CIrrDeviceStub::checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ) { const s32 MAX_MOUSEMOVE = 3; irr::u32 clickTime = getTimer()->getRealTime(); if ( (clickTime-MouseMultiClicks.LastClickTime) < MouseMultiClicks.DoubleClickTime && core::abs_(MouseMultiClicks.LastClick.X - mouseX ) <= MAX_MOUSEMOVE && core::abs_(MouseMultiClicks.LastClick.Y - mouseY ) <= MAX_MOUSEMOVE && MouseMultiClicks.CountSuccessiveClicks < 3 && MouseMultiClicks.LastMouseInputEvent == inputEvent ) { ++MouseMultiClicks.CountSuccessiveClicks; } else { MouseMultiClicks.CountSuccessiveClicks = 1; } MouseMultiClicks.LastMouseInputEvent = inputEvent; MouseMultiClicks.LastClickTime = clickTime; MouseMultiClicks.LastClick.X = mouseX; MouseMultiClicks.LastClick.Y = mouseY; return MouseMultiClicks.CountSuccessiveClicks; } //! send the event to the right receiver bool CIrrDeviceStub::postEventFromUser(const SEvent& event) { bool absorbed = false; if (UserReceiver) absorbed = UserReceiver->OnEvent(event); if (!absorbed && GUIEnvironment) absorbed = GUIEnvironment->postEventFromUser(event); scene::ISceneManager* inputReceiver = InputReceivingSceneManager; if (!inputReceiver) inputReceiver = SceneManager; if (!absorbed && inputReceiver) absorbed = inputReceiver->postEventFromUser(event); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return absorbed; } //! Sets a new event receiver to receive events void CIrrDeviceStub::setEventReceiver(IEventReceiver* receiver) { UserReceiver = receiver; Logger->setReceiver(receiver); if (GUIEnvironment) GUIEnvironment->setUserEventReceiver(receiver); } //! Returns poinhter to the current event receiver. Returns 0 if there is none. IEventReceiver* CIrrDeviceStub::getEventReceiver() { return UserReceiver; } //! \return Returns a pointer to the logger. ILogger* CIrrDeviceStub::getLogger() { return Logger; } //! Returns the operation system opertator object. IOSOperator* CIrrDeviceStub::getOSOperator() { return Operator; } //! Provides access to the engine's currently set randomizer. IRandomizer* CIrrDeviceStub::getRandomizer() const { return Randomizer; } //! Sets a new randomizer. void CIrrDeviceStub::setRandomizer(IRandomizer* r) { if (r!=Randomizer) { if (Randomizer) Randomizer->drop(); Randomizer=r; if (Randomizer) Randomizer->grab(); } } namespace { struct SDefaultRandomizer : public IRandomizer { virtual void reset(s32 value=0x0f0f0f0f) { os::Randomizer::reset(value); } virtual s32 rand() const { return os::Randomizer::rand(); } virtual f32 frand() const { return os::Randomizer::frand(); } virtual s32 randMax() const { return os::Randomizer::randMax(); } }; } //! Creates a new default randomizer. IRandomizer* CIrrDeviceStub::createDefaultRandomizer() const { IRandomizer* r = new SDefaultRandomizer(); if (r) r->reset(); return r; } //! Sets the input receiving scene manager. void CIrrDeviceStub::setInputReceivingSceneManager(scene::ISceneManager* sceneManager) { if (sceneManager) sceneManager->grab(); if (InputReceivingSceneManager) InputReceivingSceneManager->drop(); InputReceivingSceneManager = sceneManager; } //! Checks if the window is running in fullscreen mode bool CIrrDeviceStub::isFullscreen() const { return CreationParams.Fullscreen; } //! returns color format video::ECOLOR_FORMAT CIrrDeviceStub::getColorFormat() const { return video::ECF_R5G6B5; } //! No-op in this implementation bool CIrrDeviceStub::activateJoysticks(core::array & joystickInfo) { return false; } /*! */ void CIrrDeviceStub::calculateGammaRamp ( u16 *ramp, f32 gamma, f32 relativebrightness, f32 relativecontrast ) { s32 i; s32 value; s32 rbright = (s32) ( relativebrightness * (65535.f / 4 ) ); f32 rcontrast = 1.f / (255.f - ( relativecontrast * 127.5f ) ); gamma = gamma > 0.f ? 1.0f / gamma : 0.f; for ( i = 0; i < 256; ++i ) { value = (s32)(pow( rcontrast * i, gamma)*65535.f + 0.5f ); ramp[i] = (u16) core::s32_clamp ( value + rbright, 0, 65535 ); } } void CIrrDeviceStub::calculateGammaFromRamp ( f32 &gamma, const u16 *ramp ) { /* The following is adapted from a post by Garrett Bass on OpenGL Gamedev list, March 4, 2000. */ f32 sum = 0.0; s32 i, count = 0; gamma = 1.0; for ( i = 1; i < 256; ++i ) { if ( (ramp[i] != 0) && (ramp[i] != 65535) ) { f32 B = (f32)i / 256.f; f32 A = ramp[i] / 65535.f; sum += (f32) ( logf(A) / logf(B) ); count++; } } if ( count && sum ) { gamma = 1.0f / (sum / count); } } //! Set the current Gamma Value for the Display bool CIrrDeviceStub::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) { return false; } //! Get the current Gamma Value for the Display bool CIrrDeviceStub::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ) { return false; } //! Set the maximal elapsed time between 2 clicks to generate doubleclicks for the mouse. It also affects tripleclick behavior. void CIrrDeviceStub::setDoubleClickTime( u32 timeMs ) { MouseMultiClicks.DoubleClickTime = timeMs; } //! Get the maximal elapsed time between 2 clicks to generate double- and tripleclicks for the mouse. u32 CIrrDeviceStub::getDoubleClickTime() const { return MouseMultiClicks.DoubleClickTime; } //! Remove all messages pending in the system message loop void CIrrDeviceStub::clearSystemMessages() { } } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CIrrDeviceSDL.h0000644000000000000000000001316112574354552017632 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // This device code is based on the original SDL device implementation // contributed by Shane Parker (sirshane). #ifndef __C_IRR_DEVICE_SDL_H_INCLUDED__ #define __C_IRR_DEVICE_SDL_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ #include "IrrlichtDevice.h" #include "CIrrDeviceStub.h" #include "IImagePresenter.h" #include "ICursorControl.h" #include #include namespace irr { class CIrrDeviceSDL : public CIrrDeviceStub, video::IImagePresenter { public: //! constructor CIrrDeviceSDL(const SIrrlichtCreationParameters& param); //! destructor virtual ~CIrrDeviceSDL(); //! runs the device. Returns false if device wants to be deleted virtual bool run(); //! pause execution temporarily virtual void yield(); //! pause execution for a specified time virtual void sleep(u32 timeMs, bool pauseTimer); //! sets the caption of the window virtual void setWindowCaption(const wchar_t* text); //! returns if window is active. if not, nothing need to be drawn virtual bool isWindowActive() const; //! returns if window has focus. bool isWindowFocused() const; //! returns if window is minimized. bool isWindowMinimized() const; //! returns color format of the window. video::ECOLOR_FORMAT getColorFormat() const; //! presents a surface in the client area virtual bool present(video::IImage* surface, void* windowId=0, core::rect* src=0); //! notifies the device that it should close itself virtual void closeDevice(); //! \return Returns a pointer to a list with all video modes supported video::IVideoModeList* getVideoModeList(); //! Sets if the window should be resizable in windowed mode. virtual void setResizable(bool resize=false); //! Minimizes the window. virtual void minimizeWindow(); //! Maximizes the window. virtual void maximizeWindow(); //! Restores the window size. virtual void restoreWindow(); //! Activate any joysticks, and generate events for them. virtual bool activateJoysticks(core::array & joystickInfo); //! Set the current Gamma Value for the Display virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ); //! Get the current Gamma Value for the Display virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ); //! Get the device type virtual E_DEVICE_TYPE getType() const { return EIDT_SDL; } //! Implementation of the linux cursor control class CCursorControl : public gui::ICursorControl { public: CCursorControl(CIrrDeviceSDL* dev) : Device(dev), IsVisible(true) { } //! Changes the visible state of the mouse cursor. virtual void setVisible(bool visible) { IsVisible = visible; if ( visible ) SDL_ShowCursor( SDL_ENABLE ); else SDL_ShowCursor( SDL_DISABLE ); } //! Returns if the cursor is currently visible. virtual bool isVisible() const { return IsVisible; } //! Sets the new position of the cursor. virtual void setPosition(const core::position2d &pos) { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. virtual void setPosition(f32 x, f32 y) { setPosition((s32)(x*Device->Width), (s32)(y*Device->Height)); } //! Sets the new position of the cursor. virtual void setPosition(const core::position2d &pos) { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. virtual void setPosition(s32 x, s32 y) { SDL_WarpMouse( x, y ); } //! Returns the current position of the mouse cursor. virtual const core::position2d& getPosition() { updateCursorPos(); return CursorPos; } //! Returns the current position of the mouse cursor. virtual core::position2d getRelativePosition() { updateCursorPos(); return core::position2d(CursorPos.X / (f32)Device->Width, CursorPos.Y / (f32)Device->Height); } virtual void setReferenceRect(core::rect* rect=0) { } private: void updateCursorPos() { CursorPos.X = Device->MouseX; CursorPos.Y = Device->MouseY; if (CursorPos.X < 0) CursorPos.X = 0; if (CursorPos.X > (s32)Device->Width) CursorPos.X = Device->Width; if (CursorPos.Y < 0) CursorPos.Y = 0; if (CursorPos.Y > (s32)Device->Height) CursorPos.Y = Device->Height; } CIrrDeviceSDL* Device; core::position2d CursorPos; bool IsVisible; }; private: //! create the driver void createDriver(); bool createWindow(); void createKeyMap(); SDL_Surface* Screen; int SDL_Flags; #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) core::array Joysticks; #endif s32 MouseX, MouseY; u32 MouseButtonStates; u32 Width, Height; bool Resizable; bool WindowHasFocus; bool WindowMinimized; struct SKeyMap { SKeyMap() {} SKeyMap(s32 x11, s32 win32) : SDLKey(x11), Win32Key(win32) { } s32 SDLKey; s32 Win32Key; bool operator<(const SKeyMap& o) const { return SDLKey KeyMap; SDL_SysWMinfo Info; }; } // end namespace irr #endif // _IRR_COMPILE_WITH_SDL_DEVICE_ #endif // __C_IRR_DEVICE_SDL_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CIrrDeviceSDL.cpp0000644000000000000000000006746412574354552020204 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ #include "CIrrDeviceSDL.h" #include "IEventReceiver.h" #include "irrList.h" #include "os.h" #include "CTimer.h" #include "irrString.h" #include "Keycodes.h" #include "COSOperator.h" #include #include #include "SIrrCreationParameters.h" #include #include #ifdef _MSC_VER #pragma comment(lib, "SDL.lib") #endif // _MSC_VER namespace irr { namespace video { #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ IVideoDriver* createDirectX8Driver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, HWND window); #endif #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ IVideoDriver* createDirectX9Driver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, HWND window); #endif #ifdef _IRR_COMPILE_WITH_OPENGL_ IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceSDL* device); #endif } // end namespace video } // end namespace irr namespace irr { //! constructor CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) : CIrrDeviceStub(param), Screen((SDL_Surface*)param.WindowId), SDL_Flags(SDL_ANYFORMAT), MouseX(0), MouseY(0), MouseButtonStates(0), Width(param.WindowSize.Width), Height(param.WindowSize.Height), Resizable(false), WindowHasFocus(false), WindowMinimized(false) { #ifdef _DEBUG setDebugName("CIrrDeviceSDL"); #endif // Initialize SDL... Timer for sleep, video for the obvious, and // noparachute prevents SDL from catching fatal errors. if (SDL_Init( SDL_INIT_TIMER|SDL_INIT_VIDEO| #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) SDL_INIT_JOYSTICK| #endif SDL_INIT_NOPARACHUTE ) < 0) { os::Printer::log( "Unable to initialize SDL!", SDL_GetError()); Close = true; } #if defined(_IRR_WINDOWS_) SDL_putenv("SDL_VIDEODRIVER=directx"); #elif defined(_IRR_OSX_PLATFORM_) SDL_putenv("SDL_VIDEODRIVER=Quartz"); #else SDL_putenv("SDL_VIDEODRIVER=x11"); #endif // SDL_putenv("SDL_WINDOWID="); SDL_VERSION(&Info.version); SDL_GetWMInfo(&Info); core::stringc sdlversion = "SDL Version "; sdlversion += Info.version.major; sdlversion += "."; sdlversion += Info.version.minor; sdlversion += "."; sdlversion += Info.version.patch; Operator = new COSOperator(sdlversion); os::Printer::log(sdlversion.c_str(), ELL_INFORMATION); // create keymap createKeyMap(); // enable key to character translation SDL_EnableUNICODE(1); (void)SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); if ( CreationParams.Fullscreen ) SDL_Flags |= SDL_FULLSCREEN; if (CreationParams.DriverType == video::EDT_OPENGL) SDL_Flags |= SDL_OPENGL; else if (CreationParams.Doublebuffer) SDL_Flags |= SDL_DOUBLEBUF; // create window if (CreationParams.DriverType != video::EDT_NULL) { // create the window, only if we do not use the null device createWindow(); } // create cursor control CursorControl = new CCursorControl(this); // create driver createDriver(); if (VideoDriver) createGUIAndScene(); } //! destructor CIrrDeviceSDL::~CIrrDeviceSDL() { #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) const u32 numJoysticks = Joysticks.size(); for (u32 i=0; i1) { SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, CreationParams.AntiAlias ); } if ( !Screen ) Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); if ( !Screen && CreationParams.AntiAlias>1) { while (--CreationParams.AntiAlias>1) { SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, CreationParams.AntiAlias ); Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); if (Screen) break; } if ( !Screen ) { SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 0 ); Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); if (Screen) os::Printer::log("AntiAliasing disabled due to lack of support!" ); } } } else if ( !Screen ) Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); if ( !Screen && CreationParams.Doublebuffer) { // Try single buffer if (CreationParams.DriverType == video::EDT_OPENGL) SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); SDL_Flags &= ~SDL_DOUBLEBUF; Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); } if ( !Screen ) { os::Printer::log( "Could not initialize display!" ); return false; } return true; } //! create the driver void CIrrDeviceSDL::createDriver() { switch(CreationParams.DriverType) { case video::EDT_DIRECT3D8: #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ VideoDriver = video::createDirectX8Driver(CreationParams, FileSystem, HWnd); if (!VideoDriver) { os::Printer::log("Could not create DIRECT3D8 Driver.", ELL_ERROR); } #else os::Printer::log("DIRECT3D8 Driver was not compiled into this dll. Try another one.", ELL_ERROR); #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ break; case video::EDT_DIRECT3D9: #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ VideoDriver = video::createDirectX9Driver(CreationParams, FileSystem, HWnd); if (!VideoDriver) { os::Printer::log("Could not create DIRECT3D9 Driver.", ELL_ERROR); } #else os::Printer::log("DIRECT3D9 Driver was not compiled into this dll. Try another one.", ELL_ERROR); #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ break; case video::EDT_SOFTWARE: #ifdef _IRR_COMPILE_WITH_SOFTWARE_ VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); #else os::Printer::log("No Software driver support compiled in.", ELL_ERROR); #endif break; case video::EDT_BURNINGSVIDEO: #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this); #else os::Printer::log("Burning's video driver was not compiled in.", ELL_ERROR); #endif break; case video::EDT_OPENGL: #ifdef _IRR_COMPILE_WITH_OPENGL_ VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem, this); #else os::Printer::log("No OpenGL support compiled in.", ELL_ERROR); #endif break; case video::EDT_NULL: VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize); break; default: os::Printer::log("Unable to create video driver of unknown type.", ELL_ERROR); break; } } //! runs the device. Returns false if device wants to be deleted bool CIrrDeviceSDL::run() { os::Timer::tick(); SEvent irrevent; SDL_Event SDL_event; while ( !Close && SDL_PollEvent( &SDL_event ) ) { switch ( SDL_event.type ) { case SDL_MOUSEMOTION: irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT; irrevent.MouseInput.Event = irr::EMIE_MOUSE_MOVED; MouseX = irrevent.MouseInput.X = SDL_event.motion.x; MouseY = irrevent.MouseInput.Y = SDL_event.motion.y; irrevent.MouseInput.ButtonStates = MouseButtonStates; postEventFromUser(irrevent); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT; irrevent.MouseInput.X = SDL_event.button.x; irrevent.MouseInput.Y = SDL_event.button.y; irrevent.MouseInput.Event = irr::EMIE_MOUSE_MOVED; switch(SDL_event.button.button) { case SDL_BUTTON_LEFT: if (SDL_event.type == SDL_MOUSEBUTTONDOWN) { irrevent.MouseInput.Event = irr::EMIE_LMOUSE_PRESSED_DOWN; MouseButtonStates |= irr::EMBSM_LEFT; } else { irrevent.MouseInput.Event = irr::EMIE_LMOUSE_LEFT_UP; MouseButtonStates &= !irr::EMBSM_LEFT; } break; case SDL_BUTTON_RIGHT: if (SDL_event.type == SDL_MOUSEBUTTONDOWN) { irrevent.MouseInput.Event = irr::EMIE_RMOUSE_PRESSED_DOWN; MouseButtonStates |= irr::EMBSM_RIGHT; } else { irrevent.MouseInput.Event = irr::EMIE_RMOUSE_LEFT_UP; MouseButtonStates &= !irr::EMBSM_RIGHT; } break; case SDL_BUTTON_MIDDLE: if (SDL_event.type == SDL_MOUSEBUTTONDOWN) { irrevent.MouseInput.Event = irr::EMIE_MMOUSE_PRESSED_DOWN; MouseButtonStates |= irr::EMBSM_MIDDLE; } else { irrevent.MouseInput.Event = irr::EMIE_MMOUSE_LEFT_UP; MouseButtonStates &= !irr::EMBSM_MIDDLE; } break; case SDL_BUTTON_WHEELUP: irrevent.MouseInput.Event = irr::EMIE_MOUSE_WHEEL; irrevent.MouseInput.Wheel = 1.0f; break; case SDL_BUTTON_WHEELDOWN: irrevent.MouseInput.Event = irr::EMIE_MOUSE_WHEEL; irrevent.MouseInput.Wheel = -1.0f; break; } irrevent.MouseInput.ButtonStates = MouseButtonStates; if (irrevent.MouseInput.Event != irr::EMIE_MOUSE_MOVED) { postEventFromUser(irrevent); if ( irrevent.MouseInput.Event >= EMIE_LMOUSE_PRESSED_DOWN && irrevent.MouseInput.Event <= EMIE_MMOUSE_PRESSED_DOWN ) { u32 clicks = checkSuccessiveClicks(irrevent.MouseInput.X, irrevent.MouseInput.Y, irrevent.MouseInput.Event); if ( clicks == 2 ) { irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_DOUBLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN); postEventFromUser(irrevent); } else if ( clicks == 3 ) { irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_TRIPLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN); postEventFromUser(irrevent); } } } break; case SDL_KEYDOWN: case SDL_KEYUP: { SKeyMap mp; mp.SDLKey = SDL_event.key.keysym.sym; s32 idx = KeyMap.binary_search(mp); EKEY_CODE key; if (idx == -1) key = (EKEY_CODE)0; else key = (EKEY_CODE)KeyMap[idx].Win32Key; #ifdef _IRR_WINDOWS_API_ // handle alt+f4 in Windows, because SDL seems not to if ( (SDL_event.key.keysym.mod & KMOD_LALT) && key == KEY_F4) { Close = true; break; } #endif irrevent.EventType = irr::EET_KEY_INPUT_EVENT; irrevent.KeyInput.Char = SDL_event.key.keysym.unicode; irrevent.KeyInput.Key = key; irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN); irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0; irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL ) != 0; postEventFromUser(irrevent); } break; case SDL_QUIT: Close = true; break; case SDL_ACTIVEEVENT: if ((SDL_event.active.state == SDL_APPMOUSEFOCUS) || (SDL_event.active.state == SDL_APPINPUTFOCUS)) WindowHasFocus = (SDL_event.active.gain==1); else if (SDL_event.active.state == SDL_APPACTIVE) WindowMinimized = (SDL_event.active.gain!=1); break; case SDL_VIDEORESIZE: if ((SDL_event.resize.w != (int)Width) || (SDL_event.resize.h != (int)Height)) { Width = SDL_event.resize.w; Height = SDL_event.resize.h; Screen = SDL_SetVideoMode( Width, Height, 0, SDL_Flags ); if (VideoDriver) VideoDriver->OnResize(core::dimension2d(Width, Height)); } break; case SDL_USEREVENT: irrevent.EventType = irr::EET_USER_EVENT; irrevent.UserEvent.UserData1 = *(reinterpret_cast(&SDL_event.user.data1)); irrevent.UserEvent.UserData2 = *(reinterpret_cast(&SDL_event.user.data2)); postEventFromUser(irrevent); break; default: break; } // end switch } // end while #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) // TODO: Check if the multiple open/close calls are too expensive, then // open/close in the constructor/destructor instead // update joystick states manually SDL_JoystickUpdate(); // we'll always send joystick input events... SEvent joyevent; joyevent.EventType = EET_JOYSTICK_INPUT_EVENT; for (u32 i=0; i0) { switch (SDL_JoystickGetHat(joystick, 0)) { case SDL_HAT_UP: joyevent.JoystickEvent.POV=0; break; case SDL_HAT_RIGHTUP: joyevent.JoystickEvent.POV=4500; break; case SDL_HAT_RIGHT: joyevent.JoystickEvent.POV=9000; break; case SDL_HAT_RIGHTDOWN: joyevent.JoystickEvent.POV=13500; break; case SDL_HAT_DOWN: joyevent.JoystickEvent.POV=18000; break; case SDL_HAT_LEFTDOWN: joyevent.JoystickEvent.POV=22500; break; case SDL_HAT_LEFT: joyevent.JoystickEvent.POV=27000; break; case SDL_HAT_LEFTUP: joyevent.JoystickEvent.POV=31500; break; case SDL_HAT_CENTERED: default: joyevent.JoystickEvent.POV=65535; break; } } else { joyevent.JoystickEvent.POV=65535; } // we map the number directly joyevent.JoystickEvent.Joystick=static_cast(i); // now post the event postEventFromUser(joyevent); // and close the joystick } } #endif return !Close; } //! Activate any joysticks, and generate events for them. bool CIrrDeviceSDL::activateJoysticks(core::array & joystickInfo) { #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) joystickInfo.clear(); // we can name up to 256 different joysticks const int numJoysticks = core::min_(SDL_NumJoysticks(), 256); Joysticks.reallocate(numJoysticks); joystickInfo.reallocate(numJoysticks); int joystick = 0; for (; joystick 0) ? SJoystickInfo::POV_HAT_PRESENT : SJoystickInfo::POV_HAT_ABSENT; joystickInfo.push_back(info); } for(joystick = 0; joystick < (int)joystickInfo.size(); ++joystick) { char logString[256]; (void)sprintf(logString, "Found joystick %d, %d axes, %d buttons '%s'", joystick, joystickInfo[joystick].Axes, joystickInfo[joystick].Buttons, joystickInfo[joystick].Name.c_str()); os::Printer::log(logString, ELL_INFORMATION); } return true; #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ return false; } //! pause execution temporarily void CIrrDeviceSDL::yield() { SDL_Delay(0); } //! pause execution for a specified time void CIrrDeviceSDL::sleep(u32 timeMs, bool pauseTimer) { const bool wasStopped = Timer ? Timer->isStopped() : true; if (pauseTimer && !wasStopped) Timer->stop(); SDL_Delay(timeMs); if (pauseTimer && !wasStopped) Timer->start(); } //! sets the caption of the window void CIrrDeviceSDL::setWindowCaption(const wchar_t* text) { core::stringc textc = text; SDL_WM_SetCaption( textc.c_str( ), textc.c_str( ) ); } //! presents a surface in the client area bool CIrrDeviceSDL::present(video::IImage* surface, void* windowId, core::rect* srcClip) { SDL_Surface *sdlSurface = SDL_CreateRGBSurfaceFrom( surface->lock(), surface->getDimension().Width, surface->getDimension().Height, surface->getBitsPerPixel(), surface->getPitch(), surface->getRedMask(), surface->getGreenMask(), surface->getBlueMask(), surface->getAlphaMask()); if (!sdlSurface) return false; SDL_SetAlpha(sdlSurface, 0, 0); SDL_SetColorKey(sdlSurface, 0, 0); sdlSurface->format->BitsPerPixel=surface->getBitsPerPixel(); sdlSurface->format->BytesPerPixel=surface->getBytesPerPixel(); if ((surface->getColorFormat()==video::ECF_R8G8B8) || (surface->getColorFormat()==video::ECF_A8R8G8B8)) { sdlSurface->format->Rloss=0; sdlSurface->format->Gloss=0; sdlSurface->format->Bloss=0; sdlSurface->format->Rshift=16; sdlSurface->format->Gshift=8; sdlSurface->format->Bshift=0; if (surface->getColorFormat()==video::ECF_R8G8B8) { sdlSurface->format->Aloss=8; sdlSurface->format->Ashift=32; } else { sdlSurface->format->Aloss=0; sdlSurface->format->Ashift=24; } } else if (surface->getColorFormat()==video::ECF_R5G6B5) { sdlSurface->format->Rloss=3; sdlSurface->format->Gloss=2; sdlSurface->format->Bloss=3; sdlSurface->format->Aloss=8; sdlSurface->format->Rshift=11; sdlSurface->format->Gshift=5; sdlSurface->format->Bshift=0; sdlSurface->format->Ashift=16; } else if (surface->getColorFormat()==video::ECF_A1R5G5B5) { sdlSurface->format->Rloss=3; sdlSurface->format->Gloss=3; sdlSurface->format->Bloss=3; sdlSurface->format->Aloss=7; sdlSurface->format->Rshift=10; sdlSurface->format->Gshift=5; sdlSurface->format->Bshift=0; sdlSurface->format->Ashift=15; } SDL_Surface* scr = (SDL_Surface* )windowId; if (!scr) scr = Screen; if (scr) { if (srcClip) { SDL_Rect sdlsrcClip; sdlsrcClip.x = srcClip->UpperLeftCorner.X; sdlsrcClip.y = srcClip->UpperLeftCorner.Y; sdlsrcClip.w = srcClip->getWidth(); sdlsrcClip.h = srcClip->getHeight(); SDL_BlitSurface(sdlSurface, &sdlsrcClip, scr, NULL); } else SDL_BlitSurface(sdlSurface, NULL, scr, NULL); SDL_Flip(scr); } SDL_FreeSurface(sdlSurface); surface->unlock(); return (scr != 0); } //! notifies the device that it should close itself void CIrrDeviceSDL::closeDevice() { Close = true; } //! \return Pointer to a list with all video modes supported video::IVideoModeList* CIrrDeviceSDL::getVideoModeList() { if (!VideoModeList->getVideoModeCount()) { // enumerate video modes. const SDL_VideoInfo *vi = SDL_GetVideoInfo(); SDL_Rect **modes = SDL_ListModes(vi->vfmt, SDL_Flags); if (modes != 0) { if (modes == (SDL_Rect **)-1) os::Printer::log("All modes available.\n"); else { for (u32 i=0; modes[i]; ++i) VideoModeList->addMode(core::dimension2d(modes[i]->w, modes[i]->h), vi->vfmt->BitsPerPixel); } } } return VideoModeList; } //! Sets if the window should be resizable in windowed mode. void CIrrDeviceSDL::setResizable(bool resize) { if (resize != Resizable) { if (resize) SDL_Flags |= SDL_RESIZABLE; else SDL_Flags &= ~SDL_RESIZABLE; Screen = SDL_SetVideoMode( 0, 0, 0, SDL_Flags ); Resizable = resize; } } //! Minimizes window if possible void CIrrDeviceSDL::minimizeWindow() { SDL_WM_IconifyWindow(); } //! Maximize window void CIrrDeviceSDL::maximizeWindow() { // do nothing } //! Restore original window size void CIrrDeviceSDL::restoreWindow() { // do nothing } //! returns if window is active. if not, nothing need to be drawn bool CIrrDeviceSDL::isWindowActive() const { return (WindowHasFocus && !WindowMinimized); } //! returns if window has focus. bool CIrrDeviceSDL::isWindowFocused() const { return WindowHasFocus; } //! returns if window is minimized. bool CIrrDeviceSDL::isWindowMinimized() const { return WindowMinimized; } //! Set the current Gamma Value for the Display bool CIrrDeviceSDL::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) { /* // todo: Gamma in SDL takes ints, what does Irrlicht use? return (SDL_SetGamma(red, green, blue) != -1); */ return false; } //! Get the current Gamma Value for the Display bool CIrrDeviceSDL::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ) { /* brightness = 0.f; contrast = 0.f; return (SDL_GetGamma(&red, &green, &blue) != -1);*/ return false; } //! returns color format of the window. video::ECOLOR_FORMAT CIrrDeviceSDL::getColorFormat() const { if (Screen) { if (Screen->format->BitsPerPixel==16) { if (Screen->format->Amask != 0) return video::ECF_A1R5G5B5; else return video::ECF_R5G6B5; } else { if (Screen->format->Amask != 0) return video::ECF_A8R8G8B8; else return video::ECF_R8G8B8; } } else return CIrrDeviceStub::getColorFormat(); } void CIrrDeviceSDL::createKeyMap() { // I don't know if this is the best method to create // the lookuptable, but I'll leave it like that until // I find a better version. KeyMap.reallocate(105); // buttons missing KeyMap.push_back(SKeyMap(SDLK_BACKSPACE, KEY_BACK)); KeyMap.push_back(SKeyMap(SDLK_TAB, KEY_TAB)); KeyMap.push_back(SKeyMap(SDLK_CLEAR, KEY_CLEAR)); KeyMap.push_back(SKeyMap(SDLK_RETURN, KEY_RETURN)); // combined modifiers missing KeyMap.push_back(SKeyMap(SDLK_PAUSE, KEY_PAUSE)); KeyMap.push_back(SKeyMap(SDLK_CAPSLOCK, KEY_CAPITAL)); // asian letter keys missing KeyMap.push_back(SKeyMap(SDLK_ESCAPE, KEY_ESCAPE)); // asian letter keys missing KeyMap.push_back(SKeyMap(SDLK_SPACE, KEY_SPACE)); KeyMap.push_back(SKeyMap(SDLK_PAGEUP, KEY_PRIOR)); KeyMap.push_back(SKeyMap(SDLK_PAGEDOWN, KEY_NEXT)); KeyMap.push_back(SKeyMap(SDLK_END, KEY_END)); KeyMap.push_back(SKeyMap(SDLK_HOME, KEY_HOME)); KeyMap.push_back(SKeyMap(SDLK_LEFT, KEY_LEFT)); KeyMap.push_back(SKeyMap(SDLK_UP, KEY_UP)); KeyMap.push_back(SKeyMap(SDLK_RIGHT, KEY_RIGHT)); KeyMap.push_back(SKeyMap(SDLK_DOWN, KEY_DOWN)); // select missing KeyMap.push_back(SKeyMap(SDLK_PRINT, KEY_PRINT)); // execute missing KeyMap.push_back(SKeyMap(SDLK_PRINT, KEY_SNAPSHOT)); KeyMap.push_back(SKeyMap(SDLK_INSERT, KEY_INSERT)); KeyMap.push_back(SKeyMap(SDLK_DELETE, KEY_DELETE)); KeyMap.push_back(SKeyMap(SDLK_HELP, KEY_HELP)); KeyMap.push_back(SKeyMap(SDLK_0, KEY_KEY_0)); KeyMap.push_back(SKeyMap(SDLK_1, KEY_KEY_1)); KeyMap.push_back(SKeyMap(SDLK_2, KEY_KEY_2)); KeyMap.push_back(SKeyMap(SDLK_3, KEY_KEY_3)); KeyMap.push_back(SKeyMap(SDLK_4, KEY_KEY_4)); KeyMap.push_back(SKeyMap(SDLK_5, KEY_KEY_5)); KeyMap.push_back(SKeyMap(SDLK_6, KEY_KEY_6)); KeyMap.push_back(SKeyMap(SDLK_7, KEY_KEY_7)); KeyMap.push_back(SKeyMap(SDLK_8, KEY_KEY_8)); KeyMap.push_back(SKeyMap(SDLK_9, KEY_KEY_9)); KeyMap.push_back(SKeyMap(SDLK_a, KEY_KEY_A)); KeyMap.push_back(SKeyMap(SDLK_b, KEY_KEY_B)); KeyMap.push_back(SKeyMap(SDLK_c, KEY_KEY_C)); KeyMap.push_back(SKeyMap(SDLK_d, KEY_KEY_D)); KeyMap.push_back(SKeyMap(SDLK_e, KEY_KEY_E)); KeyMap.push_back(SKeyMap(SDLK_f, KEY_KEY_F)); KeyMap.push_back(SKeyMap(SDLK_g, KEY_KEY_G)); KeyMap.push_back(SKeyMap(SDLK_h, KEY_KEY_H)); KeyMap.push_back(SKeyMap(SDLK_i, KEY_KEY_I)); KeyMap.push_back(SKeyMap(SDLK_j, KEY_KEY_J)); KeyMap.push_back(SKeyMap(SDLK_k, KEY_KEY_K)); KeyMap.push_back(SKeyMap(SDLK_l, KEY_KEY_L)); KeyMap.push_back(SKeyMap(SDLK_m, KEY_KEY_M)); KeyMap.push_back(SKeyMap(SDLK_n, KEY_KEY_N)); KeyMap.push_back(SKeyMap(SDLK_o, KEY_KEY_O)); KeyMap.push_back(SKeyMap(SDLK_p, KEY_KEY_P)); KeyMap.push_back(SKeyMap(SDLK_q, KEY_KEY_Q)); KeyMap.push_back(SKeyMap(SDLK_r, KEY_KEY_R)); KeyMap.push_back(SKeyMap(SDLK_s, KEY_KEY_S)); KeyMap.push_back(SKeyMap(SDLK_t, KEY_KEY_T)); KeyMap.push_back(SKeyMap(SDLK_u, KEY_KEY_U)); KeyMap.push_back(SKeyMap(SDLK_v, KEY_KEY_V)); KeyMap.push_back(SKeyMap(SDLK_w, KEY_KEY_W)); KeyMap.push_back(SKeyMap(SDLK_x, KEY_KEY_X)); KeyMap.push_back(SKeyMap(SDLK_y, KEY_KEY_Y)); KeyMap.push_back(SKeyMap(SDLK_z, KEY_KEY_Z)); KeyMap.push_back(SKeyMap(SDLK_LSUPER, KEY_LWIN)); KeyMap.push_back(SKeyMap(SDLK_RSUPER, KEY_RWIN)); // apps missing KeyMap.push_back(SKeyMap(SDLK_POWER, KEY_SLEEP)); //?? KeyMap.push_back(SKeyMap(SDLK_KP0, KEY_NUMPAD0)); KeyMap.push_back(SKeyMap(SDLK_KP1, KEY_NUMPAD1)); KeyMap.push_back(SKeyMap(SDLK_KP2, KEY_NUMPAD2)); KeyMap.push_back(SKeyMap(SDLK_KP3, KEY_NUMPAD3)); KeyMap.push_back(SKeyMap(SDLK_KP4, KEY_NUMPAD4)); KeyMap.push_back(SKeyMap(SDLK_KP5, KEY_NUMPAD5)); KeyMap.push_back(SKeyMap(SDLK_KP6, KEY_NUMPAD6)); KeyMap.push_back(SKeyMap(SDLK_KP7, KEY_NUMPAD7)); KeyMap.push_back(SKeyMap(SDLK_KP8, KEY_NUMPAD8)); KeyMap.push_back(SKeyMap(SDLK_KP9, KEY_NUMPAD9)); KeyMap.push_back(SKeyMap(SDLK_KP_MULTIPLY, KEY_MULTIPLY)); KeyMap.push_back(SKeyMap(SDLK_KP_PLUS, KEY_ADD)); // KeyMap.push_back(SKeyMap(SDLK_KP_, KEY_SEPARATOR)); KeyMap.push_back(SKeyMap(SDLK_KP_MINUS, KEY_SUBTRACT)); KeyMap.push_back(SKeyMap(SDLK_KP_PERIOD, KEY_DECIMAL)); KeyMap.push_back(SKeyMap(SDLK_KP_DIVIDE, KEY_DIVIDE)); KeyMap.push_back(SKeyMap(SDLK_F1, KEY_F1)); KeyMap.push_back(SKeyMap(SDLK_F2, KEY_F2)); KeyMap.push_back(SKeyMap(SDLK_F3, KEY_F3)); KeyMap.push_back(SKeyMap(SDLK_F4, KEY_F4)); KeyMap.push_back(SKeyMap(SDLK_F5, KEY_F5)); KeyMap.push_back(SKeyMap(SDLK_F6, KEY_F6)); KeyMap.push_back(SKeyMap(SDLK_F7, KEY_F7)); KeyMap.push_back(SKeyMap(SDLK_F8, KEY_F8)); KeyMap.push_back(SKeyMap(SDLK_F9, KEY_F9)); KeyMap.push_back(SKeyMap(SDLK_F10, KEY_F10)); KeyMap.push_back(SKeyMap(SDLK_F11, KEY_F11)); KeyMap.push_back(SKeyMap(SDLK_F12, KEY_F12)); KeyMap.push_back(SKeyMap(SDLK_F13, KEY_F13)); KeyMap.push_back(SKeyMap(SDLK_F14, KEY_F14)); KeyMap.push_back(SKeyMap(SDLK_F15, KEY_F15)); // no higher F-keys KeyMap.push_back(SKeyMap(SDLK_NUMLOCK, KEY_NUMLOCK)); KeyMap.push_back(SKeyMap(SDLK_SCROLLOCK, KEY_SCROLL)); KeyMap.push_back(SKeyMap(SDLK_LSHIFT, KEY_LSHIFT)); KeyMap.push_back(SKeyMap(SDLK_RSHIFT, KEY_RSHIFT)); KeyMap.push_back(SKeyMap(SDLK_LCTRL, KEY_LCONTROL)); KeyMap.push_back(SKeyMap(SDLK_RCTRL, KEY_RCONTROL)); KeyMap.push_back(SKeyMap(SDLK_LALT, KEY_LMENU)); KeyMap.push_back(SKeyMap(SDLK_RALT, KEY_RMENU)); KeyMap.push_back(SKeyMap(SDLK_PLUS, KEY_PLUS)); KeyMap.push_back(SKeyMap(SDLK_COMMA, KEY_COMMA)); KeyMap.push_back(SKeyMap(SDLK_MINUS, KEY_MINUS)); KeyMap.push_back(SKeyMap(SDLK_PERIOD, KEY_PERIOD)); // some special keys missing KeyMap.sort(); } } // end namespace irr #endif // _IRR_COMPILE_WITH_SDL_DEVICE_ irrlicht-1.8.3/source/Irrlicht/CIrrDeviceLinux.h0000644000000000000000000002665512574354552020323 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IRR_DEVICE_LINUX_H_INCLUDED__ #define __C_IRR_DEVICE_LINUX_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ #include "CIrrDeviceStub.h" #include "IrrlichtDevice.h" #include "IImagePresenter.h" #include "ICursorControl.h" #include "os.h" #ifdef _IRR_COMPILE_WITH_X11_ #ifdef _IRR_COMPILE_WITH_OPENGL_ #include #define GLX_GLXEXT_LEGACY 1 #include #ifdef _IRR_OPENGL_USE_EXTPOINTER_ #include "glxext.h" #endif #endif #include #include #include #ifdef _IRR_LINUX_X11_VIDMODE_ #include #endif #ifdef _IRR_LINUX_X11_RANDR_ #include #endif #include #else #define KeySym s32 #endif namespace irr { class CIrrDeviceLinux : public CIrrDeviceStub, public video::IImagePresenter { public: //! constructor CIrrDeviceLinux(const SIrrlichtCreationParameters& param); //! destructor virtual ~CIrrDeviceLinux(); //! runs the device. Returns false if device wants to be deleted virtual bool run(); //! Cause the device to temporarily pause execution and let other processes to run // This should bring down processor usage without major performance loss for Irrlicht virtual void yield(); //! Pause execution and let other processes to run for a specified amount of time. virtual void sleep(u32 timeMs, bool pauseTimer); //! sets the caption of the window virtual void setWindowCaption(const wchar_t* text); //! returns if window is active. if not, nothing need to be drawn virtual bool isWindowActive() const; //! returns if window has focus. virtual bool isWindowFocused() const; //! returns if window is minimized. virtual bool isWindowMinimized() const; //! returns color format of the window. virtual video::ECOLOR_FORMAT getColorFormat() const; //! presents a surface in the client area virtual bool present(video::IImage* surface, void* windowId=0, core::rect* src=0 ); //! notifies the device that it should close itself virtual void closeDevice(); //! \return Returns a pointer to a list with all video modes //! supported by the gfx adapter. video::IVideoModeList* getVideoModeList(); //! Sets if the window should be resizable in windowed mode. virtual void setResizable(bool resize=false); //! Minimizes the window. virtual void minimizeWindow(); //! Maximizes the window. virtual void maximizeWindow(); //! Restores the window size. virtual void restoreWindow(); //! Activate any joysticks, and generate events for them. virtual bool activateJoysticks(core::array & joystickInfo); //! Set the current Gamma Value for the Display virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ); //! Get the current Gamma Value for the Display virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ); //! gets text from the clipboard //! \return Returns 0 if no string is in there. virtual const c8* getTextFromClipboard() const; //! copies text to the clipboard //! This sets the clipboard selection and _not_ the primary selection which you have on X on the middle mouse button. virtual void copyToClipboard(const c8* text) const; //! Remove all messages pending in the system message loop virtual void clearSystemMessages(); //! Get the device type virtual E_DEVICE_TYPE getType() const { return EIDT_X11; } #ifdef _IRR_COMPILE_WITH_X11_ // convert an Irrlicht texture to a X11 cursor Cursor TextureToCursor(irr::video::ITexture * tex, const core::rect& sourceRect, const core::position2d &hotspot); Cursor TextureToMonochromeCursor(irr::video::ITexture * tex, const core::rect& sourceRect, const core::position2d &hotspot); #ifdef _IRR_LINUX_XCURSOR_ Cursor TextureToARGBCursor(irr::video::ITexture * tex, const core::rect& sourceRect, const core::position2d &hotspot); #endif #endif private: //! create the driver void createDriver(); bool createWindow(); void createKeyMap(); void pollJoysticks(); void initXAtoms(); bool switchToFullscreen(bool reset=false); //! Implementation of the linux cursor control class CCursorControl : public gui::ICursorControl { public: CCursorControl(CIrrDeviceLinux* dev, bool null); ~CCursorControl(); //! Changes the visible state of the mouse cursor. virtual void setVisible(bool visible) { if (visible==IsVisible) return; IsVisible = visible; #ifdef _IRR_COMPILE_WITH_X11_ if (!Null) { if ( !IsVisible ) XDefineCursor( Device->display, Device->window, invisCursor ); else XUndefineCursor( Device->display, Device->window ); } #endif } //! Returns if the cursor is currently visible. virtual bool isVisible() const { return IsVisible; } //! Sets the new position of the cursor. virtual void setPosition(const core::position2d &pos) { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. virtual void setPosition(f32 x, f32 y) { setPosition((s32)(x*Device->Width), (s32)(y*Device->Height)); } //! Sets the new position of the cursor. virtual void setPosition(const core::position2d &pos) { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. virtual void setPosition(s32 x, s32 y) { #ifdef _IRR_COMPILE_WITH_X11_ if (!Null) { if (UseReferenceRect) { XWarpPointer(Device->display, None, Device->window, 0, 0, Device->Width, Device->Height, ReferenceRect.UpperLeftCorner.X + x, ReferenceRect.UpperLeftCorner.Y + y); } else { XWarpPointer(Device->display, None, Device->window, 0, 0, Device->Width, Device->Height, x, y); } XFlush(Device->display); } #endif CursorPos.X = x; CursorPos.Y = y; } //! Returns the current position of the mouse cursor. virtual const core::position2d& getPosition() { updateCursorPos(); return CursorPos; } //! Returns the current position of the mouse cursor. virtual core::position2d getRelativePosition() { updateCursorPos(); if (!UseReferenceRect) { return core::position2d(CursorPos.X / (f32)Device->Width, CursorPos.Y / (f32)Device->Height); } return core::position2d(CursorPos.X / (f32)ReferenceRect.getWidth(), CursorPos.Y / (f32)ReferenceRect.getHeight()); } virtual void setReferenceRect(core::rect* rect=0) { if (rect) { ReferenceRect = *rect; UseReferenceRect = true; // prevent division through zero and uneven sizes if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2) ReferenceRect.LowerRightCorner.Y += 1; if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2) ReferenceRect.LowerRightCorner.X += 1; } else UseReferenceRect = false; } //! Sets the active cursor icon virtual void setActiveIcon(gui::ECURSOR_ICON iconId); //! Gets the currently active icon virtual gui::ECURSOR_ICON getActiveIcon() const { return ActiveIcon; } //! Add a custom sprite as cursor icon. virtual gui::ECURSOR_ICON addIcon(const gui::SCursorSprite& icon); //! replace the given cursor icon. virtual void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon); //! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work. virtual core::dimension2di getSupportedIconSize() const; #ifdef _IRR_COMPILE_WITH_X11_ //! Set platform specific behavior flags. virtual void setPlatformBehavior(gui::ECURSOR_PLATFORM_BEHAVIOR behavior) {PlatformBehavior = behavior; } //! Return platform specific behavior. virtual gui::ECURSOR_PLATFORM_BEHAVIOR getPlatformBehavior() const { return PlatformBehavior; } void update(); void clearCursors(); #endif private: void updateCursorPos() { #ifdef _IRR_COMPILE_WITH_X11_ if (Null) return; if ( PlatformBehavior&gui::ECPB_X11_CACHE_UPDATES && !os::Timer::isStopped() ) { u32 now = os::Timer::getTime(); if (now <= lastQuery) return; lastQuery = now; } Window tmp; int itmp1, itmp2; unsigned int maskreturn; XQueryPointer(Device->display, Device->window, &tmp, &tmp, &itmp1, &itmp2, &CursorPos.X, &CursorPos.Y, &maskreturn); if (CursorPos.X < 0) CursorPos.X = 0; if (CursorPos.X > (s32) Device->Width) CursorPos.X = Device->Width; if (CursorPos.Y < 0) CursorPos.Y = 0; if (CursorPos.Y > (s32) Device->Height) CursorPos.Y = Device->Height; #endif } CIrrDeviceLinux* Device; core::position2d CursorPos; core::rect ReferenceRect; #ifdef _IRR_COMPILE_WITH_X11_ gui::ECURSOR_PLATFORM_BEHAVIOR PlatformBehavior; u32 lastQuery; Cursor invisCursor; struct CursorFrameX11 { CursorFrameX11() : IconHW(0) {} CursorFrameX11(Cursor icon) : IconHW(icon) {} Cursor IconHW; // hardware cursor }; struct CursorX11 { CursorX11() {} explicit CursorX11(Cursor iconHw, u32 frameTime=0) : FrameTime(frameTime) { Frames.push_back( CursorFrameX11(iconHw) ); } core::array Frames; u32 FrameTime; }; core::array Cursors; void initCursors(); #endif bool IsVisible; bool Null; bool UseReferenceRect; gui::ECURSOR_ICON ActiveIcon; u32 ActiveIconStartTime; }; friend class CCursorControl; #ifdef _IRR_COMPILE_WITH_X11_ friend class COpenGLDriver; Display *display; XVisualInfo* visual; int screennr; Window window; XSetWindowAttributes attributes; XSizeHints* StdHints; XImage* SoftwareImage; mutable core::stringc Clipboard; #ifdef _IRR_LINUX_X11_VIDMODE_ XF86VidModeModeInfo oldVideoMode; #endif #ifdef _IRR_LINUX_X11_RANDR_ SizeID oldRandrMode; Rotation oldRandrRotation; #endif #ifdef _IRR_COMPILE_WITH_OPENGL_ GLXWindow glxWin; GLXContext Context; #endif #endif u32 Width, Height; bool WindowHasFocus; bool WindowMinimized; bool UseXVidMode; bool UseXRandR; bool UseGLXWindow; bool ExternalWindow; int AutorepeatSupport; struct SKeyMap { SKeyMap() {} SKeyMap(s32 x11, s32 win32) : X11Key(x11), Win32Key(win32) { } KeySym X11Key; s32 Win32Key; bool operator<(const SKeyMap& o) const { return X11Key KeyMap; #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) struct JoystickInfo { int fd; int axes; int buttons; SEvent persistentData; JoystickInfo() : fd(-1), axes(0), buttons(0) { } }; core::array ActiveJoysticks; #endif }; } // end namespace irr #endif // _IRR_COMPILE_WITH_X11_DEVICE_ #endif // __C_IRR_DEVICE_LINUX_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CIrrDeviceLinux.cpp0000644000000000000000000021656712574354552020661 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CIrrDeviceLinux.h" #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ #include #include #include #include #include "IEventReceiver.h" #include "ISceneManager.h" #include "IGUIEnvironment.h" #include "os.h" #include "CTimer.h" #include "irrString.h" #include "Keycodes.h" #include "COSOperator.h" #include "CColorConverter.h" #include "SIrrCreationParameters.h" #include "IGUISpriteBank.h" #include #include #ifdef _IRR_LINUX_XCURSOR_ #include #endif #if defined _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ #include #include #ifdef __FreeBSD__ #include #else // linux/joystick.h includes linux/input.h, which #defines values for various KEY_FOO keys. // These override the irr::KEY_FOO equivalents, which stops key handling from working. // As a workaround, defining _INPUT_H stops linux/input.h from being included; it // doesn't actually seem to be necessary except to pull in sys/ioctl.h. #define _INPUT_H #include // Would normally be included in linux/input.h #include #undef _INPUT_H #endif #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ namespace irr { namespace video { IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceLinux* device); } } // end namespace irr namespace { Atom X_ATOM_CLIPBOARD; Atom X_ATOM_TARGETS; Atom X_ATOM_UTF8_STRING; Atom X_ATOM_TEXT; }; namespace irr { const char* wmDeleteWindow = "WM_DELETE_WINDOW"; //! constructor CIrrDeviceLinux::CIrrDeviceLinux(const SIrrlichtCreationParameters& param) : CIrrDeviceStub(param), #ifdef _IRR_COMPILE_WITH_X11_ display(0), visual(0), screennr(0), window(0), StdHints(0), SoftwareImage(0), #ifdef _IRR_COMPILE_WITH_OPENGL_ glxWin(0), Context(0), #endif #endif Width(param.WindowSize.Width), Height(param.WindowSize.Height), WindowHasFocus(false), WindowMinimized(false), UseXVidMode(false), UseXRandR(false), UseGLXWindow(false), ExternalWindow(false), AutorepeatSupport(0) { #ifdef _DEBUG setDebugName("CIrrDeviceLinux"); #endif // print version, distribution etc. // thx to LynxLuna for pointing me to the uname function core::stringc linuxversion; struct utsname LinuxInfo; uname(&LinuxInfo); linuxversion += LinuxInfo.sysname; linuxversion += " "; linuxversion += LinuxInfo.release; linuxversion += " "; linuxversion += LinuxInfo.version; linuxversion += " "; linuxversion += LinuxInfo.machine; Operator = new COSOperator(linuxversion, this); os::Printer::log(linuxversion.c_str(), ELL_INFORMATION); // create keymap createKeyMap(); // create window if (CreationParams.DriverType != video::EDT_NULL) { // create the window, only if we do not use the null device if (!createWindow()) return; } // create cursor control CursorControl = new CCursorControl(this, CreationParams.DriverType == video::EDT_NULL); // create driver createDriver(); if (!VideoDriver) return; createGUIAndScene(); } //! destructor CIrrDeviceLinux::~CIrrDeviceLinux() { #ifdef _IRR_COMPILE_WITH_X11_ if (StdHints) XFree(StdHints); // Disable cursor (it is drop'ed in stub) if (CursorControl) { CursorControl->setVisible(false); static_cast(CursorControl)->clearCursors(); } // Must free OpenGL textures etc before destroying context, so can't wait for stub destructor if ( GUIEnvironment ) { GUIEnvironment->drop(); GUIEnvironment = NULL; } if ( SceneManager ) { SceneManager->drop(); SceneManager = NULL; } if ( VideoDriver ) { VideoDriver->drop(); VideoDriver = NULL; } if (display) { #ifdef _IRR_COMPILE_WITH_OPENGL_ if (Context) { if (glxWin) { if (!glXMakeContextCurrent(display, None, None, NULL)) os::Printer::log("Could not release glx context.", ELL_WARNING); } else { if (!glXMakeCurrent(display, None, NULL)) os::Printer::log("Could not release glx context.", ELL_WARNING); } glXDestroyContext(display, Context); if (glxWin) glXDestroyWindow(display, glxWin); } #endif // #ifdef _IRR_COMPILE_WITH_OPENGL_ // Reset fullscreen resolution change switchToFullscreen(true); if (SoftwareImage) XDestroyImage(SoftwareImage); if (!ExternalWindow) { XDestroyWindow(display,window); XCloseDisplay(display); } } if (visual) XFree(visual); #endif // #ifdef _IRR_COMPILE_WITH_X11_ #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) for (u32 joystick = 0; joystick < ActiveJoysticks.size(); ++joystick) { if (ActiveJoysticks[joystick].fd >= 0) { close(ActiveJoysticks[joystick].fd); } } #endif } #if defined(_IRR_COMPILE_WITH_X11_) && defined(_DEBUG) int IrrPrintXError(Display *display, XErrorEvent *event) { char msg[256]; char msg2[256]; snprintf(msg, 256, "%d", event->request_code); XGetErrorDatabaseText(display, "XRequest", msg, "unknown", msg2, 256); XGetErrorText(display, event->error_code, msg, 256); os::Printer::log("X Error", msg, ELL_WARNING); os::Printer::log("From call ", msg2, ELL_WARNING); return 0; } #endif bool CIrrDeviceLinux::switchToFullscreen(bool reset) { if (!CreationParams.Fullscreen) return true; if (reset) { #ifdef _IRR_LINUX_X11_VIDMODE_ if (UseXVidMode && CreationParams.Fullscreen) { XF86VidModeSwitchToMode(display, screennr, &oldVideoMode); XF86VidModeSetViewPort(display, screennr, 0, 0); } #endif #ifdef _IRR_LINUX_X11_RANDR_ if (UseXRandR && CreationParams.Fullscreen) { XRRScreenConfiguration *config=XRRGetScreenInfo(display,DefaultRootWindow(display)); XRRSetScreenConfig(display,config,DefaultRootWindow(display),oldRandrMode,oldRandrRotation,CurrentTime); XRRFreeScreenConfigInfo(config); } #endif return true; } getVideoModeList(); #if defined(_IRR_LINUX_X11_VIDMODE_) || defined(_IRR_LINUX_X11_RANDR_) s32 eventbase, errorbase; s32 bestMode = -1; #endif #ifdef _IRR_LINUX_X11_VIDMODE_ if (XF86VidModeQueryExtension(display, &eventbase, &errorbase)) { // enumerate video modes s32 modeCount; XF86VidModeModeInfo** modes; XF86VidModeGetAllModeLines(display, screennr, &modeCount, &modes); // find fitting mode for (s32 i = 0; ihdisplay >= Width && modes[i]->vdisplay >= Height) bestMode = i; else if (bestMode!=-1 && modes[i]->hdisplay >= Width && modes[i]->vdisplay >= Height && modes[i]->hdisplay <= modes[bestMode]->hdisplay && modes[i]->vdisplay <= modes[bestMode]->vdisplay) bestMode = i; } if (bestMode != -1) { os::Printer::log("Starting vidmode fullscreen mode...", ELL_INFORMATION); os::Printer::log("hdisplay: ", core::stringc(modes[bestMode]->hdisplay).c_str(), ELL_INFORMATION); os::Printer::log("vdisplay: ", core::stringc(modes[bestMode]->vdisplay).c_str(), ELL_INFORMATION); XF86VidModeSwitchToMode(display, screennr, modes[bestMode]); XF86VidModeSetViewPort(display, screennr, 0, 0); UseXVidMode=true; } else { os::Printer::log("Could not find specified video mode, running windowed.", ELL_WARNING); CreationParams.Fullscreen = false; } XFree(modes); } else #endif #ifdef _IRR_LINUX_X11_RANDR_ if (XRRQueryExtension(display, &eventbase, &errorbase)) { s32 modeCount; XRRScreenConfiguration *config=XRRGetScreenInfo(display,DefaultRootWindow(display)); XRRScreenSize *modes=XRRConfigSizes(config,&modeCount); for (s32 i = 0; i= Width && (u32)modes[i].height >= Height) bestMode = i; else if (bestMode!=-1 && (u32)modes[i].width >= Width && (u32)modes[i].height >= Height && modes[i].width <= modes[bestMode].width && modes[i].height <= modes[bestMode].height) bestMode = i; } if (bestMode != -1) { os::Printer::log("Starting randr fullscreen mode...", ELL_INFORMATION); os::Printer::log("width: ", core::stringc(modes[bestMode].width).c_str(), ELL_INFORMATION); os::Printer::log("height: ", core::stringc(modes[bestMode].height).c_str(), ELL_INFORMATION); XRRSetScreenConfig(display,config,DefaultRootWindow(display),bestMode,oldRandrRotation,CurrentTime); UseXRandR=true; } XRRFreeScreenConfigInfo(config); } else #endif { os::Printer::log("VidMode or RandR extension must be installed to allow Irrlicht " "to switch to fullscreen mode. Running in windowed mode instead.", ELL_WARNING); CreationParams.Fullscreen = false; } return CreationParams.Fullscreen; } #if defined(_IRR_COMPILE_WITH_X11_) void IrrPrintXGrabError(int grabResult, const c8 * grabCommand ) { if ( grabResult == GrabSuccess ) { // os::Printer::log(grabCommand, ": GrabSuccess", ELL_INFORMATION); return; } switch ( grabResult ) { case AlreadyGrabbed: os::Printer::log(grabCommand, ": AlreadyGrabbed", ELL_WARNING); break; case GrabNotViewable: os::Printer::log(grabCommand, ": GrabNotViewable", ELL_WARNING); break; case GrabFrozen: os::Printer::log(grabCommand, ": GrabFrozen", ELL_WARNING); break; case GrabInvalidTime: os::Printer::log(grabCommand, ": GrabInvalidTime", ELL_WARNING); break; default: os::Printer::log(grabCommand, ": grab failed with unknown problem", ELL_WARNING); break; } } #endif bool CIrrDeviceLinux::createWindow() { #ifdef _IRR_COMPILE_WITH_X11_ #ifdef _DEBUG os::Printer::log("Creating X window...", ELL_INFORMATION); XSetErrorHandler(IrrPrintXError); #endif display = XOpenDisplay(0); if (!display) { os::Printer::log("Error: Need running XServer to start Irrlicht Engine.", ELL_ERROR); if (XDisplayName(0)[0]) os::Printer::log("Could not open display", XDisplayName(0), ELL_ERROR); else os::Printer::log("Could not open display, set DISPLAY variable", ELL_ERROR); return false; } screennr = DefaultScreen(display); switchToFullscreen(); #ifdef _IRR_COMPILE_WITH_OPENGL_ GLXFBConfig glxFBConfig; int major, minor; bool isAvailableGLX=false; if (CreationParams.DriverType==video::EDT_OPENGL) { isAvailableGLX=glXQueryExtension(display,&major,&minor); if (isAvailableGLX && glXQueryVersion(display, &major, &minor)) { #ifdef GLX_VERSION_1_3 typedef GLXFBConfig * ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); #ifdef _IRR_OPENGL_USE_EXTPOINTER_ PFNGLXCHOOSEFBCONFIGPROC glxChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddress(reinterpret_cast("glXChooseFBConfig")); #else PFNGLXCHOOSEFBCONFIGPROC glxChooseFBConfig=glXChooseFBConfig; #endif if (major==1 && minor>2 && glxChooseFBConfig) { // attribute array for the draw buffer int visualAttrBuffer[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_ALPHA_SIZE, CreationParams.WithAlphaChannel?1:0, GLX_DEPTH_SIZE, CreationParams.ZBufferBits, //10,11 GLX_DOUBLEBUFFER, CreationParams.Doublebuffer?True:False, GLX_STENCIL_SIZE, CreationParams.Stencilbuffer?1:0, #if defined(GLX_VERSION_1_4) && defined(GLX_SAMPLE_BUFFERS) // we need to check the extension string! GLX_SAMPLE_BUFFERS, 1, GLX_SAMPLES, CreationParams.AntiAlias, // 18,19 #elif defined(GLX_ARB_multisample) GLX_SAMPLE_BUFFERS_ARB, 1, GLX_SAMPLES_ARB, CreationParams.AntiAlias, // 18,19 #elif defined(GLX_SGIS_multisample) GLX_SAMPLE_BUFFERS_SGIS, 1, GLX_SAMPLES_SGIS, CreationParams.AntiAlias, // 18,19 #endif //#ifdef GL_ARB_framebuffer_sRGB // GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, CreationParams.HandleSRGB, //#elif defined(GL_EXT_framebuffer_sRGB) // GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, CreationParams.HandleSRGB, //#endif GLX_STEREO, CreationParams.Stereobuffer?True:False, None }; GLXFBConfig *configList=0; int nitems=0; if (CreationParams.AntiAlias<2) { visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; } // first round with unchanged values { configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (!configList && CreationParams.AntiAlias) { while (!configList && (visualAttrBuffer[19]>1)) { visualAttrBuffer[19] -= 1; configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); } if (!configList) { visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (configList) { os::Printer::log("No FSAA available.", ELL_WARNING); CreationParams.AntiAlias=0; } else { //reenable multisampling visualAttrBuffer[17] = 1; visualAttrBuffer[19] = CreationParams.AntiAlias; } } } } // Next try with flipped stencil buffer value // If the first round was with stencil flag it's now without // Other way round also makes sense because some configs // only have depth buffer combined with stencil buffer if (!configList) { if (CreationParams.Stencilbuffer) os::Printer::log("No stencilbuffer available, disabling stencil shadows.", ELL_WARNING); CreationParams.Stencilbuffer = !CreationParams.Stencilbuffer; visualAttrBuffer[15]=CreationParams.Stencilbuffer?1:0; configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (!configList && CreationParams.AntiAlias) { while (!configList && (visualAttrBuffer[19]>1)) { visualAttrBuffer[19] -= 1; configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); } if (!configList) { visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (configList) { os::Printer::log("No FSAA available.", ELL_WARNING); CreationParams.AntiAlias=0; } else { //reenable multisampling visualAttrBuffer[17] = 1; visualAttrBuffer[19] = CreationParams.AntiAlias; } } } } // Next try without double buffer if (!configList && CreationParams.Doublebuffer) { os::Printer::log("No doublebuffering available.", ELL_WARNING); CreationParams.Doublebuffer=false; visualAttrBuffer[13] = GLX_DONT_CARE; CreationParams.Stencilbuffer = false; visualAttrBuffer[15]=0; configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (!configList && CreationParams.AntiAlias) { while (!configList && (visualAttrBuffer[19]>1)) { visualAttrBuffer[19] -= 1; configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); } if (!configList) { visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (configList) { os::Printer::log("No FSAA available.", ELL_WARNING); CreationParams.AntiAlias=0; } else { //reenable multisampling visualAttrBuffer[17] = 1; visualAttrBuffer[19] = CreationParams.AntiAlias; } } } } if (configList) { glxFBConfig=configList[0]; XFree(configList); UseGLXWindow=true; #ifdef _IRR_OPENGL_USE_EXTPOINTER_ typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config); PFNGLXGETVISUALFROMFBCONFIGPROC glxGetVisualFromFBConfig= (PFNGLXGETVISUALFROMFBCONFIGPROC)glXGetProcAddress(reinterpret_cast("glXGetVisualFromFBConfig")); if (glxGetVisualFromFBConfig) visual = glxGetVisualFromFBConfig(display,glxFBConfig); #else visual = glXGetVisualFromFBConfig(display,glxFBConfig); #endif } } else #endif { // attribute array for the draw buffer int visualAttrBuffer[] = { GLX_RGBA, GLX_USE_GL, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_ALPHA_SIZE, CreationParams.WithAlphaChannel?1:0, GLX_DEPTH_SIZE, CreationParams.ZBufferBits, GLX_STENCIL_SIZE, CreationParams.Stencilbuffer?1:0, // 12,13 // The following attributes have no flags, but are // either present or not. As a no-op we use // GLX_USE_GL, which is silently ignored by glXChooseVisual CreationParams.Doublebuffer?GLX_DOUBLEBUFFER:GLX_USE_GL, // 14 CreationParams.Stereobuffer?GLX_STEREO:GLX_USE_GL, // 15 //#ifdef GL_ARB_framebuffer_sRGB // CreationParams.HandleSRGB?GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB:GLX_USE_GL, //#elif defined(GL_EXT_framebuffer_sRGB) // CreationParams.HandleSRGB?GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:GLX_USE_GL, //#endif None }; visual=glXChooseVisual(display, screennr, visualAttrBuffer); if (!visual) { if (CreationParams.Stencilbuffer) os::Printer::log("No stencilbuffer available, disabling.", ELL_WARNING); CreationParams.Stencilbuffer = !CreationParams.Stencilbuffer; visualAttrBuffer[13]=CreationParams.Stencilbuffer?1:0; visual=glXChooseVisual(display, screennr, visualAttrBuffer); if (!visual && CreationParams.Doublebuffer) { os::Printer::log("No doublebuffering available.", ELL_WARNING); CreationParams.Doublebuffer=false; visualAttrBuffer[14] = GLX_USE_GL; visual=glXChooseVisual(display, screennr, visualAttrBuffer); } } } } else os::Printer::log("No GLX support available. OpenGL driver will not work.", ELL_WARNING); } // don't use the XVisual with OpenGL, because it ignores all requested // properties of the CreationParams else if (!visual) #endif // _IRR_COMPILE_WITH_OPENGL_ // create visual with standard X methods { os::Printer::log("Using plain X visual"); XVisualInfo visTempl; //Template to hold requested values int visNumber; // Return value of available visuals visTempl.screen = screennr; // ARGB visuals should be avoided for usual applications visTempl.depth = CreationParams.WithAlphaChannel?32:24; while ((!visual) && (visTempl.depth>=16)) { visual = XGetVisualInfo(display, VisualScreenMask|VisualDepthMask, &visTempl, &visNumber); visTempl.depth -= 8; } } if (!visual) { os::Printer::log("Fatal error, could not get visual.", ELL_ERROR); XCloseDisplay(display); display=0; return false; } #ifdef _DEBUG else os::Printer::log("Visual chosen: ", core::stringc(static_cast(visual->visualid)).c_str(), ELL_DEBUG); #endif // create color map Colormap colormap; colormap = XCreateColormap(display, RootWindow(display, visual->screen), visual->visual, AllocNone); attributes.colormap = colormap; attributes.border_pixel = 0; attributes.event_mask = StructureNotifyMask | FocusChangeMask | ExposureMask; if (!CreationParams.IgnoreInput) attributes.event_mask |= PointerMotionMask | ButtonPressMask | KeyPressMask | ButtonReleaseMask | KeyReleaseMask; if (!CreationParams.WindowId) { // create new Window // Remove window manager decoration in fullscreen attributes.override_redirect = CreationParams.Fullscreen; window = XCreateWindow(display, RootWindow(display, visual->screen), 0, 0, Width, Height, 0, visual->depth, InputOutput, visual->visual, CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &attributes); XMapRaised(display, window); CreationParams.WindowId = (void*)window; Atom wmDelete; wmDelete = XInternAtom(display, wmDeleteWindow, True); XSetWMProtocols(display, window, &wmDelete, 1); if (CreationParams.Fullscreen) { XSetInputFocus(display, window, RevertToParent, CurrentTime); int grabKb = XGrabKeyboard(display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime); IrrPrintXGrabError(grabKb, "XGrabKeyboard"); int grabPointer = XGrabPointer(display, window, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, window, None, CurrentTime); IrrPrintXGrabError(grabPointer, "XGrabPointer"); XWarpPointer(display, None, window, 0, 0, 0, 0, 0, 0); } } else { // attach external window window = (Window)CreationParams.WindowId; if (!CreationParams.IgnoreInput) { XCreateWindow(display, window, 0, 0, Width, Height, 0, visual->depth, InputOutput, visual->visual, CWBorderPixel | CWColormap | CWEventMask, &attributes); } XWindowAttributes wa; XGetWindowAttributes(display, window, &wa); CreationParams.WindowSize.Width = wa.width; CreationParams.WindowSize.Height = wa.height; CreationParams.Fullscreen = false; ExternalWindow = true; } WindowMinimized=false; // Currently broken in X, see Bug ID 2795321 // XkbSetDetectableAutoRepeat(display, True, &AutorepeatSupport); #ifdef _IRR_COMPILE_WITH_OPENGL_ // connect glx context to window Context=0; if (isAvailableGLX && CreationParams.DriverType==video::EDT_OPENGL) { if (UseGLXWindow) { glxWin=glXCreateWindow(display,glxFBConfig,window,NULL); if (glxWin) { // create glx context Context = glXCreateNewContext(display, glxFBConfig, GLX_RGBA_TYPE, NULL, True); if (Context) { if (!glXMakeContextCurrent(display, glxWin, glxWin, Context)) { os::Printer::log("Could not make context current.", ELL_WARNING); glXDestroyContext(display, Context); } } else { os::Printer::log("Could not create GLX rendering context.", ELL_WARNING); } } else { os::Printer::log("Could not create GLX window.", ELL_WARNING); } } else { Context = glXCreateContext(display, visual, NULL, True); if (Context) { if (!glXMakeCurrent(display, window, Context)) { os::Printer::log("Could not make context current.", ELL_WARNING); glXDestroyContext(display, Context); } } else { os::Printer::log("Could not create GLX rendering context.", ELL_WARNING); } } } #endif // _IRR_COMPILE_WITH_OPENGL_ Window tmp; u32 borderWidth; int x,y; unsigned int bits; XGetGeometry(display, window, &tmp, &x, &y, &Width, &Height, &borderWidth, &bits); CreationParams.Bits = bits; CreationParams.WindowSize.Width = Width; CreationParams.WindowSize.Height = Height; StdHints = XAllocSizeHints(); long num; XGetWMNormalHints(display, window, StdHints, &num); // create an XImage for the software renderer //(thx to Nadav for some clues on how to do that!) if (CreationParams.DriverType == video::EDT_SOFTWARE || CreationParams.DriverType == video::EDT_BURNINGSVIDEO) { SoftwareImage = XCreateImage(display, visual->visual, visual->depth, ZPixmap, 0, 0, Width, Height, BitmapPad(display), 0); // use malloc because X will free it later on if (SoftwareImage) SoftwareImage->data = (char*) malloc(SoftwareImage->bytes_per_line * SoftwareImage->height * sizeof(char)); } initXAtoms(); #endif // #ifdef _IRR_COMPILE_WITH_X11_ return true; } //! create the driver void CIrrDeviceLinux::createDriver() { switch(CreationParams.DriverType) { #ifdef _IRR_COMPILE_WITH_X11_ case video::EDT_SOFTWARE: #ifdef _IRR_COMPILE_WITH_SOFTWARE_ VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); #else os::Printer::log("No Software driver support compiled in.", ELL_ERROR); #endif break; case video::EDT_BURNINGSVIDEO: #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this); #else os::Printer::log("Burning's video driver was not compiled in.", ELL_ERROR); #endif break; case video::EDT_OPENGL: #ifdef _IRR_COMPILE_WITH_OPENGL_ if (Context) VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem, this); #else os::Printer::log("No OpenGL support compiled in.", ELL_ERROR); #endif break; case video::EDT_DIRECT3D8: case video::EDT_DIRECT3D9: os::Printer::log("This driver is not available in Linux. Try OpenGL or Software renderer.", ELL_ERROR); break; case video::EDT_NULL: VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize); break; default: os::Printer::log("Unable to create video driver of unknown type.", ELL_ERROR); break; #else case video::EDT_NULL: VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize); break; default: os::Printer::log("No X11 support compiled in. Only Null driver available.", ELL_ERROR); break; #endif } } //! runs the device. Returns false if device wants to be deleted bool CIrrDeviceLinux::run() { os::Timer::tick(); #ifdef _IRR_COMPILE_WITH_X11_ if ( CursorControl ) static_cast(CursorControl)->update(); if ((CreationParams.DriverType != video::EDT_NULL) && display) { SEvent irrevent; irrevent.MouseInput.ButtonStates = 0xffffffff; while (XPending(display) > 0 && !Close) { XEvent event; XNextEvent(display, &event); switch (event.type) { case ConfigureNotify: // check for changed window size if ((event.xconfigure.width != (int) Width) || (event.xconfigure.height != (int) Height)) { Width = event.xconfigure.width; Height = event.xconfigure.height; // resize image data if (SoftwareImage) { XDestroyImage(SoftwareImage); SoftwareImage = XCreateImage(display, visual->visual, visual->depth, ZPixmap, 0, 0, Width, Height, BitmapPad(display), 0); // use malloc because X will free it later on if (SoftwareImage) SoftwareImage->data = (char*) malloc(SoftwareImage->bytes_per_line * SoftwareImage->height * sizeof(char)); } if (VideoDriver) VideoDriver->OnResize(core::dimension2d(Width, Height)); } break; case MapNotify: WindowMinimized=false; break; case UnmapNotify: WindowMinimized=true; break; case FocusIn: WindowHasFocus=true; break; case FocusOut: WindowHasFocus=false; break; case MotionNotify: irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT; irrevent.MouseInput.Event = irr::EMIE_MOUSE_MOVED; irrevent.MouseInput.X = event.xbutton.x; irrevent.MouseInput.Y = event.xbutton.y; irrevent.MouseInput.Control = (event.xkey.state & ControlMask) != 0; irrevent.MouseInput.Shift = (event.xkey.state & ShiftMask) != 0; // mouse button states irrevent.MouseInput.ButtonStates = (event.xbutton.state & Button1Mask) ? irr::EMBSM_LEFT : 0; irrevent.MouseInput.ButtonStates |= (event.xbutton.state & Button3Mask) ? irr::EMBSM_RIGHT : 0; irrevent.MouseInput.ButtonStates |= (event.xbutton.state & Button2Mask) ? irr::EMBSM_MIDDLE : 0; postEventFromUser(irrevent); break; case ButtonPress: case ButtonRelease: irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT; irrevent.MouseInput.X = event.xbutton.x; irrevent.MouseInput.Y = event.xbutton.y; irrevent.MouseInput.Control = (event.xkey.state & ControlMask) != 0; irrevent.MouseInput.Shift = (event.xkey.state & ShiftMask) != 0; // mouse button states // This sets the state which the buttons had _prior_ to the event. // So unlike on Windows the button which just got changed has still the old state here. // We handle that below by flipping the corresponding bit later. irrevent.MouseInput.ButtonStates = (event.xbutton.state & Button1Mask) ? irr::EMBSM_LEFT : 0; irrevent.MouseInput.ButtonStates |= (event.xbutton.state & Button3Mask) ? irr::EMBSM_RIGHT : 0; irrevent.MouseInput.ButtonStates |= (event.xbutton.state & Button2Mask) ? irr::EMBSM_MIDDLE : 0; irrevent.MouseInput.Event = irr::EMIE_COUNT; switch(event.xbutton.button) { case Button1: irrevent.MouseInput.Event = (event.type == ButtonPress) ? irr::EMIE_LMOUSE_PRESSED_DOWN : irr::EMIE_LMOUSE_LEFT_UP; irrevent.MouseInput.ButtonStates ^= irr::EMBSM_LEFT; break; case Button3: irrevent.MouseInput.Event = (event.type == ButtonPress) ? irr::EMIE_RMOUSE_PRESSED_DOWN : irr::EMIE_RMOUSE_LEFT_UP; irrevent.MouseInput.ButtonStates ^= irr::EMBSM_RIGHT; break; case Button2: irrevent.MouseInput.Event = (event.type == ButtonPress) ? irr::EMIE_MMOUSE_PRESSED_DOWN : irr::EMIE_MMOUSE_LEFT_UP; irrevent.MouseInput.ButtonStates ^= irr::EMBSM_MIDDLE; break; case Button4: if (event.type == ButtonPress) { irrevent.MouseInput.Event = EMIE_MOUSE_WHEEL; irrevent.MouseInput.Wheel = 1.0f; } break; case Button5: if (event.type == ButtonPress) { irrevent.MouseInput.Event = EMIE_MOUSE_WHEEL; irrevent.MouseInput.Wheel = -1.0f; } break; } if (irrevent.MouseInput.Event != irr::EMIE_COUNT) { postEventFromUser(irrevent); if ( irrevent.MouseInput.Event >= EMIE_LMOUSE_PRESSED_DOWN && irrevent.MouseInput.Event <= EMIE_MMOUSE_PRESSED_DOWN ) { u32 clicks = checkSuccessiveClicks(irrevent.MouseInput.X, irrevent.MouseInput.Y, irrevent.MouseInput.Event); if ( clicks == 2 ) { irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_DOUBLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN); postEventFromUser(irrevent); } else if ( clicks == 3 ) { irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_TRIPLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN); postEventFromUser(irrevent); } } } break; case MappingNotify: XRefreshKeyboardMapping (&event.xmapping) ; break; case KeyRelease: if (0 == AutorepeatSupport && (XPending( display ) > 0) ) { // check for Autorepeat manually // We'll do the same as Windows does: Only send KeyPressed // So every KeyRelease is a real release XEvent next_event; XPeekEvent (event.xkey.display, &next_event); if ((next_event.type == KeyPress) && (next_event.xkey.keycode == event.xkey.keycode) && (next_event.xkey.time - event.xkey.time) < 2) // usually same time, but on some systems a difference of 1 is possible { /* Ignore the key release event */ break; } } // fall-through in case the release should be handled case KeyPress: { SKeyMap mp; char buf[8]={0}; XLookupString(&event.xkey, buf, sizeof(buf), &mp.X11Key, NULL); irrevent.EventType = irr::EET_KEY_INPUT_EVENT; irrevent.KeyInput.PressedDown = (event.type == KeyPress); // mbtowc(&irrevent.KeyInput.Char, buf, sizeof(buf)); irrevent.KeyInput.Char = ((wchar_t*)(buf))[0]; irrevent.KeyInput.Control = (event.xkey.state & ControlMask) != 0; irrevent.KeyInput.Shift = (event.xkey.state & ShiftMask) != 0; event.xkey.state = 0; // ignore shift-ctrl states for figuring out the key XLookupString(&event.xkey, buf, sizeof(buf), &mp.X11Key, NULL); const s32 idx = KeyMap.binary_search(mp); if (idx != -1) { irrevent.KeyInput.Key = (EKEY_CODE)KeyMap[idx].Win32Key; } else { irrevent.KeyInput.Key = (EKEY_CODE)0; } if (irrevent.KeyInput.Key == 0) { // 1:1 mapping to windows-keys would require testing for keyboard type (us, ger, ...) // So unless we do that we will have some unknown keys here. if (idx == -1) { os::Printer::log("Could not find EKEY_CODE, using orig. X11 keycode instead", core::stringc(event.xkey.keycode).c_str(), ELL_INFORMATION); } else { os::Printer::log("EKEY_CODE is 0, using orig. X11 keycode instead", core::stringc(event.xkey.keycode).c_str(), ELL_INFORMATION); } // Any value is better than none, that allows at least using the keys. // Worst case is that some keys will be identical, still better than _all_ // unknown keys being identical. irrevent.KeyInput.Key = (EKEY_CODE)event.xkey.keycode; } postEventFromUser(irrevent); } break; case ClientMessage: { char *atom = XGetAtomName(display, event.xclient.message_type); if (*atom == *wmDeleteWindow) { os::Printer::log("Quit message received.", ELL_INFORMATION); Close = true; } else { // we assume it's a user message irrevent.EventType = irr::EET_USER_EVENT; irrevent.UserEvent.UserData1 = (s32)event.xclient.data.l[0]; irrevent.UserEvent.UserData2 = (s32)event.xclient.data.l[1]; postEventFromUser(irrevent); } XFree(atom); } break; case SelectionRequest: { XEvent respond; XSelectionRequestEvent *req = &(event.xselectionrequest); if ( req->target == XA_STRING) { XChangeProperty (display, req->requestor, req->property, req->target, 8, // format PropModeReplace, (unsigned char*) Clipboard.c_str(), Clipboard.size()); respond.xselection.property = req->property; } else if ( req->target == X_ATOM_TARGETS ) { long data[2]; data[0] = X_ATOM_TEXT; data[1] = XA_STRING; XChangeProperty (display, req->requestor, req->property, req->target, 8, PropModeReplace, (unsigned char *) &data, sizeof (data)); respond.xselection.property = req->property; } else { respond.xselection.property= None; } respond.xselection.type= SelectionNotify; respond.xselection.display= req->display; respond.xselection.requestor= req->requestor; respond.xselection.selection=req->selection; respond.xselection.target= req->target; respond.xselection.time = req->time; XSendEvent (display, req->requestor,0,0,&respond); XFlush (display); } break; default: break; } // end switch } // end while } #endif //_IRR_COMPILE_WITH_X11_ if (!Close) pollJoysticks(); return !Close; } //! Pause the current process for the minimum time allowed only to allow other processes to execute void CIrrDeviceLinux::yield() { struct timespec ts = {0,1}; nanosleep(&ts, NULL); } //! Pause execution and let other processes to run for a specified amount of time. void CIrrDeviceLinux::sleep(u32 timeMs, bool pauseTimer=false) { const bool wasStopped = Timer ? Timer->isStopped() : true; struct timespec ts; ts.tv_sec = (time_t) (timeMs / 1000); ts.tv_nsec = (long) (timeMs % 1000) * 1000000; if (pauseTimer && !wasStopped) Timer->stop(); nanosleep(&ts, NULL); if (pauseTimer && !wasStopped) Timer->start(); } //! sets the caption of the window void CIrrDeviceLinux::setWindowCaption(const wchar_t* text) { #ifdef _IRR_COMPILE_WITH_X11_ if (CreationParams.DriverType == video::EDT_NULL) return; XTextProperty txt; if (Success==XwcTextListToTextProperty(display, const_cast(&text), 1, XStdICCTextStyle, &txt)) { XSetWMName(display, window, &txt); XSetWMIconName(display, window, &txt); XFree(txt.value); } #endif } //! presents a surface in the client area bool CIrrDeviceLinux::present(video::IImage* image, void* windowId, core::rect* srcRect) { #ifdef _IRR_COMPILE_WITH_X11_ // this is only necessary for software drivers. if (!SoftwareImage) return true; // thx to Nadav, who send me some clues of how to display the image // to the X Server. const u32 destwidth = SoftwareImage->width; const u32 minWidth = core::min_(image->getDimension().Width, destwidth); const u32 destPitch = SoftwareImage->bytes_per_line; video::ECOLOR_FORMAT destColor; switch (SoftwareImage->bits_per_pixel) { case 16: if (SoftwareImage->depth==16) destColor = video::ECF_R5G6B5; else destColor = video::ECF_A1R5G5B5; break; case 24: destColor = video::ECF_R8G8B8; break; case 32: destColor = video::ECF_A8R8G8B8; break; default: os::Printer::log("Unsupported screen depth."); return false; } u8* srcdata = reinterpret_cast(image->lock()); u8* destData = reinterpret_cast(SoftwareImage->data); const u32 destheight = SoftwareImage->height; const u32 srcheight = core::min_(image->getDimension().Height, destheight); const u32 srcPitch = image->getPitch(); for (u32 y=0; y!=srcheight; ++y) { video::CColorConverter::convert_viaFormat(srcdata,image->getColorFormat(), minWidth, destData, destColor); srcdata+=srcPitch; destData+=destPitch; } image->unlock(); GC gc = DefaultGC(display, DefaultScreen(display)); Window myWindow=window; if (windowId) myWindow = reinterpret_cast(windowId); XPutImage(display, myWindow, gc, SoftwareImage, 0, 0, 0, 0, destwidth, destheight); #endif return true; } //! notifies the device that it should close itself void CIrrDeviceLinux::closeDevice() { Close = true; } //! returns if window is active. if not, nothing need to be drawn bool CIrrDeviceLinux::isWindowActive() const { return (WindowHasFocus && !WindowMinimized); } //! returns if window has focus. bool CIrrDeviceLinux::isWindowFocused() const { return WindowHasFocus; } //! returns if window is minimized. bool CIrrDeviceLinux::isWindowMinimized() const { return WindowMinimized; } //! returns color format of the window. video::ECOLOR_FORMAT CIrrDeviceLinux::getColorFormat() const { #ifdef _IRR_COMPILE_WITH_X11_ if (visual && (visual->depth != 16)) return video::ECF_R8G8B8; else #endif return video::ECF_R5G6B5; } //! Sets if the window should be resizable in windowed mode. void CIrrDeviceLinux::setResizable(bool resize) { #ifdef _IRR_COMPILE_WITH_X11_ if (CreationParams.DriverType == video::EDT_NULL || CreationParams.Fullscreen ) return; XUnmapWindow(display, window); if ( !resize ) { // Must be heap memory because data size depends on X Server XSizeHints *hints = XAllocSizeHints(); hints->flags=PSize|PMinSize|PMaxSize; hints->min_width=hints->max_width=hints->base_width=Width; hints->min_height=hints->max_height=hints->base_height=Height; XSetWMNormalHints(display, window, hints); XFree(hints); } else { XSetWMNormalHints(display, window, StdHints); } XMapWindow(display, window); XFlush(display); #endif // #ifdef _IRR_COMPILE_WITH_X11_ } //! Return pointer to a list with all video modes supported by the gfx adapter. video::IVideoModeList* CIrrDeviceLinux::getVideoModeList() { #ifdef _IRR_COMPILE_WITH_X11_ if (!VideoModeList->getVideoModeCount()) { bool temporaryDisplay = false; if (!display) { display = XOpenDisplay(0); temporaryDisplay=true; } if (display) { #if defined(_IRR_LINUX_X11_VIDMODE_) || defined(_IRR_LINUX_X11_RANDR_) s32 eventbase, errorbase; s32 defaultDepth=DefaultDepth(display,screennr); #endif #ifdef _IRR_LINUX_X11_VIDMODE_ if (XF86VidModeQueryExtension(display, &eventbase, &errorbase)) { // enumerate video modes int modeCount; XF86VidModeModeInfo** modes; XF86VidModeGetAllModeLines(display, screennr, &modeCount, &modes); // save current video mode oldVideoMode = *modes[0]; // find fitting mode VideoModeList->setDesktop(defaultDepth, core::dimension2d( modes[0]->hdisplay, modes[0]->vdisplay)); for (int i = 0; iaddMode(core::dimension2d( modes[i]->hdisplay, modes[i]->vdisplay), defaultDepth); } XFree(modes); } else #endif #ifdef _IRR_LINUX_X11_RANDR_ if (XRRQueryExtension(display, &eventbase, &errorbase)) { int modeCount; XRRScreenConfiguration *config=XRRGetScreenInfo(display,DefaultRootWindow(display)); oldRandrMode=XRRConfigCurrentConfiguration(config,&oldRandrRotation); XRRScreenSize *modes=XRRConfigSizes(config,&modeCount); VideoModeList->setDesktop(defaultDepth, core::dimension2d( modes[oldRandrMode].width, modes[oldRandrMode].height)); for (int i = 0; iaddMode(core::dimension2d( modes[i].width, modes[i].height), defaultDepth); } XRRFreeScreenConfigInfo(config); } else #endif { os::Printer::log("VidMode or RandR X11 extension requireed for VideoModeList." , ELL_WARNING); } } if (display && temporaryDisplay) { XCloseDisplay(display); display=0; } } #endif return VideoModeList; } //! Minimize window void CIrrDeviceLinux::minimizeWindow() { #ifdef _IRR_COMPILE_WITH_X11_ XIconifyWindow(display, window, screennr); #endif } //! Maximize window void CIrrDeviceLinux::maximizeWindow() { #ifdef _IRR_COMPILE_WITH_X11_ XMapWindow(display, window); #endif } //! Restore original window size void CIrrDeviceLinux::restoreWindow() { #ifdef _IRR_COMPILE_WITH_X11_ XMapWindow(display, window); #endif } void CIrrDeviceLinux::createKeyMap() { // I don't know if this is the best method to create // the lookuptable, but I'll leave it like that until // I find a better version. #ifdef _IRR_COMPILE_WITH_X11_ KeyMap.reallocate(84); KeyMap.push_back(SKeyMap(XK_BackSpace, KEY_BACK)); KeyMap.push_back(SKeyMap(XK_Tab, KEY_TAB)); KeyMap.push_back(SKeyMap(XK_ISO_Left_Tab, KEY_TAB)); KeyMap.push_back(SKeyMap(XK_Linefeed, 0)); // ??? KeyMap.push_back(SKeyMap(XK_Clear, KEY_CLEAR)); KeyMap.push_back(SKeyMap(XK_Return, KEY_RETURN)); KeyMap.push_back(SKeyMap(XK_Pause, KEY_PAUSE)); KeyMap.push_back(SKeyMap(XK_Scroll_Lock, KEY_SCROLL)); KeyMap.push_back(SKeyMap(XK_Sys_Req, 0)); // ??? KeyMap.push_back(SKeyMap(XK_Escape, KEY_ESCAPE)); KeyMap.push_back(SKeyMap(XK_Insert, KEY_INSERT)); KeyMap.push_back(SKeyMap(XK_Delete, KEY_DELETE)); KeyMap.push_back(SKeyMap(XK_Home, KEY_HOME)); KeyMap.push_back(SKeyMap(XK_Left, KEY_LEFT)); KeyMap.push_back(SKeyMap(XK_Up, KEY_UP)); KeyMap.push_back(SKeyMap(XK_Right, KEY_RIGHT)); KeyMap.push_back(SKeyMap(XK_Down, KEY_DOWN)); KeyMap.push_back(SKeyMap(XK_Prior, KEY_PRIOR)); KeyMap.push_back(SKeyMap(XK_Page_Up, KEY_PRIOR)); KeyMap.push_back(SKeyMap(XK_Next, KEY_NEXT)); KeyMap.push_back(SKeyMap(XK_Page_Down, KEY_NEXT)); KeyMap.push_back(SKeyMap(XK_End, KEY_END)); KeyMap.push_back(SKeyMap(XK_Begin, KEY_HOME)); KeyMap.push_back(SKeyMap(XK_Num_Lock, KEY_NUMLOCK)); KeyMap.push_back(SKeyMap(XK_KP_Space, KEY_SPACE)); KeyMap.push_back(SKeyMap(XK_KP_Tab, KEY_TAB)); KeyMap.push_back(SKeyMap(XK_KP_Enter, KEY_RETURN)); KeyMap.push_back(SKeyMap(XK_KP_F1, KEY_F1)); KeyMap.push_back(SKeyMap(XK_KP_F2, KEY_F2)); KeyMap.push_back(SKeyMap(XK_KP_F3, KEY_F3)); KeyMap.push_back(SKeyMap(XK_KP_F4, KEY_F4)); KeyMap.push_back(SKeyMap(XK_KP_Home, KEY_HOME)); KeyMap.push_back(SKeyMap(XK_KP_Left, KEY_LEFT)); KeyMap.push_back(SKeyMap(XK_KP_Up, KEY_UP)); KeyMap.push_back(SKeyMap(XK_KP_Right, KEY_RIGHT)); KeyMap.push_back(SKeyMap(XK_KP_Down, KEY_DOWN)); KeyMap.push_back(SKeyMap(XK_Print, KEY_PRINT)); KeyMap.push_back(SKeyMap(XK_KP_Prior, KEY_PRIOR)); KeyMap.push_back(SKeyMap(XK_KP_Page_Up, KEY_PRIOR)); KeyMap.push_back(SKeyMap(XK_KP_Next, KEY_NEXT)); KeyMap.push_back(SKeyMap(XK_KP_Page_Down, KEY_NEXT)); KeyMap.push_back(SKeyMap(XK_KP_End, KEY_END)); KeyMap.push_back(SKeyMap(XK_KP_Begin, KEY_HOME)); KeyMap.push_back(SKeyMap(XK_KP_Insert, KEY_INSERT)); KeyMap.push_back(SKeyMap(XK_KP_Delete, KEY_DELETE)); KeyMap.push_back(SKeyMap(XK_KP_Equal, 0)); // ??? KeyMap.push_back(SKeyMap(XK_KP_Multiply, KEY_MULTIPLY)); KeyMap.push_back(SKeyMap(XK_KP_Add, KEY_ADD)); KeyMap.push_back(SKeyMap(XK_KP_Separator, KEY_SEPARATOR)); KeyMap.push_back(SKeyMap(XK_KP_Subtract, KEY_SUBTRACT)); KeyMap.push_back(SKeyMap(XK_KP_Decimal, KEY_DECIMAL)); KeyMap.push_back(SKeyMap(XK_KP_Divide, KEY_DIVIDE)); KeyMap.push_back(SKeyMap(XK_KP_0, KEY_KEY_0)); KeyMap.push_back(SKeyMap(XK_KP_1, KEY_KEY_1)); KeyMap.push_back(SKeyMap(XK_KP_2, KEY_KEY_2)); KeyMap.push_back(SKeyMap(XK_KP_3, KEY_KEY_3)); KeyMap.push_back(SKeyMap(XK_KP_4, KEY_KEY_4)); KeyMap.push_back(SKeyMap(XK_KP_5, KEY_KEY_5)); KeyMap.push_back(SKeyMap(XK_KP_6, KEY_KEY_6)); KeyMap.push_back(SKeyMap(XK_KP_7, KEY_KEY_7)); KeyMap.push_back(SKeyMap(XK_KP_8, KEY_KEY_8)); KeyMap.push_back(SKeyMap(XK_KP_9, KEY_KEY_9)); KeyMap.push_back(SKeyMap(XK_F1, KEY_F1)); KeyMap.push_back(SKeyMap(XK_F2, KEY_F2)); KeyMap.push_back(SKeyMap(XK_F3, KEY_F3)); KeyMap.push_back(SKeyMap(XK_F4, KEY_F4)); KeyMap.push_back(SKeyMap(XK_F5, KEY_F5)); KeyMap.push_back(SKeyMap(XK_F6, KEY_F6)); KeyMap.push_back(SKeyMap(XK_F7, KEY_F7)); KeyMap.push_back(SKeyMap(XK_F8, KEY_F8)); KeyMap.push_back(SKeyMap(XK_F9, KEY_F9)); KeyMap.push_back(SKeyMap(XK_F10, KEY_F10)); KeyMap.push_back(SKeyMap(XK_F11, KEY_F11)); KeyMap.push_back(SKeyMap(XK_F12, KEY_F12)); KeyMap.push_back(SKeyMap(XK_Shift_L, KEY_LSHIFT)); KeyMap.push_back(SKeyMap(XK_Shift_R, KEY_RSHIFT)); KeyMap.push_back(SKeyMap(XK_Control_L, KEY_LCONTROL)); KeyMap.push_back(SKeyMap(XK_Control_R, KEY_RCONTROL)); KeyMap.push_back(SKeyMap(XK_Caps_Lock, KEY_CAPITAL)); KeyMap.push_back(SKeyMap(XK_Shift_Lock, KEY_CAPITAL)); KeyMap.push_back(SKeyMap(XK_Meta_L, KEY_LWIN)); KeyMap.push_back(SKeyMap(XK_Meta_R, KEY_RWIN)); KeyMap.push_back(SKeyMap(XK_Alt_L, KEY_LMENU)); KeyMap.push_back(SKeyMap(XK_Alt_R, KEY_RMENU)); KeyMap.push_back(SKeyMap(XK_ISO_Level3_Shift, KEY_RMENU)); KeyMap.push_back(SKeyMap(XK_Menu, KEY_MENU)); KeyMap.push_back(SKeyMap(XK_space, KEY_SPACE)); KeyMap.push_back(SKeyMap(XK_exclam, 0)); //? KeyMap.push_back(SKeyMap(XK_quotedbl, 0)); //? KeyMap.push_back(SKeyMap(XK_section, 0)); //? KeyMap.push_back(SKeyMap(XK_numbersign, KEY_OEM_2)); KeyMap.push_back(SKeyMap(XK_dollar, 0)); //? KeyMap.push_back(SKeyMap(XK_percent, 0)); //? KeyMap.push_back(SKeyMap(XK_ampersand, 0)); //? KeyMap.push_back(SKeyMap(XK_apostrophe, KEY_OEM_7)); KeyMap.push_back(SKeyMap(XK_parenleft, 0)); //? KeyMap.push_back(SKeyMap(XK_parenright, 0)); //? KeyMap.push_back(SKeyMap(XK_asterisk, 0)); //? KeyMap.push_back(SKeyMap(XK_plus, KEY_PLUS)); //? KeyMap.push_back(SKeyMap(XK_comma, KEY_COMMA)); //? KeyMap.push_back(SKeyMap(XK_minus, KEY_MINUS)); //? KeyMap.push_back(SKeyMap(XK_period, KEY_PERIOD)); //? KeyMap.push_back(SKeyMap(XK_slash, KEY_OEM_2)); //? KeyMap.push_back(SKeyMap(XK_0, KEY_KEY_0)); KeyMap.push_back(SKeyMap(XK_1, KEY_KEY_1)); KeyMap.push_back(SKeyMap(XK_2, KEY_KEY_2)); KeyMap.push_back(SKeyMap(XK_3, KEY_KEY_3)); KeyMap.push_back(SKeyMap(XK_4, KEY_KEY_4)); KeyMap.push_back(SKeyMap(XK_5, KEY_KEY_5)); KeyMap.push_back(SKeyMap(XK_6, KEY_KEY_6)); KeyMap.push_back(SKeyMap(XK_7, KEY_KEY_7)); KeyMap.push_back(SKeyMap(XK_8, KEY_KEY_8)); KeyMap.push_back(SKeyMap(XK_9, KEY_KEY_9)); KeyMap.push_back(SKeyMap(XK_colon, 0)); //? KeyMap.push_back(SKeyMap(XK_semicolon, KEY_OEM_1)); KeyMap.push_back(SKeyMap(XK_less, KEY_OEM_102)); KeyMap.push_back(SKeyMap(XK_equal, KEY_PLUS)); KeyMap.push_back(SKeyMap(XK_greater, 0)); //? KeyMap.push_back(SKeyMap(XK_question, 0)); //? KeyMap.push_back(SKeyMap(XK_at, KEY_KEY_2)); //? KeyMap.push_back(SKeyMap(XK_mu, 0)); //? KeyMap.push_back(SKeyMap(XK_EuroSign, 0)); //? KeyMap.push_back(SKeyMap(XK_A, KEY_KEY_A)); KeyMap.push_back(SKeyMap(XK_B, KEY_KEY_B)); KeyMap.push_back(SKeyMap(XK_C, KEY_KEY_C)); KeyMap.push_back(SKeyMap(XK_D, KEY_KEY_D)); KeyMap.push_back(SKeyMap(XK_E, KEY_KEY_E)); KeyMap.push_back(SKeyMap(XK_F, KEY_KEY_F)); KeyMap.push_back(SKeyMap(XK_G, KEY_KEY_G)); KeyMap.push_back(SKeyMap(XK_H, KEY_KEY_H)); KeyMap.push_back(SKeyMap(XK_I, KEY_KEY_I)); KeyMap.push_back(SKeyMap(XK_J, KEY_KEY_J)); KeyMap.push_back(SKeyMap(XK_K, KEY_KEY_K)); KeyMap.push_back(SKeyMap(XK_L, KEY_KEY_L)); KeyMap.push_back(SKeyMap(XK_M, KEY_KEY_M)); KeyMap.push_back(SKeyMap(XK_N, KEY_KEY_N)); KeyMap.push_back(SKeyMap(XK_O, KEY_KEY_O)); KeyMap.push_back(SKeyMap(XK_P, KEY_KEY_P)); KeyMap.push_back(SKeyMap(XK_Q, KEY_KEY_Q)); KeyMap.push_back(SKeyMap(XK_R, KEY_KEY_R)); KeyMap.push_back(SKeyMap(XK_S, KEY_KEY_S)); KeyMap.push_back(SKeyMap(XK_T, KEY_KEY_T)); KeyMap.push_back(SKeyMap(XK_U, KEY_KEY_U)); KeyMap.push_back(SKeyMap(XK_V, KEY_KEY_V)); KeyMap.push_back(SKeyMap(XK_W, KEY_KEY_W)); KeyMap.push_back(SKeyMap(XK_X, KEY_KEY_X)); KeyMap.push_back(SKeyMap(XK_Y, KEY_KEY_Y)); KeyMap.push_back(SKeyMap(XK_Z, KEY_KEY_Z)); KeyMap.push_back(SKeyMap(XK_bracketleft, KEY_OEM_4)); KeyMap.push_back(SKeyMap(XK_backslash, KEY_OEM_5)); KeyMap.push_back(SKeyMap(XK_bracketright, KEY_OEM_6)); KeyMap.push_back(SKeyMap(XK_asciicircum, KEY_OEM_5)); KeyMap.push_back(SKeyMap(XK_degree, 0)); //? KeyMap.push_back(SKeyMap(XK_underscore, KEY_MINUS)); //? KeyMap.push_back(SKeyMap(XK_grave, KEY_OEM_3)); KeyMap.push_back(SKeyMap(XK_acute, KEY_OEM_6)); KeyMap.push_back(SKeyMap(XK_a, KEY_KEY_A)); KeyMap.push_back(SKeyMap(XK_b, KEY_KEY_B)); KeyMap.push_back(SKeyMap(XK_c, KEY_KEY_C)); KeyMap.push_back(SKeyMap(XK_d, KEY_KEY_D)); KeyMap.push_back(SKeyMap(XK_e, KEY_KEY_E)); KeyMap.push_back(SKeyMap(XK_f, KEY_KEY_F)); KeyMap.push_back(SKeyMap(XK_g, KEY_KEY_G)); KeyMap.push_back(SKeyMap(XK_h, KEY_KEY_H)); KeyMap.push_back(SKeyMap(XK_i, KEY_KEY_I)); KeyMap.push_back(SKeyMap(XK_j, KEY_KEY_J)); KeyMap.push_back(SKeyMap(XK_k, KEY_KEY_K)); KeyMap.push_back(SKeyMap(XK_l, KEY_KEY_L)); KeyMap.push_back(SKeyMap(XK_m, KEY_KEY_M)); KeyMap.push_back(SKeyMap(XK_n, KEY_KEY_N)); KeyMap.push_back(SKeyMap(XK_o, KEY_KEY_O)); KeyMap.push_back(SKeyMap(XK_p, KEY_KEY_P)); KeyMap.push_back(SKeyMap(XK_q, KEY_KEY_Q)); KeyMap.push_back(SKeyMap(XK_r, KEY_KEY_R)); KeyMap.push_back(SKeyMap(XK_s, KEY_KEY_S)); KeyMap.push_back(SKeyMap(XK_t, KEY_KEY_T)); KeyMap.push_back(SKeyMap(XK_u, KEY_KEY_U)); KeyMap.push_back(SKeyMap(XK_v, KEY_KEY_V)); KeyMap.push_back(SKeyMap(XK_w, KEY_KEY_W)); KeyMap.push_back(SKeyMap(XK_x, KEY_KEY_X)); KeyMap.push_back(SKeyMap(XK_y, KEY_KEY_Y)); KeyMap.push_back(SKeyMap(XK_z, KEY_KEY_Z)); KeyMap.push_back(SKeyMap(XK_ssharp, KEY_OEM_4)); KeyMap.push_back(SKeyMap(XK_adiaeresis, KEY_OEM_7)); KeyMap.push_back(SKeyMap(XK_odiaeresis, KEY_OEM_3)); KeyMap.push_back(SKeyMap(XK_udiaeresis, KEY_OEM_1)); KeyMap.push_back(SKeyMap(XK_Super_L, KEY_LWIN)); KeyMap.push_back(SKeyMap(XK_Super_R, KEY_RWIN)); KeyMap.sort(); #endif } bool CIrrDeviceLinux::activateJoysticks(core::array & joystickInfo) { #if defined (_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) joystickInfo.clear(); u32 joystick; for (joystick = 0; joystick < 32; ++joystick) { // The joystick device could be here... core::stringc devName = "/dev/js"; devName += joystick; SJoystickInfo returnInfo; JoystickInfo info; info.fd = open(devName.c_str(), O_RDONLY); if (-1 == info.fd) { // ...but Ubuntu and possibly other distros // create the devices in /dev/input devName = "/dev/input/js"; devName += joystick; info.fd = open(devName.c_str(), O_RDONLY); if (-1 == info.fd) { // and BSD here devName = "/dev/joy"; devName += joystick; info.fd = open(devName.c_str(), O_RDONLY); } } if (-1 == info.fd) continue; #ifdef __FreeBSD__ info.axes=2; info.buttons=2; #else ioctl( info.fd, JSIOCGAXES, &(info.axes) ); ioctl( info.fd, JSIOCGBUTTONS, &(info.buttons) ); fcntl( info.fd, F_SETFL, O_NONBLOCK ); #endif (void)memset(&info.persistentData, 0, sizeof(info.persistentData)); info.persistentData.EventType = irr::EET_JOYSTICK_INPUT_EVENT; info.persistentData.JoystickEvent.Joystick = ActiveJoysticks.size(); // There's no obvious way to determine which (if any) axes represent a POV // hat, so we'll just set it to "not used" and forget about it. info.persistentData.JoystickEvent.POV = 65535; ActiveJoysticks.push_back(info); returnInfo.Joystick = joystick; returnInfo.PovHat = SJoystickInfo::POV_HAT_UNKNOWN; returnInfo.Axes = info.axes; returnInfo.Buttons = info.buttons; #ifndef __FreeBSD__ char name[80]; ioctl( info.fd, JSIOCGNAME(80), name); returnInfo.Name = name; #endif joystickInfo.push_back(returnInfo); } for (joystick = 0; joystick < joystickInfo.size(); ++joystick) { char logString[256]; (void)sprintf(logString, "Found joystick %u, %u axes, %u buttons '%s'", joystick, joystickInfo[joystick].Axes, joystickInfo[joystick].Buttons, joystickInfo[joystick].Name.c_str()); os::Printer::log(logString, ELL_INFORMATION); } return true; #else return false; #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ } void CIrrDeviceLinux::pollJoysticks() { #if defined (_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) if (0 == ActiveJoysticks.size()) return; for (u32 j= 0; j< ActiveJoysticks.size(); ++j) { JoystickInfo & info = ActiveJoysticks[j]; #ifdef __FreeBSD__ struct joystick js; if (read(info.fd, &js, sizeof(js)) == sizeof(js)) { info.persistentData.JoystickEvent.ButtonStates = js.b1 | (js.b2 << 1); /* should be a two-bit field */ info.persistentData.JoystickEvent.Axis[0] = js.x; /* X axis */ info.persistentData.JoystickEvent.Axis[1] = js.y; /* Y axis */ } #else struct js_event event; while (sizeof(event) == read(info.fd, &event, sizeof(event))) { switch(event.type & ~JS_EVENT_INIT) { case JS_EVENT_BUTTON: if (event.value) info.persistentData.JoystickEvent.ButtonStates |= (1 << event.number); else info.persistentData.JoystickEvent.ButtonStates &= ~(1 << event.number); break; case JS_EVENT_AXIS: if (event.number < SEvent::SJoystickEvent::NUMBER_OF_AXES) info.persistentData.JoystickEvent.Axis[event.number] = event.value; break; default: break; } } #endif // Send an irrlicht joystick event once per ::run() even if no new data were received. (void)postEventFromUser(info.persistentData); } #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ } //! Set the current Gamma Value for the Display bool CIrrDeviceLinux::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) { #if defined(_IRR_LINUX_X11_VIDMODE_) || defined(_IRR_LINUX_X11_RANDR_) s32 eventbase, errorbase; #ifdef _IRR_LINUX_X11_VIDMODE_ if (XF86VidModeQueryExtension(display, &eventbase, &errorbase)) { XF86VidModeGamma gamma; gamma.red=red; gamma.green=green; gamma.blue=blue; XF86VidModeSetGamma(display, screennr, &gamma); return true; } #endif #if defined(_IRR_LINUX_X11_VIDMODE_) && defined(_IRR_LINUX_X11_RANDR_) else #endif #ifdef _IRR_LINUX_X11_RANDR_ if (XRRQueryExtension(display, &eventbase, &errorbase)) { XRRQueryVersion(display, &eventbase, &errorbase); // major, minor if (eventbase>=1 && errorbase>1) { #if (RANDR_MAJOR>1 || RANDR_MINOR>1) XRRCrtcGamma *gamma = XRRGetCrtcGamma(display, screennr); if (gamma) { *gamma->red=(u16)red; *gamma->green=(u16)green; *gamma->blue=(u16)blue; XRRSetCrtcGamma(display, screennr, gamma); XRRFreeGamma(gamma); return true; } #endif } } #endif #endif return false; } //! Get the current Gamma Value for the Display bool CIrrDeviceLinux::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ) { brightness = 0.f; contrast = 0.f; #if defined(_IRR_LINUX_X11_VIDMODE_) || defined(_IRR_LINUX_X11_RANDR_) s32 eventbase, errorbase; #ifdef _IRR_LINUX_X11_VIDMODE_ if (XF86VidModeQueryExtension(display, &eventbase, &errorbase)) { XF86VidModeGamma gamma; XF86VidModeGetGamma(display, screennr, &gamma); red = gamma.red; green = gamma.green; blue = gamma.blue; return true; } #endif #if defined(_IRR_LINUX_X11_VIDMODE_) && defined(_IRR_LINUX_X11_RANDR_) else #endif #ifdef _IRR_LINUX_X11_RANDR_ if (XRRQueryExtension(display, &eventbase, &errorbase)) { XRRQueryVersion(display, &eventbase, &errorbase); // major, minor if (eventbase>=1 && errorbase>1) { #if (RANDR_MAJOR>1 || RANDR_MINOR>1) XRRCrtcGamma *gamma = XRRGetCrtcGamma(display, screennr); if (gamma) { red = *gamma->red; green = *gamma->green; blue= *gamma->blue; XRRFreeGamma(gamma); return true; } #endif } } #endif #endif return false; } //! gets text from the clipboard //! \return Returns 0 if no string is in there. const c8* CIrrDeviceLinux::getTextFromClipboard() const { #if defined(_IRR_COMPILE_WITH_X11_) Window ownerWindow = XGetSelectionOwner (display, X_ATOM_CLIPBOARD); if ( ownerWindow == window ) { return Clipboard.c_str(); } Clipboard = ""; if (ownerWindow != None ) { XConvertSelection (display, X_ATOM_CLIPBOARD, XA_STRING, None, ownerWindow, CurrentTime); XFlush (display); // check for data Atom type; int format; unsigned long numItems, bytesLeft, dummy; unsigned char *data; XGetWindowProperty (display, ownerWindow, XA_STRING, // property name 0, // offset 0, // length (we only check for data, so 0) 0, // Delete 0==false AnyPropertyType, // AnyPropertyType or property identifier &type, // return type &format, // return format &numItems, // number items &bytesLeft, // remaining bytes for partial reads &data); // data if ( bytesLeft > 0 ) { // there is some data to get int result = XGetWindowProperty (display, ownerWindow, XA_STRING, 0, bytesLeft, 0, AnyPropertyType, &type, &format, &numItems, &dummy, &data); if (result == Success) Clipboard = (irr::c8*)data; XFree (data); } } return Clipboard.c_str(); #else return 0; #endif } //! copies text to the clipboard void CIrrDeviceLinux::copyToClipboard(const c8* text) const { #if defined(_IRR_COMPILE_WITH_X11_) // Actually there is no clipboard on X but applications just say they own the clipboard and return text when asked. // Which btw. also means that on X you lose clipboard content when closing applications. Clipboard = text; XSetSelectionOwner (display, X_ATOM_CLIPBOARD, window, CurrentTime); XFlush (display); #endif } #ifdef _IRR_COMPILE_WITH_X11_ // return true if the passed event has the type passed in parameter arg Bool PredicateIsEventType(Display *display, XEvent *event, XPointer arg) { if ( event && event->type == *(int*)arg ) { // os::Printer::log("remove event:", core::stringc((int)arg).c_str(), ELL_INFORMATION); return True; } return False; } #endif //_IRR_COMPILE_WITH_X11_ //! Remove all messages pending in the system message loop void CIrrDeviceLinux::clearSystemMessages() { #ifdef _IRR_COMPILE_WITH_X11_ if (CreationParams.DriverType != video::EDT_NULL) { XEvent event; int usrArg = ButtonPress; while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} usrArg = ButtonRelease; while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} usrArg = MotionNotify; while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} usrArg = KeyRelease; while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} usrArg = KeyPress; while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} } #endif //_IRR_COMPILE_WITH_X11_ } void CIrrDeviceLinux::initXAtoms() { #ifdef _IRR_COMPILE_WITH_X11_ X_ATOM_CLIPBOARD = XInternAtom(display, "CLIPBOARD", False); X_ATOM_TARGETS = XInternAtom(display, "TARGETS", False); X_ATOM_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False); X_ATOM_TEXT = XInternAtom (display, "TEXT", False); #endif } #ifdef _IRR_COMPILE_WITH_X11_ Cursor CIrrDeviceLinux::TextureToMonochromeCursor(irr::video::ITexture * tex, const core::rect& sourceRect, const core::position2d &hotspot) { XImage * sourceImage = XCreateImage(display, visual->visual, 1, // depth, ZPixmap, // XYBitmap (depth=1), ZPixmap(depth=x) 0, 0, sourceRect.getWidth(), sourceRect.getHeight(), 32, // bitmap_pad, 0// bytes_per_line (0 means continuos in memory) ); sourceImage->data = new char[sourceImage->height * sourceImage->bytes_per_line]; XImage * maskImage = XCreateImage(display, visual->visual, 1, // depth, ZPixmap, 0, 0, sourceRect.getWidth(), sourceRect.getHeight(), 32, // bitmap_pad, 0 // bytes_per_line ); maskImage->data = new char[maskImage->height * maskImage->bytes_per_line]; // write texture into XImage video::ECOLOR_FORMAT format = tex->getColorFormat(); u32 bytesPerPixel = video::IImage::getBitsPerPixelFromFormat(format) / 8; u32 bytesLeftGap = sourceRect.UpperLeftCorner.X * bytesPerPixel; u32 bytesRightGap = tex->getPitch() - sourceRect.LowerRightCorner.X * bytesPerPixel; const u8* data = (const u8*)tex->lock(video::ETLM_READ_ONLY, 0); data += sourceRect.UpperLeftCorner.Y*tex->getPitch(); for ( s32 y = 0; y < sourceRect.getHeight(); ++y ) { data += bytesLeftGap; for ( s32 x = 0; x < sourceRect.getWidth(); ++x ) { video::SColor pixelCol; pixelCol.setData((const void*)data, format); data += bytesPerPixel; if ( pixelCol.getAlpha() == 0 ) // transparent { XPutPixel(maskImage, x, y, 0); XPutPixel(sourceImage, x, y, 0); } else // color { if ( pixelCol.getAverage() >= 127 ) XPutPixel(sourceImage, x, y, 1); else XPutPixel(sourceImage, x, y, 0); XPutPixel(maskImage, x, y, 1); } } data += bytesRightGap; } tex->unlock(); Pixmap sourcePixmap = XCreatePixmap(display, window, sourceImage->width, sourceImage->height, sourceImage->depth); Pixmap maskPixmap = XCreatePixmap(display, window, maskImage->width, maskImage->height, maskImage->depth); XGCValues values; values.foreground = 1; values.background = 1; GC gc = XCreateGC( display, sourcePixmap, GCForeground | GCBackground, &values ); XPutImage(display, sourcePixmap, gc, sourceImage, 0, 0, 0, 0, sourceImage->width, sourceImage->height); XPutImage(display, maskPixmap, gc, maskImage, 0, 0, 0, 0, maskImage->width, maskImage->height); XFreeGC(display, gc); XDestroyImage(sourceImage); XDestroyImage(maskImage); Cursor cursorResult = 0; XColor foreground, background; foreground.red = 65535; foreground.green = 65535; foreground.blue = 65535; foreground.flags = DoRed | DoGreen | DoBlue; background.red = 0; background.green = 0; background.blue = 0; background.flags = DoRed | DoGreen | DoBlue; cursorResult = XCreatePixmapCursor(display, sourcePixmap, maskPixmap, &foreground, &background, hotspot.X, hotspot.Y); XFreePixmap(display, sourcePixmap); XFreePixmap(display, maskPixmap); return cursorResult; } #ifdef _IRR_LINUX_XCURSOR_ Cursor CIrrDeviceLinux::TextureToARGBCursor(irr::video::ITexture * tex, const core::rect& sourceRect, const core::position2d &hotspot) { XcursorImage * image = XcursorImageCreate (sourceRect.getWidth(), sourceRect.getHeight()); image->xhot = hotspot.X; image->yhot = hotspot.Y; // write texture into XcursorImage video::ECOLOR_FORMAT format = tex->getColorFormat(); u32 bytesPerPixel = video::IImage::getBitsPerPixelFromFormat(format) / 8; u32 bytesLeftGap = sourceRect.UpperLeftCorner.X * bytesPerPixel; u32 bytesRightGap = tex->getPitch() - sourceRect.LowerRightCorner.X * bytesPerPixel; XcursorPixel* target = image->pixels; const u8* data = (const u8*)tex->lock(video::ETLM_READ_ONLY, 0); data += sourceRect.UpperLeftCorner.Y*tex->getPitch(); for ( s32 y = 0; y < sourceRect.getHeight(); ++y ) { data += bytesLeftGap; for ( s32 x = 0; x < sourceRect.getWidth(); ++x ) { video::SColor pixelCol; pixelCol.setData((const void*)data, format); data += bytesPerPixel; *target = (XcursorPixel)pixelCol.color; ++target; } data += bytesRightGap; } tex->unlock(); Cursor cursorResult=XcursorImageLoadCursor(display, image); XcursorImageDestroy(image); return cursorResult; } #endif // #ifdef _IRR_LINUX_XCURSOR_ Cursor CIrrDeviceLinux::TextureToCursor(irr::video::ITexture * tex, const core::rect& sourceRect, const core::position2d &hotspot) { #ifdef _IRR_LINUX_XCURSOR_ return TextureToARGBCursor( tex, sourceRect, hotspot ); #else return TextureToMonochromeCursor( tex, sourceRect, hotspot ); #endif } #endif // _IRR_COMPILE_WITH_X11_ CIrrDeviceLinux::CCursorControl::CCursorControl(CIrrDeviceLinux* dev, bool null) : Device(dev) #ifdef _IRR_COMPILE_WITH_X11_ , PlatformBehavior(gui::ECPB_NONE), lastQuery(0) #endif , IsVisible(true), Null(null), UseReferenceRect(false) , ActiveIcon(gui::ECI_NORMAL), ActiveIconStartTime(0) { #ifdef _IRR_COMPILE_WITH_X11_ if (!Null) { XGCValues values; unsigned long valuemask = 0; XColor fg, bg; // this code, for making the cursor invisible was sent in by // Sirshane, thank your very much! Pixmap invisBitmap = XCreatePixmap(Device->display, Device->window, 32, 32, 1); Pixmap maskBitmap = XCreatePixmap(Device->display, Device->window, 32, 32, 1); Colormap screen_colormap = DefaultColormap( Device->display, DefaultScreen( Device->display ) ); XAllocNamedColor( Device->display, screen_colormap, "black", &fg, &fg ); XAllocNamedColor( Device->display, screen_colormap, "white", &bg, &bg ); GC gc = XCreateGC( Device->display, invisBitmap, valuemask, &values ); XSetForeground( Device->display, gc, BlackPixel( Device->display, DefaultScreen( Device->display ) ) ); XFillRectangle( Device->display, invisBitmap, gc, 0, 0, 32, 32 ); XFillRectangle( Device->display, maskBitmap, gc, 0, 0, 32, 32 ); invisCursor = XCreatePixmapCursor( Device->display, invisBitmap, maskBitmap, &fg, &bg, 1, 1 ); XFreeGC(Device->display, gc); XFreePixmap(Device->display, invisBitmap); XFreePixmap(Device->display, maskBitmap); initCursors(); } #endif } CIrrDeviceLinux::CCursorControl::~CCursorControl() { // Do not clearCursors here as the display is already closed // TODO (cutealien): droping cursorcontrol earlier might work, not sure about reason why that's done in stub currently. } #ifdef _IRR_COMPILE_WITH_X11_ void CIrrDeviceLinux::CCursorControl::clearCursors() { if (!Null) XFreeCursor(Device->display, invisCursor); for ( u32 i=0; i < Cursors.size(); ++i ) { for ( u32 f=0; f < Cursors[i].Frames.size(); ++f ) { XFreeCursor(Device->display, Cursors[i].Frames[f].IconHW); } } } void CIrrDeviceLinux::CCursorControl::initCursors() { Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_top_left_arrow)) ); // (or XC_arrow?) Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_crosshair)) ); Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_hand2)) ); // (or XC_hand1? ) Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_question_arrow)) ); Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_xterm)) ); Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_X_cursor)) ); // (or XC_pirate?) Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_watch)) ); // (or XC_clock?) Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_fleur)) ); Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_top_right_corner)) ); // NESW not available in X11 Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_top_left_corner)) ); // NWSE not available in X11 Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_sb_v_double_arrow)) ); Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_sb_h_double_arrow)) ); Cursors.push_back( CursorX11(XCreateFontCursor(Device->display, XC_sb_up_arrow)) ); // (or XC_center_ptr?) } void CIrrDeviceLinux::CCursorControl::update() { if ( (u32)ActiveIcon < Cursors.size() && !Cursors[ActiveIcon].Frames.empty() && Cursors[ActiveIcon].FrameTime ) { // update animated cursors. This could also be done by X11 in case someone wants to figure that out (this way was just easier to implement) u32 now = Device->getTimer()->getRealTime(); u32 frame = ((now - ActiveIconStartTime) / Cursors[ActiveIcon].FrameTime) % Cursors[ActiveIcon].Frames.size(); XDefineCursor(Device->display, Device->window, Cursors[ActiveIcon].Frames[frame].IconHW); } } #endif //! Sets the active cursor icon void CIrrDeviceLinux::CCursorControl::setActiveIcon(gui::ECURSOR_ICON iconId) { #ifdef _IRR_COMPILE_WITH_X11_ if ( iconId >= (s32)Cursors.size() ) return; if ( Cursors[iconId].Frames.size() ) XDefineCursor(Device->display, Device->window, Cursors[iconId].Frames[0].IconHW); ActiveIconStartTime = Device->getTimer()->getRealTime(); ActiveIcon = iconId; #endif } //! Add a custom sprite as cursor icon. gui::ECURSOR_ICON CIrrDeviceLinux::CCursorControl::addIcon(const gui::SCursorSprite& icon) { #ifdef _IRR_COMPILE_WITH_X11_ if ( icon.SpriteId >= 0 ) { CursorX11 cX11; cX11.FrameTime = icon.SpriteBank->getSprites()[icon.SpriteId].frameTime; for ( u32 i=0; i < icon.SpriteBank->getSprites()[icon.SpriteId].Frames.size(); ++i ) { irr::u32 texId = icon.SpriteBank->getSprites()[icon.SpriteId].Frames[i].textureNumber; irr::u32 rectId = icon.SpriteBank->getSprites()[icon.SpriteId].Frames[i].rectNumber; irr::core::rect rectIcon = icon.SpriteBank->getPositions()[rectId]; Cursor cursor = Device->TextureToCursor(icon.SpriteBank->getTexture(texId), rectIcon, icon.HotSpot); cX11.Frames.push_back( CursorFrameX11(cursor) ); } Cursors.push_back( cX11 ); return (gui::ECURSOR_ICON)(Cursors.size() - 1); } #endif return gui::ECI_NORMAL; } //! replace the given cursor icon. void CIrrDeviceLinux::CCursorControl::changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon) { #ifdef _IRR_COMPILE_WITH_X11_ if ( iconId >= (s32)Cursors.size() ) return; for ( u32 i=0; i < Cursors[iconId].Frames.size(); ++i ) XFreeCursor(Device->display, Cursors[iconId].Frames[i].IconHW); if ( icon.SpriteId >= 0 ) { CursorX11 cX11; cX11.FrameTime = icon.SpriteBank->getSprites()[icon.SpriteId].frameTime; for ( u32 i=0; i < icon.SpriteBank->getSprites()[icon.SpriteId].Frames.size(); ++i ) { irr::u32 texId = icon.SpriteBank->getSprites()[icon.SpriteId].Frames[i].textureNumber; irr::u32 rectId = icon.SpriteBank->getSprites()[icon.SpriteId].Frames[i].rectNumber; irr::core::rect rectIcon = icon.SpriteBank->getPositions()[rectId]; Cursor cursor = Device->TextureToCursor(icon.SpriteBank->getTexture(texId), rectIcon, icon.HotSpot); cX11.Frames.push_back( CursorFrameX11(cursor) ); } Cursors[iconId] = cX11; } #endif } irr::core::dimension2di CIrrDeviceLinux::CCursorControl::getSupportedIconSize() const { // this returns the closest match that is smaller or same size, so we just pass a value which should be large enough for cursors unsigned int width=0, height=0; #ifdef _IRR_COMPILE_WITH_X11_ XQueryBestCursor(Device->display, Device->window, 64, 64, &width, &height); #endif return core::dimension2di(width, height); } } // end namespace #endif // _IRR_COMPILE_WITH_X11_DEVICE_ irrlicht-1.8.3/source/Irrlicht/CIrrDeviceFB.h0000644000000000000000000001167712574354552017511 0ustar rootroot// Copyright (C) 2002-2007 Nikolaus Gebhardt // Copyright (C) 2007-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IRR_DEVICE_FB_H_INCLUDED__ #define __C_IRR_DEVICE_FB_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_FB_DEVICE_ #include "CIrrDeviceStub.h" #include "SIrrCreationParameters.h" #include "IrrlichtDevice.h" #include "IImagePresenter.h" #include "ICursorControl.h" #define KeySym s32 #include #include namespace irr { class CIrrDeviceFB : public CIrrDeviceStub, public video::IImagePresenter { public: //! constructor CIrrDeviceFB(const SIrrlichtCreationParameters& params); //! destructor virtual ~CIrrDeviceFB(); //! runs the device. Returns false if device wants to be deleted virtual bool run(); //! Cause the device to temporarily pause execution and let other processes to run // This should bring down processor usage without major performance loss for Irrlicht virtual void yield(); //! Pause execution and let other processes to run for a specified amount of time. virtual void sleep(u32 timeMs, bool pauseTimer); //! sets the caption of the window virtual void setWindowCaption(const wchar_t* text); //! returns if window is active. if not, nothing need to be drawn virtual bool isWindowActive() const; //! returns if window has focus virtual bool isWindowFocused() const; //! returns if window is minimized virtual bool isWindowMinimized() const; //! Minimizes window virtual void minimizeWindow(); //! Maximizes window virtual void maximizeWindow(); //! Restores original window size virtual void restoreWindow(); //! presents a surface in the client area virtual bool present(video::IImage* surface, void* windowId = 0, core::rect* src=0 ); //! notifies the device that it should close itself virtual void closeDevice(); //! Sets if the window should be resizeable in windowed mode. virtual void setResizable(bool resize=false); //! Returns the type of this device virtual E_DEVICE_TYPE getType() const; private: //! create the driver void createDriver(); bool createWindow(const core::dimension2d& windowSize, u32 bits); //! Implementation of the cursor control class CCursorControl : public gui::ICursorControl { public: CCursorControl(CIrrDeviceFB* dev, bool null) : Device(dev), IsVisible(true), Null(null) { Device->grab(); } ~CCursorControl() { Device->drop(); } //! Changes the visible state of the mouse cursor. virtual void setVisible(bool visible) { IsVisible = visible; } //! Returns if the cursor is currently visible. virtual bool isVisible() const { return IsVisible; } //! Sets the new position of the cursor. virtual void setPosition(const core::position2d &pos) { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. virtual void setPosition(f32 x, f32 y) { setPosition((s32)(x*Device->CreationParams.WindowSize.Width), (s32)(y*Device->CreationParams.WindowSize.Height)); } //! Sets the new position of the cursor. virtual void setPosition(const core::position2d &pos) { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. virtual void setPosition(s32 x, s32 y) { } //! Returns the current position of the mouse cursor. virtual const core::position2d& getPosition() { updateCursorPos(); return CursorPos; } //! Returns the current position of the mouse cursor. virtual core::position2d getRelativePosition() { updateCursorPos(); return core::position2d(CursorPos.X / (f32)Device->CreationParams.WindowSize.Width, CursorPos.Y / (f32)Device->CreationParams.WindowSize.Height); } virtual void setReferenceRect(core::rect* rect=0) { } private: void updateCursorPos() { } core::position2d CursorPos; CIrrDeviceFB* Device; bool IsVisible; bool Null; }; friend class CCursorControl; int Framebuffer; int EventDevice; int KeyboardDevice; struct fb_fix_screeninfo fbfixscreeninfo; struct fb_var_screeninfo fbscreeninfo; struct fb_var_screeninfo oldscreeninfo; long KeyboardMode; u8* SoftwareImage; u32 Pitch; video::ECOLOR_FORMAT FBColorFormat; bool Close; struct SKeyMap { SKeyMap() {} SKeyMap(s32 x11, s32 win32) : X11Key(x11), Win32Key(win32) { } KeySym X11Key; s32 Win32Key; bool operator<(const SKeyMap& o) const { return X11Key KeyMap; }; } // end namespace irr #endif // _IRR_USE_FB_DEVICE_ #endif // __C_IRR_DEVICE_FB_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CIrrDeviceFB.cpp0000644000000000000000000002450712574354552020040 0ustar rootroot// Copyright (C) 2002-2007 Nikolaus Gebhardt // Copyright (C) 2007-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CIrrDeviceFB.h" #ifdef _IRR_COMPILE_WITH_FB_DEVICE_ #include #include #include #include #include #include #include #include #include #include #include #include "IEventReceiver.h" #include "os.h" #include "CTimer.h" #include "irrString.h" #include "Keycodes.h" #include "COSOperator.h" #include "CColorConverter.h" #include "SIrrCreationParameters.h" #include namespace irr { //! constructor CIrrDeviceFB::CIrrDeviceFB(const SIrrlichtCreationParameters& params) : CIrrDeviceStub(params), Framebuffer(-1), EventDevice(-1), SoftwareImage(0), Pitch(0), FBColorFormat(video::ECF_A8R8G8B8), Close(false) { #ifdef _DEBUG setDebugName("CIrrDeviceFB"); #endif // print version, distribution etc. // thx to LynxLuna for pointing me to the uname function core::stringc linuxversion; struct utsname FBInfo; uname(&FBInfo); linuxversion += FBInfo.sysname; linuxversion += " "; linuxversion += FBInfo.release; linuxversion += " "; linuxversion += FBInfo.version; linuxversion += " "; linuxversion += FBInfo.machine; Operator = new COSOperator(linuxversion); os::Printer::log(linuxversion.c_str(), ELL_INFORMATION); // create window if (params.DriverType != video::EDT_NULL) { // create the window, only if we do not use the null device if (!createWindow(params.WindowSize, params.Bits)) return; } // create cursor control CursorControl = new CCursorControl(this, params.DriverType == video::EDT_NULL); // create driver createDriver(); if (!VideoDriver) return; createGUIAndScene(); } //! destructor CIrrDeviceFB::~CIrrDeviceFB() { if (SoftwareImage) munmap(SoftwareImage, CreationParams.WindowSize.Height*Pitch); // go back to previous format if (ioctl(Framebuffer, FBIOPUT_VSCREENINFO, &oldscreeninfo) <0) perror("Restoring old fb mode"); if (KeyboardDevice != -1) if (ioctl(KeyboardDevice, KDSETMODE, &KeyboardMode) <0) perror("Restoring keyboard mode"); if (EventDevice != -1) close(EventDevice); if (KeyboardDevice != -1) close(KeyboardDevice); if (Framebuffer != -1) close(Framebuffer); } bool CIrrDeviceFB::createWindow(const core::dimension2d& windowSize, u32 bits) { char buf[256]; CreationParams.WindowSize.Width = windowSize.Width; CreationParams.WindowSize.Height = windowSize.Height; KeyboardDevice = open("/dev/tty", O_RDWR); if (KeyboardDevice == -1) perror("Open keyboard"); if (ioctl(KeyboardDevice, KDGETMODE, &KeyboardMode) <0) perror("Read keyboard mode"); if (ioctl(KeyboardDevice, KDSETMODE, KD_GRAPHICS) <0) perror("Set keyboard mode"); Framebuffer=open("/dev/fb/0", O_RDWR); if (Framebuffer == -1) { Framebuffer=open("/dev/fb0", O_RDWR); if (Framebuffer == -1) { perror("Open framebuffer"); return false; } } EventDevice = open("/dev/input/event0", O_RDONLY | O_NONBLOCK); if (EventDevice == -1) perror("Open event device"); // make format settings ioctl(Framebuffer, FBIOGET_FSCREENINFO, &fbfixscreeninfo); ioctl(Framebuffer, FBIOGET_VSCREENINFO, &oldscreeninfo); snprintf(buf, 256, "Original resolution: %d x %d\nARGB%d%d%d%d\n",oldscreeninfo.xres,oldscreeninfo.yres, oldscreeninfo.transp.length,oldscreeninfo.red.length,oldscreeninfo.green.length,oldscreeninfo.blue.length); os::Printer::log(buf); memcpy(&fbscreeninfo, &oldscreeninfo, sizeof(struct fb_var_screeninfo)); if (CreationParams.DriverType != video::EDT_NULL) { fbscreeninfo.xres = fbscreeninfo.xres_virtual = CreationParams.WindowSize.Width; fbscreeninfo.yres = fbscreeninfo.yres_virtual = CreationParams.WindowSize.Height; fbscreeninfo.bits_per_pixel = 16; fbscreeninfo.red.offset = 10; fbscreeninfo.red.length = 5; fbscreeninfo.green.offset = 5; fbscreeninfo.green.length = 5; fbscreeninfo.blue.offset = 0; fbscreeninfo.blue.length = 5; fbscreeninfo.transp.offset = 15; fbscreeninfo.transp.length = 1; ioctl(Framebuffer, FBIOPUT_VSCREENINFO, &fbscreeninfo); ioctl(Framebuffer, FBIOGET_VSCREENINFO, &fbscreeninfo); snprintf(buf, 256, "New resolution: %d x %d (%d x %d)\nARGB%d%d%d%d\n",fbscreeninfo.xres,fbscreeninfo.yres,fbscreeninfo.xres_virtual,fbscreeninfo.yres_virtual, fbscreeninfo.transp.length,fbscreeninfo.red.length,fbscreeninfo.green.length,fbscreeninfo.blue.length); os::Printer::log(buf); CreationParams.WindowSize.Width = fbscreeninfo.xres; CreationParams.WindowSize.Height = fbscreeninfo.yres; CreationParams.Bits = fbscreeninfo.bits_per_pixel; Pitch = fbfixscreeninfo.line_length; if (fbscreeninfo.bits_per_pixel == 16) { if (fbscreeninfo.transp.length == 0) FBColorFormat = video::ECF_R5G6B5; else FBColorFormat = video::ECF_A1R5G5B5; } else { if (fbscreeninfo.transp.length == 0) FBColorFormat = video::ECF_R8G8B8; else FBColorFormat = video::ECF_A8R8G8B8; } if (MAP_FAILED==(SoftwareImage=(u8*)mmap(0, CreationParams.WindowSize.Height*Pitch, PROT_READ|PROT_WRITE, MAP_SHARED, Framebuffer, 0))) { perror("mmap render target"); return false; } } return true; } //! create the driver void CIrrDeviceFB::createDriver() { switch(CreationParams.DriverType) { case video::EDT_SOFTWARE: #ifdef _IRR_COMPILE_WITH_SOFTWARE_ VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); #else os::Printer::log("No Software driver support compiled in.", ELL_WARNING); #endif break; case video::EDT_BURNINGSVIDEO: #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this); #else os::Printer::log("Burning's video driver was not compiled in.", ELL_WARNING); #endif break; case video::EDT_OPENGL: case video::EDT_DIRECT3D8: case video::EDT_DIRECT3D9: os::Printer::log("This driver is not available in FB. Try Software renderer.", ELL_WARNING); break; default: VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize); break; } } //! runs the device. Returns false if device wants to be deleted bool CIrrDeviceFB::run() { os::Timer::tick(); struct input_event ev; if (EventDevice>=0) { if ((read(EventDevice, &ev, sizeof(input_event)) < 0) && errno != EAGAIN) perror("Read input event"); if (ev.type == EV_KEY) { irr::SEvent irrevent; irrevent.EventType = irr::EET_KEY_INPUT_EVENT; irrevent.KeyInput.PressedDown = true; switch (ev.code) { case KEY_RIGHTCTRL: case KEY_LEFTCTRL: irrevent.KeyInput.Control = true; break; case KEY_RIGHTSHIFT: case KEY_LEFTSHIFT: irrevent.KeyInput.Shift = true; break; case KEY_ESC: irrevent.KeyInput.Key = (EKEY_CODE)0x1B; break; case KEY_SPACE: irrevent.KeyInput.Key = (EKEY_CODE)0x20; break; case KEY_UP: irrevent.KeyInput.Key = (EKEY_CODE)0x26; break; case KEY_LEFT: irrevent.KeyInput.Key = (EKEY_CODE)0x25; break; case KEY_RIGHT: irrevent.KeyInput.Key = (EKEY_CODE)0x27; break; case KEY_DOWN: irrevent.KeyInput.Key = (EKEY_CODE)0x28; break; default: irrevent.KeyInput.Key = (EKEY_CODE)0; break; } postEventFromUser(irrevent); } } return !Close; } //! Pause the current process for the minimum time allowed only to allow other processes to execute void CIrrDeviceFB::yield() { struct timespec ts = {0,0}; nanosleep(&ts, NULL); } //! Pause execution and let other processes to run for a specified amount of time. void CIrrDeviceFB::sleep(u32 timeMs, bool pauseTimer=false) { bool wasStopped = Timer ? Timer->isStopped() : true; struct timespec ts; ts.tv_sec = (time_t) (timeMs / 1000); ts.tv_nsec = (long) (timeMs % 1000) * 1000000; if (pauseTimer && !wasStopped) Timer->stop(); nanosleep(&ts, NULL); if (pauseTimer && !wasStopped) Timer->start(); } //! presents a surface in the client area bool CIrrDeviceFB::present(video::IImage* image, void* windowId, core::rect* src ) { // this is only necessary for software drivers. if (CreationParams.DriverType != video::EDT_SOFTWARE && CreationParams.DriverType != video::EDT_BURNINGSVIDEO) return false; if (!SoftwareImage) return false; u8* destData = SoftwareImage; u32 srcwidth = (u32)image->getDimension().Width; u32 srcheight = (u32)image->getDimension().Height; // clip images srcheight = core::min_(srcheight, CreationParams.WindowSize.Height); srcwidth = core::min_(srcwidth, CreationParams.WindowSize.Width); u8* srcdata = (u8*)image->lock(); for (u32 y=0; ygetColorFormat(), srcwidth, destData, FBColorFormat); srcdata+=image->getPitch(); destData+=Pitch; } image->unlock(); msync(SoftwareImage,CreationParams.WindowSize.Width*CreationParams.WindowSize.Height,MS_ASYNC); return true; } //! notifies the device that it should close itself void CIrrDeviceFB::closeDevice() { Close = true; } //! returns if window is active. if not, nothing need to be drawn bool CIrrDeviceFB::isWindowActive() const { return true; } //! returns if window has focus bool CIrrDeviceFB::isWindowFocused() const { return true; } //! returns if window is minimized bool CIrrDeviceFB::isWindowMinimized() const { return false; } //! sets the caption of the window void CIrrDeviceFB::setWindowCaption(const wchar_t* text) { } //! Sets if the window should be resizeable in windowed mode. void CIrrDeviceFB::setResizable(bool resize) { } //! Minimizes window void CIrrDeviceFB::minimizeWindow() { } //! Maximizes window void CIrrDeviceFB::maximizeWindow() { } //! Restores original window size void CIrrDeviceFB::restoreWindow() { } //! Returns the type of this device E_DEVICE_TYPE CIrrDeviceFB::getType() const { return EIDT_FRAMEBUFFER; } } // end namespace irr #endif // _IRR_USE_FB_DEVICE_ irrlicht-1.8.3/source/Irrlicht/CIrrDeviceConsole.h0000644000000000000000000002160112574354552020610 0ustar rootroot// Copyright (C) 2009-2012 Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IRR_DEVICE_CONSOLE_H_INCLUDED__ #define __C_IRR_DEVICE_CONSOLE_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_CONSOLE_DEVICE_ //#define _IRR_USE_CONSOLE_FONT_ #include "SIrrCreationParameters.h" #include "CIrrDeviceStub.h" #include "IImagePresenter.h" // for console font #include "IGUIFont.h" #ifdef _IRR_WINDOWS_API_ #define WIN32_LEAN_AND_MEAN #if !defined(_IRR_XBOX_PLATFORM_) #include #endif #if(_WIN32_WINNT >= 0x0500) #define _IRR_WINDOWS_NT_CONSOLE_ #endif #else #include #endif // for now we assume all other terminal types are VT100 #ifndef _IRR_WINDOWS_NT_CONSOLE_ #define _IRR_VT100_CONSOLE_ #endif namespace irr { class CIrrDeviceConsole : public CIrrDeviceStub, video::IImagePresenter { public: //! constructor CIrrDeviceConsole(const SIrrlichtCreationParameters& params); //! destructor virtual ~CIrrDeviceConsole(); //! runs the device. Returns false if device wants to be deleted virtual bool run(); //! Cause the device to temporarily pause execution and let other processes to run // This should bring down processor usage without major performance loss for Irrlicht virtual void yield(); //! Pause execution and let other processes to run for a specified amount of time. virtual void sleep(u32 timeMs, bool pauseTimer); //! sets the caption of the window virtual void setWindowCaption(const wchar_t* text); //! returns if window is active. if not, nothing need to be drawn virtual bool isWindowActive() const; //! returns if window has focus virtual bool isWindowFocused() const; //! returns if window is minimized virtual bool isWindowMinimized() const; //! presents a surface in the client area virtual bool present(video::IImage* surface, void* windowId=0, core::rect* src=0); //! notifies the device that it should close itself virtual void closeDevice(); //! Sets if the window should be resizable in windowed mode. virtual void setResizable(bool resize=false); //! Minimizes the window. virtual void minimizeWindow(); //! Maximizes the window. virtual void maximizeWindow(); //! Restores the window size. virtual void restoreWindow(); //! Get the device type virtual E_DEVICE_TYPE getType() const { return EIDT_CONSOLE; } void addPostPresentText(s16 X, s16 Y, const wchar_t *text); //! Implementation of the win32 console mouse cursor class CCursorControl : public gui::ICursorControl { public: CCursorControl(const core::dimension2d& wsize) : WindowSize(wsize), InvWindowSize(0.0f, 0.0f), IsVisible(true), UseReferenceRect(false) { if (WindowSize.Width!=0) InvWindowSize.Width = 1.0f / WindowSize.Width; if (WindowSize.Height!=0) InvWindowSize.Height = 1.0f / WindowSize.Height; } //! Changes the visible state of the mouse cursor. virtual void setVisible(bool visible) { if(visible != IsVisible) { IsVisible = visible; setPosition(CursorPos.X, CursorPos.Y); } } //! Returns if the cursor is currently visible. virtual bool isVisible() const { return IsVisible; } //! Sets the new position of the cursor. virtual void setPosition(const core::position2d &pos) { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. virtual void setPosition(f32 x, f32 y) { if (!UseReferenceRect) setPosition((s32)(x*WindowSize.Width), (s32)(y*WindowSize.Height)); else setPosition((s32)(x*ReferenceRect.getWidth()), (s32)(y*ReferenceRect.getHeight())); } //! Sets the new position of the cursor. virtual void setPosition(const core::position2d &pos) { setPosition(pos.X, pos.Y); } //! Sets the new position of the cursor. virtual void setPosition(s32 x, s32 y) { setInternalCursorPosition(core::position2di(x,y)); } //! Returns the current position of the mouse cursor. virtual const core::position2d& getPosition() { return CursorPos; } //! Returns the current position of the mouse cursor. virtual core::position2d getRelativePosition() { if (!UseReferenceRect) { return core::position2d(CursorPos.X * InvWindowSize.Width, CursorPos.Y * InvWindowSize.Height); } return core::position2d(CursorPos.X / (f32)ReferenceRect.getWidth(), CursorPos.Y / (f32)ReferenceRect.getHeight()); } //! Sets an absolute reference rect for calculating the cursor position. virtual void setReferenceRect(core::rect* rect=0) { if (rect) { ReferenceRect = *rect; UseReferenceRect = true; // prevent division through zero and uneven sizes if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2) ReferenceRect.LowerRightCorner.Y += 1; if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2) ReferenceRect.LowerRightCorner.X += 1; } else UseReferenceRect = false; } //! Updates the internal cursor position void setInternalCursorPosition(const core::position2di &pos) { CursorPos = pos; if (UseReferenceRect) CursorPos -= ReferenceRect.UpperLeftCorner; } private: core::position2d CursorPos; core::dimension2d WindowSize; core::dimension2d InvWindowSize; bool IsVisible, UseReferenceRect; core::rect ReferenceRect; }; private: //! Set the position of the text caret void setTextCursorPos(s16 x, s16 y); // text to be added after drawing the screen struct SPostPresentText { core::position2d Pos; core::stringc Text; }; bool IsWindowFocused; core::array OutputBuffer; gui::IGUIFont *ConsoleFont; core::array Text; FILE *OutFile; #ifdef _IRR_WINDOWS_NT_CONSOLE_ HANDLE WindowsSTDIn, WindowsSTDOut; u32 MouseButtonStates; #endif }; #ifdef _IRR_USE_CONSOLE_FONT_ namespace gui { class CGUIConsoleFont : public IGUIFont { public: CGUIConsoleFont(CIrrDeviceConsole* device) : Device(device) { } //! Draws some text and clips it to the specified rectangle if wanted. virtual void draw(const wchar_t* text, const core::rect& position, video::SColor color, bool hcenter=false, bool vcenter=false, const core::rect* clip=0) { core::rect Area = clip ? *clip : position; if (Area.UpperLeftCorner.X < 0) Area.UpperLeftCorner.X = 0; if (Area.UpperLeftCorner.Y < 0) Area.UpperLeftCorner.Y = 0; core::position2d pos; // centre vertically pos.Y = vcenter ? (position.UpperLeftCorner.Y + position.LowerRightCorner.Y) / 2 : position.UpperLeftCorner.Y; // nothing to display? if (pos.Y < Area.UpperLeftCorner.Y || pos.Y > Area.LowerRightCorner.Y) return; tempText = text; // centre horizontally pos.X = hcenter ? position.getCenter().X - ( tempText.size() / 2) : position.UpperLeftCorner.X; // clip u32 xlclip = 0, xrclip = 0; // get right clip if (pos.X + (s32)tempText.size() > Area.LowerRightCorner.X) xrclip = Area.LowerRightCorner.X - pos.X; // get left clip if (pos.X < Area.UpperLeftCorner.X) xlclip = Area.UpperLeftCorner.X - pos.X; // totally clipped? if ((s32)tempText.size() - xlclip - xrclip < 0) return; // null terminate the string if (xrclip > 0) tempText[xrclip] = L'\0'; Device->addPostPresentText(pos.X + xlclip, pos.Y, &(tempText.c_str()[xlclip])); } //! Calculates the dimension of some text. virtual core::dimension2d getDimension(const wchar_t* text) const { return core::dimension2d(wcslen(text),1); } //! Calculates the index of the character in the text which is on a specific position. virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const { return pixel_x; }; //! No kerning virtual void setKerningWidth (s32 kerning) { } virtual void setKerningHeight (s32 kerning) { } virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const {return 0;} virtual s32 getKerningHeight() const { return 0;} virtual void setInvisibleCharacters( const wchar_t *s ) { } // I guess this is an OS specific font virtual EGUI_FONT_TYPE getType() const { return EGFT_OS; } private: CIrrDeviceConsole* Device; core::stringw tempText; }; } // end namespace gui #endif // _IRR_USE_CONSOLE_FONT_ } // end namespace irr #endif // _IRR_COMPILE_WITH_CONSOLE_DEVICE_ #endif // __C_IRR_DEVICE_CONSOLE_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CIrrDeviceConsole.cpp0000644000000000000000000003055012574354552021146 0ustar rootroot// Copyright (C) 2009-2012 Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CIrrDeviceConsole.h" #ifdef _IRR_COMPILE_WITH_CONSOLE_DEVICE_ #include "os.h" #include "IGUISkin.h" #include "IGUIEnvironment.h" // to close the device on terminate signal irr::CIrrDeviceConsole *DeviceToClose; #ifdef _IRR_WINDOWS_NT_CONSOLE_ // Callback for Windows BOOL WINAPI ConsoleHandler(DWORD CEvent) { switch(CEvent) { case CTRL_C_EVENT: irr::os::Printer::log("Closing console device", "CTRL+C"); break; case CTRL_BREAK_EVENT: irr::os::Printer::log("Closing console device", "CTRL+Break"); break; case CTRL_CLOSE_EVENT: irr::os::Printer::log("Closing console device", "User closed console"); break; case CTRL_LOGOFF_EVENT: irr::os::Printer::log("Closing console device", "User is logging off"); break; case CTRL_SHUTDOWN_EVENT: irr::os::Printer::log("Closing console device", "Computer shutting down"); break; } DeviceToClose->closeDevice(); return TRUE; } #elif defined(_IRR_POSIX_API_) // sigterm handler #include void sighandler(int sig) { irr::core::stringc code = "Signal "; code += sig; code += " received"; irr::os::Printer::log("Closing console device", code.c_str()); DeviceToClose->closeDevice(); } #endif namespace irr { const c8 ASCIIArtChars[] = " .,'~:;!+>=icopjtJY56SB8XDQKHNWM"; //MWNHKQDX8BS65YJtjpoci=+>!;:~',. "; const u16 ASCIIArtCharsCount = 32; //const c8 ASCIIArtChars[] = " \xb0\xb1\xf9\xb2\xdb"; //const u16 ASCIIArtCharsCount = 5; //! constructor CIrrDeviceConsole::CIrrDeviceConsole(const SIrrlichtCreationParameters& params) : CIrrDeviceStub(params), IsWindowFocused(true), ConsoleFont(0), OutFile(stdout) { DeviceToClose = this; #ifdef _IRR_WINDOWS_NT_CONSOLE_ MouseButtonStates = 0; WindowsSTDIn = GetStdHandle(STD_INPUT_HANDLE); WindowsSTDOut = GetStdHandle(STD_OUTPUT_HANDLE); PCOORD Dimensions = 0; if (CreationParams.Fullscreen) { // Some mingw versions lack this define, so avoid it in case it does not exist #if (_WIN32_WINNT >= 0x0501) && defined(CONSOLE_FULLSCREEN_MODE) if (SetConsoleDisplayMode(WindowsSTDOut, CONSOLE_FULLSCREEN_MODE, Dimensions)) { CreationParams.WindowSize.Width = Dimensions->X; CreationParams.WindowSize.Width = Dimensions->Y; } #endif } else { COORD ConsoleSize; ConsoleSize.X = CreationParams.WindowSize.Width; ConsoleSize.X = CreationParams.WindowSize.Height; SetConsoleScreenBufferSize(WindowsSTDOut, ConsoleSize); } // catch windows close/break signals SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE); #elif defined(_IRR_POSIX_API_) // catch other signals signal(SIGABRT, &sighandler); signal(SIGTERM, &sighandler); signal(SIGINT, &sighandler); // set output stream if (params.WindowId) OutFile = (FILE*)(params.WindowId); #endif #ifdef _IRR_VT100_CONSOLE_ // reset terminal fprintf(OutFile, "%cc", 27); // disable line wrapping fprintf(OutFile, "%c[7l", 27); #endif switch (params.DriverType) { case video::EDT_SOFTWARE: #ifdef _IRR_COMPILE_WITH_SOFTWARE_ VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); #else os::Printer::log("Software driver was not compiled in.", ELL_ERROR); #endif break; case video::EDT_BURNINGSVIDEO: #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this); #else os::Printer::log("Burning's Video driver was not compiled in.", ELL_ERROR); #endif break; case video::EDT_DIRECT3D8: case video::EDT_DIRECT3D9: case video::EDT_OPENGL: os::Printer::log("The console device cannot use hardware drivers yet.", ELL_ERROR); break; case video::EDT_NULL: VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize); break; default: break; } // set up output buffer for (u32 y=0; ygetSkin(); if (skin) { for (u32 i=0; i < gui::EGDF_COUNT; ++i) skin->setFont(ConsoleFont, gui::EGUI_DEFAULT_FONT(i)); } } #endif } } //! destructor CIrrDeviceConsole::~CIrrDeviceConsole() { // GUI and scene are dropped in the stub if (CursorControl) { CursorControl->drop(); CursorControl = 0; } if (ConsoleFont) { ConsoleFont->drop(); ConsoleFont = 0; } #ifdef _IRR_VT100_CONSOLE_ // reset terminal fprintf(OutFile, "%cc", 27); #endif } //! runs the device. Returns false if device wants to be deleted bool CIrrDeviceConsole::run() { // increment timer os::Timer::tick(); // process Windows console input #ifdef _IRR_WINDOWS_NT_CONSOLE_ INPUT_RECORD in; DWORD oldMode; DWORD count, waste; // get old input mode GetConsoleMode(WindowsSTDIn, &oldMode); SetConsoleMode(WindowsSTDIn, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT); GetNumberOfConsoleInputEvents(WindowsSTDIn, &count); // read keyboard and mouse input while (count) { ReadConsoleInput(WindowsSTDIn, &in, 1, &waste ); switch(in.EventType) { case KEY_EVENT: { SEvent e; e.EventType = EET_KEY_INPUT_EVENT; e.KeyInput.PressedDown = (in.Event.KeyEvent.bKeyDown == TRUE); e.KeyInput.Control = (in.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0; e.KeyInput.Shift = (in.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) != 0; e.KeyInput.Key = EKEY_CODE(in.Event.KeyEvent.wVirtualKeyCode); e.KeyInput.Char = in.Event.KeyEvent.uChar.UnicodeChar; postEventFromUser(e); break; } case MOUSE_EVENT: { SEvent e; e.EventType = EET_MOUSE_INPUT_EVENT; e.MouseInput.X = in.Event.MouseEvent.dwMousePosition.X; e.MouseInput.Y = in.Event.MouseEvent.dwMousePosition.Y; e.MouseInput.Wheel = 0.f; e.MouseInput.ButtonStates = ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) ? EMBSM_LEFT : 0 ) | ( (in.Event.MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED) ? EMBSM_RIGHT : 0 ) | ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) ? EMBSM_MIDDLE : 0 ) | ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_3RD_BUTTON_PRESSED) ? EMBSM_EXTRA1 : 0 ) | ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_4TH_BUTTON_PRESSED) ? EMBSM_EXTRA2 : 0 ); if (in.Event.MouseEvent.dwEventFlags & MOUSE_MOVED) { CursorControl->setPosition(core::position2di(e.MouseInput.X, e.MouseInput.Y)); // create mouse moved event e.MouseInput.Event = EMIE_MOUSE_MOVED; postEventFromUser(e); } if (in.Event.MouseEvent.dwEventFlags & MOUSE_WHEELED) { e.MouseInput.Event = EMIE_MOUSE_WHEEL; e.MouseInput.Wheel = (in.Event.MouseEvent.dwButtonState & 0xFF000000) ? -1.0f : 1.0f; postEventFromUser(e); } if ( (MouseButtonStates & EMBSM_LEFT) != (e.MouseInput.ButtonStates & EMBSM_LEFT) ) { e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_LEFT) ? EMIE_LMOUSE_PRESSED_DOWN : EMIE_LMOUSE_LEFT_UP; postEventFromUser(e); } if ( (MouseButtonStates & EMBSM_RIGHT) != (e.MouseInput.ButtonStates & EMBSM_RIGHT) ) { e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_RIGHT) ? EMIE_RMOUSE_PRESSED_DOWN : EMIE_RMOUSE_LEFT_UP; postEventFromUser(e); } if ( (MouseButtonStates & EMBSM_MIDDLE) != (e.MouseInput.ButtonStates & EMBSM_MIDDLE) ) { e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_MIDDLE) ? EMIE_MMOUSE_PRESSED_DOWN : EMIE_MMOUSE_LEFT_UP; postEventFromUser(e); } // save current button states MouseButtonStates = e.MouseInput.ButtonStates; break; } case WINDOW_BUFFER_SIZE_EVENT: VideoDriver->OnResize( core::dimension2d(in.Event.WindowBufferSizeEvent.dwSize.X, in.Event.WindowBufferSizeEvent.dwSize.Y)); break; case FOCUS_EVENT: IsWindowFocused = (in.Event.FocusEvent.bSetFocus == TRUE); break; default: break; } GetNumberOfConsoleInputEvents(WindowsSTDIn, &count); } // set input mode SetConsoleMode(WindowsSTDIn, oldMode); #else // todo: keyboard input from terminal in raw mode #endif return !Close; } //! Cause the device to temporarily pause execution and let other processes to run // This should bring down processor usage without major performance loss for Irrlicht void CIrrDeviceConsole::yield() { #ifdef _IRR_WINDOWS_API_ Sleep(1); #else struct timespec ts = {0,0}; nanosleep(&ts, NULL); #endif } //! Pause execution and let other processes to run for a specified amount of time. void CIrrDeviceConsole::sleep(u32 timeMs, bool pauseTimer) { const bool wasStopped = Timer ? Timer->isStopped() : true; #ifdef _IRR_WINDOWS_API_ Sleep(timeMs); #else struct timespec ts; ts.tv_sec = (time_t) (timeMs / 1000); ts.tv_nsec = (long) (timeMs % 1000) * 1000000; if (pauseTimer && !wasStopped) Timer->stop(); nanosleep(&ts, NULL); #endif if (pauseTimer && !wasStopped) Timer->start(); } //! sets the caption of the window void CIrrDeviceConsole::setWindowCaption(const wchar_t* text) { #ifdef _IRR_WINDOWS_NT_CONSOLE_ SetConsoleTitleW(text); #endif } //! returns if window is active. if not, nothing need to be drawn bool CIrrDeviceConsole::isWindowActive() const { // there is no window, but we always assume it is active return true; } //! returns if window has focus bool CIrrDeviceConsole::isWindowFocused() const { return IsWindowFocused; } //! returns if window is minimized bool CIrrDeviceConsole::isWindowMinimized() const { return false; } //! presents a surface in the client area bool CIrrDeviceConsole::present(video::IImage* surface, void* windowId, core::rect* src) { if (surface) { for (u32 y=0; y < surface->getDimension().Height; ++y) { for (u32 x=0; x< surface->getDimension().Width; ++x) { // get average pixel u32 avg = surface->getPixel(x,y).getAverage() * (ASCIIArtCharsCount-1); avg /= 255; OutputBuffer[y] [x] = ASCIIArtChars[avg]; } } } #ifdef _IRR_USE_CONSOLE_FONT_ for (u32 i=0; i< Text.size(); ++i) { s32 y = Text[i].Pos.Y; if ( y < (s32)OutputBuffer.size() && y > 0) for (u32 c=0; c < Text[i].Text.size() && c + Text[i].Pos.X < OutputBuffer[y].size(); ++c) //if (Text[i].Text[c] != ' ') OutputBuffer[y] [c+Text[i].Pos.X] = Text[i].Text[c]; } Text.clear(); #endif // draw output for (u32 y=0; ygetDimension().Width; imageHeader.ImageHeight = image->getDimension().Height; // top left of image is the top. the image loader needs to // be fixed to only swap/flip imageHeader.ImageDescriptor = (1 << 5); // chances are good we'll need to swizzle data, so i'm going // to convert and write one scan line at a time. it's also // a bit cleaner this way void (*CColorConverter_convertFORMATtoFORMAT)(const void*, s32, void*) = 0; switch(image->getColorFormat()) { case ECF_A8R8G8B8: CColorConverter_convertFORMATtoFORMAT = CColorConverter::convert_A8R8G8B8toA8R8G8B8; imageHeader.PixelDepth = 32; imageHeader.ImageDescriptor |= 8; break; case ECF_A1R5G5B5: CColorConverter_convertFORMATtoFORMAT = CColorConverter::convert_A1R5G5B5toA1R5G5B5; imageHeader.PixelDepth = 16; imageHeader.ImageDescriptor |= 1; break; case ECF_R5G6B5: CColorConverter_convertFORMATtoFORMAT = CColorConverter::convert_R5G6B5toA1R5G5B5; imageHeader.PixelDepth = 16; imageHeader.ImageDescriptor |= 1; break; case ECF_R8G8B8: CColorConverter_convertFORMATtoFORMAT = CColorConverter::convert_R8G8B8toR8G8B8; imageHeader.PixelDepth = 24; imageHeader.ImageDescriptor |= 0; break; #ifndef _DEBUG default: break; #endif } // couldn't find a color converter if (!CColorConverter_convertFORMATtoFORMAT) return false; if (file->write(&imageHeader, sizeof(imageHeader)) != sizeof(imageHeader)) return false; u8* scan_lines = (u8*)image->lock(); if (!scan_lines) return false; // size of one pixel in bytes u32 pixel_size = image->getBytesPerPixel(); // length of one row of the source image in bytes u32 row_stride = (pixel_size * imageHeader.ImageWidth); // length of one output row in bytes s32 row_size = ((imageHeader.PixelDepth / 8) * imageHeader.ImageWidth); // allocate a row do translate data into u8* row_pointer = new u8[row_size]; u32 y; for (y = 0; y < imageHeader.ImageHeight; ++y) { // source, length [pixels], destination if (image->getColorFormat()==ECF_R8G8B8) CColorConverter::convert24BitTo24Bit(&scan_lines[y * row_stride], row_pointer, imageHeader.ImageWidth, 1, 0, 0, true); else CColorConverter_convertFORMATtoFORMAT(&scan_lines[y * row_stride], imageHeader.ImageWidth, row_pointer); if (file->write(row_pointer, row_size) != row_size) break; } delete [] row_pointer; image->unlock(); STGAFooter imageFooter; imageFooter.ExtensionOffset = 0; imageFooter.DeveloperOffset = 0; strncpy(imageFooter.Signature, "TRUEVISION-XFILE.", 18); if (file->write(&imageFooter, sizeof(imageFooter)) < (s32)sizeof(imageFooter)) return false; return imageHeader.ImageHeight <= y; } } // namespace video } // namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageWriterPSD.h0000644000000000000000000000153612574354552020204 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef _C_IMAGE_WRITER_PSD_H_INCLUDED__ #define _C_IMAGE_WRITER_PSD_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_PSD_WRITER_ #include "IImageWriter.h" namespace irr { namespace video { class CImageWriterPSD : public IImageWriter { public: //! constructor CImageWriterPSD(); //! return true if this writer can write a file with the given extension virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image,u32 param) const; }; } // namespace video } // namespace irr #endif // _I_IMAGE_WRITER_PSD_H_INCLUDED__ #endif irrlicht-1.8.3/source/Irrlicht/CImageWriterPSD.cpp0000644000000000000000000000171412574354552020535 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageWriterPSD.h" #ifdef _IRR_COMPILE_WITH_PSD_WRITER_ #include "CImageLoaderPSD.h" #include "IWriteFile.h" #include "os.h" // for logging #include "irrString.h" namespace irr { namespace video { IImageWriter* createImageWriterPSD() { return new CImageWriterPSD; } CImageWriterPSD::CImageWriterPSD() { #ifdef _DEBUG setDebugName("CImageWriterPSD"); #endif } bool CImageWriterPSD::isAWriteableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "psd" ); } bool CImageWriterPSD::writeImage(io::IWriteFile *file, IImage *image,u32 param) const { os::Printer::log("PSD writer not yet implemented. Image not written.", ELL_WARNING); return false; } } // namespace video } // namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageWriterPPM.h0000644000000000000000000000153712574354552020213 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef _C_IMAGE_WRITER_PPM_H_INCLUDED__ #define _C_IMAGE_WRITER_PPM_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_PPM_WRITER_ #include "IImageWriter.h" namespace irr { namespace video { class CImageWriterPPM : public IImageWriter { public: //! constructor CImageWriterPPM(); //! return true if this writer can write a file with the given extension virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; }; } // namespace video } // namespace irr #endif // _C_IMAGE_WRITER_PPM_H_INCLUDED__ #endif irrlicht-1.8.3/source/Irrlicht/CImageWriterPPM.cpp0000644000000000000000000000425312574354552020544 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageWriterPPM.h" #ifdef _IRR_COMPILE_WITH_PPM_WRITER_ #include "IWriteFile.h" #include "IImage.h" #include "dimension2d.h" #include "irrString.h" namespace irr { namespace video { IImageWriter* createImageWriterPPM() { return new CImageWriterPPM; } CImageWriterPPM::CImageWriterPPM() { #ifdef _DEBUG setDebugName("CImageWriterPPM"); #endif } bool CImageWriterPPM::isAWriteableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "ppm" ); } bool CImageWriterPPM::writeImage(io::IWriteFile *file, IImage *image, u32 param) const { char cache[70]; int size; const core::dimension2d& imageSize = image->getDimension(); const bool binary = false; if (binary) size = snprintf(cache, 70, "P6\n"); else size = snprintf(cache, 70, "P3\n"); if (file->write(cache, size) != size) return false; size = snprintf(cache, 70, "%d %d\n", imageSize.Width, imageSize.Height); if (file->write(cache, size) != size) return false; size = snprintf(cache, 70, "255\n"); if (file->write(cache, size) != size) return false; if (binary) { for (u32 h = 0; h < imageSize.Height; ++h) { for (u32 c = 0; c < imageSize.Width; ++c) { const video::SColor& pixel = image->getPixel(c, h); const u8 r = (u8)(pixel.getRed() & 0xff); const u8 g = (u8)(pixel.getGreen() & 0xff); const u8 b = (u8)(pixel.getBlue() & 0xff); file->write(&r, 1); file->write(&g, 1); file->write(&b, 1); } } } else { s32 n = 0; for (u32 h = 0; h < imageSize.Height; ++h) { for (u32 c = 0; c < imageSize.Width; ++c, ++n) { const video::SColor& pixel = image->getPixel(c, h); size = snprintf(cache, 70, "%.3u %.3u %.3u%s", pixel.getRed(), pixel.getGreen(), pixel.getBlue(), n % 5 == 4 ? "\n" : " "); if (file->write(cache, size) != size) return false; } } } return true; } } // namespace video } // namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageWriterPNG.h0000644000000000000000000000153712574354552020203 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef _C_IMAGE_WRITER_PNG_H_INCLUDED__ #define _C_IMAGE_WRITER_PNG_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_PNG_WRITER_ #include "IImageWriter.h" namespace irr { namespace video { class CImageWriterPNG : public IImageWriter { public: //! constructor CImageWriterPNG(); //! return true if this writer can write a file with the given extension virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; }; } // namespace video } // namespace irr #endif // _C_IMAGE_WRITER_PNG_H_INCLUDED__ #endif irrlicht-1.8.3/source/Irrlicht/CImageWriterPNG.cpp0000644000000000000000000001367512574354552020544 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageWriterPNG.h" #ifdef _IRR_COMPILE_WITH_PNG_WRITER_ #include "CImageLoaderPNG.h" #include "CColorConverter.h" #include "IWriteFile.h" #include "irrString.h" #include "os.h" // for logging #ifdef _IRR_COMPILE_WITH_LIBPNG_ #ifndef _IRR_USE_NON_SYSTEM_LIB_PNG_ #include // use system lib png #else // _IRR_USE_NON_SYSTEM_LIB_PNG_ #include "libpng/png.h" // use irrlicht included lib png #endif // _IRR_USE_NON_SYSTEM_LIB_PNG_ #endif // _IRR_COMPILE_WITH_LIBPNG_ namespace irr { namespace video { IImageWriter* createImageWriterPNG() { return new CImageWriterPNG; } #ifdef _IRR_COMPILE_WITH_LIBPNG_ // PNG function for error handling static void png_cpexcept_error(png_structp png_ptr, png_const_charp msg) { os::Printer::log("PNG fatal error", msg, ELL_ERROR); longjmp(png_jmpbuf(png_ptr), 1); } // PNG function for warning handling static void png_cpexcept_warning(png_structp png_ptr, png_const_charp msg) { os::Printer::log("PNG warning", msg, ELL_WARNING); } // PNG function for file writing void PNGAPI user_write_data_fcn(png_structp png_ptr, png_bytep data, png_size_t length) { png_size_t check; io::IWriteFile* file=(io::IWriteFile*)png_get_io_ptr(png_ptr); check=(png_size_t) file->write((const void*)data,(u32)length); if (check != length) png_error(png_ptr, "Write Error"); } #endif // _IRR_COMPILE_WITH_LIBPNG_ CImageWriterPNG::CImageWriterPNG() { #ifdef _DEBUG setDebugName("CImageWriterPNG"); #endif } bool CImageWriterPNG::isAWriteableFileExtension(const io::path& filename) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ return core::hasFileExtension ( filename, "png" ); #else return false; #endif } bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ if (!file || !image) return false; // Allocate the png write struct png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warning); if (!png_ptr) { os::Printer::log("PNGWriter: Internal PNG create write struct failure\n", file->getFileName(), ELL_ERROR); return false; } // Allocate the png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { os::Printer::log("PNGWriter: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR); png_destroy_write_struct(&png_ptr, NULL); return false; } // for proper error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return false; } png_set_write_fn(png_ptr, file, user_write_data_fcn, NULL); // Set info switch(image->getColorFormat()) { case ECF_A8R8G8B8: case ECF_A1R5G5B5: png_set_IHDR(png_ptr, info_ptr, image->getDimension().Width, image->getDimension().Height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); break; default: png_set_IHDR(png_ptr, info_ptr, image->getDimension().Width, image->getDimension().Height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } s32 lineWidth = image->getDimension().Width; switch(image->getColorFormat()) { case ECF_R8G8B8: case ECF_R5G6B5: lineWidth*=3; break; case ECF_A8R8G8B8: case ECF_A1R5G5B5: lineWidth*=4; break; // TODO: Error handling in case of unsupported color format default: break; } u8* tmpImage = new u8[image->getDimension().Height*lineWidth]; if (!tmpImage) { os::Printer::log("PNGWriter: Internal PNG create image failure\n", file->getFileName(), ELL_ERROR); png_destroy_write_struct(&png_ptr, &info_ptr); return false; } u8* data = (u8*)image->lock(); switch(image->getColorFormat()) { case ECF_R8G8B8: CColorConverter::convert_R8G8B8toR8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage); break; case ECF_A8R8G8B8: CColorConverter::convert_A8R8G8B8toA8R8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage); break; case ECF_R5G6B5: CColorConverter::convert_R5G6B5toR8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage); break; case ECF_A1R5G5B5: CColorConverter::convert_A1R5G5B5toA8R8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage); break; #ifndef _DEBUG // TODO: Error handling in case of unsupported color format default: break; #endif } image->unlock(); // Create array of pointers to rows in image data //Used to point to image rows u8** RowPointers = new png_bytep[image->getDimension().Height]; if (!RowPointers) { os::Printer::log("PNGWriter: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR); png_destroy_write_struct(&png_ptr, &info_ptr); delete [] tmpImage; return false; } data=tmpImage; // Fill array of pointers to rows in image data for (u32 i=0; igetDimension().Height; ++i) { RowPointers[i]=data; data += lineWidth; } // for proper error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); delete [] RowPointers; delete [] tmpImage; return false; } png_set_rows(png_ptr, info_ptr, RowPointers); if (image->getColorFormat()==ECF_A8R8G8B8 || image->getColorFormat()==ECF_A1R5G5B5) png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL); else { png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); } delete [] RowPointers; delete [] tmpImage; png_destroy_write_struct(&png_ptr, &info_ptr); return true; #else return false; #endif } } // namespace video } // namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageWriterPCX.h0000644000000000000000000000153712574354552020211 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef _C_IMAGE_WRITER_PCX_H_INCLUDED__ #define _C_IMAGE_WRITER_PCX_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_PCX_WRITER_ #include "IImageWriter.h" namespace irr { namespace video { class CImageWriterPCX : public IImageWriter { public: //! constructor CImageWriterPCX(); //! return true if this writer can write a file with the given extension virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; }; } // namespace video } // namespace irr #endif #endif // _C_IMAGE_WRITER_PCX_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CImageWriterPCX.cpp0000644000000000000000000000643612574354552020547 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageWriterPCX.h" #ifdef _IRR_COMPILE_WITH_PCX_WRITER_ #include "CImageLoaderPCX.h" #include "IWriteFile.h" #include "os.h" // for logging #include "irrString.h" namespace irr { namespace video { IImageWriter* createImageWriterPCX() { return new CImageWriterPCX; } CImageWriterPCX::CImageWriterPCX() { #ifdef _DEBUG setDebugName("CImageWriterPCX"); #endif } bool CImageWriterPCX::isAWriteableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "pcx" ); } bool CImageWriterPCX::writeImage(io::IWriteFile *file, IImage *image,u32 param) const { if (!file || !image) return false; u8 d1; u16 d2; u32 i; d1 = 10; // Manufacturer file->write(&d1, 1); d1 = 5; // Version file->write(&d1, 1); d1 = 1; // Encoding file->write(&d1, 1); d1 = 8; // Bits per Pixel file->write(&d1, 1); d2 = 0; // pixel origin file->write(&d2, 2); file->write(&d2, 2); d2 = image->getDimension().Width-1; // width #ifdef __BIG_ENDIAN__ d2 = os::Byteswap::byteswap(d2); #endif file->write(&d2, 2); d2 = image->getDimension().Height-1; // height #ifdef __BIG_ENDIAN__ d2 = os::Byteswap::byteswap(d2); #endif file->write(&d2, 2); d2 = 300; // dpi #ifdef __BIG_ENDIAN__ d2 = os::Byteswap::byteswap(d2); #endif file->write(&d2, 2); file->write(&d2, 2); d2 = 0; // palette (not used) for (i=0; i<24; ++i) { file->write(&d2, 2); } d1 = 0; // reserved file->write(&d1, 1); d1 = 3; // planes file->write(&d1, 1); d2 = image->getDimension().Width; // pitch if (d2&0x0001) // must be even ++d2; #ifdef __BIG_ENDIAN__ d2 = os::Byteswap::byteswap(d2); #endif file->write(&d2, 2); d2 = 1; // color mode #ifdef __BIG_ENDIAN__ d2 = os::Byteswap::byteswap(d2); #endif file->write(&d2, 2); d2 = 800; // screen width #ifdef __BIG_ENDIAN__ d2 = os::Byteswap::byteswap(d2); #endif file->write(&d2, 2); d2 = 600; // screen height #ifdef __BIG_ENDIAN__ d2 = os::Byteswap::byteswap(d2); #endif file->write(&d2, 2); d2 = 0; // filler (not used) for (i=0; i<27; ++i) { file->write(&d2, 2); } u8 cnt, value; for (i=0; igetDimension().Height; ++i) { cnt = 0; value = 0; for (u32 j=0; j<3; ++j) // color planes { for (u32 k=0; kgetDimension().Width; ++k) { const SColor pix = image->getPixel(k,i); if ((cnt!=0) && (cnt<63) && (((j==0) && (value==pix.getRed())) || ((j==1) && (value==pix.getGreen())) || ((j==2) && (value==pix.getBlue())))) { ++cnt; } else { if (cnt!=0) { if ((cnt>1) || ((value&0xc0)==0xc0)) { cnt |= 0xc0; file->write(&cnt, 1); } file->write(&value, 1); } cnt=1; if (j==0) value=(u8)pix.getRed(); else if (j==1) value=(u8)pix.getGreen(); else if (j==2) value=(u8)pix.getBlue(); } } } if ((cnt>1) || ((value&0xc0)==0xc0)) { cnt |= 0xc0; file->write(&cnt, 1); } file->write(&value, 1); } return true; } } // namespace video } // namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageWriterJPG.h0000644000000000000000000000147312574354552020176 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef _C_IMAGE_WRITER_JPG_H_INCLUDED__ #define _C_IMAGE_WRITER_JPG_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_JPG_WRITER_ #include "IImageWriter.h" namespace irr { namespace video { class CImageWriterJPG : public IImageWriter { public: //! constructor CImageWriterJPG(); //! return true if this writer can write a file with the given extension virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; }; } } #endif // _C_IMAGE_WRITER_JPG_H_INCLUDED__ #endif irrlicht-1.8.3/source/Irrlicht/CImageWriterJPG.cpp0000644000000000000000000001214212574354552020524 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageWriterJPG.h" #ifdef _IRR_COMPILE_WITH_JPG_WRITER_ #include "CColorConverter.h" #include "IWriteFile.h" #include "CImage.h" #include "irrString.h" #ifdef _IRR_COMPILE_WITH_LIBJPEG_ #include // required for jpeglib.h extern "C" { #ifndef _IRR_USE_NON_SYSTEM_JPEG_LIB_ #include #include #else #include "jpeglib/jpeglib.h" #include "jpeglib/jerror.h" #endif } namespace irr { namespace video { // The writer uses a 4k buffer and flushes to disk each time it's filled #define OUTPUT_BUF_SIZE 4096 typedef struct { struct jpeg_destination_mgr pub;/* public fields */ io::IWriteFile* file; /* target file */ JOCTET buffer[OUTPUT_BUF_SIZE]; /* image buffer */ } mem_destination_mgr; typedef mem_destination_mgr * mem_dest_ptr; // init static void jpeg_init_destination(j_compress_ptr cinfo) { mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } // flush to disk and reset buffer static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo) { mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; // for now just exit upon file error if (dest->file->write(dest->buffer, OUTPUT_BUF_SIZE) != OUTPUT_BUF_SIZE) ERREXIT (cinfo, JERR_FILE_WRITE); dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE; } static void jpeg_term_destination(j_compress_ptr cinfo) { mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; const s32 datacount = (s32)(OUTPUT_BUF_SIZE - dest->pub.free_in_buffer); // for now just exit upon file error if (dest->file->write(dest->buffer, datacount) != datacount) ERREXIT (cinfo, JERR_FILE_WRITE); } // set up buffer data static void jpeg_file_dest(j_compress_ptr cinfo, io::IWriteFile* file) { if (cinfo->dest == NULL) { /* first time for this JPEG object? */ cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(mem_destination_mgr)); } mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; /* for casting */ /* Initialize method pointers */ dest->pub.init_destination = jpeg_init_destination; dest->pub.empty_output_buffer = jpeg_empty_output_buffer; dest->pub.term_destination = jpeg_term_destination; /* Initialize private member */ dest->file = file; } /* write_JPEG_memory: store JPEG compressed image into memory. */ static bool writeJPEGFile(io::IWriteFile* file, IImage* image, u32 quality) { void (*format)(const void*, s32, void*) = 0; switch( image->getColorFormat () ) { case ECF_R8G8B8: format = CColorConverter::convert_R8G8B8toR8G8B8; break; case ECF_A8R8G8B8: format = CColorConverter::convert_A8R8G8B8toR8G8B8; break; case ECF_A1R5G5B5: format = CColorConverter::convert_A1R5G5B5toB8G8R8; break; case ECF_R5G6B5: format = CColorConverter::convert_R5G6B5toR8G8B8; break; #ifndef _DEBUG default: break; #endif } // couldn't find a color converter if ( 0 == format ) return false; const core::dimension2du dim = image->getDimension(); struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_file_dest(&cinfo, file); cinfo.image_width = dim.Width; cinfo.image_height = dim.Height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); if ( 0 == quality ) quality = 75; jpeg_set_quality(&cinfo, quality, TRUE); jpeg_start_compress(&cinfo, TRUE); u8 * dest = new u8[dim.Width*3]; if (dest) { const u32 pitch = image->getPitch(); JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ row_pointer[0] = dest; u8* src = (u8*)image->lock(); while (cinfo.next_scanline < cinfo.image_height) { // convert next line format( src, dim.Width, dest ); src += pitch; jpeg_write_scanlines(&cinfo, row_pointer, 1); } image->unlock(); delete [] dest; /* Step 6: Finish compression */ jpeg_finish_compress(&cinfo); } /* Step 7: Destroy */ jpeg_destroy_compress(&cinfo); return (dest != 0); } } // namespace video } // namespace irr #endif // _IRR_COMPILE_WITH_LIBJPEG_ namespace irr { namespace video { IImageWriter* createImageWriterJPG() { return new CImageWriterJPG; } CImageWriterJPG::CImageWriterJPG() { #ifdef _DEBUG setDebugName("CImageWriterJPG"); #endif } bool CImageWriterJPG::isAWriteableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "jpg", "jpeg" ); } bool CImageWriterJPG::writeImage(io::IWriteFile *file, IImage *image, u32 quality) const { #ifndef _IRR_COMPILE_WITH_LIBJPEG_ return false; #else return writeJPEGFile(file, image, quality); #endif } } // namespace video } // namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageWriterBMP.h0000644000000000000000000000153712574354552020175 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef _C_IMAGE_WRITER_BMP_H_INCLUDED__ #define _C_IMAGE_WRITER_BMP_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_BMP_WRITER_ #include "IImageWriter.h" namespace irr { namespace video { class CImageWriterBMP : public IImageWriter { public: //! constructor CImageWriterBMP(); //! return true if this writer can write a file with the given extension virtual bool isAWriteableFileExtension(const io::path& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; }; } // namespace video } // namespace irr #endif #endif // _C_IMAGE_WRITER_BMP_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CImageWriterBMP.cpp0000644000000000000000000000750112574354552020525 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageWriterBMP.h" #ifdef _IRR_COMPILE_WITH_BMP_WRITER_ #include "CImageLoaderBMP.h" #include "IWriteFile.h" #include "CColorConverter.h" #include "irrString.h" namespace irr { namespace video { IImageWriter* createImageWriterBMP() { return new CImageWriterBMP; } CImageWriterBMP::CImageWriterBMP() { #ifdef _DEBUG setDebugName("CImageWriterBMP"); #endif } bool CImageWriterBMP::isAWriteableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "bmp" ); } bool CImageWriterBMP::writeImage(io::IWriteFile* file, IImage* image, u32 param) const { // we always write 24-bit color because nothing really reads 32-bit SBMPHeader imageHeader; imageHeader.Id = 0x4d42; imageHeader.Reserved = 0; imageHeader.BitmapDataOffset = sizeof(imageHeader); imageHeader.BitmapHeaderSize = 0x28; imageHeader.Width = image->getDimension().Width; imageHeader.Height = image->getDimension().Height; imageHeader.Planes = 1; imageHeader.BPP = 24; imageHeader.Compression = 0; imageHeader.PixelPerMeterX = 0; imageHeader.PixelPerMeterY = 0; imageHeader.Colors = 0; imageHeader.ImportantColors = 0; // data size is rounded up to next larger 4 bytes boundary imageHeader.BitmapDataSize = imageHeader.Width * imageHeader.BPP / 8; imageHeader.BitmapDataSize = (imageHeader.BitmapDataSize + 3) & ~3; imageHeader.BitmapDataSize *= imageHeader.Height; // file size is data size plus offset to data imageHeader.FileSize = imageHeader.BitmapDataOffset + imageHeader.BitmapDataSize; // bitmaps are stored upside down and padded so we always do this void (*CColorConverter_convertFORMATtoFORMAT)(const void*, s32, void*) = 0; switch(image->getColorFormat()) { case ECF_R8G8B8: CColorConverter_convertFORMATtoFORMAT = CColorConverter::convert_R8G8B8toR8G8B8; break; case ECF_A8R8G8B8: CColorConverter_convertFORMATtoFORMAT = CColorConverter::convert_A8R8G8B8toB8G8R8; break; case ECF_A1R5G5B5: CColorConverter_convertFORMATtoFORMAT = CColorConverter::convert_A1R5G5B5toR8G8B8; break; case ECF_R5G6B5: CColorConverter_convertFORMATtoFORMAT = CColorConverter::convert_R5G6B5toR8G8B8; break; #ifndef _DEBUG default: break; #endif } // couldn't find a color converter if (!CColorConverter_convertFORMATtoFORMAT) return false; // write the bitmap header if (file->write(&imageHeader, sizeof(imageHeader)) != sizeof(imageHeader)) return false; u8* scan_lines = (u8*)image->lock(); if (!scan_lines) return false; // size of one pixel in bytes u32 pixel_size = image->getBytesPerPixel(); // length of one row of the source image in bytes u32 row_stride = (pixel_size * imageHeader.Width); // length of one row in bytes, rounded up to nearest 4-byte boundary s32 row_size = ((3 * imageHeader.Width) + 3) & ~3; // allocate and clear memory for our scan line u8* row_pointer = new u8[row_size]; memset(row_pointer, 0, row_size); // convert the image to 24-bit BGR and flip it over s32 y; for (y = imageHeader.Height - 1; 0 <= y; --y) { if (image->getColorFormat()==ECF_R8G8B8) CColorConverter::convert24BitTo24Bit(&scan_lines[y * row_stride], row_pointer, imageHeader.Width, 1, 0, false, true); else // source, length [pixels], destination CColorConverter_convertFORMATtoFORMAT(&scan_lines[y * row_stride], imageHeader.Width, row_pointer); if (file->write(row_pointer, row_size) < row_size) break; } // clean up our scratch area delete [] row_pointer; // give back image handle image->unlock(); return y < 0; } } // namespace video } // namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderWAL.h0000644000000000000000000000460112574354552020127 0ustar rootroot// Copyright (C) 2004 Murphy McCauley // Copyright (C) 2007-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h /* Thanks to: Max McGuire for his Flipcode article about WAL textures Nikolaus Gebhardt for the Irrlicht 3D engine */ #ifndef __C_IMAGE_LOADER_WAL_H_INCLUDED__ #define __C_IMAGE_LOADER_WAL_H_INCLUDED__ #include "IrrCompileConfig.h" #include "IImageLoader.h" namespace irr { namespace video { #ifdef _IRR_COMPILE_WITH_LMP_LOADER_ // byte-align structures #include "irrpack.h" struct SLMPHeader { u32 width; // width u32 height; // height // variably sized } PACK_STRUCT; // Default alignment #include "irrunpack.h" //! An Irrlicht image loader for Quake1,2 engine lmp textures/palette class CImageLoaderLMP : public irr::video::IImageLoader { public: virtual bool isALoadableFileExtension(const io::path& filename) const; virtual bool isALoadableFileFormat(irr::io::IReadFile* file) const; virtual irr::video::IImage* loadImage(irr::io::IReadFile* file) const; }; #endif #ifdef _IRR_COMPILE_WITH_WAL_LOADER_ //! An Irrlicht image loader for quake2 wal engine textures class CImageLoaderWAL : public irr::video::IImageLoader { public: virtual bool isALoadableFileExtension(const io::path& filename) const; virtual bool isALoadableFileFormat(irr::io::IReadFile* file) const; virtual irr::video::IImage* loadImage(irr::io::IReadFile* file) const; }; //! An Irrlicht image loader for Halflife 1 engine textures class CImageLoaderWAL2 : public irr::video::IImageLoader { public: virtual bool isALoadableFileExtension(const io::path& filename) const; virtual bool isALoadableFileFormat(irr::io::IReadFile* file) const; virtual irr::video::IImage* loadImage(irr::io::IReadFile* file) const; }; // byte-align structures #include "irrpack.h" // Halfelife wad3 type 67 file struct miptex_halflife { c8 name[16]; u32 width, height; u32 mipmap[4]; // four mip maps stored } PACK_STRUCT; //quake2 texture struct miptex_quake2 { c8 name[32]; u32 width; u32 height; u32 mipmap[4]; // four mip maps stored c8 animname[32]; // next frame in animation chain s32 flags; s32 contents; s32 value; } PACK_STRUCT; // Default alignment #include "irrunpack.h" #endif } } #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderWAL.cpp0000644000000000000000000002511212574354552020462 0ustar rootroot// Copyright (C) 2004 Murphy McCauley // Copyright (C) 2007-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageLoaderWAL.h" #include "CColorConverter.h" #include "CImage.h" #include "os.h" #include "dimension2d.h" #include "IVideoDriver.h" #include "IFileSystem.h" #include "IReadFile.h" #include "irrString.h" namespace irr { namespace video { #ifdef _IRR_COMPILE_WITH_LMP_LOADER_ // Palette quake2 colormap.h, 768 byte, last is transparent static const u32 colormap_h[256] = { 0xFF000000,0xFF0F0F0F,0xFF1F1F1F,0xFF2F2F2F,0xFF3F3F3F,0xFF4B4B4B,0xFF5B5B5B,0xFF6B6B6B, 0xFF7B7B7B,0xFF8B8B8B,0xFF9B9B9B,0xFFABABAB,0xFFBBBBBB,0xFFCBCBCB,0xFFDBDBDB,0xFFEBEBEB, 0xFF0F0B07,0xFF170F0B,0xFF1F170B,0xFF271B0F,0xFF2F2313,0xFF372B17,0xFF3F2F17,0xFF4B371B, 0xFF533B1B,0xFF5B431F,0xFF634B1F,0xFF6B531F,0xFF73571F,0xFF7B5F23,0xFF836723,0xFF8F6F23, 0xFF0B0B0F,0xFF13131B,0xFF1B1B27,0xFF272733,0xFF2F2F3F,0xFF37374B,0xFF3F3F57,0xFF474767, 0xFF4F4F73,0xFF5B5B7F,0xFF63638B,0xFF6B6B97,0xFF7373A3,0xFF7B7BAF,0xFF8383BB,0xFF8B8BCB, 0xFF000000,0xFF070700,0xFF0B0B00,0xFF131300,0xFF1B1B00,0xFF232300,0xFF2B2B07,0xFF2F2F07, 0xFF373707,0xFF3F3F07,0xFF474707,0xFF4B4B0B,0xFF53530B,0xFF5B5B0B,0xFF63630B,0xFF6B6B0F, 0xFF070000,0xFF0F0000,0xFF170000,0xFF1F0000,0xFF270000,0xFF2F0000,0xFF370000,0xFF3F0000, 0xFF470000,0xFF4F0000,0xFF570000,0xFF5F0000,0xFF670000,0xFF6F0000,0xFF770000,0xFF7F0000, 0xFF131300,0xFF1B1B00,0xFF232300,0xFF2F2B00,0xFF372F00,0xFF433700,0xFF4B3B07,0xFF574307, 0xFF5F4707,0xFF6B4B0B,0xFF77530F,0xFF835713,0xFF8B5B13,0xFF975F1B,0xFFA3631F,0xFFAF6723, 0xFF231307,0xFF2F170B,0xFF3B1F0F,0xFF4B2313,0xFF572B17,0xFF632F1F,0xFF733723,0xFF7F3B2B, 0xFF8F4333,0xFF9F4F33,0xFFAF632F,0xFFBF772F,0xFFCF8F2B,0xFFDFAB27,0xFFEFCB1F,0xFFFFF31B, 0xFF0B0700,0xFF1B1300,0xFF2B230F,0xFF372B13,0xFF47331B,0xFF533723,0xFF633F2B,0xFF6F4733, 0xFF7F533F,0xFF8B5F47,0xFF9B6B53,0xFFA77B5F,0xFFB7876B,0xFFC3937B,0xFFD3A38B,0xFFE3B397, 0xFFAB8BA3,0xFF9F7F97,0xFF937387,0xFF8B677B,0xFF7F5B6F,0xFF775363,0xFF6B4B57,0xFF5F3F4B, 0xFF573743,0xFF4B2F37,0xFF43272F,0xFF371F23,0xFF2B171B,0xFF231313,0xFF170B0B,0xFF0F0707, 0xFFBB739F,0xFFAF6B8F,0xFFA35F83,0xFF975777,0xFF8B4F6B,0xFF7F4B5F,0xFF734353,0xFF6B3B4B, 0xFF5F333F,0xFF532B37,0xFF47232B,0xFF3B1F23,0xFF2F171B,0xFF231313,0xFF170B0B,0xFF0F0707, 0xFFDBC3BB,0xFFCBB3A7,0xFFBFA39B,0xFFAF978B,0xFFA3877B,0xFF977B6F,0xFF876F5F,0xFF7B6353, 0xFF6B5747,0xFF5F4B3B,0xFF533F33,0xFF433327,0xFF372B1F,0xFF271F17,0xFF1B130F,0xFF0F0B07, 0xFF6F837B,0xFF677B6F,0xFF5F7367,0xFF576B5F,0xFF4F6357,0xFF475B4F,0xFF3F5347,0xFF374B3F, 0xFF2F4337,0xFF2B3B2F,0xFF233327,0xFF1F2B1F,0xFF172317,0xFF0F1B13,0xFF0B130B,0xFF070B07, 0xFFFFF31B,0xFFEFDF17,0xFFDBCB13,0xFFCBB70F,0xFFBBA70F,0xFFAB970B,0xFF9B8307,0xFF8B7307, 0xFF7B6307,0xFF6B5300,0xFF5B4700,0xFF4B3700,0xFF3B2B00,0xFF2B1F00,0xFF1B0F00,0xFF0B0700, 0xFF0000FF,0xFF0B0BEF,0xFF1313DF,0xFF1B1BCF,0xFF2323BF,0xFF2B2BAF,0xFF2F2F9F,0xFF2F2F8F, 0xFF2F2F7F,0xFF2F2F6F,0xFF2F2F5F,0xFF2B2B4F,0xFF23233F,0xFF1B1B2F,0xFF13131F,0xFF0B0B0F, 0xFF2B0000,0xFF3B0000,0xFF4B0700,0xFF5F0700,0xFF6F0F00,0xFF7F1707,0xFF931F07,0xFFA3270B, 0xFFB7330F,0xFFC34B1B,0xFFCF632B,0xFFDB7F3B,0xFFE3974F,0xFFE7AB5F,0xFFEFBF77,0xFFF7D38B, 0xFFA77B3B,0xFFB79B37,0xFFC7C337,0xFFE7E357,0xFF7FBFFF,0xFFABE7FF,0xFFD7FFFF,0xFF670000, 0xFF8B0000,0xFFB30000,0xFFD70000,0xFFFF0000,0xFFFFF393,0xFFFFF7C7,0xFFFFFFFF,0x009F5B53 }; bool CImageLoaderLMP::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "lmp" ); } bool CImageLoaderLMP::isALoadableFileFormat(irr::io::IReadFile* file) const { return false; } /*! Quake1, Quake2, Hallife lmp texture */ IImage* CImageLoaderLMP::loadImage(irr::io::IReadFile* file) const { SLMPHeader header; file->seek(0); file->read(&header, sizeof(header)); // maybe palette file u32 rawtexsize = header.width * header.height; if ( rawtexsize + sizeof ( header ) != (u32)file->getSize() ) return 0; u8 *rawtex = new u8 [ rawtexsize ]; file->read(rawtex, rawtexsize); IImage* image = new CImage(ECF_A8R8G8B8, core::dimension2d(header.width, header.height)); CColorConverter::convert8BitTo32Bit(rawtex, (u8*)image->lock(), header.width, header.height, (u8*) colormap_h, 0, false); image->unlock(); delete [] rawtex; return image; } IImageLoader* createImageLoaderLMP() { return new irr::video::CImageLoaderLMP(); } #endif #ifdef _IRR_COMPILE_WITH_WAL_LOADER_ // Palette quake2 demo pics/colormap.pcx, last is transparent static const u32 colormap_pcx[256] = { 0xFF000000,0xFF0F0F0F,0xFF1F1F1F,0xFF2F2F2F,0xFF3F3F3F,0xFF4B4B4B,0xFF5B5B5B,0xFF6B6B6B, 0xFF7B7B7B,0xFF8B8B8B,0xFF9B9B9B,0xFFABABAB,0xFFBBBBBB,0xFFCBCBCB,0xFFDBDBDB,0xFFEBEBEB, 0xFF634B23,0xFF5B431F,0xFF533F1F,0xFF4F3B1B,0xFF47371B,0xFF3F2F17,0xFF3B2B17,0xFF332713, 0xFF2F2313,0xFF2B1F13,0xFF271B0F,0xFF23170F,0xFF1B130B,0xFF170F0B,0xFF130F07,0xFF0F0B07, 0xFF5F5F6F,0xFF5B5B67,0xFF5B535F,0xFF574F5B,0xFF534B53,0xFF4F474B,0xFF473F43,0xFF3F3B3B, 0xFF3B3737,0xFF332F2F,0xFF2F2B2B,0xFF272727,0xFF232323,0xFF1B1B1B,0xFF171717,0xFF131313, 0xFF8F7753,0xFF7B6343,0xFF735B3B,0xFF674F2F,0xFFCF974B,0xFFA77B3B,0xFF8B672F,0xFF6F5327, 0xFFEB9F27,0xFFCB8B23,0xFFAF771F,0xFF93631B,0xFF774F17,0xFF5B3B0F,0xFF3F270B,0xFF231707, 0xFFA73B2B,0xFF9F2F23,0xFF972B1B,0xFF8B2713,0xFF7F1F0F,0xFF73170B,0xFF671707,0xFF571300, 0xFF4B0F00,0xFF430F00,0xFF3B0F00,0xFF330B00,0xFF2B0B00,0xFF230B00,0xFF1B0700,0xFF130700, 0xFF7B5F4B,0xFF735743,0xFF6B533F,0xFF674F3B,0xFF5F4737,0xFF574333,0xFF533F2F,0xFF4B372B, 0xFF433327,0xFF3F2F23,0xFF37271B,0xFF2F2317,0xFF271B13,0xFF1F170F,0xFF170F0B,0xFF0F0B07, 0xFF6F3B17,0xFF5F3717,0xFF532F17,0xFF432B17,0xFF372313,0xFF271B0F,0xFF1B130B,0xFF0F0B07, 0xFFB35B4F,0xFFBF7B6F,0xFFCB9B93,0xFFD7BBB7,0xFFCBD7DF,0xFFB3C7D3,0xFF9FB7C3,0xFF87A7B7, 0xFF7397A7,0xFF5B879B,0xFF47778B,0xFF2F677F,0xFF17536F,0xFF134B67,0xFF0F435B,0xFF0B3F53, 0xFF07374B,0xFF072F3F,0xFF072733,0xFF001F2B,0xFF00171F,0xFF000F13,0xFF00070B,0xFF000000, 0xFF8B5757,0xFF834F4F,0xFF7B4747,0xFF734343,0xFF6B3B3B,0xFF633333,0xFF5B2F2F,0xFF572B2B, 0xFF4B2323,0xFF3F1F1F,0xFF331B1B,0xFF2B1313,0xFF1F0F0F,0xFF130B0B,0xFF0B0707,0xFF000000, 0xFF979F7B,0xFF8F9773,0xFF878B6B,0xFF7F8363,0xFF777B5F,0xFF737357,0xFF6B6B4F,0xFF636347, 0xFF5B5B43,0xFF4F4F3B,0xFF434333,0xFF37372B,0xFF2F2F23,0xFF23231B,0xFF171713,0xFF0F0F0B, 0xFF9F4B3F,0xFF934337,0xFF8B3B2F,0xFF7F3727,0xFF772F23,0xFF6B2B1B,0xFF632317,0xFF571F13, 0xFF4F1B0F,0xFF43170B,0xFF37130B,0xFF2B0F07,0xFF1F0B07,0xFF170700,0xFF0B0000,0xFF000000, 0xFF777BCF,0xFF6F73C3,0xFF676BB7,0xFF6363A7,0xFF5B5B9B,0xFF53578F,0xFF4B4F7F,0xFF474773, 0xFF3F3F67,0xFF373757,0xFF2F2F4B,0xFF27273F,0xFF231F2F,0xFF1B1723,0xFF130F17,0xFF0B0707, 0xFF9BAB7B,0xFF8F9F6F,0xFF879763,0xFF7B8B57,0xFF73834B,0xFF677743,0xFF5F6F3B,0xFF576733, 0xFF4B5B27,0xFF3F4F1B,0xFF374313,0xFF2F3B0B,0xFF232F07,0xFF1B2300,0xFF131700,0xFF0B0F00, 0xFF00FF00,0xFF23E70F,0xFF3FD31B,0xFF53BB27,0xFF5FA72F,0xFF5F8F33,0xFF5F7B33,0xFFFFFFFF, 0xFFFFFFD3,0xFFFFFFA7,0xFFFFFF7F,0xFFFFFF53,0xFFFFFF27,0xFFFFEB1F,0xFFFFD717,0xFFFFBF0F, 0xFFFFAB07,0xFFFF9300,0xFFEF7F00,0xFFE36B00,0xFFD35700,0xFFC74700,0xFFB73B00,0xFFAB2B00, 0xFF9B1F00,0xFF8F1700,0xFF7F0F00,0xFF730700,0xFF5F0000,0xFF470000,0xFF2F0000,0xFF1B0000, 0xFFEF0000,0xFF3737FF,0xFFFF0000,0xFF0000FF,0xFF2B2B23,0xFF1B1B17,0xFF13130F,0xFFEB977F, 0xFFC37353,0xFF9F5733,0xFF7B3F1B,0xFFEBD3C7,0xFFC7AB9B,0xFFA78B77,0xFF876B57,0x009F5B53 }; /*! Halflife */ bool CImageLoaderWAL2::isALoadableFileExtension(const io::path& filename) const { // embedded in Wad(WAD3 format). originally it has no extension return core::hasFileExtension ( filename, "wal2" ); } bool CImageLoaderWAL2::isALoadableFileFormat(irr::io::IReadFile* file) const { return false; } /* Halflite Texture WAD */ IImage* CImageLoaderWAL2::loadImage(irr::io::IReadFile* file) const { miptex_halflife header; file->seek(0); file->read(&header, sizeof(header)); #ifdef __BIG_ENDIAN__ header.width = os::Byteswap::byteswap(header.width); header.height = os::Byteswap::byteswap(header.height); #endif // palette //u32 paletteofs = header.mipmap[0] + ((rawtexsize * 85) >> 6) + 2; u32 *pal = new u32 [ 192 + 256 ]; u8 *s = (u8*) pal; file->seek ( file->getSize() - 768 - 2 ); file->read ( s, 768 ); u32 i; for ( i = 0; i < 256; ++i, s+= 3 ) { pal [ 192 + i ] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2]; } ECOLOR_FORMAT format = ECF_R8G8B8; // transparency in filename;-) funny. rgb:0x0000FF is colorkey if ( file->getFileName().findFirst ( '{' ) >= 0 ) { format = ECF_A8R8G8B8; pal [ 192 + 255 ] &= 0x00FFFFFF; } u32 rawtexsize = header.width * header.height; u8 *rawtex = new u8 [ rawtexsize ]; file->seek ( header.mipmap[0] ); file->read(rawtex, rawtexsize); IImage* image = new CImage(format, core::dimension2d(header.width, header.height)); switch ( format ) { case ECF_R8G8B8: CColorConverter::convert8BitTo24Bit(rawtex, (u8*)image->lock(), header.width, header.height, (u8*) pal + 768, 0, false); break; case ECF_A8R8G8B8: CColorConverter::convert8BitTo32Bit(rawtex, (u8*)image->lock(), header.width, header.height, (u8*) pal + 768, 0, false); break; } image->unlock(); delete [] rawtex; delete [] pal; return image; } bool CImageLoaderWAL::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "wal" ); } bool CImageLoaderWAL::isALoadableFileFormat(irr::io::IReadFile* file) const { return false; } /*! quake2 */ IImage* CImageLoaderWAL::loadImage(irr::io::IReadFile* file) const { miptex_quake2 header; file->seek(0); file->read(&header, sizeof(header)); #ifdef __BIG_ENDIAN__ header.width = os::Byteswap::byteswap(header.width); header.height = os::Byteswap::byteswap(header.height); #endif u32 rawtexsize = header.width * header.height; u8 *rawtex = new u8 [ rawtexsize ]; file->seek ( header.mipmap[0] ); file->read(rawtex, rawtexsize); IImage* image = new CImage(ECF_A8R8G8B8, core::dimension2d(header.width, header.height)); CColorConverter::convert8BitTo32Bit(rawtex, (u8*)image->lock(), header.width, header.height, (u8*) colormap_pcx, 0, false); image->unlock(); delete [] rawtex; return image; } IImageLoader* createImageLoaderWAL() { return new irr::video::CImageLoaderWAL(); } IImageLoader* createImageLoaderHalfLife() { return new irr::video::CImageLoaderWAL2(); } #endif } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CImageLoaderTGA.h0000644000000000000000000000355112574354552020122 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IMAGE_LOADER_TGA_H_INCLUDED__ #define __C_IMAGE_LOADER_TGA_H_INCLUDED__ #include "IrrCompileConfig.h" #include "IImageLoader.h" namespace irr { namespace video { #if defined(_IRR_COMPILE_WITH_TGA_LOADER_) || defined(_IRR_COMPILE_WITH_TGA_WRITER_) // byte-align structures #include "irrpack.h" // these structs are also used in the TGA writer struct STGAHeader{ u8 IdLength; u8 ColorMapType; u8 ImageType; u8 FirstEntryIndex[2]; u16 ColorMapLength; u8 ColorMapEntrySize; u8 XOrigin[2]; u8 YOrigin[2]; u16 ImageWidth; u16 ImageHeight; u8 PixelDepth; u8 ImageDescriptor; } PACK_STRUCT; struct STGAFooter { u32 ExtensionOffset; u32 DeveloperOffset; c8 Signature[18]; } PACK_STRUCT; // Default alignment #include "irrunpack.h" #endif // compiled with loader or reader #ifdef _IRR_COMPILE_WITH_TGA_LOADER_ /*! Surface Loader for targa images */ class CImageLoaderTGA : public IImageLoader { public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! creates a surface from the file virtual IImage* loadImage(io::IReadFile* file) const; private: //! loads a compressed tga. Was written and sent in by Jon Pry, thank you very much! u8* loadCompressedImage(io::IReadFile *file, const STGAHeader& header) const; }; #endif // compiled with loader } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderTGA.cpp0000644000000000000000000001452512574354552020460 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageLoaderTGA.h" #ifdef _IRR_COMPILE_WITH_TGA_LOADER_ #include "IReadFile.h" #include "os.h" #include "CColorConverter.h" #include "CImage.h" #include "irrString.h" namespace irr { namespace video { //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") bool CImageLoaderTGA::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "tga" ); } //! loads a compressed tga. u8 *CImageLoaderTGA::loadCompressedImage(io::IReadFile *file, const STGAHeader& header) const { // This was written and sent in by Jon Pry, thank you very much! // I only changed the formatting a little bit. s32 bytesPerPixel = header.PixelDepth/8; s32 imageSize = header.ImageHeight * header.ImageWidth * bytesPerPixel; u8* data = new u8[imageSize]; s32 currentByte = 0; while(currentByte < imageSize) { u8 chunkheader = 0; file->read(&chunkheader, sizeof(u8)); // Read The Chunk's Header if(chunkheader < 128) // If The Chunk Is A 'RAW' Chunk { chunkheader++; // Add 1 To The Value To Get Total Number Of Raw Pixels file->read(&data[currentByte], bytesPerPixel * chunkheader); currentByte += bytesPerPixel * chunkheader; } else { // thnx to neojzs for some fixes with this code // If It's An RLE Header chunkheader -= 127; // Subtract 127 To Get Rid Of The ID Bit s32 dataOffset = currentByte; file->read(&data[dataOffset], bytesPerPixel); currentByte += bytesPerPixel; for(s32 counter = 1; counter < chunkheader; counter++) { for(s32 elementCounter=0; elementCounter < bytesPerPixel; elementCounter++) data[currentByte + elementCounter] = data[dataOffset + elementCounter]; currentByte += bytesPerPixel; } } } return data; } //! returns true if the file maybe is able to be loaded by this class bool CImageLoaderTGA::isALoadableFileFormat(io::IReadFile* file) const { if (!file) return false; STGAFooter footer; memset(&footer, 0, sizeof(STGAFooter)); file->seek(file->getSize()-sizeof(STGAFooter)); file->read(&footer, sizeof(STGAFooter)); return (!strcmp(footer.Signature,"TRUEVISION-XFILE.")); // very old tgas are refused. } //! creates a surface from the file IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const { STGAHeader header; u32 *palette = 0; file->read(&header, sizeof(STGAHeader)); #ifdef __BIG_ENDIAN__ header.ColorMapLength = os::Byteswap::byteswap(header.ColorMapLength); header.ImageWidth = os::Byteswap::byteswap(header.ImageWidth); header.ImageHeight = os::Byteswap::byteswap(header.ImageHeight); #endif // skip image identification field if (header.IdLength) file->seek(header.IdLength, true); if (header.ColorMapType) { // create 32 bit palette palette = new u32[ header.ColorMapLength]; // read color map u8 * colorMap = new u8[header.ColorMapEntrySize/8 * header.ColorMapLength]; file->read(colorMap,header.ColorMapEntrySize/8 * header.ColorMapLength); // convert to 32-bit palette switch ( header.ColorMapEntrySize ) { case 16: CColorConverter::convert_A1R5G5B5toA8R8G8B8(colorMap, header.ColorMapLength, palette); break; case 24: CColorConverter::convert_B8G8R8toA8R8G8B8(colorMap, header.ColorMapLength, palette); break; case 32: CColorConverter::convert_B8G8R8A8toA8R8G8B8(colorMap, header.ColorMapLength, palette); break; } delete [] colorMap; } // read image u8* data = 0; if ( header.ImageType == 1 || // Uncompressed, color-mapped images. header.ImageType == 2 || // Uncompressed, RGB images header.ImageType == 3 // Uncompressed, black and white images ) { const s32 imageSize = header.ImageHeight * header.ImageWidth * header.PixelDepth/8; data = new u8[imageSize]; file->read(data, imageSize); } else if(header.ImageType == 10) { // Runlength encoded RGB images data = loadCompressedImage(file, header); } else { os::Printer::log("Unsupported TGA file type", file->getFileName(), ELL_ERROR); delete [] palette; return 0; } IImage* image = 0; switch(header.PixelDepth) { case 8: { if (header.ImageType==3) // grey image { image = new CImage(ECF_R8G8B8, core::dimension2d(header.ImageWidth, header.ImageHeight)); if (image) CColorConverter::convert8BitTo24Bit((u8*)data, (u8*)image->lock(), header.ImageWidth,header.ImageHeight, 0, 0, (header.ImageDescriptor&0x20)==0); } else { image = new CImage(ECF_A1R5G5B5, core::dimension2d(header.ImageWidth, header.ImageHeight)); if (image) CColorConverter::convert8BitTo16Bit((u8*)data, (s16*)image->lock(), header.ImageWidth,header.ImageHeight, (s32*) palette, 0, (header.ImageDescriptor&0x20)==0); } } break; case 16: image = new CImage(ECF_A1R5G5B5, core::dimension2d(header.ImageWidth, header.ImageHeight)); if (image) CColorConverter::convert16BitTo16Bit((s16*)data, (s16*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0); break; case 24: image = new CImage(ECF_R8G8B8, core::dimension2d(header.ImageWidth, header.ImageHeight)); if (image) CColorConverter::convert24BitTo24Bit( (u8*)data, (u8*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0, true); break; case 32: image = new CImage(ECF_A8R8G8B8, core::dimension2d(header.ImageWidth, header.ImageHeight)); if (image) CColorConverter::convert32BitTo32Bit((s32*)data, (s32*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0); break; default: os::Printer::log("Unsupported TGA format", file->getFileName(), ELL_ERROR); break; } if (image) image->unlock(); delete [] data; delete [] palette; return image; } //! creates a loader which is able to load tgas IImageLoader* createImageLoaderTGA() { return new CImageLoaderTGA(); } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderRGB.h0000644000000000000000000001011012574354552020106 0ustar rootroot// Copyright (C) 2009-2012 Gary Conway // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h /* Author: Gary Conway (Viper) - co-author of the ZIP file format, Feb 1989, see the story at http://www.idcnet.us/ziphistory.html Website: http://idcnet.us Email: codeslinger@vipergc.com Created: March 1, 2009 Version: 1.0 Updated: */ #ifndef __C_IMAGE_LOADER_RGB_H_INCLUDED__ #define __C_IMAGE_LOADER_RGB_H_INCLUDED__ // define _IRR_RGB_FILE_INVERTED_IMAGE_ to preserve the inverted format of the RGB file // commenting this out will invert the inverted image,resulting in the image being upright #define _IRR_RGB_FILE_INVERTED_IMAGE_ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_RGB_LOADER_ #include "IImageLoader.h" namespace irr { namespace video { // byte-align structures #include "irrpack.h" // the RGB image file header structure struct SRGBHeader { u16 Magic; // IRIS image file magic number u8 Storage; // Storage format u8 BPC; // Number of bytes per pixel channel u16 Dimension; // Number of dimensions u16 Xsize; // X size in pixels u16 Ysize; // Y size in pixels u16 Zsize; // Z size in pixels u32 Pixmin; // Minimum pixel value u32 Pixmax; // Maximum pixel value u32 Dummy1; // ignored char Imagename[80];// Image name u32 Colormap; // Colormap ID // char Dummy2[404];// Ignored } PACK_STRUCT; // Default alignment #include "irrunpack.h" // this structure holds context specific data about the file being loaded. typedef struct _RGBdata { u8 *tmp, *tmpR, *tmpG, *tmpB, *tmpA; u32 *StartTable; // compressed data table, holds file offsets u32 *LengthTable; // length for the above data, hold lengths for above u32 TableLen; // len of above tables SRGBHeader Header; // define the .rgb file header u32 ImageSize; u8 *rgbData; public: _RGBdata() : tmp(0), tmpR(0), tmpG(0), tmpB(0), tmpA(0), StartTable(0), LengthTable(0), TableLen(0), ImageSize(0), rgbData(0) { } ~_RGBdata() { delete [] tmp; delete [] tmpR; delete [] tmpG; delete [] tmpB; delete [] tmpA; delete [] StartTable; delete [] LengthTable; delete [] rgbData; } bool allocateTemps() { tmp = tmpR = tmpG = tmpB = tmpA = 0; tmp = new u8 [Header.Xsize * 256 * Header.BPC]; if (!tmp) return false; if (Header.Zsize >= 1) { tmpR = new u8[Header.Xsize * Header.BPC]; if (!tmpR) return false; } if (Header.Zsize >= 2) { tmpG = new u8[Header.Xsize * Header.BPC]; if (!tmpG) return false; } if (Header.Zsize >= 3) { tmpB = new u8[Header.Xsize * Header.BPC]; if (!tmpB) return false; } if (Header.Zsize >= 4) { tmpA = new u8[Header.Xsize * Header.BPC]; if (!tmpA) return false; } return true; } } rgbStruct; //! Surface Loader for Silicon Graphics RGB files class CImageLoaderRGB : public IImageLoader { public: //! constructor CImageLoaderRGB(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! creates a surface from the file virtual IImage* loadImage(io::IReadFile* file) const; private: bool readHeader(io::IReadFile* file, rgbStruct& rgb) const; void readRGBrow(u8 *buf, int y, int z, io::IReadFile* file, rgbStruct& rgb) const; void processFile(io::IReadFile *file, rgbStruct& rgb) const; bool checkFormat(io::IReadFile *file, rgbStruct& rgb) const; bool readOffsetTables(io::IReadFile* file, rgbStruct& rgb) const; void converttoARGB(u32* in, const u32 size) const; }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_RGB_LOADER_ #endif // __C_IMAGE_LOADER_RGB_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CImageLoaderRGB.cpp0000644000000000000000000005415712574354552020464 0ustar rootroot//! Copyright (C) 2009-2012 Gary Conway //! This file is part of the "Irrlicht Engine". //! For conditions of distribution and use, see copyright notice in irrlicht.h /* Author: Gary Conway (Viper) - co-author of the ZIP file format, Feb 1989, see the story at http://www.idcnet.us/ziphistory.html Website: http://idcnet.us Email: codeslinger@vipergc.com Created: March 1, 2009 Version: 1.0 Updated: This module will load SGI .rgb files (along with the other extensions). The module complies with version 1.0 of the SGI Image File Format by Paul Haeberli of Silicon Graphics Computer Systems The module handles BW, RGB and RGBA images. RGB images are stored with either 8 bits per COLOR VALUE, one each for red,green,blue (24bpp) or 16 bits per COLOR VALUE, again one each for red,green,blue (48 bpp), not including the alpha channel OPTIONS NOT SUPPORTED 1. 16 bit COLOR VALUES (48bpp modes) 2. COLORMAP = DITHERED mode For non- run length encoded files, this is the structure The Header The Image Data If the image is run length encoded, this is the structure: The Header The Offset Tables The Image Data The Header consists of the following: Size | Type | Name | Description 2 bytes | short | MAGIC | IRIS image file magic number 1 byte | char | STORAGE | Storage format 1 byte | char | BPC | Number of bytes per pixel channel 2 bytes | ushort | DIMENSION | Number of dimensions 2 bytes | ushort | XSIZE | X size in pixels 2 bytes | ushort | YSIZE | Y size in pixels 2 bytes | ushort | ZSIZE | Number of channels 4 bytes | long | PIXMIN | Minimum pixel value 4 bytes | long | PIXMAX | Maximum pixel value 4 bytes | char | DUMMY | Ignored 80 bytes | char | IMAGENAME | Image name 4 bytes | long | COLORMAP | Colormap ID 404 bytes | char | DUMMY | Ignored Here is a description of each field in the image file Header: MAGIC - This is the decimal value 474 saved as a short. This identifies the file as an SGI image file. STORAGE - specifies whether the image is stored using run length encoding (RLE) or not (VERBATIM). If RLE is used, the value of this byte will be 1. Otherwise the value of this byte will be 0. The only allowed values for this field are 0 or 1. BPC - describes the precision that is used to store each channel of an image. This is the number of bytes per pixel component. The majority of SGI image files use 1 byte per pixel component, giving 256 levels. Some SGI image files use 2 bytes per component. The only allowed values for this field are 1 or 2. DIMENSION - described the number of dimensions in the data stored in the image file. The only allowed values are 1, 2, or 3. If this value is 1, the image file consists of only 1 channel and only 1 scanline (row). The length of this scanline is given by the value of XSIZE below. If this value is 2, the file consists of a single channel with a number of scanlines. The width and height of the image are given by the values of XSIZE and YSIZE below. If this value is 3, the file consists of a number of channels. The width and height of the image are given by the values of XSIZE and YSIZE below. The number of channels is given by the value of ZSIZE below. XSIZE - The width of the image in pixels YSIZE - The height of the image in pixels ZSIZE - The number of channels in the image. B/W (greyscale) images are stored as 2 dimensional images with a ZSIZE of 1. RGB color images are stored as 3 dimensional images with a ZSIZE of 3. An RGB image with an ALPHA channel is stored as a 3 dimensional image with a ZSIZE of 4. There are no inherent limitations in the SGI image file format that would preclude the creation of image files with more than 4 channels. PINMIN - The minimum pixel value in the image. The value of 0 may be used if no pixel has a value that is smaller than 0. PINMAX - The maximum pixel value in the image. The value of 255 may be used if no pixel has a value that is greater than 255. This is the value that is considered to be full brightness in the image. DUMMY - This 4 bytes of data should be set to 0. IMAGENAME - An null terminated ascii string of up to 79 characters terminated by a null may be included here. This is not commonly used. COLORMAP - This controls how the pixel values in the file should be interpreted. It can have one of these four values: 0: NORMAL - The data in the channels represent B/W values for images with 1 channel, RGB values for images with 3 channels, and RGBA values for images with 4 channels. Almost all the SGI image files are of this type. 1: DITHERED - The image will have only 1 channel of data. For each pixel, RGB data is packed into one 8 bit value. 3 bits are used for red and green, while blue uses 2 bits. Red data is found in bits[2..0], green data in bits[5..3], and blue data in bits[7..6]. This format is obsolete. 2: SCREEN - The image will have only 1 channel of data. This format was used to store color-indexed pixels. To convert the pixel values into RGB values a colormap must be used. The appropriate color map varies from image to image. This format is obsolete. 3: COLORMAP - The image is used to store a color map from an SGI machine. In this case the image is not displayable in the conventional sense. DUMMY - This 404 bytes of data should be set to 0. This makes the Header exactly 512 bytes. */ #include "CImageLoaderRGB.h" #ifdef _IRR_COMPILE_WITH_RGB_LOADER_ #include "IReadFile.h" #include "SColor.h" #include "CColorConverter.h" #include "CImage.h" #include "os.h" #include "irrString.h" namespace irr { namespace video { //! constructor CImageLoaderRGB::CImageLoaderRGB() { #ifdef _DEBUG setDebugName("CImageLoaderRGB"); #endif } //! returns true if the file maybe is able to be loaded by this class //! based on the file extensions listed here bool CImageLoaderRGB::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension( filename, "rgb", "rgba", "sgi" ) || core::hasFileExtension( filename, "int", "inta", "bw" ); } //! returns true if the file maybe is able to be loaded by this class bool CImageLoaderRGB::isALoadableFileFormat(io::IReadFile* file) const { rgbStruct rgb; return checkFormat(file, rgb); } /** The main entry point, read and format the image file. \return Pointer to the image data on success null pointer on fail */ IImage* CImageLoaderRGB::loadImage(io::IReadFile* file) const { IImage* image = 0; s32* paletteData = 0; rgbStruct rgb; // construct our structure for holding data // read Header information if (checkFormat(file, rgb)) { // 16 bits per COLOR VALUE, not supported, this is 48bpp mode if (rgb.Header.BPC != 1) { os::Printer::log("Only one byte per pixel RGB files are supported", file->getFileName(), ELL_ERROR); } else if (rgb.Header.Colormap != 0) { os::Printer::log("Dithered, Screen and Colormap RGB files are not supported", file->getFileName(), ELL_ERROR); } else if (rgb.Header.Storage == 1 && !readOffsetTables(file, rgb)) { os::Printer::log("Failed to read RLE table in RGB file", file->getFileName(), ELL_ERROR); } else if (!rgb.allocateTemps()) { os::Printer::log("Out of memory in RGB file loader", file->getFileName(), ELL_ERROR); } else { // read and process the file to rgbData processFile(file, rgb); /* ZSIZE Description 1 BW (grayscale) image 3 RGB image 4 RGBa image with one alpha channel When the Alpha channel is present, I am not sure with RGB files if it's a precomputed RGB color or it needs to be completely calculated. My guess would be that it's not precomputed for two reasons. 1. the loss of precision when calculating the fraction, then storing the result as an int 2. the loss of the original color data when the image might be composited with another. Yes the original color data could be computed, however, not without another loss in precision Also, I don't know where to find the background color Pixmin and Pixmax are apparently the min and max alpha blend values (0-100%) Complete Alpha blending computation The actual resulting merged color is computed this way: (image color ◊ alpha) + (background color ◊ (100% - alpha)). Using precomputed blending (image color) + (background color ◊ (100% - alpha)). Alternatively, the RGB files could use another blending technique entirely */ switch (rgb.Header.Zsize) { case 1: // BW (grayscale) image paletteData = new s32[256]; for (int n=0; n<256; n++) paletteData[n] = n; image = new CImage(ECF_A1R5G5B5, core::dimension2d(rgb.Header.Xsize, rgb.Header.Ysize)); if (image) CColorConverter::convert8BitTo16Bit(rgb.rgbData, (s16*)image->lock(), rgb.Header.Xsize, rgb.Header.Ysize, paletteData, 0, true); break; case 3: // RGB image // one byte per COLOR VALUE, eg, 24bpp image = new CImage(ECF_R8G8B8, core::dimension2d(rgb.Header.Xsize, rgb.Header.Ysize)); if (image) CColorConverter::convert24BitTo24Bit(rgb.rgbData, (u8*)image->lock(), rgb.Header.Xsize, rgb.Header.Ysize, 0, true, false); break; case 4: // RGBa image with one alpha channel (32bpp) // image is stored in rgbData as RGBA converttoARGB(reinterpret_cast(rgb.rgbData), rgb.Header.Ysize * rgb.Header.Xsize); image = new CImage(ECF_A8R8G8B8, core::dimension2d(rgb.Header.Xsize, rgb.Header.Ysize)); if (image) CColorConverter::convert32BitTo32Bit((s32*)rgb.rgbData, (s32*)image->lock(), rgb.Header.Xsize, rgb.Header.Ysize, 0, true); break; default: // Format unknown os::Printer::log("Unsupported pixel format in RGB file", file->getFileName(), ELL_ERROR); } if (image) image->unlock(); } } // and tidy up allocated memory delete [] paletteData; return image; } // returns true on success bool CImageLoaderRGB::readHeader(io::IReadFile* file, rgbStruct& rgb) const { if ( file->read(&rgb.Header, sizeof(rgb.Header)) < s32(sizeof(rgb.Header)) ) return false; // test for INTEL or BIG ENDIAN processor // if INTEL, then swap the byte order on 16 bit INT's to make them BIG ENDIAN // because that is the native format for the .rgb file #ifndef __BIG_ENDIAN__ rgb.Header.Magic = os::Byteswap::byteswap(rgb.Header.Magic); rgb.Header.Storage = os::Byteswap::byteswap(rgb.Header.Storage); rgb.Header.Dimension = os::Byteswap::byteswap(rgb.Header.Dimension); rgb.Header.Xsize = os::Byteswap::byteswap(rgb.Header.Xsize); rgb.Header.Ysize = os::Byteswap::byteswap(rgb.Header.Ysize); rgb.Header.Zsize = os::Byteswap::byteswap(rgb.Header.Zsize); rgb.Header.Pixmin = os::Byteswap::byteswap(rgb.Header.Pixmin); rgb.Header.Pixmax = os::Byteswap::byteswap(rgb.Header.Pixmax); rgb.Header.Colormap = os::Byteswap::byteswap(rgb.Header.Colormap); #endif // calculate the size of the buffer needed: XSIZE * YSIZE * ZSIZE * BPC rgb.ImageSize = (rgb.Header.Xsize)*(rgb.Header.Ysize)*(rgb.Header.Zsize)*(rgb.Header.BPC); return true; } bool CImageLoaderRGB::checkFormat(io::IReadFile* file, rgbStruct& rgb) const { if (!readHeader(file, rgb)) return false; return (rgb.Header.Magic == 0x1DA); } /* If the image is stored using run length encoding, offset tables follow the Header that describe what the file offsets are to the RLE for each scanline. This information only applies if the value for STORAGE above is 1. Size | Type | Name | Description tablen longs | long | STARTTAB | Start table tablen longs | long | LENGTHTAB | Length table One entry in each table is needed for each scanline of RLE data. The total number of scanlines in the image (tablen) is determined by the product of the YSIZE and ZSIZE. There are two tables of longs that are written. Each consists of tablen longs of data. The first table has the file offsets to the RLE data for each scanline in the image. In a file with more than 1 channel (ZSIZE > 1) this table first has all the offsets for the scanlines in the first channel, followed be offsets for the scanlines in the second channel, etc. The second table has the RLE data length for each scanline in the image. In a file with more than 1 channel (ZSIZE > 1) this table first has all the RLE data lengths for the scanlines in the first channel, followed be RLE data lengths for the scanlines in the second channel, etc. To find the the file offset, and the number of bytes in the RLE data for a particular scanline, these two arrays may be read in and indexed as follows: To read in the tables: unsigned long *starttab, *lengthtab; tablen = YSIZE*ZSIZE*sizeof(long); starttab = (unsigned long *)mymalloc(tablen); lengthtab = (unsigned long *)mymalloc(tablen); fseek(rgb->inf,512,SEEK_SET); readlongtab(rgb->inf,starttab); readlongtab(rgb->inf,lengthtab); To find the file offset and RLE data length for a scanline: rowno is an integer in the range 0 to YSIZE-1 channo is an integer in the range 0 to ZSIZE-1 rleoffset = starttab[rowno+channo*YSIZE] rlelength = lengthtab[rowno+channo*YSIZE] It is possible for two identical rows (scanlines) to share compressed data. A completely white image could be written as a single compressed row and having all table entries point to that row. Another little hack that should work is if you are writing out a RGB RLE file, and a particular scanline is achromatic (greyscale), you could just make the r, g and b rows point to the same data!! RETURNS: on success true, else returns false */ bool CImageLoaderRGB::readOffsetTables(io::IReadFile* file, rgbStruct& rgb) const { rgb.TableLen = rgb.Header.Ysize * rgb.Header.Zsize ; // calc size of tables // return error if unable to allocate tables rgb.StartTable = new u32[rgb.TableLen]; if (!rgb.StartTable) return false; rgb.LengthTable = new u32[rgb.TableLen]; if (!rgb.LengthTable) return false; file->seek(512); file->read(rgb.StartTable, rgb.TableLen* sizeof(u32)); file->read(rgb.LengthTable, rgb.TableLen* sizeof(u32)); // if we are on an INTEL platform, swap the bytes #ifndef __BIG_ENDIAN__ const u32 length = rgb.TableLen; for (u32 i=0; i=0; --i) #endif { // check the number of channels and read a row of data if (rgb.Header.Zsize >= 1) readRGBrow( rgb.tmpR, i, 0, file, rgb); if (rgb.Header.Zsize >= 2) readRGBrow( rgb.tmpG, i, 1, file, rgb); if (rgb.Header.Zsize >= 3) readRGBrow( rgb.tmpB, i, 2, file, rgb); if (rgb.Header.Zsize >= 4) readRGBrow( rgb.tmpA, i, 3, file, rgb); // cycle thru all values for this row for (u16 j = 0; j < rgb.Header.Xsize; ++j) { if(rgb.Header.BPC == 1) { // ONE byte per color if (rgb.Header.Zsize >= 1) *ptr++ = rgb.tmpR[j]; if (rgb.Header.Zsize >= 2) *ptr++ = rgb.tmpG[j]; if (rgb.Header.Zsize >= 3) *ptr++ = rgb.tmpB[j]; if (rgb.Header.Zsize >= 4) *ptr++ = rgb.tmpA[j]; } else { // TWO bytes per color if( rgb.Header.Zsize >= 1 ) { // two bytes of color data tempShort = (u16 *) (ptr); *tempShort = *( (u16 *) (rgb.tmpR) + j); tempShort++; ptr = ( u8 *)(tempShort); } if( rgb.Header.Zsize >= 2 ) { tempShort = ( u16 *) (ptr); *tempShort = *( ( u16 *) (rgb.tmpG) + j); tempShort++; ptr = ( u8 *) (tempShort); } if( rgb.Header.Zsize >= 3 ) { tempShort = ( u16 *) (ptr); *tempShort = *( ( u16 *) (rgb.tmpB) + j); tempShort++; ptr = ( u8 *)(tempShort); } if( rgb.Header.Zsize >= 4 ) { tempShort = ( u16 *) (ptr); *tempShort = *( ( u16 *) (rgb.tmpA) + j); tempShort++; ptr = ( u8 *)(tempShort); } } // end if(rgb.Header.BPC == 1) } // end for } // end for } /* This information only applies if the value for STORAGE is 1. If the image is stored using run length encoding, the image data follows the offset/length tables. The RLE data is not in any particular order. The offset tables are used to locate the rle data for any scanline. The RLE data must be read in from the file and expanded into pixel data in the following manner: If BPC is 1, then there is one byte per pixel. In this case the RLE data should be read into an array of chars. To expand data, the low order seven bits of the first byte: bits[6..0] are used to form a count. If the high order bit of the first byte is 1: bit[7], then the count is used to specify how many bytes to copy from the RLE data buffer to the destination. Otherwise, if the high order bit of the first byte is 0: bit[7], then the count is used to specify how many times to repeat the value of the following byte, in the destination. This process continues until a count of 0 is found. This should decompress exactly XSIZE pixels. One entry in each table is needed for each scanline of RLE data. The total number of scanlines in the image (tablen) is determined by the product of the YSIZE and ZSIZE. There are two tables of longs that are written. Each consists of tablen longs of data. The first table has the file offsets to the RLE data for each scanline in the image. In a file with more than 1 channel (ZSIZE > 1) this table first has all the offsets for the scanlines in the first channel, followed be offsets for the scanlines in the second channel, etc. The second table has the RLE data length for each scanline in the image. In a file with more than 1 channel (ZSIZE > 1) this table first has all the RLE data lengths for the scanlines in the first channel, followed be RLE data lengths for the scanlines in the second channel, etc. Return a row of data, expanding RLE compression if necessary */ void CImageLoaderRGB::readRGBrow(u8 *buf, int y, int z, io::IReadFile* file, rgbStruct& rgb) const { if (rgb.Header.Storage != 1) { // stored VERBATIM file->seek(512+(y*rgb.Header.Xsize * rgb.Header.BPC)+(z* rgb.Header.Xsize * rgb.Header.Ysize * rgb.Header.BPC)); file->read(buf, rgb.Header.Xsize * rgb.Header.BPC); #ifndef __BIG_ENDIAN__ if (rgb.Header.BPC != 1) { u16* tmpbuf = reinterpret_cast(buf); for (u16 i=0; iseek((long) rgb.StartTable[y+z * rgb.Header.Ysize]); file->read(rgb.tmp, rgb.LengthTable[y+z * rgb.Header.Ysize]); // rgb.tmp has the data u16 pixel; u16 *tempShort; u8* iPtr = rgb.tmp; u8* oPtr = buf; while (true) { // if BPC = 1, then one byte per pixel if (rgb.Header.BPC == 1) { pixel = *iPtr++; } else { // BPC = 2, so two bytes per pixel tempShort = (u16 *) iPtr; pixel = *tempShort; tempShort++; iPtr = (u8 *) tempShort; } #ifndef __BIG_ENDIAN__ if (rgb.Header.BPC != 1) pixel = os::Byteswap::byteswap(pixel); #endif s32 count = (s32)(pixel & 0x7F); // limit the count value to the remaining row size if (oPtr + count*rgb.Header.BPC > buf + rgb.Header.Xsize * rgb.Header.BPC) { count = ( (buf + rgb.Header.Xsize * rgb.Header.BPC) - oPtr ) / rgb.Header.BPC; } if (count<=0) break; else if (pixel & 0x80) { // repeat the byte pointed to by iPtr, count times while (count--) { if(rgb.Header.BPC == 1) { *oPtr++ = *iPtr++; } else { // write pixel from iPtr to oPtr, move both two bytes ahead tempShort = (u16 *) (iPtr); pixel = *tempShort; tempShort++; iPtr = (u8 *) (tempShort); #ifndef __BIG_ENDIAN__ pixel = os::Byteswap::byteswap(pixel); #endif tempShort = (u16 *) (oPtr); *tempShort = pixel; tempShort++; oPtr = (u8 *) (tempShort); } } } else { if (rgb.Header.BPC == 1) { pixel = *iPtr++; } else { tempShort = (u16 *) (iPtr); pixel = *tempShort; tempShort++; iPtr = (u8 *) (tempShort); } #ifndef __BIG_ENDIAN__ if (rgb.Header.BPC != 1) pixel = os::Byteswap::byteswap(pixel); #endif while (count--) { if(rgb.Header.BPC == 1) { *oPtr++ = (u8) pixel; } else { tempShort = (u16 *) (oPtr); *tempShort = pixel; tempShort++; oPtr = (u8 *) (tempShort); } } } // else if (pixel & 0x80) } // while (true) } // we have 1 byte per COLOR VALUE, eg 24bpp and 1 alpha channel // color values are stored as RGBA, convert to ARGB // todo: replace with CColorConverter method void CImageLoaderRGB::converttoARGB(u32* in, const u32 size) const { for (u32 x=0; x < size; ++x) { *in=(*in>>8)|(*in<<24); ++in; } } //! creates a loader which is able to load SGI RGB images IImageLoader* createImageLoaderRGB() { return new CImageLoaderRGB; } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderPSD.h0000644000000000000000000000345212574354552020135 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IMAGE_LOADER_PSD_H_INCLUDED__ #define __C_IMAGE_LOADER_PSD_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_PSD_LOADER_ #include "IImageLoader.h" namespace irr { namespace video { // byte-align structures #include "irrpack.h" struct PsdHeader { c8 signature [4]; // Always equal to 8BPS. u16 version; // Always equal to 1 c8 reserved [6]; // Must be zero u16 channels; // Number of any channels inc. alphas u32 height; // Rows Height of image in pixel u32 width; // Colums Width of image in pixel u16 depth; // Bits/channel u16 mode; // Color mode of the file (Bitmap/Grayscale..) } PACK_STRUCT; // Default alignment #include "irrunpack.h" /*! Surface Loader for psd images */ class CImageLoaderPSD : public IImageLoader { public: //! constructor CImageLoaderPSD(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! creates a surface from the file virtual IImage* loadImage(io::IReadFile* file) const; private: bool readRawImageData(io::IReadFile* file, const PsdHeader& header, u32* imageData) const; bool readRLEImageData(io::IReadFile* file, const PsdHeader& header, u32* imageData) const; s16 getShiftFromChannel(c8 channelNr, const PsdHeader& header) const; }; } // end namespace video } // end namespace irr #endif #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderPSD.cpp0000644000000000000000000002132012574354552020462 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageLoaderPSD.h" #ifdef _IRR_COMPILE_WITH_PSD_LOADER_ #include "IReadFile.h" #include "os.h" #include "CImage.h" #include "irrString.h" namespace irr { namespace video { //! constructor CImageLoaderPSD::CImageLoaderPSD() { #ifdef _DEBUG setDebugName("CImageLoaderPSD"); #endif } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") bool CImageLoaderPSD::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "psd" ); } //! returns true if the file maybe is able to be loaded by this class bool CImageLoaderPSD::isALoadableFileFormat(io::IReadFile* file) const { if (!file) return false; u8 type[3]; file->read(&type, sizeof(u8)*3); return (type[2]==2); // we currently only handle tgas of type 2. } //! creates a surface from the file IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const { u32* imageData = 0; PsdHeader header; file->read(&header, sizeof(PsdHeader)); #ifndef __BIG_ENDIAN__ header.version = os::Byteswap::byteswap(header.version); header.channels = os::Byteswap::byteswap(header.channels); header.height = os::Byteswap::byteswap(header.height); header.width = os::Byteswap::byteswap(header.width); header.depth = os::Byteswap::byteswap(header.depth); header.mode = os::Byteswap::byteswap(header.mode); #endif if (header.signature[0] != '8' || header.signature[1] != 'B' || header.signature[2] != 'P' || header.signature[3] != 'S') return 0; if (header.version != 1) { os::Printer::log("Unsupported PSD file version", file->getFileName(), ELL_ERROR); return 0; } if (header.mode != 3 || header.depth != 8) { os::Printer::log("Unsupported PSD color mode or depth.\n", file->getFileName(), ELL_ERROR); return 0; } // skip color mode data u32 l; file->read(&l, sizeof(u32)); #ifndef __BIG_ENDIAN__ l = os::Byteswap::byteswap(l); #endif if (!file->seek(l, true)) { os::Printer::log("Error seeking file pos to image resources.\n", file->getFileName(), ELL_ERROR); return 0; } // skip image resources file->read(&l, sizeof(u32)); #ifndef __BIG_ENDIAN__ l = os::Byteswap::byteswap(l); #endif if (!file->seek(l, true)) { os::Printer::log("Error seeking file pos to layer and mask.\n", file->getFileName(), ELL_ERROR); return 0; } // skip layer & mask file->read(&l, sizeof(u32)); #ifndef __BIG_ENDIAN__ l = os::Byteswap::byteswap(l); #endif if (!file->seek(l, true)) { os::Printer::log("Error seeking file pos to image data section.\n", file->getFileName(), ELL_ERROR); return 0; } // read image data u16 compressionType; file->read(&compressionType, sizeof(u16)); #ifndef __BIG_ENDIAN__ compressionType = os::Byteswap::byteswap(compressionType); #endif if (compressionType != 1 && compressionType != 0) { os::Printer::log("Unsupported psd compression mode.\n", file->getFileName(), ELL_ERROR); return 0; } // create image data block imageData = new u32[header.width * header.height]; bool res = false; if (compressionType == 0) res = readRawImageData(file, header, imageData); // RAW image data else res = readRLEImageData(file, header, imageData); // RLE compressed data video::IImage* image = 0; if (res) { // create surface image = new CImage(ECF_A8R8G8B8, core::dimension2d(header.width, header.height), imageData); } if (!image) delete [] imageData; imageData = 0; return image; } bool CImageLoaderPSD::readRawImageData(io::IReadFile* file, const PsdHeader& header, u32* imageData) const { u8* tmpData = new u8[header.width * header.height]; for (s32 channel=0; channelread(tmpData, sizeof(c8) * header.width * header.height)) { os::Printer::log("Error reading color channel\n", file->getFileName(), ELL_ERROR); break; } s16 shift = getShiftFromChannel((c8)channel, header); if (shift != -1) { u32 mask = 0xff << shift; for (u32 x=0; xread(&rleCount[y], sizeof(u16))) { delete [] tmpData; delete [] rleCount; os::Printer::log("Error reading rle rows\n", file->getFileName(), ELL_ERROR); return false; } #ifndef __BIG_ENDIAN__ rleCount[y] = os::Byteswap::byteswap(rleCount[y]); #endif size += rleCount[y]; } s8 *buf = new s8[size]; if (!file->read(buf, size)) { delete [] rleCount; delete [] buf; delete [] tmpData; os::Printer::log("Error reading rle rows\n", file->getFileName(), ELL_ERROR); return false; } u16 *rcount=rleCount; s8 rh; u16 bytesRead; u8 *dest; s8 *pBuf = buf; // decompress packbit rle for (s32 channel=0; channel= 0) { ++rh; while (rh--) { *dest = *pBuf++; ++bytesRead; ++dest; } } else if (rh > -128) { rh = -rh +1; while (rh--) { *dest = *pBuf; ++dest; } ++pBuf; ++bytesRead; } } } s16 shift = getShiftFromChannel((c8)channel, header); if (shift != -1) { u32 mask = 0xff << shift; for (u32 x=0; xread(&id, 2); return (id[0]=='P' && id[1]>'0' && id[1]<'7'); } //! creates a surface from the file IImage* CImageLoaderPPM::loadImage(io::IReadFile* file) const { IImage* image; if (file->getSize() < 12) return 0; c8 id[2]; file->read(&id, 2); if (id[0]!='P' || id[1]<'1' || id[1]>'6') return 0; const u8 format = id[1] - '0'; const bool binary = format>3; core::stringc token; getNextToken(file, token); const u32 width = core::strtoul10(token.c_str()); getNextToken(file, token); const u32 height = core::strtoul10(token.c_str()); u8* data = 0; const u32 size = width*height; if (format==1 || format==4) { skipToNextToken(file); // go to start of data const u32 bytesize = size/8+(size & 3)?1:0; if (binary) { if (file->getSize()-file->getPos() < (long)bytesize) return 0; data = new u8[bytesize]; file->read(data, bytesize); } else { if (file->getSize()-file->getPos() < (long)(2*size)) // optimistic test return 0; data = new u8[bytesize]; memset(data, 0, bytesize); u32 shift=0; for (u32 i=0; i(width, height)); if (image) CColorConverter::convert1BitTo16Bit(data, (s16*)image->lock(), width, height); } else { getNextToken(file, token); const u32 maxDepth = core::strtoul10(token.c_str()); if (maxDepth > 255) // no double bytes yet return 0; skipToNextToken(file); // go to start of data if (format==2 || format==5) { if (binary) { if (file->getSize()-file->getPos() < (long)size) return 0; data = new u8[size]; file->read(data, size); image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); if (image) { u8* ptr = (u8*)image->lock(); for (u32 i=0; igetSize()-file->getPos() < (long)(2*size)) // optimistic test return 0; image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); if (image) { u8* ptr = (u8*)image->lock(); for (u32 i=0; igetSize()-file->getPos() < (long)bytesize) return 0; data = new u8[bytesize]; file->read(data, bytesize); image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); if (image) { u8* ptr = (u8*)image->lock(); for (u32 i=0; igetSize()-file->getPos() < (long)(2*bytesize)) // optimistic test return 0; image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); if (image) { u8* ptr = (u8*)image->lock(); for (u32 i=0; iunlock(); delete [] data; return image; } //! read the next token from file void CImageLoaderPPM::getNextToken(io::IReadFile* file, core::stringc& token) const { token = ""; c8 c; while(file->getPos()getSize()) { file->read(&c, 1); if (c=='#') { while (c!='\n' && c!='\r' && (file->getPos()getSize())) file->read(&c, 1); } else if (!core::isspace(c)) { token.append(c); break; } } while(file->getPos()getSize()) { file->read(&c, 1); if (c=='#') { while (c!='\n' && c!='\r' && (file->getPos()getSize())) file->read(&c, 1); } else if (!core::isspace(c)) token.append(c); else break; } } //! skip to next token (skip whitespace) void CImageLoaderPPM::skipToNextToken(io::IReadFile* file) const { c8 c; while(file->getPos()getSize()) { file->read(&c, 1); if (c=='#') { while (c!='\n' && c!='\r' && (file->getPos()getSize())) file->read(&c, 1); } else if (!core::isspace(c)) { file->seek(-1, true); // put back break; } } } //! creates a loader which is able to load windows bitmaps IImageLoader* createImageLoaderPPM() { return new CImageLoaderPPM; } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderPNG.h0000644000000000000000000000230212574354552020124 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // this file was created by rt (www.tomkorp.com), based on ttk's png-reader // i wanted to be able to read in PNG images with irrlicht :) // why? lossless compression with 8-bit alpha channel! #ifndef __C_IMAGE_LOADER_PNG_H_INCLUDED__ #define __C_IMAGE_LOADER_PNG_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_PNG_LOADER_ #include "IImageLoader.h" namespace irr { namespace video { //! Surface Loader for PNG files class CImageLoaderPng : public IImageLoader { public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".png") virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! creates a surface from the file virtual IImage* loadImage(io::IReadFile* file) const; }; } // end namespace video } // end namespace irr #endif #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderPNG.cpp0000644000000000000000000001664612574354552020477 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageLoaderPNG.h" #ifdef _IRR_COMPILE_WITH_PNG_LOADER_ #ifdef _IRR_COMPILE_WITH_LIBPNG_ #ifndef _IRR_USE_NON_SYSTEM_LIB_PNG_ #include // use system lib png #else // _IRR_USE_NON_SYSTEM_LIB_PNG_ #include "libpng/png.h" // use irrlicht included lib png #endif // _IRR_USE_NON_SYSTEM_LIB_PNG_ #endif // _IRR_COMPILE_WITH_LIBPNG_ #include "CImage.h" #include "CReadFile.h" #include "os.h" namespace irr { namespace video { #ifdef _IRR_COMPILE_WITH_LIBPNG_ // PNG function for error handling static void png_cpexcept_error(png_structp png_ptr, png_const_charp msg) { os::Printer::log("PNG fatal error", msg, ELL_ERROR); longjmp(png_jmpbuf(png_ptr), 1); } // PNG function for warning handling static void png_cpexcept_warn(png_structp png_ptr, png_const_charp msg) { os::Printer::log("PNG warning", msg, ELL_WARNING); } // PNG function for file reading void PNGAPI user_read_data_fcn(png_structp png_ptr, png_bytep data, png_size_t length) { png_size_t check; // changed by zola { io::IReadFile* file=(io::IReadFile*)png_get_io_ptr(png_ptr); check=(png_size_t) file->read((void*)data,(u32)length); // } if (check != length) png_error(png_ptr, "Read Error"); } #endif // _IRR_COMPILE_WITH_LIBPNG_ //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") bool CImageLoaderPng::isALoadableFileExtension(const io::path& filename) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ return core::hasFileExtension ( filename, "png" ); #else return false; #endif // _IRR_COMPILE_WITH_LIBPNG_ } //! returns true if the file maybe is able to be loaded by this class bool CImageLoaderPng::isALoadableFileFormat(io::IReadFile* file) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ if (!file) return false; png_byte buffer[8]; // Read the first few bytes of the PNG file if (file->read(buffer, 8) != 8) return false; // Check if it really is a PNG file return !png_sig_cmp(buffer, 0, 8); #else return false; #endif // _IRR_COMPILE_WITH_LIBPNG_ } // load in the image data IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ if (!file) return 0; video::IImage* image = 0; //Used to point to image rows u8** RowPointers = 0; png_byte buffer[8]; // Read the first few bytes of the PNG file if( file->read(buffer, 8) != 8 ) { os::Printer::log("LOAD PNG: can't read file\n", file->getFileName(), ELL_ERROR); return 0; } // Check if it really is a PNG file if( png_sig_cmp(buffer, 0, 8) ) { os::Printer::log("LOAD PNG: not really a png\n", file->getFileName(), ELL_ERROR); return 0; } // Allocate the png read struct png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warn); if (!png_ptr) { os::Printer::log("LOAD PNG: Internal PNG create read struct failure\n", file->getFileName(), ELL_ERROR); return 0; } // Allocate the png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { os::Printer::log("LOAD PNG: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR); png_destroy_read_struct(&png_ptr, NULL, NULL); return 0; } // for proper error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (RowPointers) delete [] RowPointers; return 0; } // changed by zola so we don't need to have public FILE pointers png_set_read_fn(png_ptr, file, user_read_data_fcn); png_set_sig_bytes(png_ptr, 8); // Tell png that we read the signature png_read_info(png_ptr, info_ptr); // Read the info section of the png file u32 Width; u32 Height; s32 BitDepth; s32 ColorType; { // Use temporary variables to avoid passing casted pointers png_uint_32 w,h; // Extract info png_get_IHDR(png_ptr, info_ptr, &w, &h, &BitDepth, &ColorType, NULL, NULL, NULL); Width=w; Height=h; } // Convert palette color to true color if (ColorType==PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); // Convert low bit colors to 8 bit colors if (BitDepth < 8) { if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA) png_set_expand_gray_1_2_4_to_8(png_ptr); else png_set_packing(png_ptr); } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); // Convert high bit colors to 8 bit colors if (BitDepth == 16) png_set_strip_16(png_ptr); // Convert gray color to true color if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); int intent; const double screen_gamma = 2.2; if (png_get_sRGB(png_ptr, info_ptr, &intent)) png_set_gamma(png_ptr, screen_gamma, 0.45455); else { double image_gamma; if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) png_set_gamma(png_ptr, screen_gamma, image_gamma); else png_set_gamma(png_ptr, screen_gamma, 0.45455); } // Update the changes in between, as we need to get the new color type // for proper processing of the RGBA type png_read_update_info(png_ptr, info_ptr); { // Use temporary variables to avoid passing casted pointers png_uint_32 w,h; // Extract info png_get_IHDR(png_ptr, info_ptr, &w, &h, &BitDepth, &ColorType, NULL, NULL, NULL); Width=w; Height=h; } // Convert RGBA to BGRA if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA) { #ifdef __BIG_ENDIAN__ png_set_swap_alpha(png_ptr); #else png_set_bgr(png_ptr); #endif } // Create the image structure to be filled by png data if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA) image = new CImage(ECF_A8R8G8B8, core::dimension2d(Width, Height)); else image = new CImage(ECF_R8G8B8, core::dimension2d(Width, Height)); if (!image) { os::Printer::log("LOAD PNG: Internal PNG create image struct failure\n", file->getFileName(), ELL_ERROR); png_destroy_read_struct(&png_ptr, NULL, NULL); return 0; } // Create array of pointers to rows in image data RowPointers = new png_bytep[Height]; if (!RowPointers) { os::Printer::log("LOAD PNG: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR); png_destroy_read_struct(&png_ptr, NULL, NULL); delete image; return 0; } // Fill array of pointers to rows in image data unsigned char* data = (unsigned char*)image->lock(); for (u32 i=0; igetPitch(); } // for proper error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); delete [] RowPointers; image->unlock(); delete image; return 0; } // Read data using the library function that handles all transformations including interlacing png_read_image(png_ptr, RowPointers); png_read_end(png_ptr, NULL); delete [] RowPointers; image->unlock(); png_destroy_read_struct(&png_ptr,&info_ptr, 0); // Clean up memory return image; #else return 0; #endif // _IRR_COMPILE_WITH_LIBPNG_ } IImageLoader* createImageLoaderPNG() { return new CImageLoaderPng(); } }// end namespace irr }//end namespace video #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderPCX.h0000644000000000000000000000333212574354552020136 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IMAGE_LOADER_PCX_H_INCLUDED__ #define __C_IMAGE_LOADER_PCX_H_INCLUDED__ #include "IrrCompileConfig.h" #include "IImageLoader.h" namespace irr { namespace video { #if defined(_IRR_COMPILE_WITH_PCX_LOADER_) || defined(_IRR_COMPILE_WITH_PCX_WRITER_) // byte-align structures #include "irrpack.h" struct SPCXHeader { u8 Manufacturer; u8 Version; u8 Encoding; u8 BitsPerPixel; u16 XMin; u16 YMin; u16 XMax; u16 YMax; u16 HorizDPI; u16 VertDPI; u8 Palette[48]; u8 Reserved; u8 Planes; u16 BytesPerLine; u16 PaletteType; u16 HScrSize; u16 VScrSize; u8 Filler[54]; } PACK_STRUCT; // Default alignment #include "irrunpack.h" #endif // compile with loader or writer #ifdef _IRR_COMPILE_WITH_PCX_LOADER_ /*! Image Loader for Windows PCX bitmaps. This loader was written and sent in by Dean P. Macri. I modified only some small bits of it. */ class CImageLoaderPCX : public IImageLoader { public: //! constructor CImageLoaderPCX(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! creates a surface from the file virtual IImage* loadImage(io::IReadFile* file) const; }; #endif // compile with loader } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderPCX.cpp0000644000000000000000000001351512574354552020475 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageLoaderPCX.h" #ifdef _IRR_COMPILE_WITH_PCX_LOADER_ #include "IReadFile.h" #include "SColor.h" #include "CColorConverter.h" #include "CImage.h" #include "os.h" #include "irrString.h" namespace irr { namespace video { //! constructor CImageLoaderPCX::CImageLoaderPCX() { #ifdef _DEBUG setDebugName("CImageLoaderPCX"); #endif } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") bool CImageLoaderPCX::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "pcx" ); } //! returns true if the file maybe is able to be loaded by this class bool CImageLoaderPCX::isALoadableFileFormat(io::IReadFile* file) const { u8 headerID; file->read(&headerID, sizeof(headerID)); return headerID == 0x0a; } //! creates a image from the file IImage* CImageLoaderPCX::loadImage(io::IReadFile* file) const { SPCXHeader header; s32* paletteData = 0; file->read(&header, sizeof(header)); #ifdef __BIG_ENDIAN__ header.XMin = os::Byteswap::byteswap(header.XMin); header.YMin = os::Byteswap::byteswap(header.YMin); header.XMax = os::Byteswap::byteswap(header.XMax); header.YMax = os::Byteswap::byteswap(header.YMax); header.HorizDPI = os::Byteswap::byteswap(header.HorizDPI); header.VertDPI = os::Byteswap::byteswap(header.VertDPI); header.BytesPerLine = os::Byteswap::byteswap(header.BytesPerLine); header.PaletteType = os::Byteswap::byteswap(header.PaletteType); header.HScrSize = os::Byteswap::byteswap(header.HScrSize); header.VScrSize = os::Byteswap::byteswap(header.VScrSize); #endif //! return if the header is wrong if (header.Manufacturer != 0x0a && header.Encoding != 0x01) return 0; // return if this isn't a supported type if ((header.BitsPerPixel != 8) && (header.BitsPerPixel != 4) && (header.BitsPerPixel != 1)) { os::Printer::log("Unsupported bits per pixel in PCX file.", file->getFileName(), irr::ELL_WARNING); return 0; } // read palette if( (header.BitsPerPixel == 8) && (header.Planes == 1) ) { // the palette indicator (usually a 0x0c is found infront of the actual palette data) // is ignored because some exporters seem to forget to write it. This would result in // no image loaded before, now only wrong colors will be set. const long pos = file->getPos(); file->seek( file->getSize()-256*3, false ); u8 *tempPalette = new u8[768]; paletteData = new s32[256]; file->read( tempPalette, 768 ); for( s32 i=0; i<256; i++ ) { paletteData[i] = (0xff000000 | (tempPalette[i*3+0] << 16) | (tempPalette[i*3+1] << 8) | (tempPalette[i*3+2])); } delete [] tempPalette; file->seek(pos); } else if( header.BitsPerPixel == 4 ) { paletteData = new s32[16]; for( s32 i=0; i<16; i++ ) { paletteData[i] = (0xff000000 | (header.Palette[i*3+0] << 16) | (header.Palette[i*3+1] << 8) | (header.Palette[i*3+2])); } } // read image data const s32 width = header.XMax - header.XMin + 1; const s32 height = header.YMax - header.YMin + 1; const s32 imagebytes = header.BytesPerLine * header.Planes * header.BitsPerPixel * height / 8; u8* PCXData = new u8[imagebytes]; u8 cnt, value; s32 lineoffset=0, linestart=0, nextmode=1; for(s32 offset = 0; offset < imagebytes; offset += cnt) { file->read(&cnt, 1); if( !((cnt & 0xc0) == 0xc0) ) { value = cnt; cnt = 1; } else { cnt &= 0x3f; file->read(&value, 1); } if (header.Planes==1) memset(PCXData+offset, value, cnt); else { for (u8 i=0; i=3*header.BytesPerLine) { lineoffset=nextmode; if (++nextmode==3) nextmode=0; if (lineoffset==0) linestart += 3*header.BytesPerLine; } } } } // create image video::IImage* image = 0; s32 pad = (header.BytesPerLine - width * header.BitsPerPixel / 8) * header.Planes; if (pad < 0) pad = -pad; if (header.BitsPerPixel==8) { switch(header.Planes) // TODO: Other formats { case 1: image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); if (image) CColorConverter::convert8BitTo16Bit(PCXData, (s16*)image->lock(), width, height, paletteData, pad); break; case 3: image = new CImage(ECF_R8G8B8, core::dimension2d(width, height)); if (image) CColorConverter::convert24BitTo24Bit(PCXData, (u8*)image->lock(), width, height, pad); break; } } else if (header.BitsPerPixel==4) { if (header.Planes==1) { image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); if (image) CColorConverter::convert4BitTo16Bit(PCXData, (s16*)image->lock(), width, height, paletteData, pad); } } else if (header.BitsPerPixel==1) { if (header.Planes==4) { image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); if (image) CColorConverter::convert4BitTo16Bit(PCXData, (s16*)image->lock(), width, height, paletteData, pad); } else if (header.Planes==1) { image = new CImage(ECF_A1R5G5B5, core::dimension2d(width, height)); if (image) CColorConverter::convert1BitTo16Bit(PCXData, (s16*)image->lock(), width, height, pad); } } if (image) image->unlock(); // clean up delete [] paletteData; delete [] PCXData; return image; } //! creates a loader which is able to load pcx images IImageLoader* createImageLoaderPCX() { return new CImageLoaderPCX(); } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderJPG.h0000644000000000000000000000771412574354552020134 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IMAGE_LOADER_JPG_H_INCLUDED__ #define __C_IMAGE_LOADER_JPG_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_JPG_LOADER_ #include "IImageLoader.h" #include // required for jpeglib.h #ifdef _IRR_COMPILE_WITH_LIBJPEG_ extern "C" { #ifndef _IRR_USE_NON_SYSTEM_JPEG_LIB_ #include // use system lib #else #include "jpeglib/jpeglib.h" // use irrlicht jpeglib #endif #include } #endif // _IRR_COMPILE_WITH_LIBJPEG_ namespace irr { namespace video { //! Surface Loader for JPG images class CImageLoaderJPG : public IImageLoader { public: //! constructor CImageLoaderJPG(); //! destructor virtual ~CImageLoaderJPG(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! creates a surface from the file virtual IImage* loadImage(io::IReadFile* file) const; private: #ifdef _IRR_COMPILE_WITH_LIBJPEG_ // several methods used via function pointers by jpeglib /* Receives control for a fatal error. Information sufficient to generate the error message has been stored in cinfo->err; call output_message to display it. Control must NOT return to the caller; generally this routine will exit() or longjmp() somewhere. Typically you would override this routine to get rid of the exit() default behavior. Note that if you continue processing, you should clean up the JPEG object with jpeg_abort() or jpeg_destroy(). */ static void error_exit (j_common_ptr cinfo); /* output error messages via Irrlicht logger. */ static void output_message(j_common_ptr cinfo); /* Initialize source. This is called by jpeg_read_header() before any data is actually read. Unlike init_destination(), it may leave bytes_in_buffer set to 0 (in which case a fill_input_buffer() call will occur immediately). */ static void init_source (j_decompress_ptr cinfo); /* This is called whenever bytes_in_buffer has reached zero and more data is wanted. In typical applications, it should read fresh data into the buffer (ignoring the current state of next_input_byte and bytes_in_buffer), reset the pointer & count to the start of the buffer, and return TRUE indicating that the buffer has been reloaded. It is not necessary to fill the buffer entirely, only to obtain at least one more byte. bytes_in_buffer MUST be set to a positive value if TRUE is returned. A FALSE return should only be used when I/O suspension is desired (this mode is discussed in the next section). */ static boolean fill_input_buffer (j_decompress_ptr cinfo); /* Skip num_bytes worth of data. The buffer pointer and count should be advanced over num_bytes input bytes, refilling the buffer as needed. This is used to skip over a potentially large amount of uninteresting data (such as an APPn marker). In some applications it may be possible to optimize away the reading of the skipped data, but it's not clear that being smart is worth much trouble; large skips are uncommon. bytes_in_buffer may be zero on return. A zero or negative skip count should be treated as a no-op. */ static void skip_input_data (j_decompress_ptr cinfo, long num_bytes); /* Terminate source --- called by jpeg_finish_decompress() after all data has been read. Often a no-op. */ static void term_source (j_decompress_ptr cinfo); // Copy filename to have it around for error-messages static io::path Filename; #endif // _IRR_COMPILE_WITH_LIBJPEG_ }; } // end namespace video } // end namespace irr #endif #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderJPG.cpp0000644000000000000000000001646012574354552020465 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageLoaderJPG.h" #ifdef _IRR_COMPILE_WITH_JPG_LOADER_ #include "IReadFile.h" #include "CImage.h" #include "os.h" #include "irrString.h" namespace irr { namespace video { #ifdef _IRR_COMPILE_WITH_LIBJPEG_ // Static members io::path CImageLoaderJPG::Filename; #endif //! constructor CImageLoaderJPG::CImageLoaderJPG() { #ifdef _DEBUG setDebugName("CImageLoaderJPG"); #endif } //! destructor CImageLoaderJPG::~CImageLoaderJPG() { } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") bool CImageLoaderJPG::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "jpg", "jpeg" ); } #ifdef _IRR_COMPILE_WITH_LIBJPEG_ // struct for handling jpeg errors struct irr_jpeg_error_mgr { // public jpeg error fields struct jpeg_error_mgr pub; // for longjmp, to return to caller on a fatal error jmp_buf setjmp_buffer; }; void CImageLoaderJPG::init_source (j_decompress_ptr cinfo) { // DO NOTHING } boolean CImageLoaderJPG::fill_input_buffer (j_decompress_ptr cinfo) { // DO NOTHING return 1; } void CImageLoaderJPG::skip_input_data (j_decompress_ptr cinfo, long count) { jpeg_source_mgr * src = cinfo->src; if(count > 0) { src->bytes_in_buffer -= count; src->next_input_byte += count; } } void CImageLoaderJPG::term_source (j_decompress_ptr cinfo) { // DO NOTHING } void CImageLoaderJPG::error_exit (j_common_ptr cinfo) { // unfortunately we need to use a goto rather than throwing an exception // as gcc crashes under linux crashes when using throw from within // extern c code // Always display the message (*cinfo->err->output_message) (cinfo); // cinfo->err really points to a irr_error_mgr struct irr_jpeg_error_mgr *myerr = (irr_jpeg_error_mgr*) cinfo->err; longjmp(myerr->setjmp_buffer, 1); } void CImageLoaderJPG::output_message(j_common_ptr cinfo) { // display the error message. c8 temp1[JMSG_LENGTH_MAX]; (*cinfo->err->format_message)(cinfo, temp1); core::stringc errMsg("JPEG FATAL ERROR in "); errMsg += core::stringc(Filename); os::Printer::log(errMsg.c_str(),temp1, ELL_ERROR); } #endif // _IRR_COMPILE_WITH_LIBJPEG_ //! returns true if the file maybe is able to be loaded by this class bool CImageLoaderJPG::isALoadableFileFormat(io::IReadFile* file) const { #ifndef _IRR_COMPILE_WITH_LIBJPEG_ return false; #else if (!file) return false; s32 jfif = 0; file->seek(6); file->read(&jfif, sizeof(s32)); return (jfif == 0x4a464946 || jfif == 0x4649464a); #endif } //! creates a surface from the file IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const { #ifndef _IRR_COMPILE_WITH_LIBJPEG_ os::Printer::log("Can't load as not compiled with _IRR_COMPILE_WITH_LIBJPEG_:", file->getFileName(), ELL_DEBUG); return 0; #else if (!file) return 0; Filename = file->getFileName(); u8 **rowPtr=0; u8* input = new u8[file->getSize()]; file->read(input, file->getSize()); // allocate and initialize JPEG decompression object struct jpeg_decompress_struct cinfo; struct irr_jpeg_error_mgr jerr; //We have to set up the error handler first, in case the initialization //step fails. (Unlikely, but it could happen if you are out of memory.) //This routine fills in the contents of struct jerr, and returns jerr's //address which we place into the link field in cinfo. cinfo.err = jpeg_std_error(&jerr.pub); cinfo.err->error_exit = error_exit; cinfo.err->output_message = output_message; // compatibility fudge: // we need to use setjmp/longjmp for error handling as gcc-linux // crashes when throwing within external c code if (setjmp(jerr.setjmp_buffer)) { // If we get here, the JPEG code has signaled an error. // We need to clean up the JPEG object and return. jpeg_destroy_decompress(&cinfo); delete [] input; // if the row pointer was created, we delete it. if (rowPtr) delete [] rowPtr; // return null pointer return 0; } // Now we can initialize the JPEG decompression object. jpeg_create_decompress(&cinfo); // specify data source jpeg_source_mgr jsrc; // Set up data pointer jsrc.bytes_in_buffer = file->getSize(); jsrc.next_input_byte = (JOCTET*)input; cinfo.src = &jsrc; jsrc.init_source = init_source; jsrc.fill_input_buffer = fill_input_buffer; jsrc.skip_input_data = skip_input_data; jsrc.resync_to_restart = jpeg_resync_to_restart; jsrc.term_source = term_source; // Decodes JPG input from whatever source // Does everything AFTER jpeg_create_decompress // and BEFORE jpeg_destroy_decompress // Caller is responsible for arranging these + setting up cinfo // read file parameters with jpeg_read_header() jpeg_read_header(&cinfo, TRUE); bool useCMYK=false; if (cinfo.jpeg_color_space==JCS_CMYK) { cinfo.out_color_space=JCS_CMYK; cinfo.out_color_components=4; useCMYK=true; } else { cinfo.out_color_space=JCS_RGB; cinfo.out_color_components=3; } cinfo.output_gamma=2.2; cinfo.do_fancy_upsampling=FALSE; // Start decompressor jpeg_start_decompress(&cinfo); // Get image data u16 rowspan = cinfo.image_width * cinfo.out_color_components; u32 width = cinfo.image_width; u32 height = cinfo.image_height; // Allocate memory for buffer u8* output = new u8[rowspan * height]; // Here we use the library's state variable cinfo.output_scanline as the // loop counter, so that we don't have to keep track ourselves. // Create array of row pointers for lib rowPtr = new u8* [height]; for( u32 i = 0; i < height; i++ ) rowPtr[i] = &output[ i * rowspan ]; u32 rowsRead = 0; while( cinfo.output_scanline < cinfo.output_height ) rowsRead += jpeg_read_scanlines( &cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead ); delete [] rowPtr; // Finish decompression jpeg_finish_decompress(&cinfo); // Release JPEG decompression object // This is an important step since it will release a good deal of memory. jpeg_destroy_decompress(&cinfo); // convert image IImage* image = 0; if (useCMYK) { image = new CImage(ECF_R8G8B8, core::dimension2d(width, height)); const u32 size = 3*width*height; u8* data = (u8*)image->lock(); if (data) { for (u32 i=0,j=0; iunlock(); delete [] output; } else image = new CImage(ECF_R8G8B8, core::dimension2d(width, height), output); delete [] input; return image; #endif } //! creates a loader which is able to load jpeg images IImageLoader* createImageLoaderJPG() { return new CImageLoaderJPG(); } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderDDS.h0000644000000000000000000001170312574354552020117 0ustar rootroot// Copyright (C) 2002-2012 Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IMAGE_LOADER_DDS_H_INCLUDED__ #define __C_IMAGE_LOADER_DDS_H_INCLUDED__ #include "IrrCompileConfig.h" #if defined(_IRR_COMPILE_WITH_DDS_LOADER_) #include "IImageLoader.h" namespace irr { namespace video { /* dependencies */ /* dds definition */ enum eDDSPixelFormat { DDS_PF_ARGB8888, DDS_PF_DXT1, DDS_PF_DXT2, DDS_PF_DXT3, DDS_PF_DXT4, DDS_PF_DXT5, DDS_PF_UNKNOWN }; /* 16bpp stuff */ #define DDS_LOW_5 0x001F; #define DDS_MID_6 0x07E0; #define DDS_HIGH_5 0xF800; #define DDS_MID_555 0x03E0; #define DDS_HI_555 0x7C00; // byte-align structures #include "irrpack.h" /* structures */ struct ddsColorKey { u32 colorSpaceLowValue; u32 colorSpaceHighValue; } PACK_STRUCT; struct ddsCaps { u32 caps1; u32 caps2; u32 caps3; u32 caps4; } PACK_STRUCT; struct ddsMultiSampleCaps { u16 flipMSTypes; u16 bltMSTypes; } PACK_STRUCT; struct ddsPixelFormat { u32 size; u32 flags; u32 fourCC; union { u32 rgbBitCount; u32 yuvBitCount; u32 zBufferBitDepth; u32 alphaBitDepth; u32 luminanceBitCount; u32 bumpBitCount; u32 privateFormatBitCount; }; union { u32 rBitMask; u32 yBitMask; u32 stencilBitDepth; u32 luminanceBitMask; u32 bumpDuBitMask; u32 operations; }; union { u32 gBitMask; u32 uBitMask; u32 zBitMask; u32 bumpDvBitMask; ddsMultiSampleCaps multiSampleCaps; }; union { u32 bBitMask; u32 vBitMask; u32 stencilBitMask; u32 bumpLuminanceBitMask; }; union { u32 rgbAlphaBitMask; u32 yuvAlphaBitMask; u32 luminanceAlphaBitMask; u32 rgbZBitMask; u32 yuvZBitMask; }; } PACK_STRUCT; struct ddsBuffer { /* magic: 'dds ' */ c8 magic[ 4 ]; /* directdraw surface */ u32 size; u32 flags; u32 height; u32 width; union { s32 pitch; u32 linearSize; }; u32 backBufferCount; union { u32 mipMapCount; u32 refreshRate; u32 srcVBHandle; }; u32 alphaBitDepth; u32 reserved; void *surface; union { ddsColorKey ckDestOverlay; u32 emptyFaceColor; }; ddsColorKey ckDestBlt; ddsColorKey ckSrcOverlay; ddsColorKey ckSrcBlt; union { ddsPixelFormat pixelFormat; u32 fvf; }; ddsCaps caps; u32 textureStage; /* data (Varying size) */ u8 data[ 4 ]; } PACK_STRUCT; struct ddsColorBlock { u16 colors[ 2 ]; u8 row[ 4 ]; } PACK_STRUCT; struct ddsAlphaBlockExplicit { u16 row[ 4 ]; } PACK_STRUCT; struct ddsAlphaBlock3BitLinear { u8 alpha0; u8 alpha1; u8 stuff[ 6 ]; } PACK_STRUCT; struct ddsColor { u8 r, g, b, a; } PACK_STRUCT; // Default alignment #include "irrunpack.h" /* endian tomfoolery */ typedef union { f32 f; c8 c[ 4 ]; } floatSwapUnion; #ifndef __BIG_ENDIAN__ #ifdef _SGI_SOURCE #define __BIG_ENDIAN__ #endif #endif #ifdef __BIG_ENDIAN__ s32 DDSBigLong( s32 src ) { return src; } s16 DDSBigShort( s16 src ) { return src; } f32 DDSBigFloat( f32 src ) { return src; } s32 DDSLittleLong( s32 src ) { return ((src & 0xFF000000) >> 24) | ((src & 0x00FF0000) >> 8) | ((src & 0x0000FF00) << 8) | ((src & 0x000000FF) << 24); } s16 DDSLittleShort( s16 src ) { return ((src & 0xFF00) >> 8) | ((src & 0x00FF) << 8); } f32 DDSLittleFloat( f32 src ) { floatSwapUnion in,out; in.f = src; out.c[ 0 ] = in.c[ 3 ]; out.c[ 1 ] = in.c[ 2 ]; out.c[ 2 ] = in.c[ 1 ]; out.c[ 3 ] = in.c[ 0 ]; return out.f; } #else /*__BIG_ENDIAN__*/ s32 DDSLittleLong( s32 src ) { return src; } s16 DDSLittleShort( s16 src ) { return src; } f32 DDSLittleFloat( f32 src ) { return src; } s32 DDSBigLong( s32 src ) { return ((src & 0xFF000000) >> 24) | ((src & 0x00FF0000) >> 8) | ((src & 0x0000FF00) << 8) | ((src & 0x000000FF) << 24); } s16 DDSBigShort( s16 src ) { return ((src & 0xFF00) >> 8) | ((src & 0x00FF) << 8); } f32 DDSBigFloat( f32 src ) { floatSwapUnion in,out; in.f = src; out.c[ 0 ] = in.c[ 3 ]; out.c[ 1 ] = in.c[ 2 ]; out.c[ 2 ] = in.c[ 1 ]; out.c[ 3 ] = in.c[ 0 ]; return out.f; } #endif /*__BIG_ENDIAN__*/ /*! Surface Loader for DDS images */ class CImageLoaderDDS : public IImageLoader { public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! creates a surface from the file virtual IImage* loadImage(io::IReadFile* file) const; }; } // end namespace video } // end namespace irr #endif // compiled with DDS loader #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderDDS.cpp0000644000000000000000000004043212574354552020453 0ustar rootroot// Copyright (C) 2002-2012 Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h /* Based on Code from Copyright (c) 2003 Randy Reddig Based on code from Nvidia's DDS example: http://www.nvidia.com/object/dxtc_decompression_code.html mainly c to cpp */ #include "CImageLoaderDDS.h" #ifdef _IRR_COMPILE_WITH_DDS_LOADER_ #include "IReadFile.h" #include "os.h" #include "CColorConverter.h" #include "CImage.h" #include "irrString.h" namespace irr { namespace video { namespace { /*! DDSDecodePixelFormat() determines which pixel format the dds texture is in */ void DDSDecodePixelFormat( ddsBuffer *dds, eDDSPixelFormat *pf ) { /* dummy check */ if( dds == NULL || pf == NULL ) return; /* extract fourCC */ const u32 fourCC = dds->pixelFormat.fourCC; /* test it */ if( fourCC == 0 ) *pf = DDS_PF_ARGB8888; else if( fourCC == *((u32*) "DXT1") ) *pf = DDS_PF_DXT1; else if( fourCC == *((u32*) "DXT2") ) *pf = DDS_PF_DXT2; else if( fourCC == *((u32*) "DXT3") ) *pf = DDS_PF_DXT3; else if( fourCC == *((u32*) "DXT4") ) *pf = DDS_PF_DXT4; else if( fourCC == *((u32*) "DXT5") ) *pf = DDS_PF_DXT5; else *pf = DDS_PF_UNKNOWN; } /*! DDSGetInfo() extracts relevant info from a dds texture, returns 0 on success */ s32 DDSGetInfo( ddsBuffer *dds, s32 *width, s32 *height, eDDSPixelFormat *pf ) { /* dummy test */ if( dds == NULL ) return -1; /* test dds header */ if( *((s32*) dds->magic) != *((s32*) "DDS ") ) return -1; if( DDSLittleLong( dds->size ) != 124 ) return -1; /* extract width and height */ if( width != NULL ) *width = DDSLittleLong( dds->width ); if( height != NULL ) *height = DDSLittleLong( dds->height ); /* get pixel format */ DDSDecodePixelFormat( dds, pf ); /* return ok */ return 0; } /*! DDSGetColorBlockColors() extracts colors from a dds color block */ void DDSGetColorBlockColors( ddsColorBlock *block, ddsColor colors[ 4 ] ) { u16 word; /* color 0 */ word = DDSLittleShort( block->colors[ 0 ] ); colors[ 0 ].a = 0xff; /* extract rgb bits */ colors[ 0 ].b = (u8) word; colors[ 0 ].b <<= 3; colors[ 0 ].b |= (colors[ 0 ].b >> 5); word >>= 5; colors[ 0 ].g = (u8) word; colors[ 0 ].g <<= 2; colors[ 0 ].g |= (colors[ 0 ].g >> 5); word >>= 6; colors[ 0 ].r = (u8) word; colors[ 0 ].r <<= 3; colors[ 0 ].r |= (colors[ 0 ].r >> 5); /* same for color 1 */ word = DDSLittleShort( block->colors[ 1 ] ); colors[ 1 ].a = 0xff; /* extract rgb bits */ colors[ 1 ].b = (u8) word; colors[ 1 ].b <<= 3; colors[ 1 ].b |= (colors[ 1 ].b >> 5); word >>= 5; colors[ 1 ].g = (u8) word; colors[ 1 ].g <<= 2; colors[ 1 ].g |= (colors[ 1 ].g >> 5); word >>= 6; colors[ 1 ].r = (u8) word; colors[ 1 ].r <<= 3; colors[ 1 ].r |= (colors[ 1 ].r >> 5); /* use this for all but the super-freak math method */ if( block->colors[ 0 ] > block->colors[ 1 ] ) { /* four-color block: derive the other two colors. 00 = color 0, 01 = color 1, 10 = color 2, 11 = color 3 these two bit codes correspond to the 2-bit fields stored in the 64-bit block. */ word = ((u16) colors[ 0 ].r * 2 + (u16) colors[ 1 ].r ) / 3; /* no +1 for rounding */ /* as bits have been shifted to 888 */ colors[ 2 ].r = (u8) word; word = ((u16) colors[ 0 ].g * 2 + (u16) colors[ 1 ].g) / 3; colors[ 2 ].g = (u8) word; word = ((u16) colors[ 0 ].b * 2 + (u16) colors[ 1 ].b) / 3; colors[ 2 ].b = (u8) word; colors[ 2 ].a = 0xff; word = ((u16) colors[ 0 ].r + (u16) colors[ 1 ].r * 2) / 3; colors[ 3 ].r = (u8) word; word = ((u16) colors[ 0 ].g + (u16) colors[ 1 ].g * 2) / 3; colors[ 3 ].g = (u8) word; word = ((u16) colors[ 0 ].b + (u16) colors[ 1 ].b * 2) / 3; colors[ 3 ].b = (u8) word; colors[ 3 ].a = 0xff; } else { /* three-color block: derive the other color. 00 = color 0, 01 = color 1, 10 = color 2, 11 = transparent. These two bit codes correspond to the 2-bit fields stored in the 64-bit block */ word = ((u16) colors[ 0 ].r + (u16) colors[ 1 ].r) / 2; colors[ 2 ].r = (u8) word; word = ((u16) colors[ 0 ].g + (u16) colors[ 1 ].g) / 2; colors[ 2 ].g = (u8) word; word = ((u16) colors[ 0 ].b + (u16) colors[ 1 ].b) / 2; colors[ 2 ].b = (u8) word; colors[ 2 ].a = 0xff; /* random color to indicate alpha */ colors[ 3 ].r = 0x00; colors[ 3 ].g = 0xff; colors[ 3 ].b = 0xff; colors[ 3 ].a = 0x00; } } /* DDSDecodeColorBlock() decodes a dds color block fixme: make endian-safe */ void DDSDecodeColorBlock( u32 *pixel, ddsColorBlock *block, s32 width, u32 colors[ 4 ] ) { s32 r, n; u32 bits; u32 masks[] = { 3, 12, 3 << 4, 3 << 6 }; /* bit masks = 00000011, 00001100, 00110000, 11000000 */ s32 shift[] = { 0, 2, 4, 6 }; /* r steps through lines in y */ for( r = 0; r < 4; r++, pixel += (width - 4) ) /* no width * 4 as u32 ptr inc will * 4 */ { /* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */ /* n steps through pixels */ for( n = 0; n < 4; n++ ) { bits = block->row[ r ] & masks[ n ]; bits >>= shift[ n ]; switch( bits ) { case 0: *pixel = colors[ 0 ]; pixel++; break; case 1: *pixel = colors[ 1 ]; pixel++; break; case 2: *pixel = colors[ 2 ]; pixel++; break; case 3: *pixel = colors[ 3 ]; pixel++; break; default: /* invalid */ pixel++; break; } } } } /* DDSDecodeAlphaExplicit() decodes a dds explicit alpha block */ void DDSDecodeAlphaExplicit( u32 *pixel, ddsAlphaBlockExplicit *alphaBlock, s32 width, u32 alphaZero ) { s32 row, pix; u16 word; ddsColor color; /* clear color */ color.r = 0; color.g = 0; color.b = 0; /* walk rows */ for( row = 0; row < 4; row++, pixel += (width - 4) ) { word = DDSLittleShort( alphaBlock->row[ row ] ); /* walk pixels */ for( pix = 0; pix < 4; pix++ ) { /* zero the alpha bits of image pixel */ *pixel &= alphaZero; color.a = word & 0x000F; color.a = color.a | (color.a << 4); *pixel |= *((u32*) &color); word >>= 4; /* move next bits to lowest 4 */ pixel++; /* move to next pixel in the row */ } } } /* DDSDecodeAlpha3BitLinear() decodes interpolated alpha block */ void DDSDecodeAlpha3BitLinear( u32 *pixel, ddsAlphaBlock3BitLinear *alphaBlock, s32 width, u32 alphaZero ) { s32 row, pix; u32 stuff; u8 bits[ 4 ][ 4 ]; u16 alphas[ 8 ]; ddsColor aColors[ 4 ][ 4 ]; /* get initial alphas */ alphas[ 0 ] = alphaBlock->alpha0; alphas[ 1 ] = alphaBlock->alpha1; /* 8-alpha block */ if( alphas[ 0 ] > alphas[ 1 ] ) { /* 000 = alpha_0, 001 = alpha_1, others are interpolated */ alphas[ 2 ] = ( 6 * alphas[ 0 ] + alphas[ 1 ]) / 7; /* bit code 010 */ alphas[ 3 ] = ( 5 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 7; /* bit code 011 */ alphas[ 4 ] = ( 4 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 7; /* bit code 100 */ alphas[ 5 ] = ( 3 * alphas[ 0 ] + 4 * alphas[ 1 ]) / 7; /* bit code 101 */ alphas[ 6 ] = ( 2 * alphas[ 0 ] + 5 * alphas[ 1 ]) / 7; /* bit code 110 */ alphas[ 7 ] = ( alphas[ 0 ] + 6 * alphas[ 1 ]) / 7; /* bit code 111 */ } /* 6-alpha block */ else { /* 000 = alpha_0, 001 = alpha_1, others are interpolated */ alphas[ 2 ] = (4 * alphas[ 0 ] + alphas[ 1 ]) / 5; /* bit code 010 */ alphas[ 3 ] = (3 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 5; /* bit code 011 */ alphas[ 4 ] = (2 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 5; /* bit code 100 */ alphas[ 5 ] = ( alphas[ 0 ] + 4 * alphas[ 1 ]) / 5; /* bit code 101 */ alphas[ 6 ] = 0; /* bit code 110 */ alphas[ 7 ] = 255; /* bit code 111 */ } /* decode 3-bit fields into array of 16 bytes with same value */ /* first two rows of 4 pixels each */ stuff = *((u32*) &(alphaBlock->stuff[ 0 ])); bits[ 0 ][ 0 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 0 ][ 1 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 0 ][ 2 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 0 ][ 3 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 1 ][ 0 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 1 ][ 1 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 1 ][ 2 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 1 ][ 3 ] = (u8) (stuff & 0x00000007); /* last two rows */ stuff = *((u32*) &(alphaBlock->stuff[ 3 ])); /* last 3 bytes */ bits[ 2 ][ 0 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 2 ][ 1 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 2 ][ 2 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 2 ][ 3 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 3 ][ 0 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 3 ][ 1 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 3 ][ 2 ] = (u8) (stuff & 0x00000007); stuff >>= 3; bits[ 3 ][ 3 ] = (u8) (stuff & 0x00000007); /* decode the codes into alpha values */ for( row = 0; row < 4; row++ ) { for( pix=0; pix < 4; pix++ ) { aColors[ row ][ pix ].r = 0; aColors[ row ][ pix ].g = 0; aColors[ row ][ pix ].b = 0; aColors[ row ][ pix ].a = (u8) alphas[ bits[ row ][ pix ] ]; } } /* write out alpha values to the image bits */ for( row = 0; row < 4; row++, pixel += width-4 ) { for( pix = 0; pix < 4; pix++ ) { /* zero the alpha bits of image pixel */ *pixel &= alphaZero; /* or the bits into the prev. nulled alpha */ *pixel |= *((u32*) &(aColors[ row ][ pix ])); pixel++; } } } /* DDSDecompressDXT1() decompresses a dxt1 format texture */ s32 DDSDecompressDXT1( ddsBuffer *dds, s32 width, s32 height, u8 *pixels ) { s32 x, y, xBlocks, yBlocks; u32 *pixel; ddsColorBlock *block; ddsColor colors[ 4 ]; /* setup */ xBlocks = width / 4; yBlocks = height / 4; /* walk y */ for( y = 0; y < yBlocks; y++ ) { /* 8 bytes per block */ block = (ddsColorBlock*) (dds->data + y * xBlocks * 8); /* walk x */ for( x = 0; x < xBlocks; x++, block++ ) { DDSGetColorBlockColors( block, colors ); pixel = (u32*) (pixels + x * 16 + (y * 4) * width * 4); DDSDecodeColorBlock( pixel, block, width, (u32*) colors ); } } /* return ok */ return 0; } /* DDSDecompressDXT3() decompresses a dxt3 format texture */ s32 DDSDecompressDXT3( ddsBuffer *dds, s32 width, s32 height, u8 *pixels ) { s32 x, y, xBlocks, yBlocks; u32 *pixel, alphaZero; ddsColorBlock *block; ddsAlphaBlockExplicit *alphaBlock; ddsColor colors[ 4 ]; /* setup */ xBlocks = width / 4; yBlocks = height / 4; /* create zero alpha */ colors[ 0 ].a = 0; colors[ 0 ].r = 0xFF; colors[ 0 ].g = 0xFF; colors[ 0 ].b = 0xFF; alphaZero = *((u32*) &colors[ 0 ]); /* walk y */ for( y = 0; y < yBlocks; y++ ) { /* 8 bytes per block, 1 block for alpha, 1 block for color */ block = (ddsColorBlock*) (dds->data + y * xBlocks * 16); /* walk x */ for( x = 0; x < xBlocks; x++, block++ ) { /* get alpha block */ alphaBlock = (ddsAlphaBlockExplicit*) block; /* get color block */ block++; DDSGetColorBlockColors( block, colors ); /* decode color block */ pixel = (u32*) (pixels + x * 16 + (y * 4) * width * 4); DDSDecodeColorBlock( pixel, block, width, (u32*) colors ); /* overwrite alpha bits with alpha block */ DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero ); } } /* return ok */ return 0; } /* DDSDecompressDXT5() decompresses a dxt5 format texture */ s32 DDSDecompressDXT5( ddsBuffer *dds, s32 width, s32 height, u8 *pixels ) { s32 x, y, xBlocks, yBlocks; u32 *pixel, alphaZero; ddsColorBlock *block; ddsAlphaBlock3BitLinear *alphaBlock; ddsColor colors[ 4 ]; /* setup */ xBlocks = width / 4; yBlocks = height / 4; /* create zero alpha */ colors[ 0 ].a = 0; colors[ 0 ].r = 0xFF; colors[ 0 ].g = 0xFF; colors[ 0 ].b = 0xFF; alphaZero = *((u32*) &colors[ 0 ]); /* walk y */ for( y = 0; y < yBlocks; y++ ) { /* 8 bytes per block, 1 block for alpha, 1 block for color */ block = (ddsColorBlock*) (dds->data + y * xBlocks * 16); /* walk x */ for( x = 0; x < xBlocks; x++, block++ ) { /* get alpha block */ alphaBlock = (ddsAlphaBlock3BitLinear*) block; /* get color block */ block++; DDSGetColorBlockColors( block, colors ); /* decode color block */ pixel = (u32*) (pixels + x * 16 + (y * 4) * width * 4); DDSDecodeColorBlock( pixel, block, width, (u32*) colors ); /* overwrite alpha bits with alpha block */ DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero ); } } /* return ok */ return 0; } /* DDSDecompressDXT2() decompresses a dxt2 format texture (fixme: un-premultiply alpha) */ s32 DDSDecompressDXT2( ddsBuffer *dds, s32 width, s32 height, u8 *pixels ) { /* decompress dxt3 first */ const s32 r = DDSDecompressDXT3( dds, width, height, pixels ); /* return to sender */ return r; } /* DDSDecompressDXT4() decompresses a dxt4 format texture (fixme: un-premultiply alpha) */ s32 DDSDecompressDXT4( ddsBuffer *dds, s32 width, s32 height, u8 *pixels ) { /* decompress dxt5 first */ const s32 r = DDSDecompressDXT5( dds, width, height, pixels ); /* return to sender */ return r; } /* DDSDecompressARGB8888() decompresses an argb 8888 format texture */ s32 DDSDecompressARGB8888( ddsBuffer *dds, s32 width, s32 height, u8 *pixels ) { /* setup */ u8* in = dds->data; u8* out = pixels; /* walk y */ for(s32 y = 0; y < height; y++) { /* walk x */ for(s32 x = 0; x < width; x++) { *out++ = *in++; *out++ = *in++; *out++ = *in++; *out++ = *in++; } } /* return ok */ return 0; } /* DDSDecompress() decompresses a dds texture into an rgba image buffer, returns 0 on success */ s32 DDSDecompress( ddsBuffer *dds, u8 *pixels ) { s32 width, height; eDDSPixelFormat pf; /* get dds info */ s32 r = DDSGetInfo( dds, &width, &height, &pf ); if ( r ) return r; /* decompress */ switch( pf ) { case DDS_PF_ARGB8888: /* fixme: support other [a]rgb formats */ r = DDSDecompressARGB8888( dds, width, height, pixels ); break; case DDS_PF_DXT1: r = DDSDecompressDXT1( dds, width, height, pixels ); break; case DDS_PF_DXT2: r = DDSDecompressDXT2( dds, width, height, pixels ); break; case DDS_PF_DXT3: r = DDSDecompressDXT3( dds, width, height, pixels ); break; case DDS_PF_DXT4: r = DDSDecompressDXT4( dds, width, height, pixels ); break; case DDS_PF_DXT5: r = DDSDecompressDXT5( dds, width, height, pixels ); break; default: case DDS_PF_UNKNOWN: memset( pixels, 0xFF, width * height * 4 ); r = -1; break; } /* return to sender */ return r; } } // end anonymous namespace //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") bool CImageLoaderDDS::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "dds" ); } //! returns true if the file maybe is able to be loaded by this class bool CImageLoaderDDS::isALoadableFileFormat(io::IReadFile* file) const { if (!file) return false; ddsBuffer header; file->read(&header, sizeof(header)); s32 width, height; eDDSPixelFormat pixelFormat; return (0 == DDSGetInfo( &header, &width, &height, &pixelFormat)); } //! creates a surface from the file IImage* CImageLoaderDDS::loadImage(io::IReadFile* file) const { u8 *memFile = new u8 [ file->getSize() ]; file->read ( memFile, file->getSize() ); ddsBuffer *header = (ddsBuffer*) memFile; IImage* image = 0; s32 width, height; eDDSPixelFormat pixelFormat; if ( 0 == DDSGetInfo( header, &width, &height, &pixelFormat) ) { image = new CImage(ECF_A8R8G8B8, core::dimension2d(width, height)); if ( DDSDecompress( header, (u8*) image->lock() ) == -1) { image->unlock(); image->drop(); image = 0; } } delete [] memFile; if ( image ) image->unlock(); return image; } //! creates a loader which is able to load dds images IImageLoader* createImageLoaderDDS() { return new CImageLoaderDDS(); } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderBMP.h0000644000000000000000000000524412574354552020126 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IMAGE_LOADER_BMP_H_INCLUDED__ #define __C_IMAGE_LOADER_BMP_H_INCLUDED__ #include "IrrCompileConfig.h" #include "IImageLoader.h" namespace irr { namespace video { #if defined(_IRR_COMPILE_WITH_BMP_LOADER_) || defined(_IRR_COMPILE_WITH_BMP_WRITER_) // byte-align structures #include "irrpack.h" struct SBMPHeader { u16 Id; // BM - Windows 3.1x, 95, NT, 98, 2000, ME, XP // BA - OS/2 Bitmap Array // CI - OS/2 Color Icon // CP - OS/2 Color Pointer // IC - OS/2 Icon // PT - OS/2 Pointer u32 FileSize; u32 Reserved; u32 BitmapDataOffset; u32 BitmapHeaderSize; // should be 28h for windows bitmaps or // 0Ch for OS/2 1.x or F0h for OS/2 2.x u32 Width; u32 Height; u16 Planes; u16 BPP; // 1: Monochrome bitmap // 4: 16 color bitmap // 8: 256 color bitmap // 16: 16bit (high color) bitmap // 24: 24bit (true color) bitmap // 32: 32bit (true color) bitmap u32 Compression; // 0: none (Also identified by BI_RGB) // 1: RLE 8-bit / pixel (Also identified by BI_RLE4) // 2: RLE 4-bit / pixel (Also identified by BI_RLE8) // 3: Bitfields (Also identified by BI_BITFIELDS) u32 BitmapDataSize; // Size of the bitmap data in bytes. This number must be rounded to the next 4 byte boundary. u32 PixelPerMeterX; u32 PixelPerMeterY; u32 Colors; u32 ImportantColors; } PACK_STRUCT; // Default alignment #include "irrunpack.h" #endif // defined with loader or writer #ifdef _IRR_COMPILE_WITH_BMP_LOADER_ /*! Surface Loader for Windows bitmaps */ class CImageLoaderBMP : public IImageLoader { public: //! constructor CImageLoaderBMP(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") virtual bool isALoadableFileExtension(const io::path& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! creates a surface from the file virtual IImage* loadImage(io::IReadFile* file) const; private: void decompress8BitRLE(u8*& BmpData, s32 size, s32 width, s32 height, s32 pitch) const; void decompress4BitRLE(u8*& BmpData, s32 size, s32 width, s32 height, s32 pitch) const; }; #endif // compiled with loader } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImageLoaderBMP.cpp0000644000000000000000000002066212574354552020462 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImageLoaderBMP.h" #ifdef _IRR_COMPILE_WITH_BMP_LOADER_ #include "IReadFile.h" #include "SColor.h" #include "CColorConverter.h" #include "CImage.h" #include "os.h" #include "irrString.h" namespace irr { namespace video { //! constructor CImageLoaderBMP::CImageLoaderBMP() { #ifdef _DEBUG setDebugName("CImageLoaderBMP"); #endif } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") bool CImageLoaderBMP::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "bmp" ); } //! returns true if the file maybe is able to be loaded by this class bool CImageLoaderBMP::isALoadableFileFormat(io::IReadFile* file) const { u16 headerID; file->read(&headerID, sizeof(u16)); #ifdef __BIG_ENDIAN__ headerID = os::Byteswap::byteswap(headerID); #endif return headerID == 0x4d42; } void CImageLoaderBMP::decompress8BitRLE(u8*& bmpData, s32 size, s32 width, s32 height, s32 pitch) const { u8* p = bmpData; u8* newBmp = new u8[(width+pitch)*height]; u8* d = newBmp; u8* destEnd = newBmp + (width+pitch)*height; s32 line = 0; while (bmpData - p < size && d < destEnd) { if (*p == 0) { ++p; switch(*p) { case 0: // end of line ++p; ++line; d = newBmp + (line*(width+pitch)); break; case 1: // end of bmp delete [] bmpData; bmpData = newBmp; return; case 2: ++p; d +=(u8)*p; // delta ++p; d += ((u8)*p)*(width+pitch); ++p; break; default: { // absolute mode s32 count = (u8)*p; ++p; s32 readAdditional = ((2-(count%2))%2); s32 i; for (i=0; i> readShift) & 0x0f; readShift -= 4; if (readShift < 0) { ++*p; readShift = 4; } u8 mask = 0x0f << shift; *d = (*d & (~mask)) | ((color << shift) & mask); shift -= 4; if (shift < 0) { shift = 4; ++d; } } for (i=0; i> 4) & 0x0f; ++p; for (s32 i=0; iread(&header, sizeof(header)); #ifdef __BIG_ENDIAN__ header.Id = os::Byteswap::byteswap(header.Id); header.FileSize = os::Byteswap::byteswap(header.FileSize); header.BitmapDataOffset = os::Byteswap::byteswap(header.BitmapDataOffset); header.BitmapHeaderSize = os::Byteswap::byteswap(header.BitmapHeaderSize); header.Width = os::Byteswap::byteswap(header.Width); header.Height = os::Byteswap::byteswap(header.Height); header.Planes = os::Byteswap::byteswap(header.Planes); header.BPP = os::Byteswap::byteswap(header.BPP); header.Compression = os::Byteswap::byteswap(header.Compression); header.BitmapDataSize = os::Byteswap::byteswap(header.BitmapDataSize); header.PixelPerMeterX = os::Byteswap::byteswap(header.PixelPerMeterX); header.PixelPerMeterY = os::Byteswap::byteswap(header.PixelPerMeterY); header.Colors = os::Byteswap::byteswap(header.Colors); header.ImportantColors = os::Byteswap::byteswap(header.ImportantColors); #endif s32 pitch = 0; //! return if the header is false if (header.Id != 0x4d42) return 0; if (header.Compression > 2) // we'll only handle RLE-Compression { os::Printer::log("Compression mode not supported.", ELL_ERROR); return 0; } // adjust bitmap data size to dword boundary header.BitmapDataSize += (4-(header.BitmapDataSize%4))%4; // read palette long pos = file->getPos(); s32 paletteSize = (header.BitmapDataOffset - pos) / 4; s32* paletteData = 0; if (paletteSize) { paletteData = new s32[paletteSize]; file->read(paletteData, paletteSize * sizeof(s32)); #ifdef __BIG_ENDIAN__ for (s32 i=0; i(file->getSize()) - header.BitmapDataOffset; } file->seek(header.BitmapDataOffset); f32 t = (header.Width) * (header.BPP / 8.0f); s32 widthInBytes = (s32)t; t -= widthInBytes; if (t!=0.0f) ++widthInBytes; s32 lineData = widthInBytes + ((4-(widthInBytes%4)))%4; pitch = lineData - widthInBytes; u8* bmpData = new u8[header.BitmapDataSize]; file->read(bmpData, header.BitmapDataSize); // decompress data if needed switch(header.Compression) { case 1: // 8 bit rle decompress8BitRLE(bmpData, header.BitmapDataSize, header.Width, header.Height, pitch); break; case 2: // 4 bit rle decompress4BitRLE(bmpData, header.BitmapDataSize, header.Width, header.Height, pitch); break; } // create surface // no default constructor from packed area! ARM problem! core::dimension2d dim; dim.Width = header.Width; dim.Height = header.Height; IImage* image = 0; switch(header.BPP) { case 1: image = new CImage(ECF_A1R5G5B5, dim); if (image) CColorConverter::convert1BitTo16Bit(bmpData, (s16*)image->lock(), header.Width, header.Height, pitch, true); break; case 4: image = new CImage(ECF_A1R5G5B5, dim); if (image) CColorConverter::convert4BitTo16Bit(bmpData, (s16*)image->lock(), header.Width, header.Height, paletteData, pitch, true); break; case 8: image = new CImage(ECF_A1R5G5B5, dim); if (image) CColorConverter::convert8BitTo16Bit(bmpData, (s16*)image->lock(), header.Width, header.Height, paletteData, pitch, true); break; case 16: image = new CImage(ECF_A1R5G5B5, dim); if (image) CColorConverter::convert16BitTo16Bit((s16*)bmpData, (s16*)image->lock(), header.Width, header.Height, pitch, true); break; case 24: image = new CImage(ECF_R8G8B8, dim); if (image) CColorConverter::convert24BitTo24Bit(bmpData, (u8*)image->lock(), header.Width, header.Height, pitch, true, true); break; case 32: // thx to Reinhard Ostermeier image = new CImage(ECF_A8R8G8B8, dim); if (image) CColorConverter::convert32BitTo32Bit((s32*)bmpData, (s32*)image->lock(), header.Width, header.Height, pitch, true); break; }; if (image) image->unlock(); // clean up delete [] paletteData; delete [] bmpData; return image; } //! creates a loader which is able to load windows bitmaps IImageLoader* createImageLoaderBMP() { return new CImageLoaderBMP; } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImage.h0000644000000000000000000000733312574354552016441 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_IMAGE_H_INCLUDED__ #define __C_IMAGE_H_INCLUDED__ #include "IImage.h" #include "rect.h" namespace irr { namespace video { //! IImage implementation with a lot of special image operations for //! 16 bit A1R5G5B5/32 Bit A8R8G8B8 images, which are used by the SoftwareDevice. class CImage : public IImage { public: //! constructor from raw image data /** \param useForeignMemory: If true, the image will use the data pointer directly and own it from now on, which means it will also try to delete [] the data when the image will be destructed. If false, the memory will by copied. */ CImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* data, bool ownForeignMemory=true, bool deleteMemory = true); //! constructor for empty image CImage(ECOLOR_FORMAT format, const core::dimension2d& size); //! destructor virtual ~CImage(); //! Lock function. virtual void* lock() { return Data; } //! Unlock function. virtual void unlock() {} //! Returns width and height of image data. virtual const core::dimension2d& getDimension() const; //! Returns bits per pixel. virtual u32 getBitsPerPixel() const; //! Returns bytes per pixel virtual u32 getBytesPerPixel() const; //! Returns image data size in bytes virtual u32 getImageDataSizeInBytes() const; //! Returns image data size in pixels virtual u32 getImageDataSizeInPixels() const; //! returns mask for red value of a pixel virtual u32 getRedMask() const; //! returns mask for green value of a pixel virtual u32 getGreenMask() const; //! returns mask for blue value of a pixel virtual u32 getBlueMask() const; //! returns mask for alpha value of a pixel virtual u32 getAlphaMask() const; //! returns a pixel virtual SColor getPixel(u32 x, u32 y) const; //! sets a pixel virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ); //! returns the color format virtual ECOLOR_FORMAT getColorFormat() const; //! returns pitch of image virtual u32 getPitch() const { return Pitch; } //! copies this surface into another, scaling it to fit. virtual void copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch=0); //! copies this surface into another, scaling it to fit. virtual void copyToScaling(IImage* target); //! copies this surface into another virtual void copyTo(IImage* target, const core::position2d& pos=core::position2d(0,0)); //! copies this surface into another virtual void copyTo(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect=0); //! copies this surface into another, using the alpha mask, an cliprect and a color to add with virtual void copyToWithAlpha(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const SColor &color, const core::rect* clipRect = 0); //! copies this surface into another, scaling it to fit, appyling a box filter virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false); //! fills the surface with given color virtual void fill(const SColor &color); private: //! assumes format and size has been set and creates the rest void initData(); inline SColor getPixelBox ( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const; u8* Data; core::dimension2d Size; u32 BytesPerPixel; u32 Pitch; ECOLOR_FORMAT Format; bool DeleteMemory; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CImage.cpp0000644000000000000000000002320512574354552016770 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CImage.h" #include "irrString.h" #include "CColorConverter.h" #include "CBlit.h" namespace irr { namespace video { //! Constructor of empty image CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size) :Data(0), Size(size), Format(format), DeleteMemory(true) { initData(); } //! Constructor from raw data CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* data, bool ownForeignMemory, bool deleteForeignMemory) : Data(0), Size(size), Format(format), DeleteMemory(deleteForeignMemory) { if (ownForeignMemory) { Data = (u8*)0xbadf00d; initData(); Data = (u8*)data; } else { Data = 0; initData(); memcpy(Data, data, Size.Height * Pitch); } } //! assumes format and size has been set and creates the rest void CImage::initData() { #ifdef _DEBUG setDebugName("CImage"); #endif BytesPerPixel = getBitsPerPixelFromFormat(Format) / 8; // Pitch should be aligned... Pitch = BytesPerPixel * Size.Width; if (!Data) { DeleteMemory=true; Data = new u8[Size.Height * Pitch]; } } //! destructor CImage::~CImage() { if ( DeleteMemory ) delete [] Data; } //! Returns width and height of image data. const core::dimension2d& CImage::getDimension() const { return Size; } //! Returns bits per pixel. u32 CImage::getBitsPerPixel() const { return getBitsPerPixelFromFormat(Format); } //! Returns bytes per pixel u32 CImage::getBytesPerPixel() const { return BytesPerPixel; } //! Returns image data size in bytes u32 CImage::getImageDataSizeInBytes() const { return Pitch * Size.Height; } //! Returns image data size in pixels u32 CImage::getImageDataSizeInPixels() const { return Size.Width * Size.Height; } //! returns mask for red value of a pixel u32 CImage::getRedMask() const { switch(Format) { case ECF_A1R5G5B5: return 0x1F<<10; case ECF_R5G6B5: return 0x1F<<11; case ECF_R8G8B8: return 0x00FF0000; case ECF_A8R8G8B8: return 0x00FF0000; default: return 0x0; } } //! returns mask for green value of a pixel u32 CImage::getGreenMask() const { switch(Format) { case ECF_A1R5G5B5: return 0x1F<<5; case ECF_R5G6B5: return 0x3F<<5; case ECF_R8G8B8: return 0x0000FF00; case ECF_A8R8G8B8: return 0x0000FF00; default: return 0x0; } } //! returns mask for blue value of a pixel u32 CImage::getBlueMask() const { switch(Format) { case ECF_A1R5G5B5: return 0x1F; case ECF_R5G6B5: return 0x1F; case ECF_R8G8B8: return 0x000000FF; case ECF_A8R8G8B8: return 0x000000FF; default: return 0x0; } } //! returns mask for alpha value of a pixel u32 CImage::getAlphaMask() const { switch(Format) { case ECF_A1R5G5B5: return 0x1<<15; case ECF_R5G6B5: return 0x0; case ECF_R8G8B8: return 0x0; case ECF_A8R8G8B8: return 0xFF000000; default: return 0x0; } } //! sets a pixel void CImage::setPixel(u32 x, u32 y, const SColor &color, bool blend) { if (x >= Size.Width || y >= Size.Height) return; switch(Format) { case ECF_A1R5G5B5: { u16 * dest = (u16*) (Data + ( y * Pitch ) + ( x << 1 )); *dest = video::A8R8G8B8toA1R5G5B5( color.color ); } break; case ECF_R5G6B5: { u16 * dest = (u16*) (Data + ( y * Pitch ) + ( x << 1 )); *dest = video::A8R8G8B8toR5G6B5( color.color ); } break; case ECF_R8G8B8: { u8* dest = Data + ( y * Pitch ) + ( x * 3 ); dest[0] = (u8)color.getRed(); dest[1] = (u8)color.getGreen(); dest[2] = (u8)color.getBlue(); } break; case ECF_A8R8G8B8: { u32 * dest = (u32*) (Data + ( y * Pitch ) + ( x << 2 )); *dest = blend ? PixelBlend32 ( *dest, color.color ) : color.color; } break; #ifndef _DEBUG default: break; #endif } } //! returns a pixel SColor CImage::getPixel(u32 x, u32 y) const { if (x >= Size.Width || y >= Size.Height) return SColor(0); switch(Format) { case ECF_A1R5G5B5: return A1R5G5B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]); case ECF_R5G6B5: return R5G6B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]); case ECF_A8R8G8B8: return ((u32*)Data)[y*Size.Width + x]; case ECF_R8G8B8: { u8* p = Data+(y*3)*Size.Width + (x*3); return SColor(255,p[0],p[1],p[2]); } #ifndef _DEBUG default: break; #endif } return SColor(0); } //! returns the color format ECOLOR_FORMAT CImage::getColorFormat() const { return Format; } //! copies this surface into another at given position void CImage::copyTo(IImage* target, const core::position2d& pos) { Blit(BLITTER_TEXTURE, target, 0, &pos, this, 0, 0); } //! copies this surface partially into another at given position void CImage::copyTo(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect) { Blit(BLITTER_TEXTURE, target, clipRect, &pos, this, &sourceRect, 0); } //! copies this surface into another, using the alpha mask, a cliprect and a color to add with void CImage::copyToWithAlpha(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const SColor &color, const core::rect* clipRect) { // color blend only necessary on not full spectrum aka. color.color != 0xFFFFFFFF Blit(color.color == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND: BLITTER_TEXTURE_ALPHA_COLOR_BLEND, target, clipRect, &pos, this, &sourceRect, color.color); } //! copies this surface into another, scaling it to the target image size // note: this is very very slow. void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch) { if (!target || !width || !height) return; const u32 bpp=getBitsPerPixelFromFormat(format)/8; if (0==pitch) pitch = width*bpp; if (Format==format && Size.Width==width && Size.Height==height) { if (pitch==Pitch) { memcpy(target, Data, height*pitch); return; } else { u8* tgtpos = (u8*) target; u8* srcpos = Data; const u32 bwidth = width*bpp; const u32 rest = pitch-bwidth; for (u32 y=0; y& targetSize = target->getDimension(); if (targetSize==Size) { copyTo(target); return; } copyToScaling(target->lock(), targetSize.Width, targetSize.Height, target->getColorFormat()); target->unlock(); } //! copies this surface into another, scaling it to fit it. void CImage::copyToScalingBoxFilter(IImage* target, s32 bias, bool blend) { const core::dimension2d destSize = target->getDimension(); const f32 sourceXStep = (f32) Size.Width / (f32) destSize.Width; const f32 sourceYStep = (f32) Size.Height / (f32) destSize.Height; target->lock(); s32 fx = core::ceil32( sourceXStep ); s32 fy = core::ceil32( sourceYStep ); f32 sx; f32 sy; sy = 0.f; for ( u32 y = 0; y != destSize.Height; ++y ) { sx = 0.f; for ( u32 x = 0; x != destSize.Width; ++x ) { target->setPixel( x, y, getPixelBox( core::floor32(sx), core::floor32(sy), fx, fy, bias ), blend ); sx += sourceXStep; } sy += sourceYStep; } target->unlock(); } //! fills the surface with given color void CImage::fill(const SColor &color) { u32 c; switch ( Format ) { case ECF_A1R5G5B5: c = color.toA1R5G5B5(); c |= c << 16; break; case ECF_R5G6B5: c = video::A8R8G8B8toR5G6B5( color.color ); c |= c << 16; break; case ECF_A8R8G8B8: c = color.color; break; case ECF_R8G8B8: { u8 rgb[3]; CColorConverter::convert_A8R8G8B8toR8G8B8(&color, 1, rgb); const u32 size = getImageDataSizeInBytes(); for (u32 i=0; i> sdiv ) + bias, 0, 255 ); r = core::s32_clamp( ( r >> sdiv ) + bias, 0, 255 ); g = core::s32_clamp( ( g >> sdiv ) + bias, 0, 255 ); b = core::s32_clamp( ( b >> sdiv ) + bias, 0, 255 ); c.set( a, r, g, b ); return c; } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CGUIWindow.h0000644000000000000000000000530612574354552017231 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_WINDOW_H_INCLUDED__ #define __C_GUI_WINDOW_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIWindow.h" namespace irr { namespace gui { class IGUIButton; class CGUIWindow : public IGUIWindow { public: //! constructor CGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle); //! destructor virtual ~CGUIWindow(); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! update absolute position virtual void updateAbsolutePosition(); //! draws the element and its children virtual void draw(); //! Returns pointer to the close button virtual IGUIButton* getCloseButton() const; //! Returns pointer to the minimize button virtual IGUIButton* getMinimizeButton() const; //! Returns pointer to the maximize button virtual IGUIButton* getMaximizeButton() const; //! Returns true if the window is draggable, false if not virtual bool isDraggable() const; //! Sets whether the window is draggable virtual void setDraggable(bool draggable); //! Set if the window background will be drawn virtual void setDrawBackground(bool draw); //! Get if the window background will be drawn virtual bool getDrawBackground() const; //! Set if the window titlebar will be drawn //! Note: If the background is not drawn, then the titlebar is automatically also not drawn virtual void setDrawTitlebar(bool draw); //! Get if the window titlebar will be drawn virtual bool getDrawTitlebar() const; //! Returns the rectangle of the drawable area (without border and without titlebar) virtual core::rect getClientRect() const; //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); protected: void updateClientRect(); void refreshSprites(); IGUIButton* CloseButton; IGUIButton* MinButton; IGUIButton* RestoreButton; core::rect ClientRect; video::SColor CurrentIconColor; core::position2d DragStart; bool Dragging, IsDraggable; bool DrawBackground; bool DrawTitlebar; bool IsActive; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif irrlicht-1.8.3/source/Irrlicht/CGUIWindow.cpp0000644000000000000000000002516212574354552017566 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIWindow.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIButton.h" #include "IGUIFont.h" #include "IGUIFontBitmap.h" namespace irr { namespace gui { //! constructor CGUIWindow::CGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIWindow(environment, parent, id, rectangle), Dragging(false), IsDraggable(true), DrawBackground(true), DrawTitlebar(true), IsActive(false) { #ifdef _DEBUG setDebugName("CGUIWindow"); #endif IGUISkin* skin = 0; if (environment) skin = environment->getSkin(); CurrentIconColor = video::SColor(255,255,255,255); s32 buttonw = 15; if (skin) { buttonw = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); } s32 posx = RelativeRect.getWidth() - buttonw - 4; CloseButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close" ); CloseButton->setSubElement(true); CloseButton->setTabStop(false); CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); posx -= buttonw + 2; RestoreButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_RESTORE) : L"Restore" ); RestoreButton->setVisible(false); RestoreButton->setSubElement(true); RestoreButton->setTabStop(false); RestoreButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); posx -= buttonw + 2; MinButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_MINIMIZE) : L"Minimize" ); MinButton->setVisible(false); MinButton->setSubElement(true); MinButton->setTabStop(false); MinButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); MinButton->grab(); RestoreButton->grab(); CloseButton->grab(); // this element is a tab group setTabGroup(true); setTabStop(true); setTabOrder(-1); refreshSprites(); updateClientRect(); } //! destructor CGUIWindow::~CGUIWindow() { if (MinButton) MinButton->drop(); if (RestoreButton) RestoreButton->drop(); if (CloseButton) CloseButton->drop(); } void CGUIWindow::refreshSprites() { if (!Environment) return; IGUISkin* skin = Environment->getSkin(); if ( !skin ) return; IGUISpriteBank* sprites = skin->getSpriteBank(); if ( !sprites ) return; CurrentIconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL); if (sprites) { CloseButton->setSpriteBank(sprites); CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), CurrentIconColor); CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), CurrentIconColor); RestoreButton->setSpriteBank(sprites); RestoreButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_RESTORE), CurrentIconColor); RestoreButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_RESTORE), CurrentIconColor); MinButton->setSpriteBank(sprites); MinButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_MINIMIZE), CurrentIconColor); MinButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_MINIMIZE), CurrentIconColor); } } //! called if an event happened. bool CGUIWindow::OnEvent(const SEvent& event) { if (isEnabled()) { switch(event.EventType) { case EET_GUI_EVENT: if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) { Dragging = false; IsActive = false; } else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED) { if (Parent && ((event.GUIEvent.Caller == this) || isMyChild(event.GUIEvent.Caller))) { Parent->bringToFront(this); IsActive = true; } else { IsActive = false; } } else if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) { if (event.GUIEvent.Caller == CloseButton) { if (Parent) { // send close event to parent SEvent e; e.EventType = EET_GUI_EVENT; e.GUIEvent.Caller = this; e.GUIEvent.Element = 0; e.GUIEvent.EventType = EGET_ELEMENT_CLOSED; // if the event was not absorbed if (!Parent->OnEvent(e)) remove(); return true; } else { remove(); return true; } } } break; case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; Dragging = IsDraggable; if (Parent) Parent->bringToFront(this); return true; case EMIE_LMOUSE_LEFT_UP: Dragging = false; return true; case EMIE_MOUSE_MOVED: if (!event.MouseInput.isLeftPressed()) Dragging = false; if (Dragging) { // gui window should not be dragged outside its parent if (Parent && (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 || event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 || event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 || event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1)) return true; move(core::position2d(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y)); DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; return true; } break; default: break; } default: break; } } return IGUIElement::OnEvent(event); } //! Updates the absolute position. void CGUIWindow::updateAbsolutePosition() { IGUIElement::updateAbsolutePosition(); } //! draws the element and its children void CGUIWindow::draw() { if (IsVisible) { IGUISkin* skin = Environment->getSkin(); // update each time because the skin is allowed to change this always. updateClientRect(); if ( CurrentIconColor != skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL) ) refreshSprites(); core::rect rect = AbsoluteRect; // draw body fast if (DrawBackground) { rect = skin->draw3DWindowBackground(this, DrawTitlebar, skin->getColor(IsActive ? EGDC_ACTIVE_BORDER : EGDC_INACTIVE_BORDER), AbsoluteRect, &AbsoluteClippingRect); if (DrawTitlebar && Text.size()) { rect.UpperLeftCorner.X += skin->getSize(EGDS_TITLEBARTEXT_DISTANCE_X); rect.UpperLeftCorner.Y += skin->getSize(EGDS_TITLEBARTEXT_DISTANCE_Y); rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5; IGUIFont* font = skin->getFont(EGDF_WINDOW); if (font) { font->draw(Text.c_str(), rect, skin->getColor(IsActive ? EGDC_ACTIVE_CAPTION:EGDC_INACTIVE_CAPTION), false, true, &AbsoluteClippingRect); } } } } IGUIElement::draw(); } //! Returns pointer to the close button IGUIButton* CGUIWindow::getCloseButton() const { return CloseButton; } //! Returns pointer to the minimize button IGUIButton* CGUIWindow::getMinimizeButton() const { return MinButton; } //! Returns pointer to the maximize button IGUIButton* CGUIWindow::getMaximizeButton() const { return RestoreButton; } //! Returns true if the window is draggable, false if not bool CGUIWindow::isDraggable() const { return IsDraggable; } //! Sets whether the window is draggable void CGUIWindow::setDraggable(bool draggable) { IsDraggable = draggable; if (Dragging && !IsDraggable) Dragging = false; } //! Set if the window background will be drawn void CGUIWindow::setDrawBackground(bool draw) { DrawBackground = draw; } //! Get if the window background will be drawn bool CGUIWindow::getDrawBackground() const { return DrawBackground; } //! Set if the window titlebar will be drawn void CGUIWindow::setDrawTitlebar(bool draw) { DrawTitlebar = draw; } //! Get if the window titlebar will be drawn bool CGUIWindow::getDrawTitlebar() const { return DrawTitlebar; } void CGUIWindow::updateClientRect() { if (! DrawBackground ) { ClientRect = core::rect(0,0, AbsoluteRect.getWidth(), AbsoluteRect.getHeight()); return; } IGUISkin* skin = Environment->getSkin(); skin->draw3DWindowBackground(this, DrawTitlebar, skin->getColor(IsActive ? EGDC_ACTIVE_BORDER : EGDC_INACTIVE_BORDER), AbsoluteRect, &AbsoluteClippingRect, &ClientRect); ClientRect -= AbsoluteRect.UpperLeftCorner; } //! Returns the rectangle of the drawable area (without border, without titlebar and without scrollbars) core::rect CGUIWindow::getClientRect() const { return ClientRect; } //! Writes attributes of the element. void CGUIWindow::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUIWindow::serializeAttributes(out,options); out->addBool("IsDraggable", IsDraggable); out->addBool("DrawBackground", DrawBackground); out->addBool("DrawTitlebar", DrawTitlebar); // Currently we can't just serialize attributes of sub-elements. // To do this we either // a) allow further serialization after attribute serialiation (second function, callback or event) // b) add an IGUIElement attribute // c) extend the attribute system to allow attributes to have sub-attributes // We just serialize the most important info for now until we can do one of the above solutions. out->addBool("IsCloseVisible", CloseButton->isVisible()); out->addBool("IsMinVisible", MinButton->isVisible()); out->addBool("IsRestoreVisible", RestoreButton->isVisible()); } //! Reads attributes of the element void CGUIWindow::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUIWindow::deserializeAttributes(in,options); Dragging = false; IsActive = false; IsDraggable = in->getAttributeAsBool("IsDraggable"); DrawBackground = in->getAttributeAsBool("DrawBackground"); DrawTitlebar = in->getAttributeAsBool("DrawTitlebar"); CloseButton->setVisible(in->getAttributeAsBool("IsCloseVisible")); MinButton->setVisible(in->getAttributeAsBool("IsMinVisible")); RestoreButton->setVisible(in->getAttributeAsBool("IsRestoreVisible")); updateClientRect(); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUITreeView.h0000644000000000000000000002446312574354552017521 0ustar rootroot// This file is part of the "Irrlicht Engine". // written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de #ifndef __C_GUI_TREE_VIEW_H_INCLUDED__ #define __C_GUI_TREE_VIEW_H_INCLUDED__ #include "IGUITreeView.h" #include "irrList.h" namespace irr { namespace gui { // forward declarations class IGUIFont; class IGUIScrollBar; class CGUITreeView; //! Node for gui tree view class CGUITreeViewNode : public IGUITreeViewNode { friend class CGUITreeView; public: //! constructor CGUITreeViewNode( CGUITreeView* owner, CGUITreeViewNode* parent ); //! destructor ~CGUITreeViewNode(); //! returns the owner (tree view) of this node virtual IGUITreeView* getOwner() const; //! Returns the parent node of this node. virtual IGUITreeViewNode* getParent() const; //! returns the text of the node virtual const wchar_t* getText() const { return Text.c_str(); } //! sets the text of the node virtual void setText( const wchar_t* text ); //! returns the icon text of the node virtual const wchar_t* getIcon() const { return Icon.c_str(); } //! sets the icon text of the node virtual void setIcon( const wchar_t* icon ); //! returns the image index of the node virtual u32 getImageIndex() const { return ImageIndex; } //! sets the image index of the node virtual void setImageIndex( u32 imageIndex ) { ImageIndex = imageIndex; } //! returns the image index of the node virtual u32 getSelectedImageIndex() const { return SelectedImageIndex; } //! sets the image index of the node virtual void setSelectedImageIndex( u32 imageIndex ) { SelectedImageIndex = imageIndex; } //! returns the user data (void*) of this node virtual void* getData() const { return Data; } //! sets the user data (void*) of this node virtual void setData( void* data ) { Data = data; } //! returns the user data2 (IReferenceCounted) of this node virtual IReferenceCounted* getData2() const { return Data2; } //! sets the user data2 (IReferenceCounted) of this node virtual void setData2( IReferenceCounted* data ) { if( Data2 ) { Data2->drop(); } Data2 = data; if( Data2 ) { Data2->grab(); } } //! returns the child item count virtual u32 getChildCount() const { return Children.getSize(); } //! removes all children (recursive) from this node virtual void clearChildren(); //! returns true if this node has child nodes virtual bool hasChildren() const { return !Children.empty(); } //! Adds a new node behind the last child node. //! \param text text of the new node //! \param icon icon text of the new node //! \param imageIndex index of the image for the new node (-1 = none) //! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) //! \param data user data (void*) of the new node //! \param data2 user data2 (IReferenceCounted*) of the new node //! \return //! returns the new node virtual IGUITreeViewNode* addChildBack( const wchar_t* text, const wchar_t* icon = 0, s32 imageIndex = -1, s32 selectedImageIndex = -1, void* data = 0, IReferenceCounted* data2 = 0); //! Adds a new node before the first child node. //! \param text text of the new node //! \param icon icon text of the new node //! \param imageIndex index of the image for the new node (-1 = none) //! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) //! \param data user data (void*) of the new node //! \param data2 user data2 (IReferenceCounted*) of the new node //! \return //! returns the new node virtual IGUITreeViewNode* addChildFront( const wchar_t* text, const wchar_t* icon = 0, s32 imageIndex = -1, s32 selectedImageIndex = -1, void* data = 0, IReferenceCounted* data2 = 0 ); //! Adds a new node behind the other node. //! The other node has also te be a child node from this node. //! \param text text of the new node //! \param icon icon text of the new node //! \param imageIndex index of the image for the new node (-1 = none) //! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) //! \param data user data (void*) of the new node //! \param data2 user data2 (IReferenceCounted*) of the new node //! \return //! returns the new node or 0 if other is no child node from this virtual IGUITreeViewNode* insertChildAfter( IGUITreeViewNode* other, const wchar_t* text, const wchar_t* icon = 0, s32 imageIndex = -1, s32 selectedImageIndex = -1, void* data = 0, IReferenceCounted* data2 = 0 ); //! Adds a new node before the other node. //! The other node has also te be a child node from this node. //! \param text text of the new node //! \param icon icon text of the new node //! \param imageIndex index of the image for the new node (-1 = none) //! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) //! \param data user data (void*) of the new node //! \param data2 user data2 (IReferenceCounted*) of the new node //! \return //! returns the new node or 0 if other is no child node from this virtual IGUITreeViewNode* insertChildBefore( IGUITreeViewNode* other, const wchar_t* text, const wchar_t* icon = 0, s32 imageIndex = -1, s32 selectedImageIndex = -1, void* data = 0, IReferenceCounted* data2 = 0 ); //! Return the first child note from this node. virtual IGUITreeViewNode* getFirstChild() const; //! Return the last child note from this node. virtual IGUITreeViewNode* getLastChild() const; //! Returns the preverse sibling node from this node. virtual IGUITreeViewNode* getPrevSibling() const; //! Returns the next sibling node from this node. virtual IGUITreeViewNode* getNextSibling() const; //! Returns the next visible (expanded, may be out of scrolling) node from this node. virtual IGUITreeViewNode* getNextVisible() const; //! Deletes a child node. virtual bool deleteChild( IGUITreeViewNode* child ); //! Moves a child node one position up. virtual bool moveChildUp( IGUITreeViewNode* child ); //! Moves a child node one position down. virtual bool moveChildDown( IGUITreeViewNode* child ); //! Returns true if the node is expanded (children are visible). virtual bool getExpanded() const { return Expanded; } //! Sets if the node is expanded. virtual void setExpanded( bool expanded ); //! Returns true if the node is currently selected. virtual bool getSelected() const; //! Sets this node as selected. virtual void setSelected( bool selected ); //! Returns true if this node is the root node. virtual bool isRoot() const; //! Returns the level of this node. virtual s32 getLevel() const; //! Returns true if this node is visible (all parents are expanded). virtual bool isVisible() const; private: CGUITreeView* Owner; CGUITreeViewNode* Parent; core::stringw Text; core::stringw Icon; s32 ImageIndex; s32 SelectedImageIndex; void* Data; IReferenceCounted* Data2; bool Expanded; core::list Children; }; //! Default tree view GUI element. class CGUITreeView : public IGUITreeView { friend class CGUITreeViewNode; public: //! constructor CGUITreeView( IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool clip = true, bool drawBack = false, bool scrollBarVertical = true, bool scrollBarHorizontal = true ); //! destructor virtual ~CGUITreeView(); //! returns the root node (not visible) from the tree. virtual IGUITreeViewNode* getRoot() const { return Root; } //! returns the selected node of the tree or 0 if none is selected virtual IGUITreeViewNode* getSelected() const { return Selected; } //! returns true if the tree lines are visible virtual bool getLinesVisible() const { return LinesVisible; } //! sets if the tree lines are visible virtual void setLinesVisible( bool visible ) { LinesVisible = visible; } //! called if an event happened. virtual bool OnEvent( const SEvent &event ); //! draws the element and its children virtual void draw(); //! Sets the font which should be used as icon font. This font is set to the Irrlicht engine //! built-in-font by default. Icons can be displayed in front of every list item. //! An icon is a string, displayed with the icon font. When using the build-in-font of the //! Irrlicht engine as icon font, the icon strings defined in GUIIcons.h can be used. virtual void setIconFont( IGUIFont* font ); //! Sets the image list which should be used for the image and selected image of every node. //! The default is 0 (no images). virtual void setImageList( IGUIImageList* imageList ); //! Returns the image list which is used for the nodes. virtual IGUIImageList* getImageList() const { return ImageList; } //! Sets if the image is left of the icon. Default is true. virtual void setImageLeftOfIcon( bool bLeftOf ) { ImageLeftOfIcon = bLeftOf; } //! Returns if the Image is left of the icon. Default is true. virtual bool getImageLeftOfIcon() const { return ImageLeftOfIcon; } //! Returns the node which is associated to the last event. virtual IGUITreeViewNode* getLastEventNode() const { return LastEventNode; } private: //! calculates the heigth of an node and of all visible nodes. void recalculateItemHeight(); //! executes an mouse action (like selectNew of CGUIListBox) void mouseAction( s32 xpos, s32 ypos, bool onlyHover = false ); CGUITreeViewNode* Root; IGUITreeViewNode* Selected; s32 ItemHeight; s32 IndentWidth; s32 TotalItemHeight; s32 TotalItemWidth; IGUIFont* Font; IGUIFont* IconFont; IGUIScrollBar* ScrollBarH; IGUIScrollBar* ScrollBarV; IGUIImageList* ImageList; IGUITreeViewNode* LastEventNode; bool LinesVisible; bool Selecting; bool Clip; bool DrawBack; bool ImageLeftOfIcon; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CGUITreeView.cpp0000644000000000000000000006344512574354552020057 0ustar rootroot// This file is part of the "Irrlicht Engine". // written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de // expaned by burningwater #include "CGUITreeView.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIFont.h" #include "CGUIScrollBar.h" #include "os.h" namespace irr { namespace gui { CGUITreeViewNode::CGUITreeViewNode( CGUITreeView* owner, CGUITreeViewNode* parent ) : Owner(owner), Parent(parent), ImageIndex(-1), SelectedImageIndex(-1), Data(0), Data2(0), Expanded(false) { #ifdef _DEBUG setDebugName( "CGUITreeView" ); #endif } CGUITreeViewNode::~CGUITreeViewNode() { if( Owner && this == Owner->getSelected() ) { setSelected( false ); } clearChildren(); if( Data2 ) { Data2->drop(); } } IGUITreeView* CGUITreeViewNode::getOwner() const { return Owner; } IGUITreeViewNode* CGUITreeViewNode::getParent() const { return Parent; } void CGUITreeViewNode::setText( const wchar_t* text ) { Text = text; } void CGUITreeViewNode::setIcon( const wchar_t* icon ) { Icon = icon; } void CGUITreeViewNode::clearChildren() { core::list::Iterator it; for( it = Children.begin(); it != Children.end(); it++ ) { ( *it )->drop(); } Children.clear(); } IGUITreeViewNode* CGUITreeViewNode::addChildBack( const wchar_t* text, const wchar_t* icon /*= 0*/, s32 imageIndex /*= -1*/, s32 selectedImageIndex /*= -1*/, void* data /*= 0*/, IReferenceCounted* data2 /*= 0*/ ) { CGUITreeViewNode* newChild = new CGUITreeViewNode( Owner, this ); Children.push_back( newChild ); newChild->Text = text; newChild->Icon = icon; newChild->ImageIndex = imageIndex; newChild->SelectedImageIndex = selectedImageIndex; newChild->Data = data; newChild->Data2 = data2; if( data2 ) { data2->grab(); } return newChild; } IGUITreeViewNode* CGUITreeViewNode::addChildFront( const wchar_t* text, const wchar_t* icon /*= 0*/, s32 imageIndex /*= -1*/, s32 selectedImageIndex /*= -1*/, void* data /*= 0*/, IReferenceCounted* data2 /*= 0*/ ) { CGUITreeViewNode* newChild = new CGUITreeViewNode( Owner, this ); Children.push_front( newChild ); newChild->Text = text; newChild->Icon = icon; newChild->ImageIndex = imageIndex; newChild->SelectedImageIndex = selectedImageIndex; newChild->Data = data; newChild->Data2 = data2; if( data2 ) { data2->grab(); } return newChild; } IGUITreeViewNode* CGUITreeViewNode::insertChildAfter( IGUITreeViewNode* other, const wchar_t* text, const wchar_t* icon /*= 0*/, s32 imageIndex /*= -1*/, s32 selectedImageIndex /*= -1*/, void* data /*= 0*/, IReferenceCounted* data2/* = 0*/ ) { core::list::Iterator itOther; CGUITreeViewNode* newChild = 0; for( itOther = Children.begin(); itOther != Children.end(); itOther++ ) { if( other == *itOther ) { newChild = new CGUITreeViewNode( Owner, this ); newChild->Text = text; newChild->Icon = icon; newChild->ImageIndex = imageIndex; newChild->SelectedImageIndex = selectedImageIndex; newChild->Data = data; newChild->Data2 = data2; if( data2 ) { data2->grab(); } Children.insert_after( itOther, newChild ); break; } } return newChild; } IGUITreeViewNode* CGUITreeViewNode::insertChildBefore( IGUITreeViewNode* other, const wchar_t* text, const wchar_t* icon /*= 0*/, s32 imageIndex /*= -1*/, s32 selectedImageIndex /*= -1*/, void* data /*= 0*/, IReferenceCounted* data2/* = 0*/ ) { core::list::Iterator itOther; CGUITreeViewNode* newChild = 0; for( itOther = Children.begin(); itOther != Children.end(); itOther++ ) { if( other == *itOther ) { newChild = new CGUITreeViewNode( Owner, this ); newChild->Text = text; newChild->Icon = icon; newChild->ImageIndex = imageIndex; newChild->SelectedImageIndex = selectedImageIndex; newChild->Data = data; newChild->Data2 = data2; if( data2 ) { data2->grab(); } Children.insert_before( itOther, newChild ); break; } } return newChild; } IGUITreeViewNode* CGUITreeViewNode::getFirstChild() const { if( Children.empty() ) { return 0; } else { return *( Children.begin() ); } } IGUITreeViewNode* CGUITreeViewNode::getLastChild() const { if( Children.empty() ) { return 0; } else { return *( Children.getLast() ); } } IGUITreeViewNode* CGUITreeViewNode::getPrevSibling() const { core::list::Iterator itThis; core::list::Iterator itOther; CGUITreeViewNode* other = 0; if( Parent ) { for( itThis = Parent->Children.begin(); itThis != Parent->Children.end(); itThis++ ) { if( this == *itThis ) { if( itThis != Parent->Children.begin() ) { other = *itOther; } break; } itOther = itThis; } } return other; } IGUITreeViewNode* CGUITreeViewNode::getNextSibling() const { core::list::Iterator itThis; CGUITreeViewNode* other = 0; if( Parent ) { for( itThis = Parent->Children.begin(); itThis != Parent->Children.end(); itThis++ ) { if( this == *itThis ) { if( itThis != Parent->Children.getLast() ) { other = *( ++itThis ); } break; } } } return other; } IGUITreeViewNode* CGUITreeViewNode::getNextVisible() const { IGUITreeViewNode* next = 0; IGUITreeViewNode* node = 0; node = const_cast( this ); if( node->getExpanded() && node->hasChildren() ) { next = node->getFirstChild(); } else { next = node->getNextSibling(); } while( !next && node->getParent() ) { next = node->getParent()->getNextSibling(); if( !next ) { node = node->getParent(); } } return next; } bool CGUITreeViewNode::deleteChild( IGUITreeViewNode* child ) { core::list::Iterator itChild; bool deleted = false; for( itChild = Children.begin(); itChild != Children.end(); itChild++ ) { if( child == *itChild ) { child->drop(); Children.erase( itChild ); deleted = true; break; } } return deleted; } bool CGUITreeViewNode::moveChildUp( IGUITreeViewNode* child ) { core::list::Iterator itChild; core::list::Iterator itOther; CGUITreeViewNode* nodeTmp; bool moved = false; for( itChild = Children.begin(); itChild != Children.end(); itChild++ ) { if( child == *itChild ) { if( itChild != Children.begin() ) { nodeTmp = *itChild; *itChild = *itOther; *itOther = nodeTmp; moved = true; } break; } itOther = itChild; } return moved; } bool CGUITreeViewNode::moveChildDown( IGUITreeViewNode* child ) { core::list::Iterator itChild; core::list::Iterator itOther; CGUITreeViewNode* nodeTmp; bool moved = false; for( itChild = Children.begin(); itChild != Children.end(); itChild++ ) { if( child == *itChild ) { if( itChild != Children.getLast() ) { itOther = itChild; ++itOther; nodeTmp = *itChild; *itChild = *itOther; *itOther = nodeTmp; moved = true; } break; } } return moved; } void CGUITreeViewNode::setExpanded( bool expanded ) { Expanded = expanded; } void CGUITreeViewNode::setSelected( bool selected ) { if( Owner ) { if( selected ) { Owner->Selected = this; } else { if( Owner->Selected == this ) { Owner->Selected = 0; } } } } bool CGUITreeViewNode::getSelected() const { if( Owner ) { return Owner->Selected == (IGUITreeViewNode*)this; } else { return false; } } bool CGUITreeViewNode::isRoot() const { return ( Owner && ( this == Owner->Root ) ); } s32 CGUITreeViewNode::getLevel() const { if( Parent ) { return Parent->getLevel() + 1; } else { return 0; } } bool CGUITreeViewNode::isVisible() const { if( Parent ) { return Parent->getExpanded() && Parent->isVisible(); } else { return true; } } //! constructor CGUITreeView::CGUITreeView(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool clip, bool drawBack,bool scrollBarVertical, bool scrollBarHorizontal) : IGUITreeView( environment, parent, id, rectangle ), Root(0), Selected(0), ItemHeight( 0 ), IndentWidth( 0 ), TotalItemHeight( 0 ), TotalItemWidth ( 0 ), Font( 0 ), IconFont( 0 ), ScrollBarH( 0 ), ScrollBarV( 0 ), ImageList( 0 ), LastEventNode( 0 ), LinesVisible( true ), Selecting( false ), Clip( clip ), DrawBack( drawBack ), ImageLeftOfIcon( true ) { #ifdef _DEBUG setDebugName( "CGUITreeView" ); #endif IGUISkin* skin = Environment->getSkin(); s32 s = skin->getSize( EGDS_SCROLLBAR_SIZE ); if ( scrollBarVertical ) { ScrollBarV = new CGUIScrollBar( false, Environment, this, 0, core::rect( RelativeRect.getWidth() - s, 0, RelativeRect.getWidth(), RelativeRect.getHeight() - (scrollBarHorizontal ? s : 0 ) ), !clip ); ScrollBarV->drop(); ScrollBarV->setSubElement(true); ScrollBarV->setPos( 0 ); ScrollBarV->grab(); } if ( scrollBarHorizontal ) { ScrollBarH = new CGUIScrollBar( true, Environment, this, 1, core::rect( 0, RelativeRect.getHeight() - s, RelativeRect.getWidth() - s, RelativeRect.getHeight() ), !clip ); ScrollBarH->drop(); ScrollBarH->setSubElement(true); ScrollBarH->setPos( 0 ); ScrollBarH->grab(); } Root = new CGUITreeViewNode( this, 0 ); Root->Expanded = true; recalculateItemHeight(); } //! destructor CGUITreeView::~CGUITreeView() { if( ScrollBarV ) { ScrollBarV->drop(); } if( ScrollBarH ) { ScrollBarH->drop(); } if( Font ) { Font->drop(); } if( IconFont ) { IconFont->drop(); } if( ImageList ) { ImageList->drop(); } if( Root ) { Root->drop(); } } void CGUITreeView::recalculateItemHeight() { IGUISkin* skin = Environment->getSkin(); IGUITreeViewNode* node; if( Font != skin->getFont() ) { if( Font ) { Font->drop(); } Font = skin->getFont(); ItemHeight = 0; if( Font ) { ItemHeight = Font->getDimension( L"A" ).Height + 4; Font->grab(); } if( IconFont ) { s32 height = IconFont->getDimension( L" " ).Height; if( height > ItemHeight ) { ItemHeight = height; } } if( ImageList ) { if( ImageList->getImageSize().Height + 1 > ItemHeight ) { ItemHeight = ImageList->getImageSize().Height + 1; } } } IndentWidth = ItemHeight; if( IndentWidth < 9 ) { IndentWidth = 9; } else if( IndentWidth > 15 ) { IndentWidth = 15; } else { if( ( ( IndentWidth >> 1 ) << 1 ) - IndentWidth == 0 ) { --IndentWidth; } } TotalItemHeight = 0; TotalItemWidth = AbsoluteRect.getWidth() * 2; node = Root->getFirstChild(); while( node ) { TotalItemHeight += ItemHeight; node = node->getNextVisible(); } if ( ScrollBarV ) ScrollBarV->setMax( core::max_(0,TotalItemHeight - AbsoluteRect.getHeight()) ); if ( ScrollBarH ) ScrollBarH->setMax( core::max_(0, TotalItemWidth - AbsoluteRect.getWidth()) ); } //! called if an event happened. bool CGUITreeView::OnEvent( const SEvent &event ) { if ( isEnabled() ) { switch( event.EventType ) { case EET_GUI_EVENT: switch( event.GUIEvent.EventType ) { case gui::EGET_SCROLL_BAR_CHANGED: if( event.GUIEvent.Caller == ScrollBarV || event.GUIEvent.Caller == ScrollBarH ) { //s32 pos = ( ( gui::IGUIScrollBar* )event.GUIEvent.Caller )->getPos(); return true; } break; case gui::EGET_ELEMENT_FOCUS_LOST: { Selecting = false; return false; } break; default: break; } break; case EET_MOUSE_INPUT_EVENT: { core::position2d p( event.MouseInput.X, event.MouseInput.Y ); switch( event.MouseInput.Event ) { case EMIE_MOUSE_WHEEL: if ( ScrollBarV ) ScrollBarV->setPos( ScrollBarV->getPos() + (event.MouseInput.Wheel < 0 ? -1 : 1) * -10 ); return true; break; case EMIE_LMOUSE_PRESSED_DOWN: if (Environment->hasFocus(this) && !AbsoluteClippingRect.isPointInside(p) ) { Environment->removeFocus(this); return false; } if( Environment->hasFocus( this ) && ( ( ScrollBarV && ScrollBarV->getAbsolutePosition().isPointInside( p ) && ScrollBarV->OnEvent( event ) ) || ( ScrollBarH && ScrollBarH->getAbsolutePosition().isPointInside( p ) && ScrollBarH->OnEvent( event ) ) ) ) { return true; } Selecting = true; Environment->setFocus( this ); return true; break; case EMIE_LMOUSE_LEFT_UP: if( Environment->hasFocus( this ) && ( ( ScrollBarV && ScrollBarV->getAbsolutePosition().isPointInside( p ) && ScrollBarV->OnEvent( event ) ) || ( ScrollBarH && ScrollBarH->getAbsolutePosition().isPointInside( p ) && ScrollBarH->OnEvent( event ) ) ) ) { return true; } Selecting = false; Environment->removeFocus( this ); mouseAction( event.MouseInput.X, event.MouseInput.Y ); return true; break; case EMIE_MOUSE_MOVED: if( Selecting ) { if( getAbsolutePosition().isPointInside( p ) ) { mouseAction( event.MouseInput.X, event.MouseInput.Y, true ); return true; } } break; default: break; } } break; default: break; } } return Parent ? Parent->OnEvent( event ) : false; } /*! */ void CGUITreeView::mouseAction( s32 xpos, s32 ypos, bool onlyHover /*= false*/ ) { IGUITreeViewNode* oldSelected = Selected; IGUITreeViewNode* hitNode = 0; s32 selIdx=-1; s32 n; IGUITreeViewNode* node; SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; xpos -= AbsoluteRect.UpperLeftCorner.X; ypos -= AbsoluteRect.UpperLeftCorner.Y; // find new selected item. if( ItemHeight != 0 && ScrollBarV ) { selIdx = ( ( ypos - 1 ) + ScrollBarV->getPos() ) / ItemHeight; } hitNode = 0; node = Root->getFirstChild(); n = 0; while( node ) { if( selIdx == n ) { hitNode = node; break; } node = node->getNextVisible(); ++n; } if( hitNode && xpos > hitNode->getLevel() * IndentWidth ) { Selected = hitNode; } if( hitNode && !onlyHover && xpos < hitNode->getLevel() * IndentWidth && xpos > ( hitNode->getLevel() - 1 ) * IndentWidth && hitNode->hasChildren() ) { hitNode->setExpanded( !hitNode->getExpanded() ); // post expand/collaps news if( hitNode->getExpanded() ) { event.GUIEvent.EventType = EGET_TREEVIEW_NODE_EXPAND; } else { event.GUIEvent.EventType = EGET_TREEVIEW_NODE_COLLAPS; } LastEventNode = hitNode; Parent->OnEvent( event ); LastEventNode = 0; } if( Selected && !Selected->isVisible() ) { Selected = 0; } // post selection news if( Parent && !onlyHover && Selected != oldSelected ) { if( oldSelected ) { event.GUIEvent.EventType = EGET_TREEVIEW_NODE_DESELECT; LastEventNode = oldSelected; Parent->OnEvent( event ); LastEventNode = 0; } if( Selected ) { event.GUIEvent.EventType = EGET_TREEVIEW_NODE_SELECT; LastEventNode = Selected; Parent->OnEvent( event ); LastEventNode = 0; } } } //! draws the element and its children void CGUITreeView::draw() { if( !IsVisible ) { return; } recalculateItemHeight(); // if the font changed IGUISkin* skin = Environment->getSkin(); irr::video::IVideoDriver* driver = Environment->getVideoDriver(); core::rect* clipRect = 0; if( Clip ) { clipRect = &AbsoluteClippingRect; } // draw background core::rect frameRect( AbsoluteRect ); if( DrawBack ) { driver->draw2DRectangle( skin->getColor( EGDC_3D_HIGH_LIGHT ), frameRect, clipRect ); } // draw the border frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + 1; driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), frameRect, clipRect ); frameRect.LowerRightCorner.Y = AbsoluteRect.LowerRightCorner.Y; frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + 1; driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), frameRect, clipRect ); frameRect = AbsoluteRect; frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X - 1; driver->draw2DRectangle( skin->getColor( EGDC_3D_HIGH_LIGHT ), frameRect, clipRect ); frameRect = AbsoluteRect; frameRect.UpperLeftCorner.Y = AbsoluteRect.LowerRightCorner.Y - 1; frameRect.LowerRightCorner.Y = AbsoluteRect.LowerRightCorner.Y; driver->draw2DRectangle( skin->getColor( EGDC_3D_HIGH_LIGHT ), frameRect, clipRect ); // draw items core::rect clientClip( AbsoluteRect ); clientClip.UpperLeftCorner.Y += 1; clientClip.UpperLeftCorner.X += 1; clientClip.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X; clientClip.LowerRightCorner.Y -= 1; if ( ScrollBarV ) clientClip.LowerRightCorner.X -= skin->getSize( EGDS_SCROLLBAR_SIZE ); if ( ScrollBarH ) clientClip.LowerRightCorner.Y -= skin->getSize( EGDS_SCROLLBAR_SIZE ); if( clipRect ) { clientClip.clipAgainst( *clipRect ); } frameRect = AbsoluteRect; frameRect.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize( EGDS_SCROLLBAR_SIZE ); frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight; if ( ScrollBarV ) { frameRect.UpperLeftCorner.Y -= ScrollBarV->getPos(); frameRect.LowerRightCorner.Y -= ScrollBarV->getPos(); } if ( ScrollBarH ) { frameRect.UpperLeftCorner.X -= ScrollBarH->getPos(); frameRect.LowerRightCorner.X -= ScrollBarH->getPos(); } IGUITreeViewNode* node = Root->getFirstChild(); while( node ) { frameRect.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X + 1 + node->getLevel() * IndentWidth; if( frameRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y && frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y ) { if( node == Selected ) { driver->draw2DRectangle( skin->getColor( EGDC_HIGH_LIGHT ), frameRect, &clientClip ); } if( node->hasChildren() ) { core::rect rc; core::rect expanderRect; expanderRect.UpperLeftCorner.X = frameRect.UpperLeftCorner.X - IndentWidth + 2; expanderRect.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y + ( ( frameRect.getHeight() - ( IndentWidth - 4 ) ) >> 1 ); expanderRect.LowerRightCorner.X = expanderRect.UpperLeftCorner.X + IndentWidth - 4; expanderRect.LowerRightCorner.Y = expanderRect.UpperLeftCorner.Y + IndentWidth - 4; // box upper line rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X; rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y; rc.LowerRightCorner.X = expanderRect.LowerRightCorner.X; rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + 1; driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, clipRect ); // box left line rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X; rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y; rc.LowerRightCorner.X = rc.UpperLeftCorner.X + 1; rc.LowerRightCorner.Y = expanderRect.LowerRightCorner.Y; driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, clipRect ); // box right line rc.UpperLeftCorner.X = expanderRect.LowerRightCorner.X - 1; rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y; rc.LowerRightCorner.X = rc.UpperLeftCorner.X + 1; rc.LowerRightCorner.Y = expanderRect.LowerRightCorner.Y; driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, clipRect ); // box bottom line rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X; rc.UpperLeftCorner.Y = expanderRect.LowerRightCorner.Y - 1; rc.LowerRightCorner.X = expanderRect.LowerRightCorner.X; rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + 1; driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, clipRect ); // horizontal '-' line rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X + 2; rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y + ( expanderRect.getHeight() >> 1 ); rc.LowerRightCorner.X = rc.UpperLeftCorner.X + expanderRect.getWidth() - 4; rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + 1; driver->draw2DRectangle( skin->getColor( EGDC_BUTTON_TEXT ), rc, clipRect ); if( !node->getExpanded() ) { // vertical '+' line rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X + ( expanderRect.getWidth() >> 1 ); rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y + 2; rc.LowerRightCorner.X = rc.UpperLeftCorner.X + 1; rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + expanderRect.getHeight() - 4; driver->draw2DRectangle( skin->getColor( EGDC_BUTTON_TEXT ), rc, clipRect ); } } core::rect textRect = frameRect; if( Font ) { EGUI_DEFAULT_COLOR textCol = EGDC_GRAY_TEXT; if ( isEnabled() ) textCol = ( node == Selected ) ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT; s32 iconWidth = 0; for( s32 n = 0; n < 2; ++n ) { s32 index = node->getImageIndex(); if( ( ImageList && index >= 0 ) && ( ( ImageLeftOfIcon && n == 0 ) || ( !ImageLeftOfIcon && n == 1 ) ) ) { index = node->getSelectedImageIndex(); if( node != Selected || index < 0 ) { index = node->getImageIndex(); } ImageList->draw( index, core::position2d( textRect.UpperLeftCorner.X, textRect.UpperLeftCorner.Y + ( ( textRect.getHeight() - ImageList->getImageSize().Height ) >> 1 ) ), &clientClip ); iconWidth += ImageList->getImageSize().Width + 3; textRect.UpperLeftCorner.X += ImageList->getImageSize().Width + 3; } else if( ( IconFont && reinterpret_cast( node )->Icon.size() ) && ( ( ImageLeftOfIcon && n == 1 ) || ( !ImageLeftOfIcon && n == 0 ) ) ) { IconFont->draw( node->getIcon(), textRect, skin->getColor(textCol), false, true, &clientClip ); iconWidth += IconFont->getDimension( node->getIcon() ).Width + 3; textRect.UpperLeftCorner.X += IconFont->getDimension( node->getIcon() ).Width + 3; } } Font->draw( node->getText(), textRect, skin->getColor(textCol), false, true, &clientClip ); textRect.UpperLeftCorner.X -= iconWidth; } // draw the lines if neccessary if( LinesVisible ) { core::rect rc; // horizontal line rc.UpperLeftCorner.X = frameRect.UpperLeftCorner.X - IndentWidth - ( IndentWidth >> 1 ) - 1; rc.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y + ( ( frameRect.getHeight() ) >> 1 ); if( node->hasChildren() ) { rc.LowerRightCorner.X = frameRect.UpperLeftCorner.X - IndentWidth; } else { rc.LowerRightCorner.X = frameRect.UpperLeftCorner.X - 2; } rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + 1; driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, clipRect ); if( node->getParent() != Root ) { // vertical line if( node == node->getParent()->getFirstChild() ) { rc.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - ( ( frameRect.getHeight() - IndentWidth ) >> 1 ); } else { rc.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - ( frameRect.getHeight() >> 1 ); } rc.LowerRightCorner.X = rc.UpperLeftCorner.X + 1; driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, clipRect ); // the vertical lines of all parents IGUITreeViewNode* nodeTmp = node->getParent(); rc.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - ( frameRect.getHeight() >> 1 ); for( s32 n = 0; n < node->getLevel() - 2; ++n ) { rc.UpperLeftCorner.X -= IndentWidth; rc.LowerRightCorner.X -= IndentWidth; if( nodeTmp != nodeTmp->getParent()->getLastChild() ) { driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, clipRect ); } nodeTmp = nodeTmp->getParent(); } } } } frameRect.UpperLeftCorner.Y += ItemHeight; frameRect.LowerRightCorner.Y += ItemHeight; node = node->getNextVisible(); } IGUIElement::draw(); } //! Sets the font which should be used as icon font. This font is set to the Irrlicht engine //! built-in-font by default. Icons can be displayed in front of every list item. //! An icon is a string, displayed with the icon font. When using the build-in-font of the //! Irrlicht engine as icon font, the icon strings defined in GUIIcons.h can be used. void CGUITreeView::setIconFont( IGUIFont* font ) { s32 height; if ( font ) font->grab(); if ( IconFont ) { IconFont->drop(); } IconFont = font; if( IconFont ) { height = IconFont->getDimension( L" " ).Height; if( height > ItemHeight ) { ItemHeight = height; } } } //! Sets the image list which should be used for the image and selected image of every node. //! The default is 0 (no images). void CGUITreeView::setImageList( IGUIImageList* imageList ) { if (imageList ) imageList->grab(); if( ImageList ) { ImageList->drop(); } ImageList = imageList; if( ImageList ) { if( ImageList->getImageSize().Height + 1 > ItemHeight ) { ItemHeight = ImageList->getImageSize().Height + 1; } } } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIToolBar.h0000644000000000000000000000235712574354552017327 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_TOOL_BAR_H_INCLUDED__ #define __C_GUI_TOOL_BAR_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIToolbar.h" namespace irr { namespace gui { //! Stays at the top of its parent like the menu bar and contains tool buttons class CGUIToolBar : public IGUIToolBar { public: //! constructor CGUIToolBar(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! draws the element and its children virtual void draw(); //! Updates the absolute position. virtual void updateAbsolutePosition(); //! Adds a button to the tool bar virtual IGUIButton* addButton(s32 id=-1, const wchar_t* text=0,const wchar_t* tooltiptext=0, video::ITexture* img=0, video::ITexture* pressed=0, bool isPushButton=false, bool useAlphaChannel=false); private: s32 ButtonX; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif irrlicht-1.8.3/source/Irrlicht/CGUIToolBar.cpp0000644000000000000000000001026712574354552017661 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIToolBar.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIButton.h" #include "IGUIFont.h" #include "CGUIButton.h" namespace irr { namespace gui { //! constructor CGUIToolBar::CGUIToolBar(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) :IGUIToolBar(environment, parent, id, rectangle), ButtonX(5) { #ifdef _DEBUG setDebugName("CGUIToolBar"); #endif // calculate position and find other menubars s32 y = 0; s32 parentwidth = 100; if (parent) { parentwidth = Parent->getAbsolutePosition().getWidth(); const core::list& children = parent->getChildren(); core::list::ConstIterator it = children.begin(); for (; it != children.end(); ++it) { core::rect r = (*it)->getAbsolutePosition(); if (r.UpperLeftCorner.X == 0 && r.UpperLeftCorner.Y <= y && r.LowerRightCorner.X == parentwidth) y = r.LowerRightCorner.Y; } } core::rect rr; rr.UpperLeftCorner.X = 0; rr.UpperLeftCorner.Y = y; s32 height = Environment->getSkin()->getSize ( EGDS_MENU_HEIGHT ); /*IGUISkin* skin = Environment->getSkin(); IGUIFont* font = skin->getFont(); if (font) { s32 t = font->getDimension(L"A").Height + 5; if (t > height) height = t; }*/ rr.LowerRightCorner.X = parentwidth; rr.LowerRightCorner.Y = rr.UpperLeftCorner.Y + height; setRelativePosition(rr); } //! called if an event happened. bool CGUIToolBar::OnEvent(const SEvent& event) { if (isEnabled()) { if (event.EventType == EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { if (AbsoluteClippingRect.isPointInside(core::position2di(event.MouseInput.X, event.MouseInput.Y))) return true; } } return IGUIElement::OnEvent(event); } //! draws the element and its children void CGUIToolBar::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); if (!skin) return; core::rect rect = AbsoluteRect; core::rect* clip = &AbsoluteClippingRect; // draw frame skin->draw3DToolBar(this, rect, clip); IGUIElement::draw(); } //! Updates the absolute position. void CGUIToolBar::updateAbsolutePosition() { if (Parent) { DesiredRect.UpperLeftCorner.X = 0; DesiredRect.LowerRightCorner.X = Parent->getAbsolutePosition().getWidth(); } IGUIElement::updateAbsolutePosition(); } //! Adds a button to the tool bar IGUIButton* CGUIToolBar::addButton(s32 id, const wchar_t* text,const wchar_t* tooltiptext, video::ITexture* img, video::ITexture* pressed, bool isPushButton, bool useAlphaChannel) { ButtonX += 3; core::rect rectangle(ButtonX,2,ButtonX+1,3); if ( img ) { const core::dimension2du &size = img->getOriginalSize(); rectangle.LowerRightCorner.X = rectangle.UpperLeftCorner.X + size.Width + 8; rectangle.LowerRightCorner.Y = rectangle.UpperLeftCorner.Y + size.Height + 6; } if ( text ) { IGUISkin* skin = Environment->getSkin(); IGUIFont * font = skin->getFont(EGDF_BUTTON); if ( font ) { core::dimension2d dim = font->getDimension(text); if ( (s32)dim.Width > rectangle.getWidth() ) rectangle.LowerRightCorner.X = rectangle.UpperLeftCorner.X + dim.Width + 8; if ( (s32)dim.Height > rectangle.getHeight() ) rectangle.LowerRightCorner.Y = rectangle.UpperLeftCorner.Y + dim.Height + 6; } } ButtonX += rectangle.getWidth(); IGUIButton* button = new CGUIButton(Environment, this, id, rectangle); button->drop(); if (text) button->setText(text); if (tooltiptext) button->setToolTipText(tooltiptext); if (img) button->setImage(img); if (pressed) button->setPressedImage(pressed); if (isPushButton) button->setIsPushButton(isPushButton); if (useAlphaChannel) button->setUseAlphaChannel(useAlphaChannel); return button; } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUITable.h0000644000000000000000000001616612574354552017017 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // 07.10.2005 - Multicolor-Listbox addet by A. Buschhueter (Acki) // A_Buschhueter@gmx.de #ifndef __C_GUI_TABLE_BAR_H_INCLUDED__ #define __C_GUI_TABLE_BAR_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUITable.h" #include "irrArray.h" namespace irr { namespace gui { class IGUIFont; class IGUIScrollBar; class CGUITable : public IGUITable { public: //! constructor CGUITable(IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle, bool clip=true, bool drawBack=false, bool moveOverSelect=true); //! destructor ~CGUITable(); //! Adds a column //! If columnIndex is outside the current range, do push new colum at the end virtual void addColumn(const wchar_t* caption, s32 columnIndex=-1); //! remove a column from the table virtual void removeColumn(u32 columnIndex); //! Returns the number of columns in the table control virtual s32 getColumnCount() const; //! Makes a column active. This will trigger an ordering process. /** \param idx: The id of the column to make active. \return True if successful. */ virtual bool setActiveColumn(s32 columnIndex, bool doOrder=false); //! Returns which header is currently active virtual s32 getActiveColumn() const; //! Returns the ordering used by the currently active column virtual EGUI_ORDERING_MODE getActiveColumnOrdering() const; //! set a column width virtual void setColumnWidth(u32 columnIndex, u32 width); //! Get the width of a column virtual u32 getColumnWidth(u32 columnIndex) const; //! columns can be resized by drag 'n drop virtual void setResizableColumns(bool resizable); //! can columns be resized by dran 'n drop? virtual bool hasResizableColumns() const; //! This tells the table control which ordering mode should be used when //! a column header is clicked. /** \param columnIndex: The index of the column header. \param state: If true, a EGET_TABLE_HEADER_CHANGED message will be sent and you can order the table data as you whish.*/ //! \param mode: One of the modes defined in EGUI_COLUMN_ORDERING virtual void setColumnOrdering(u32 columnIndex, EGUI_COLUMN_ORDERING mode); //! Returns which row is currently selected virtual s32 getSelected() const; //! set wich row is currently selected virtual void setSelected( s32 index ); //! Returns amount of rows in the tabcontrol virtual s32 getRowCount() const; //! adds a row to the table /** \param rowIndex: zero based index of rows. The row will be inserted at this position. If a row already exists there, it will be placed after it. If the row is larger than the actual number of rows by more than one, it won't be created. Note that if you create a row that is not at the end, there might be performance issues*/ virtual u32 addRow(u32 rowIndex); //! Remove a row from the table virtual void removeRow(u32 rowIndex); //! clear the table rows, but keep the columns intact virtual void clearRows(); //! Swap two row positions. This is useful for a custom ordering algo. virtual void swapRows(u32 rowIndexA, u32 rowIndexB); //! This tells the table to start ordering all the rows. You //! need to explicitly tell the table to reorder the rows when //! a new row is added or the cells data is changed. This makes //! the system more flexible and doesn't make you pay the cost //! of ordering when adding a lot of rows. //! \param columnIndex: When set to -1 the active column is used. virtual void orderRows(s32 columnIndex=-1, EGUI_ORDERING_MODE mode=EGOM_NONE); //! Set the text of a cell virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text); //! Set the text of a cell, and set a color of this cell. virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color); //! Set the data of a cell //! data will not be serialized. virtual void setCellData(u32 rowIndex, u32 columnIndex, void *data); //! Set the color of a cell text virtual void setCellColor(u32 rowIndex, u32 columnIndex, video::SColor color); //! Get the text of a cell virtual const wchar_t* getCellText(u32 rowIndex, u32 columnIndex ) const; //! Get the data of a cell virtual void* getCellData(u32 rowIndex, u32 columnIndex ) const; //! clears the table, deletes all items in the table virtual void clear(); //! called if an event happened. virtual bool OnEvent(const SEvent &event); //! draws the element and its children virtual void draw(); //! Set flags, as defined in EGUI_TABLE_DRAW_FLAGS, which influence the layout virtual void setDrawFlags(s32 flags); //! Get the flags, as defined in EGUI_TABLE_DRAW_FLAGS, which influence the layout virtual s32 getDrawFlags() const; //! Writes attributes of the object. //! Implement this to expose the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml serialization purposes. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the object. //! Implement this to set the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml deserialization purposes. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); protected: virtual void refreshControls(); virtual void checkScrollbars(); private: struct Cell { Cell() : IsOverrideColor(false), Data(0) {} core::stringw Text; core::stringw BrokenText; bool IsOverrideColor; video::SColor Color; void *Data; }; struct Row { Row() {} core::array Items; }; struct Column { Column() : Width(0), OrderingMode(EGCO_NONE) {} core::stringw Name; u32 Width; EGUI_COLUMN_ORDERING OrderingMode; }; void breakText(const core::stringw &text, core::stringw & brokenText, u32 cellWidth); void selectNew(s32 ypos, bool onlyHover=false); bool selectColumnHeader(s32 xpos, s32 ypos); bool dragColumnStart(s32 xpos, s32 ypos); bool dragColumnUpdate(s32 xpos); void recalculateHeights(); void recalculateWidths(); core::array< Column > Columns; core::array< Row > Rows; gui::IGUIFont* Font; gui::IGUIScrollBar* VerticalScrollBar; gui::IGUIScrollBar* HorizontalScrollBar; bool Clip; bool DrawBack; bool MoveOverSelect; bool Selecting; s32 CurrentResizedColumn; s32 ResizeStart; bool ResizableColumns; s32 ItemHeight; s32 TotalItemHeight; s32 TotalItemWidth; s32 Selected; s32 CellHeightPadding; s32 CellWidthPadding; s32 ActiveTab; EGUI_ORDERING_MODE CurrentOrdering; s32 DrawFlags; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif irrlicht-1.8.3/source/Irrlicht/CGUITable.cpp0000644000000000000000000010023612574354552017342 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // 07.10.2005 - Multicolor-Listbox added by A. Buschhueter (Acki) // A_Buschhueter@gmx.de #include "CGUITable.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIFont.h" #include "CGUIScrollBar.h" #include "os.h" #define ARROW_PAD 15 namespace irr { namespace gui { //! constructor CGUITable::CGUITable(IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle, bool clip, bool drawBack, bool moveOverSelect) : IGUITable(environment, parent, id, rectangle), Font(0), VerticalScrollBar(0), HorizontalScrollBar(0), Clip(clip), DrawBack(drawBack), MoveOverSelect(moveOverSelect), Selecting(false), CurrentResizedColumn(-1), ResizeStart(0), ResizableColumns(true), ItemHeight(0), TotalItemHeight(0), TotalItemWidth(0), Selected(-1), CellHeightPadding(2), CellWidthPadding(5), ActiveTab(-1), CurrentOrdering(EGOM_NONE), DrawFlags(EGTDF_ROWS | EGTDF_COLUMNS | EGTDF_ACTIVE_ROW ) { #ifdef _DEBUG setDebugName("CGUITable"); #endif VerticalScrollBar = Environment->addScrollBar(false, core::rect(0, 0, 100, 100), this, -1); if (VerticalScrollBar) { VerticalScrollBar->grab(); VerticalScrollBar->setNotClipped(false); VerticalScrollBar->setSubElement(true); } HorizontalScrollBar = Environment->addScrollBar(true, core::rect(0, 0, 100, 100), this, -1); if ( HorizontalScrollBar ) { HorizontalScrollBar->grab(); HorizontalScrollBar->setNotClipped(false); HorizontalScrollBar->setSubElement(true); } refreshControls(); } //! destructor CGUITable::~CGUITable() { if (VerticalScrollBar) VerticalScrollBar->drop(); if ( HorizontalScrollBar ) HorizontalScrollBar->drop(); if (Font) Font->drop(); } void CGUITable::addColumn(const wchar_t* caption, s32 columnIndex) { Column tabHeader; tabHeader.Name = caption; tabHeader.Width = Font->getDimension(caption).Width + (CellWidthPadding * 2) + ARROW_PAD; tabHeader.OrderingMode = EGCO_NONE; if ( columnIndex < 0 || columnIndex >= (s32)Columns.size() ) { Columns.push_back(tabHeader); for ( u32 i=0; i < Rows.size(); ++i ) { Cell cell; Rows[i].Items.push_back(cell); } } else { Columns.insert(tabHeader, columnIndex); for ( u32 i=0; i < Rows.size(); ++i ) { Cell cell; Rows[i].Items.insert(cell, columnIndex); } } if (ActiveTab == -1) ActiveTab = 0; recalculateWidths(); } //! remove a column from the table void CGUITable::removeColumn(u32 columnIndex) { if ( columnIndex < Columns.size() ) { Columns.erase(columnIndex); for ( u32 i=0; i < Rows.size(); ++i ) { Rows[i].Items.erase(columnIndex); } } if ( (s32)columnIndex <= ActiveTab ) ActiveTab = Columns.size() ? 0 : -1; recalculateWidths(); } s32 CGUITable::getColumnCount() const { return Columns.size(); } s32 CGUITable::getRowCount() const { return Rows.size(); } bool CGUITable::setActiveColumn(s32 idx, bool doOrder ) { if (idx < 0 || idx >= (s32)Columns.size()) return false; bool changed = (ActiveTab != idx); ActiveTab = idx; if ( ActiveTab < 0 ) return false; if ( doOrder ) { switch ( Columns[idx].OrderingMode ) { case EGCO_NONE: CurrentOrdering = EGOM_NONE; break; case EGCO_CUSTOM: CurrentOrdering = EGOM_NONE; if (Parent) { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_TABLE_HEADER_CHANGED; Parent->OnEvent(event); } break; case EGCO_ASCENDING: CurrentOrdering = EGOM_ASCENDING; break; case EGCO_DESCENDING: CurrentOrdering = EGOM_DESCENDING; break; case EGCO_FLIP_ASCENDING_DESCENDING: CurrentOrdering = EGOM_ASCENDING == CurrentOrdering ? EGOM_DESCENDING : EGOM_ASCENDING; break; default: CurrentOrdering = EGOM_NONE; } orderRows(getActiveColumn(), CurrentOrdering); } if (changed) { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_TABLE_HEADER_CHANGED; Parent->OnEvent(event); } return true; } s32 CGUITable::getActiveColumn() const { return ActiveTab; } EGUI_ORDERING_MODE CGUITable::getActiveColumnOrdering() const { return CurrentOrdering; } void CGUITable::setColumnWidth(u32 columnIndex, u32 width) { if ( columnIndex < Columns.size() ) { const u32 MIN_WIDTH = Font->getDimension(Columns[columnIndex].Name.c_str() ).Width + (CellWidthPadding * 2); if ( width < MIN_WIDTH ) width = MIN_WIDTH; Columns[columnIndex].Width = width; for ( u32 i=0; i < Rows.size(); ++i ) { breakText( Rows[i].Items[columnIndex].Text, Rows[i].Items[columnIndex].BrokenText, Columns[columnIndex].Width ); } } recalculateWidths(); } //! Get the width of a column u32 CGUITable::getColumnWidth(u32 columnIndex) const { if ( columnIndex >= Columns.size() ) return 0; return Columns[columnIndex].Width; } void CGUITable::setResizableColumns(bool resizable) { ResizableColumns = resizable; } bool CGUITable::hasResizableColumns() const { return ResizableColumns; } u32 CGUITable::addRow(u32 rowIndex) { if ( rowIndex > Rows.size() ) { rowIndex = Rows.size(); } Row row; if ( rowIndex == Rows.size() ) Rows.push_back(row); else Rows.insert(row, rowIndex); Rows[rowIndex].Items.reallocate(Columns.size()); for ( u32 i = 0 ; i < Columns.size() ; ++i ) { Rows[rowIndex].Items.push_back(Cell()); } recalculateHeights(); return rowIndex; } void CGUITable::removeRow(u32 rowIndex) { if ( rowIndex > Rows.size() ) return; Rows.erase( rowIndex ); if ( !(Selected < s32(Rows.size())) ) Selected = Rows.size() - 1; recalculateHeights(); } //! adds an list item, returns id of item void CGUITable::setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text) { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) { Rows[rowIndex].Items[columnIndex].Text = text; breakText( Rows[rowIndex].Items[columnIndex].Text, Rows[rowIndex].Items[columnIndex].BrokenText, Columns[columnIndex].Width ); IGUISkin* skin = Environment->getSkin(); if ( skin ) Rows[rowIndex].Items[columnIndex].Color = skin->getColor(EGDC_BUTTON_TEXT); } } void CGUITable::setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color) { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) { Rows[rowIndex].Items[columnIndex].Text = text; breakText( Rows[rowIndex].Items[columnIndex].Text, Rows[rowIndex].Items[columnIndex].BrokenText, Columns[columnIndex].Width ); Rows[rowIndex].Items[columnIndex].Color = color; Rows[rowIndex].Items[columnIndex].IsOverrideColor = true; } } void CGUITable::setCellColor(u32 rowIndex, u32 columnIndex, video::SColor color) { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) { Rows[rowIndex].Items[columnIndex].Color = color; Rows[rowIndex].Items[columnIndex].IsOverrideColor = true; } } void CGUITable::setCellData(u32 rowIndex, u32 columnIndex, void *data) { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) { Rows[rowIndex].Items[columnIndex].Data = data; } } const wchar_t* CGUITable::getCellText(u32 rowIndex, u32 columnIndex ) const { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) { return Rows[rowIndex].Items[columnIndex].Text.c_str(); } return 0; } void* CGUITable::getCellData(u32 rowIndex, u32 columnIndex ) const { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) { return Rows[rowIndex].Items[columnIndex].Data; } return 0; } //! clears the list void CGUITable::clear() { Selected = -1; Rows.clear(); Columns.clear(); if (VerticalScrollBar) VerticalScrollBar->setPos(0); if ( HorizontalScrollBar ) HorizontalScrollBar->setPos(0); recalculateHeights(); recalculateWidths(); } void CGUITable::clearRows() { Selected = -1; Rows.clear(); if (VerticalScrollBar) VerticalScrollBar->setPos(0); recalculateHeights(); } /*! */ s32 CGUITable::getSelected() const { return Selected; } //! set wich row is currently selected void CGUITable::setSelected( s32 index ) { Selected = -1; if ( index >= 0 && index < (s32) Rows.size() ) Selected = index; } void CGUITable::recalculateWidths() { TotalItemWidth=0; for ( u32 i=0; i < Columns.size(); ++i ) { TotalItemWidth += Columns[i].Width; } checkScrollbars(); } void CGUITable::recalculateHeights() { TotalItemHeight = 0; IGUISkin* skin = Environment->getSkin(); if (Font != skin->getFont()) { if (Font) Font->drop(); Font = skin->getFont(); ItemHeight = 0; if(Font) { ItemHeight = Font->getDimension(L"A").Height + (CellHeightPadding * 2); Font->grab(); } } TotalItemHeight = ItemHeight * Rows.size(); // header is not counted, because we only want items checkScrollbars(); } // automatic enabled/disabling and resizing of scrollbars void CGUITable::checkScrollbars() { IGUISkin* skin = Environment->getSkin(); if ( !HorizontalScrollBar || !VerticalScrollBar || !skin) return; s32 scrollBarSize = skin->getSize(EGDS_SCROLLBAR_SIZE); bool wasHorizontalScrollBarVisible = HorizontalScrollBar->isVisible(); bool wasVerticalScrollBarVisible = VerticalScrollBar->isVisible(); HorizontalScrollBar->setVisible(false); VerticalScrollBar->setVisible(false); // CAREFUL: near identical calculations for tableRect and clientClip are also done in draw // area of table used for drawing without scrollbars core::rect tableRect(AbsoluteRect); tableRect.UpperLeftCorner.X += 1; tableRect.UpperLeftCorner.Y += 1; s32 headerBottom = tableRect.UpperLeftCorner.Y + ItemHeight; // area of for the items (without header and without scrollbars) core::rect clientClip(tableRect); clientClip.UpperLeftCorner.Y = headerBottom + 1; // needs horizontal scroll be visible? if( TotalItemWidth > clientClip.getWidth() ) { clientClip.LowerRightCorner.Y -= scrollBarSize; HorizontalScrollBar->setVisible(true); HorizontalScrollBar->setMax(core::max_(0,TotalItemWidth - clientClip.getWidth())); } // needs vertical scroll be visible? if( TotalItemHeight > clientClip.getHeight() ) { clientClip.LowerRightCorner.X -= scrollBarSize; VerticalScrollBar->setVisible(true); VerticalScrollBar->setMax(core::max_(0,TotalItemHeight - clientClip.getHeight())); // check horizontal again because we have now smaller clientClip if ( !HorizontalScrollBar->isVisible() ) { if( TotalItemWidth > clientClip.getWidth() ) { clientClip.LowerRightCorner.Y -= scrollBarSize; HorizontalScrollBar->setVisible(true); HorizontalScrollBar->setMax(core::max_(0,TotalItemWidth - clientClip.getWidth())); } } } // find the correct size for the vertical scrollbar if ( VerticalScrollBar->isVisible() ) { if (!wasVerticalScrollBarVisible ) VerticalScrollBar->setPos(0); if ( HorizontalScrollBar->isVisible() ) { VerticalScrollBar->setRelativePosition( core::rect(RelativeRect.getWidth() - scrollBarSize, 1, RelativeRect.getWidth()-1, RelativeRect.getHeight()-(1+scrollBarSize) ) ); } else { VerticalScrollBar->setRelativePosition( core::rect(RelativeRect.getWidth() - scrollBarSize, 1, RelativeRect.getWidth()-1, RelativeRect.getHeight()-1) ); } } // find the correct size for the horizontal scrollbar if ( HorizontalScrollBar->isVisible() ) { if ( !wasHorizontalScrollBarVisible ) HorizontalScrollBar->setPos(0); if ( VerticalScrollBar->isVisible() ) { HorizontalScrollBar->setRelativePosition( core::rect(1, RelativeRect.getHeight() - scrollBarSize, RelativeRect.getWidth()-(1+scrollBarSize), RelativeRect.getHeight()-1) ); } else { HorizontalScrollBar->setRelativePosition( core::rect(1, RelativeRect.getHeight() - scrollBarSize, RelativeRect.getWidth()-1, RelativeRect.getHeight()-1) ); } } } void CGUITable::refreshControls() { updateAbsolutePosition(); if ( VerticalScrollBar ) VerticalScrollBar->setVisible(false); if ( HorizontalScrollBar ) HorizontalScrollBar->setVisible(false); recalculateHeights(); recalculateWidths(); } //! called if an event happened. bool CGUITable::OnEvent(const SEvent &event) { if (isEnabled()) { switch(event.EventType) { case EET_GUI_EVENT: switch(event.GUIEvent.EventType) { case gui::EGET_SCROLL_BAR_CHANGED: if (event.GUIEvent.Caller == VerticalScrollBar) { // current position will get read out in draw return true; } if (event.GUIEvent.Caller == HorizontalScrollBar) { // current position will get read out in draw return true; } break; case gui::EGET_ELEMENT_FOCUS_LOST: { CurrentResizedColumn = -1; Selecting = false; } break; default: break; } break; case EET_MOUSE_INPUT_EVENT: { if ( !isEnabled() ) return false; core::position2d p(event.MouseInput.X, event.MouseInput.Y); switch(event.MouseInput.Event) { case EMIE_MOUSE_WHEEL: VerticalScrollBar->setPos(VerticalScrollBar->getPos() + (event.MouseInput.Wheel < 0 ? -1 : 1)*-10); return true; case EMIE_LMOUSE_PRESSED_DOWN: if (Environment->hasFocus(this) && VerticalScrollBar->isVisible() && VerticalScrollBar->getAbsolutePosition().isPointInside(p) && VerticalScrollBar->OnEvent(event)) return true; if (Environment->hasFocus(this) && HorizontalScrollBar->isVisible() && HorizontalScrollBar->getAbsolutePosition().isPointInside(p) && HorizontalScrollBar->OnEvent(event)) return true; if ( dragColumnStart( event.MouseInput.X, event.MouseInput.Y ) ) { Environment->setFocus(this); return true; } if ( selectColumnHeader( event.MouseInput.X, event.MouseInput.Y ) ) return true; Selecting = true; Environment->setFocus(this); return true; case EMIE_LMOUSE_LEFT_UP: CurrentResizedColumn = -1; Selecting = false; if (!getAbsolutePosition().isPointInside(p)) { Environment->removeFocus(this); } if (Environment->hasFocus(this) && VerticalScrollBar->isVisible() && VerticalScrollBar->getAbsolutePosition().isPointInside(p) && VerticalScrollBar->OnEvent(event)) { return true; } if (Environment->hasFocus(this) && HorizontalScrollBar->isVisible() && HorizontalScrollBar->getAbsolutePosition().isPointInside(p) && HorizontalScrollBar->OnEvent(event)) { return true; } selectNew(event.MouseInput.Y); return true; case EMIE_MOUSE_MOVED: if ( CurrentResizedColumn >= 0 ) { if ( dragColumnUpdate(event.MouseInput.X) ) { return true; } } if (Selecting || MoveOverSelect) { if (getAbsolutePosition().isPointInside(p)) { selectNew(event.MouseInput.Y); return true; } } break; default: break; } } break; default: break; } } return IGUIElement::OnEvent(event); } void CGUITable::setColumnOrdering(u32 columnIndex, EGUI_COLUMN_ORDERING mode) { if ( columnIndex < Columns.size() ) Columns[columnIndex].OrderingMode = mode; } void CGUITable::swapRows(u32 rowIndexA, u32 rowIndexB) { if ( rowIndexA >= Rows.size() ) return; if ( rowIndexB >= Rows.size() ) return; Row swap = Rows[rowIndexA]; Rows[rowIndexA] = Rows[rowIndexB]; Rows[rowIndexB] = swap; if ( Selected == s32(rowIndexA) ) Selected = rowIndexB; else if( Selected == s32(rowIndexB) ) Selected = rowIndexA; } bool CGUITable::dragColumnStart(s32 xpos, s32 ypos) { if ( !ResizableColumns ) return false; if ( ypos > ( AbsoluteRect.UpperLeftCorner.Y + ItemHeight ) ) return false; const s32 CLICK_AREA = 12; // to left and right of line which can be dragged s32 pos = AbsoluteRect.UpperLeftCorner.X+1; if ( HorizontalScrollBar && HorizontalScrollBar->isVisible() ) pos -= HorizontalScrollBar->getPos(); pos += TotalItemWidth; // have to search from the right as otherwise lines could no longer be resized when a column width is 0 for ( s32 i = (s32)Columns.size()-1; i >= 0 ; --i ) { u32 colWidth = Columns[i].Width; if ( xpos >= (pos - CLICK_AREA) && xpos < ( pos + CLICK_AREA ) ) { CurrentResizedColumn = i; ResizeStart = xpos; return true; } pos -= colWidth; } return false; } bool CGUITable::dragColumnUpdate(s32 xpos) { if ( !ResizableColumns || CurrentResizedColumn < 0 || CurrentResizedColumn >= s32(Columns.size()) ) { CurrentResizedColumn = -1; return false; } s32 width = s32(Columns[CurrentResizedColumn].Width) + (xpos-ResizeStart); if ( width < 0 ) width = 0; setColumnWidth(CurrentResizedColumn, u32(width)); ResizeStart = xpos; return false; } bool CGUITable::selectColumnHeader(s32 xpos, s32 ypos) { if ( ypos > ( AbsoluteRect.UpperLeftCorner.Y + ItemHeight ) ) return false; s32 pos = AbsoluteRect.UpperLeftCorner.X+1; if ( HorizontalScrollBar && HorizontalScrollBar->isVisible() ) pos -= HorizontalScrollBar->getPos(); for ( u32 i = 0 ; i < Columns.size() ; ++i ) { u32 colWidth = Columns[i].Width; if ( xpos >= pos && xpos < ( pos + s32(colWidth) ) ) { setActiveColumn( i, true ); return true; } pos += colWidth; } return false; } void CGUITable::orderRows(s32 columnIndex, EGUI_ORDERING_MODE mode) { Row swap; if ( columnIndex == -1 ) columnIndex = getActiveColumn(); if ( columnIndex < 0 ) return; if ( mode == EGOM_ASCENDING ) { for ( s32 i = 0 ; i < s32(Rows.size()) - 1 ; ++i ) { for ( s32 j = 0 ; j < s32(Rows.size()) - i - 1 ; ++j ) { if ( Rows[j+1].Items[columnIndex].Text < Rows[j].Items[columnIndex].Text ) { swap = Rows[j]; Rows[j] = Rows[j+1]; Rows[j+1] = swap; if ( Selected == j ) Selected = j+1; else if( Selected == j+1 ) Selected = j; } } } } else if ( mode == EGOM_DESCENDING ) { for ( s32 i = 0 ; i < s32(Rows.size()) - 1 ; ++i ) { for ( s32 j = 0 ; j < s32(Rows.size()) - i - 1 ; ++j ) { if ( Rows[j].Items[columnIndex].Text < Rows[j+1].Items[columnIndex].Text) { swap = Rows[j]; Rows[j] = Rows[j+1]; Rows[j+1] = swap; if ( Selected == j ) Selected = j+1; else if( Selected == j+1 ) Selected = j; } } } } } void CGUITable::selectNew(s32 ypos, bool onlyHover) { IGUISkin* skin = Environment->getSkin(); if (!skin) return; s32 oldSelected = Selected; if ( ypos < ( AbsoluteRect.UpperLeftCorner.Y + ItemHeight ) ) return; // find new selected item. if (ItemHeight!=0) Selected = ((ypos - AbsoluteRect.UpperLeftCorner.Y - ItemHeight - 1) + VerticalScrollBar->getPos()) / ItemHeight; if (Selected >= (s32)Rows.size()) Selected = Rows.size() - 1; else if (Selected<0) Selected = 0; // post the news if (Parent && !onlyHover) { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = (Selected != oldSelected) ? EGET_TABLE_CHANGED : EGET_TABLE_SELECTED_AGAIN; Parent->OnEvent(event); } } //! draws the element and its children void CGUITable::draw() { if (!IsVisible) return; irr::video::IVideoDriver* driver = Environment->getVideoDriver(); IGUISkin* skin = Environment->getSkin(); if (!skin) return; IGUIFont* font = skin->getFont(); if (!font) return; // CAREFUL: near identical calculations for tableRect and clientClip are also done in checkScrollbars and selectColumnHeader // Area of table used for drawing without scrollbars core::rect tableRect(AbsoluteRect); tableRect.UpperLeftCorner.X += 1; tableRect.UpperLeftCorner.Y += 1; if ( VerticalScrollBar && VerticalScrollBar->isVisible() ) tableRect.LowerRightCorner.X -= skin->getSize(EGDS_SCROLLBAR_SIZE); if ( HorizontalScrollBar && HorizontalScrollBar->isVisible() ) tableRect.LowerRightCorner.Y -= skin->getSize(EGDS_SCROLLBAR_SIZE); s32 headerBottom = tableRect.UpperLeftCorner.Y + ItemHeight; // area of for the items (without header and without scrollbars) core::rect clientClip(tableRect); clientClip.UpperLeftCorner.Y = headerBottom + 1; clientClip.clipAgainst(AbsoluteClippingRect); // draw background for whole element skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT), true, DrawBack, AbsoluteRect, &AbsoluteClippingRect); // scrolledTableClient is the area where the table items would be if it could be drawn completely core::rect scrolledTableClient(tableRect); scrolledTableClient.UpperLeftCorner.Y = headerBottom + 1; scrolledTableClient.LowerRightCorner.Y = scrolledTableClient.UpperLeftCorner.Y + TotalItemHeight; scrolledTableClient.LowerRightCorner.X = scrolledTableClient.UpperLeftCorner.X + TotalItemWidth; if ( VerticalScrollBar && VerticalScrollBar->isVisible() ) { scrolledTableClient.UpperLeftCorner.Y -= VerticalScrollBar->getPos(); scrolledTableClient.LowerRightCorner.Y -= VerticalScrollBar->getPos(); } if ( HorizontalScrollBar && HorizontalScrollBar->isVisible() ) { scrolledTableClient.UpperLeftCorner.X -= HorizontalScrollBar->getPos(); scrolledTableClient.LowerRightCorner.X -= HorizontalScrollBar->getPos(); } // rowRect is around the scrolled row core::rect rowRect(scrolledTableClient); rowRect.LowerRightCorner.Y = rowRect.UpperLeftCorner.Y + ItemHeight; u32 pos; for ( u32 i = 0 ; i < Rows.size() ; ++i ) { if (rowRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y && rowRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y) { // draw row seperator if ( DrawFlags & EGTDF_ROWS ) { core::rect lineRect(rowRect); lineRect.UpperLeftCorner.Y = lineRect.LowerRightCorner.Y - 1; driver->draw2DRectangle(skin->getColor(EGDC_3D_SHADOW), lineRect, &clientClip); } core::rect textRect(rowRect); pos = rowRect.UpperLeftCorner.X; // draw selected row background highlighted if ((s32)i == Selected && DrawFlags & EGTDF_ACTIVE_ROW ) driver->draw2DRectangle(skin->getColor(EGDC_HIGH_LIGHT), rowRect, &clientClip); for ( u32 j = 0 ; j < Columns.size() ; ++j ) { textRect.UpperLeftCorner.X = pos + CellWidthPadding; textRect.LowerRightCorner.X = pos + Columns[j].Width - CellWidthPadding; // draw item text if ((s32)i == Selected) { font->draw(Rows[i].Items[j].BrokenText.c_str(), textRect, skin->getColor(isEnabled() ? EGDC_HIGH_LIGHT_TEXT : EGDC_GRAY_TEXT), false, true, &clientClip); } else { if ( !Rows[i].Items[j].IsOverrideColor ) // skin-colors can change Rows[i].Items[j].Color = skin->getColor(EGDC_BUTTON_TEXT); font->draw(Rows[i].Items[j].BrokenText.c_str(), textRect, isEnabled() ? Rows[i].Items[j].Color : skin->getColor(EGDC_GRAY_TEXT), false, true, &clientClip); } pos += Columns[j].Width; } } rowRect.UpperLeftCorner.Y += ItemHeight; rowRect.LowerRightCorner.Y += ItemHeight; } core::rect columnSeparator(clientClip); pos = scrolledTableClient.UpperLeftCorner.X; core::rect tableClip(tableRect); tableClip.clipAgainst(AbsoluteClippingRect); for (u32 i = 0 ; i < Columns.size() ; ++i ) { const wchar_t* text = Columns[i].Name.c_str(); u32 colWidth = Columns[i].Width; //core::dimension2d dim = font->getDimension(text); core::rect columnrect(pos, tableRect.UpperLeftCorner.Y, pos + colWidth, headerBottom); // draw column background skin->draw3DButtonPaneStandard(this, columnrect, &tableClip); // draw column seperator if ( DrawFlags & EGTDF_COLUMNS ) { columnSeparator.UpperLeftCorner.X = pos; columnSeparator.LowerRightCorner.X = pos + 1; driver->draw2DRectangle(skin->getColor(EGDC_3D_SHADOW), columnSeparator, &tableClip); } // draw header column text columnrect.UpperLeftCorner.X += CellWidthPadding; font->draw(text, columnrect, skin->getColor( isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), false, true, &tableClip); // draw icon for active column tab if ( (s32)i == ActiveTab ) { if ( CurrentOrdering == EGOM_ASCENDING ) { columnrect.UpperLeftCorner.X = columnrect.LowerRightCorner.X - CellWidthPadding - ARROW_PAD / 2 + 2; columnrect.UpperLeftCorner.Y += 7; skin->drawIcon(this,EGDI_CURSOR_UP,columnrect.UpperLeftCorner,0,0,false,&tableClip); } else { columnrect.UpperLeftCorner.X = columnrect.LowerRightCorner.X - CellWidthPadding - ARROW_PAD / 2 + 2; columnrect.UpperLeftCorner.Y += 7; skin->drawIcon(this,EGDI_CURSOR_DOWN,columnrect.UpperLeftCorner,0,0,false,&tableClip); } } pos += colWidth; } // fill up header background up to the right side core::rect columnrect(pos, tableRect.UpperLeftCorner.Y, tableRect.LowerRightCorner.X , headerBottom); skin->draw3DButtonPaneStandard(this, columnrect, &tableClip); IGUIElement::draw(); } void CGUITable::breakText(const core::stringw& text, core::stringw& brokenText, u32 cellWidth) { IGUISkin* skin = Environment->getSkin(); if (!skin) return; if (!Font) return; IGUIFont* font = skin->getFont(); if (!font) return; core::stringw line, lineDots; wchar_t c[2]; c[1] = L'\0'; const u32 maxLength = cellWidth - (CellWidthPadding * 2); const u32 maxLengthDots = cellWidth - (CellWidthPadding * 2) - font->getDimension(L"...").Width; const u32 size = text.size(); u32 pos = 0; u32 i; for (i=0; igetDimension(c).Width; if ( pos > maxLength ) break; if ( font->getDimension( (line + c).c_str() ).Width > maxLengthDots ) lineDots = line; line += c[0]; } if ( i < size ) brokenText = lineDots + L"..."; else brokenText = line; } //! Set some flags influencing the layout of the table void CGUITable::setDrawFlags(s32 flags) { DrawFlags = flags; } //! Get the flags which influence the layout of the table s32 CGUITable::getDrawFlags() const { return DrawFlags; } //! Writes attributes of the element. void CGUITable::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { IGUITable::serializeAttributes(out, options); out->addInt("ColumnCount", Columns.size()); u32 i; for (i=0;iaddString(label.c_str(), Columns[i].Name.c_str() ); label = "Column"; label += i; label += "width"; out->addInt(label.c_str(), Columns[i].Width ); label = "Column"; label += i; label += "OrderingMode"; out->addEnum(label.c_str(), Columns[i].OrderingMode, GUIColumnOrderingNames); } out->addInt("RowCount", Rows.size()); for (i=0;iaddInt(label.c_str(), Rows[i].Height ); //label = "Row"; label += i; label += "ItemCount"; //out->addInt(label.c_str(), Rows[i].Items.size()); u32 c; for ( c=0; c < Rows[i].Items.size(); ++c ) { label = "Row"; label += i; label += "cell"; label += c; label += "text"; out->addString(label.c_str(), Rows[i].Items[c].Text.c_str() ); // core::stringw BrokenText; // can be recalculated label = "Row"; label += i; label += "cell"; label += c; label += "color"; out->addColor(label.c_str(), Rows[i].Items[c].Color ); label = "Row"; label += i; label += "cell"; label += c; label += "IsOverrideColor"; out->addColor(label.c_str(), Rows[i].Items[c].IsOverrideColor ); // void *data; // can't be serialized } } // s32 ItemHeight; // can be calculated // TotalItemHeight // calculated // TotalItemWidth // calculated // gui::IGUIFont* Font; // font is just the current font from environment // gui::IGUIScrollBar* VerticalScrollBar; // not serialized // gui::IGUIScrollBar* HorizontalScrollBar; // not serialized out->addBool ("Clip", Clip); out->addBool ("DrawBack", DrawBack); out->addBool ("MoveOverSelect", MoveOverSelect); // s32 CurrentResizedColumn; // runtime info - depends on user action out->addBool ("ResizableColumns", ResizableColumns); // s32 Selected; // runtime info - depends on user action out->addInt("CellWidthPadding", CellWidthPadding ); out->addInt("CellHeightPadding", CellHeightPadding ); // s32 ActiveTab; // runtime info - depends on user action // bool Selecting; // runtime info - depends on user action out->addEnum("CurrentOrdering", CurrentOrdering, GUIOrderingModeNames); out->addInt("DrawFlags", DrawFlags); } //! Reads attributes of the element void CGUITable::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { IGUITable::deserializeAttributes(in, options); Columns.clear(); u32 columnCount = in->getAttributeAsInt("ColumnCount"); u32 i; for (i=0;igetAttributeAsString(label.c_str()).c_str()); label = "Column"; label += i; label += "width"; column.Width = in->getAttributeAsInt(label.c_str()); label = "Column"; label += i; label += "OrderingMode"; column.OrderingMode = EGCO_NONE; s32 co = in->getAttributeAsEnumeration(label.c_str(), GUIColumnOrderingNames); if (co > 0) column.OrderingMode = EGUI_COLUMN_ORDERING(co); Columns.push_back(column); } Rows.clear(); u32 rowCount = in->getAttributeAsInt("RowCount"); for (i=0; igetAttributeAsInt(label.c_str() ); Rows.push_back(row); //label = "Row"; label += i; label += "ItemCount"; //u32 itemCount = in->getAttributeAsInt(label.c_str()); u32 c; for ( c=0; c < columnCount; ++c ) { Cell cell; label = "Row"; label += i; label += "cell"; label += c; label += "text"; cell.Text = core::stringw(in->getAttributeAsString(label.c_str()).c_str()); breakText( cell.Text, cell.BrokenText, Columns[c].Width ); label = "Row"; label += i; label += "cell"; label += c; label += "color"; cell.Color = in->getAttributeAsColor(label.c_str()); label = "Row"; label += i; label += "cell"; label += c; label += "IsOverrideColor"; cell.IsOverrideColor = in->getAttributeAsBool(label.c_str()); cell.Data = NULL; Rows[Rows.size()-1].Items.push_back(cell); } } ItemHeight = 0; // calculated TotalItemHeight = 0; // calculated TotalItemWidth = 0; // calculated // force font recalculation if ( Font ) { Font->drop(); Font = 0; } Clip = in->getAttributeAsBool("Clip"); DrawBack = in->getAttributeAsBool("DrawBack"); MoveOverSelect = in->getAttributeAsBool("MoveOverSelect"); CurrentResizedColumn = -1; ResizeStart = 0; ResizableColumns = in->getAttributeAsBool("ResizableColumns"); Selected = -1; CellWidthPadding = in->getAttributeAsInt("CellWidthPadding"); CellHeightPadding = in->getAttributeAsInt("CellHeightPadding"); ActiveTab = -1; Selecting = false; CurrentOrdering = (EGUI_ORDERING_MODE) in->getAttributeAsEnumeration("CurrentOrdering", GUIOrderingModeNames); DrawFlags = in->getAttributeAsInt("DrawFlags"); refreshControls(); } } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CGUITabControl.h0000644000000000000000000001323712574354552020033 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_TAB_CONTROL_H_INCLUDED__ #define __C_GUI_TAB_CONTROL_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUITabControl.h" #include "irrArray.h" #include "IGUISkin.h" namespace irr { namespace gui { class CGUITabControl; class IGUIButton; // A tab, onto which other gui elements could be added. class CGUITab : public IGUITab { public: //! constructor CGUITab(s32 number, IGUIEnvironment* environment, IGUIElement* parent, const core::rect& rectangle, s32 id); //! destructor //virtual ~CGUITab(); //! Returns number of this tab in tabcontrol. Can be accessed //! later IGUITabControl::getTab() by this number. virtual s32 getNumber() const; //! Sets the number virtual void setNumber(s32 n); //! draws the element and its children virtual void draw(); //! sets if the tab should draw its background virtual void setDrawBackground(bool draw=true); //! sets the color of the background, if it should be drawn. virtual void setBackgroundColor(video::SColor c); //! sets the color of the text virtual void setTextColor(video::SColor c); //! returns true if the tab is drawing its background, false if not virtual bool isDrawingBackground() const; //! returns the color of the background virtual video::SColor getBackgroundColor() const; virtual video::SColor getTextColor() const; //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); //! only for internal use by CGUITabControl void refreshSkinColors(); private: s32 Number; video::SColor BackColor; bool OverrideTextColorEnabled; video::SColor TextColor; bool DrawBackground; }; //! A standard tab control class CGUITabControl : public IGUITabControl { public: //! destructor CGUITabControl(IGUIEnvironment* environment, IGUIElement* parent, const core::rect& rectangle, bool fillbackground=true, bool border=true, s32 id=-1); //! destructor virtual ~CGUITabControl(); //! Adds a tab virtual IGUITab* addTab(const wchar_t* caption, s32 id=-1); //! Adds a tab that has already been created virtual void addTab(CGUITab* tab); //! Insert the tab at the given index virtual IGUITab* insertTab(s32 idx, const wchar_t* caption, s32 id=-1); //! Removes a tab from the tabcontrol virtual void removeTab(s32 idx); //! Clears the tabcontrol removing all tabs virtual void clear(); //! Returns amount of tabs in the tabcontrol virtual s32 getTabCount() const; //! Returns a tab based on zero based index virtual IGUITab* getTab(s32 idx) const; //! Brings a tab to front. virtual bool setActiveTab(s32 idx); //! Brings a tab to front. virtual bool setActiveTab(IGUITab *tab); //! Returns which tab is currently active virtual s32 getActiveTab() const; //! get the the id of the tab at the given absolute coordinates virtual s32 getTabAt(s32 xpos, s32 ypos) const; //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! draws the element and its children virtual void draw(); //! Removes a child. virtual void removeChild(IGUIElement* child); //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Set the height of the tabs virtual void setTabHeight( s32 height ); //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); //! Get the height of the tabs virtual s32 getTabHeight() const; //! set the maximal width of a tab. Per default width is 0 which means "no width restriction". virtual void setTabMaxWidth(s32 width ); //! get the maximal width of a tab virtual s32 getTabMaxWidth() const; //! Set the alignment of the tabs //! note: EGUIA_CENTER is not an option virtual void setTabVerticalAlignment( gui::EGUI_ALIGNMENT alignment ); //! Get the alignment of the tabs virtual gui::EGUI_ALIGNMENT getTabVerticalAlignment() const; //! Set the extra width added to tabs on each side of the text virtual void setTabExtraWidth( s32 extraWidth ); //! Get the extra width added to tabs on each side of the text virtual s32 getTabExtraWidth() const; //! Update the position of the element, decides scroll button status virtual void updateAbsolutePosition(); private: void scrollLeft(); void scrollRight(); bool needScrollControl( s32 startIndex=0, bool withScrollControl=false ); s32 calcTabWidth(s32 pos, IGUIFont* font, const wchar_t* text, bool withScrollControl ) const; core::rect calcTabPos(); void recalculateScrollButtonPlacement(); void recalculateScrollBar(); void refreshSprites(); core::array Tabs; // CGUITab* because we need setNumber (which is certainly not nice) s32 ActiveTab; bool Border; bool FillBackground; bool ScrollControl; s32 TabHeight; gui::EGUI_ALIGNMENT VerticalAlignment; IGUIButton* UpButton; IGUIButton* DownButton; s32 TabMaxWidth; s32 CurrentScrollTabIndex; s32 TabExtraWidth; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif irrlicht-1.8.3/source/Irrlicht/CGUITabControl.cpp0000644000000000000000000006120712574354552020366 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUITabControl.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "CGUIButton.h" #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IGUIFont.h" #include "IVideoDriver.h" #include "rect.h" #include "os.h" namespace irr { namespace gui { // ------------------------------------------------------------------ // Tab // ------------------------------------------------------------------ //! constructor CGUITab::CGUITab(s32 number, IGUIEnvironment* environment, IGUIElement* parent, const core::rect& rectangle, s32 id) : IGUITab(environment, parent, id, rectangle), Number(number), BackColor(0,0,0,0), OverrideTextColorEnabled(false), TextColor(255,0,0,0), DrawBackground(false) { #ifdef _DEBUG setDebugName("CGUITab"); #endif const IGUISkin* const skin = environment->getSkin(); if (skin) TextColor = skin->getColor(EGDC_BUTTON_TEXT); } //! Returns number of tab in tabcontrol. Can be accessed //! later IGUITabControl::getTab() by this number. s32 CGUITab::getNumber() const { return Number; } //! Sets the number void CGUITab::setNumber(s32 n) { Number = n; } void CGUITab::refreshSkinColors() { if ( !OverrideTextColorEnabled ) { TextColor = Environment->getSkin()->getColor(EGDC_BUTTON_TEXT); } } //! draws the element and its children void CGUITab::draw() { if (!IsVisible) return; IGUISkin *skin = Environment->getSkin(); if (skin && DrawBackground) skin->draw2DRectangle(this, BackColor, AbsoluteRect, &AbsoluteClippingRect); IGUIElement::draw(); } //! sets if the tab should draw its background void CGUITab::setDrawBackground(bool draw) { DrawBackground = draw; } //! sets the color of the background, if it should be drawn. void CGUITab::setBackgroundColor(video::SColor c) { BackColor = c; } //! sets the color of the text void CGUITab::setTextColor(video::SColor c) { OverrideTextColorEnabled = true; TextColor = c; } video::SColor CGUITab::getTextColor() const { return TextColor; } //! returns true if the tab is drawing its background, false if not bool CGUITab::isDrawingBackground() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return DrawBackground; } //! returns the color of the background video::SColor CGUITab::getBackgroundColor() const { return BackColor; } //! Writes attributes of the element. void CGUITab::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUITab::serializeAttributes(out,options); out->addInt ("TabNumber", Number); out->addBool ("DrawBackground", DrawBackground); out->addColor ("BackColor", BackColor); out->addBool ("OverrideTextColorEnabled", OverrideTextColorEnabled); out->addColor ("TextColor", TextColor); } //! Reads attributes of the element void CGUITab::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUITab::deserializeAttributes(in,options); setNumber(in->getAttributeAsInt("TabNumber")); setDrawBackground(in->getAttributeAsBool("DrawBackground")); setBackgroundColor(in->getAttributeAsColor("BackColor")); bool override = in->getAttributeAsBool("OverrideTextColorEnabled"); setTextColor(in->getAttributeAsColor("TextColor")); if ( !override ) { OverrideTextColorEnabled = false; } if (Parent && Parent->getType() == EGUIET_TAB_CONTROL) { ((CGUITabControl*)Parent)->addTab(this); if (isVisible()) ((CGUITabControl*)Parent)->setActiveTab(this); } } // ------------------------------------------------------------------ // Tabcontrol // ------------------------------------------------------------------ //! constructor CGUITabControl::CGUITabControl(IGUIEnvironment* environment, IGUIElement* parent, const core::rect& rectangle, bool fillbackground, bool border, s32 id) : IGUITabControl(environment, parent, id, rectangle), ActiveTab(-1), Border(border), FillBackground(fillbackground), ScrollControl(false), TabHeight(0), VerticalAlignment(EGUIA_UPPERLEFT), UpButton(0), DownButton(0), TabMaxWidth(0), CurrentScrollTabIndex(0), TabExtraWidth(20) { #ifdef _DEBUG setDebugName("CGUITabControl"); #endif IGUISkin* skin = Environment->getSkin(); IGUISpriteBank* sprites = 0; TabHeight = 32; if (skin) { sprites = skin->getSpriteBank(); TabHeight = skin->getSize(gui::EGDS_BUTTON_HEIGHT) + 2; } UpButton = Environment->addButton(core::rect(0,0,10,10), this); if (UpButton) { UpButton->setSpriteBank(sprites); UpButton->setVisible(false); UpButton->setSubElement(true); UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); UpButton->setOverrideFont(Environment->getBuiltInFont()); UpButton->grab(); } DownButton = Environment->addButton(core::rect(0,0,10,10), this); if (DownButton) { DownButton->setSpriteBank(sprites); DownButton->setVisible(false); DownButton->setSubElement(true); DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); DownButton->setOverrideFont(Environment->getBuiltInFont()); DownButton->grab(); } setTabVerticalAlignment(EGUIA_UPPERLEFT); refreshSprites(); } //! destructor CGUITabControl::~CGUITabControl() { for (u32 i=0; idrop(); } if (UpButton) UpButton->drop(); if (DownButton) DownButton->drop(); } void CGUITabControl::refreshSprites() { video::SColor color(255,255,255,255); IGUISkin* skin = Environment->getSkin(); if (skin) { color = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL); } if (UpButton) { UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_LEFT), color); UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_LEFT), color); } if (DownButton) { DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_RIGHT), color); DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_RIGHT), color); } } //! Adds a tab IGUITab* CGUITabControl::addTab(const wchar_t* caption, s32 id) { CGUITab* tab = new CGUITab(Tabs.size(), Environment, this, calcTabPos(), id); tab->setText(caption); tab->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); tab->setVisible(false); Tabs.push_back(tab); if (ActiveTab == -1) { ActiveTab = 0; tab->setVisible(true); } recalculateScrollBar(); return tab; } //! adds a tab which has been created elsewhere void CGUITabControl::addTab(CGUITab* tab) { if (!tab) return; // check if its already added for (u32 i=0; i < Tabs.size(); ++i) { if (Tabs[i] == tab) return; } tab->grab(); if (tab->getNumber() == -1) tab->setNumber((s32)Tabs.size()); while (tab->getNumber() >= (s32)Tabs.size()) Tabs.push_back(0); if (Tabs[tab->getNumber()]) { Tabs.push_back(Tabs[tab->getNumber()]); Tabs[Tabs.size()-1]->setNumber(Tabs.size()); } Tabs[tab->getNumber()] = tab; if (ActiveTab == -1) ActiveTab = tab->getNumber(); if (tab->getNumber() == ActiveTab) { setActiveTab(ActiveTab); } } //! Insert the tab at the given index IGUITab* CGUITabControl::insertTab(s32 idx, const wchar_t* caption, s32 id) { if ( idx < 0 || idx > (s32)Tabs.size() ) // idx == Tabs.size() is indeed ok here as core::array can handle that return NULL; CGUITab* tab = new CGUITab(idx, Environment, this, calcTabPos(), id); tab->setText(caption); tab->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); tab->setVisible(false); Tabs.insert(tab, (u32)idx); if (ActiveTab == -1) { ActiveTab = 0; tab->setVisible(true); } for ( u32 i=(u32)idx+1; i < Tabs.size(); ++i ) { Tabs[i]->setNumber(i); } recalculateScrollBar(); return tab; } //! Removes a tab from the tabcontrol void CGUITabControl::removeTab(s32 idx) { if ( idx < 0 || idx >= (s32)Tabs.size() ) return; Tabs[(u32)idx]->drop(); Tabs.erase((u32)idx); for ( u32 i=(u32)idx; i < Tabs.size(); ++i ) { Tabs[i]->setNumber(i); } } //! Clears the tabcontrol removing all tabs void CGUITabControl::clear() { for (u32 i=0; idrop(); } Tabs.clear(); } //! Returns amount of tabs in the tabcontrol s32 CGUITabControl::getTabCount() const { return Tabs.size(); } //! Returns a tab based on zero based index IGUITab* CGUITabControl::getTab(s32 idx) const { if ((u32)idx >= Tabs.size()) return 0; return Tabs[idx]; } //! called if an event happened. bool CGUITabControl::OnEvent(const SEvent& event) { if (isEnabled()) { switch(event.EventType) { case EET_GUI_EVENT: switch(event.GUIEvent.EventType) { case EGET_BUTTON_CLICKED: if (event.GUIEvent.Caller == UpButton) { scrollLeft(); return true; } else if (event.GUIEvent.Caller == DownButton) { scrollRight(); return true; } break; default: break; } break; case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: // todo: dragging tabs around return true; case EMIE_LMOUSE_LEFT_UP: { s32 idx = getTabAt(event.MouseInput.X, event.MouseInput.Y); if ( idx >= 0 ) { setActiveTab(idx); return true; } break; } default: break; } break; default: break; } } return IGUIElement::OnEvent(event); } void CGUITabControl::scrollLeft() { if ( CurrentScrollTabIndex > 0 ) --CurrentScrollTabIndex; recalculateScrollBar(); } void CGUITabControl::scrollRight() { if ( CurrentScrollTabIndex < (s32)(Tabs.size()) - 1 ) { if ( needScrollControl(CurrentScrollTabIndex, true) ) ++CurrentScrollTabIndex; } recalculateScrollBar(); } s32 CGUITabControl::calcTabWidth(s32 pos, IGUIFont* font, const wchar_t* text, bool withScrollControl) const { if ( !font ) return 0; s32 len = font->getDimension(text).Width + TabExtraWidth; if ( TabMaxWidth > 0 && len > TabMaxWidth ) len = TabMaxWidth; // check if we miss the place to draw the tab-button if ( withScrollControl && ScrollControl && pos+len > UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 ) { s32 tabMinWidth = font->getDimension(L"A").Width; if ( TabExtraWidth > 0 && TabExtraWidth > tabMinWidth ) tabMinWidth = TabExtraWidth; if ( ScrollControl && pos+tabMinWidth <= UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 ) { len = UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 - pos; } } return len; } bool CGUITabControl::needScrollControl(s32 startIndex, bool withScrollControl) { if ( startIndex >= (s32)Tabs.size() ) startIndex -= 1; if ( startIndex < 0 ) startIndex = 0; IGUISkin* skin = Environment->getSkin(); if (!skin) return false; IGUIFont* font = skin->getFont(); core::rect frameRect(AbsoluteRect); if (Tabs.empty()) return false; if (!font) return false; s32 pos = frameRect.UpperLeftCorner.X + 2; for (s32 i=startIndex; i<(s32)Tabs.size(); ++i) { // get Text const wchar_t* text = 0; if (Tabs[i]) text = Tabs[i]->getText(); // get text length s32 len = calcTabWidth(pos, font, text, false); // always without withScrollControl here or len would be shortened frameRect.LowerRightCorner.X += len; frameRect.UpperLeftCorner.X = pos; frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len; pos += len; if ( withScrollControl && pos > UpButton->getAbsolutePosition().UpperLeftCorner.X - 2) return true; if ( !withScrollControl && pos > AbsoluteRect.LowerRightCorner.X ) return true; } return false; } core::rect CGUITabControl::calcTabPos() { core::rect r; r.UpperLeftCorner.X = 0; r.LowerRightCorner.X = AbsoluteRect.getWidth(); if ( Border ) { ++r.UpperLeftCorner.X; --r.LowerRightCorner.X; } if ( VerticalAlignment == EGUIA_UPPERLEFT ) { r.UpperLeftCorner.Y = TabHeight+2; r.LowerRightCorner.Y = AbsoluteRect.getHeight()-1; if ( Border ) { --r.LowerRightCorner.Y; } } else { r.UpperLeftCorner.Y = 0; r.LowerRightCorner.Y = AbsoluteRect.getHeight()-(TabHeight+2); if ( Border ) { ++r.UpperLeftCorner.Y; } } return r; } //! draws the element and its children void CGUITabControl::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); if (!skin) return; IGUIFont* font = skin->getFont(); video::IVideoDriver* driver = Environment->getVideoDriver(); core::rect frameRect(AbsoluteRect); if (Tabs.empty()) driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect); if (!font) return; if ( VerticalAlignment == EGUIA_UPPERLEFT ) { frameRect.UpperLeftCorner.Y += 2; frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + TabHeight; } else { frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - TabHeight - 1; frameRect.LowerRightCorner.Y -= 2; } core::rect tr; s32 pos = frameRect.UpperLeftCorner.X + 2; bool needLeftScroll = CurrentScrollTabIndex > 0; bool needRightScroll = false; // left and right pos of the active tab s32 left = 0; s32 right = 0; //const wchar_t* activetext = 0; CGUITab *activeTab = 0; for (u32 i=CurrentScrollTabIndex; igetText(); // get text length s32 len = calcTabWidth(pos, font, text, true); if ( ScrollControl && pos+len > UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 ) { needRightScroll = true; break; } frameRect.LowerRightCorner.X += len; frameRect.UpperLeftCorner.X = pos; frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len; pos += len; if ( text ) Tabs[i]->refreshSkinColors(); if ((s32)i == ActiveTab) { left = frameRect.UpperLeftCorner.X; right = frameRect.LowerRightCorner.X; //activetext = text; activeTab = Tabs[i]; } else { skin->draw3DTabButton(this, false, frameRect, &AbsoluteClippingRect, VerticalAlignment); // draw text core::rect textClipRect(frameRect); // TODO: exact size depends on borders in draw3DTabButton which we don't get with current interface textClipRect.clipAgainst(AbsoluteClippingRect); font->draw(text, frameRect, Tabs[i]->getTextColor(), true, true, &textClipRect); } } // draw active tab if (left != 0 && right != 0 && activeTab != 0) { // draw upper highlight frame if ( VerticalAlignment == EGUIA_UPPERLEFT ) { frameRect.UpperLeftCorner.X = left-2; frameRect.LowerRightCorner.X = right+2; frameRect.UpperLeftCorner.Y -= 2; skin->draw3DTabButton(this, true, frameRect, &AbsoluteClippingRect, VerticalAlignment); // draw text core::rect textClipRect(frameRect); // TODO: exact size depends on borders in draw3DTabButton which we don't get with current interface textClipRect.clipAgainst(AbsoluteClippingRect); font->draw(activeTab->getText(), frameRect, activeTab->getTextColor(), true, true, &textClipRect); tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X; tr.LowerRightCorner.X = left - 1; tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1; tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y; driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect); tr.UpperLeftCorner.X = right; tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X; driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect); } else { frameRect.UpperLeftCorner.X = left-2; frameRect.LowerRightCorner.X = right+2; frameRect.LowerRightCorner.Y += 2; skin->draw3DTabButton(this, true, frameRect, &AbsoluteClippingRect, VerticalAlignment); // draw text font->draw(activeTab->getText(), frameRect, activeTab->getTextColor(), true, true, &frameRect); tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X; tr.LowerRightCorner.X = left - 1; tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1; tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y; driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect); tr.UpperLeftCorner.X = right; tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X; driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect); } } else { if ( VerticalAlignment == EGUIA_UPPERLEFT ) { tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X; tr.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X; tr.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - 1; tr.LowerRightCorner.Y = frameRect.LowerRightCorner.Y; driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect); } else { tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X; tr.LowerRightCorner.X = 1000; tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1; tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y; driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect); } } skin->draw3DTabBody(this, Border, FillBackground, AbsoluteRect, &AbsoluteClippingRect, TabHeight, VerticalAlignment); // enable scrollcontrols on need if ( UpButton ) UpButton->setEnabled(needLeftScroll); if ( DownButton ) DownButton->setEnabled(needRightScroll); refreshSprites(); IGUIElement::draw(); } //! Set the height of the tabs void CGUITabControl::setTabHeight( s32 height ) { if ( height < 0 ) height = 0; TabHeight = height; recalculateScrollButtonPlacement(); recalculateScrollBar(); } //! Get the height of the tabs s32 CGUITabControl::getTabHeight() const { return TabHeight; } //! set the maximal width of a tab. Per default width is 0 which means "no width restriction". void CGUITabControl::setTabMaxWidth(s32 width ) { TabMaxWidth = width; } //! get the maximal width of a tab s32 CGUITabControl::getTabMaxWidth() const { return TabMaxWidth; } //! Set the extra width added to tabs on each side of the text void CGUITabControl::setTabExtraWidth( s32 extraWidth ) { if ( extraWidth < 0 ) extraWidth = 0; TabExtraWidth = extraWidth; recalculateScrollBar(); } //! Get the extra width added to tabs on each side of the text s32 CGUITabControl::getTabExtraWidth() const { return TabExtraWidth; } void CGUITabControl::recalculateScrollBar() { if (!UpButton || !DownButton) return; ScrollControl = needScrollControl() || CurrentScrollTabIndex > 0; if (ScrollControl) { UpButton->setVisible( true ); DownButton->setVisible( true ); } else { UpButton->setVisible( false ); DownButton->setVisible( false ); } bringToFront( UpButton ); bringToFront( DownButton ); } //! Set the alignment of the tabs void CGUITabControl::setTabVerticalAlignment( EGUI_ALIGNMENT alignment ) { VerticalAlignment = alignment; recalculateScrollButtonPlacement(); recalculateScrollBar(); core::rect r(calcTabPos()); for ( u32 i=0; isetRelativePosition(r); } } void CGUITabControl::recalculateScrollButtonPlacement() { IGUISkin* skin = Environment->getSkin(); s32 ButtonSize = 16; s32 ButtonHeight = TabHeight - 2; if ( ButtonHeight < 0 ) ButtonHeight = TabHeight; if (skin) { ButtonSize = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); if (ButtonSize > TabHeight) ButtonSize = TabHeight; } s32 ButtonX = RelativeRect.getWidth() - (s32)(2.5f*(f32)ButtonSize) - 1; s32 ButtonY = 0; if (VerticalAlignment == EGUIA_UPPERLEFT) { ButtonY = 2 + (TabHeight / 2) - (ButtonHeight / 2); UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); } else { ButtonY = RelativeRect.getHeight() - (TabHeight / 2) - (ButtonHeight / 2) - 2; UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); } UpButton->setRelativePosition(core::rect(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight)); ButtonX += ButtonSize + 1; DownButton->setRelativePosition(core::rect(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight)); } //! Get the alignment of the tabs EGUI_ALIGNMENT CGUITabControl::getTabVerticalAlignment() const { return VerticalAlignment; } s32 CGUITabControl::getTabAt(s32 xpos, s32 ypos) const { core::position2di p(xpos, ypos); IGUISkin* skin = Environment->getSkin(); IGUIFont* font = skin->getFont(); core::rect frameRect(AbsoluteRect); if ( VerticalAlignment == EGUIA_UPPERLEFT ) { frameRect.UpperLeftCorner.Y += 2; frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + TabHeight; } else { frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - TabHeight; } s32 pos = frameRect.UpperLeftCorner.X + 2; if (!frameRect.isPointInside(p)) return -1; for (s32 i=CurrentScrollTabIndex; i<(s32)Tabs.size(); ++i) { // get Text const wchar_t* text = 0; if (Tabs[i]) text = Tabs[i]->getText(); // get text length s32 len = calcTabWidth(pos, font, text, true); if ( ScrollControl && pos+len > UpButton->getAbsolutePosition().UpperLeftCorner.X - 2 ) return -1; frameRect.UpperLeftCorner.X = pos; frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + len; pos += len; if (frameRect.isPointInside(p)) { return i; } } return -1; } //! Returns which tab is currently active s32 CGUITabControl::getActiveTab() const { return ActiveTab; } //! Brings a tab to front. bool CGUITabControl::setActiveTab(s32 idx) { if ((u32)idx >= Tabs.size()) return false; bool changed = (ActiveTab != idx); ActiveTab = idx; for (s32 i=0; i<(s32)Tabs.size(); ++i) if (Tabs[i]) Tabs[i]->setVisible( i == ActiveTab ); if (changed) { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_TAB_CHANGED; Parent->OnEvent(event); } return true; } bool CGUITabControl::setActiveTab(IGUITab *tab) { for (s32 i=0; i<(s32)Tabs.size(); ++i) if (Tabs[i] == tab) return setActiveTab(i); return false; } //! Removes a child. void CGUITabControl::removeChild(IGUIElement* child) { bool isTab = false; u32 i=0; // check if it is a tab while (idrop(); Tabs.erase(i); isTab = true; } else ++i; } // reassign numbers if (isTab) { for (i=0; isetNumber(i); } // remove real element IGUIElement::removeChild(child); recalculateScrollBar(); } //! Update the position of the element, decides scroll button status void CGUITabControl::updateAbsolutePosition() { IGUIElement::updateAbsolutePosition(); recalculateScrollBar(); } //! Writes attributes of the element. void CGUITabControl::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUITabControl::serializeAttributes(out,options); out->addInt ("ActiveTab", ActiveTab); out->addBool("Border", Border); out->addBool("FillBackground", FillBackground); out->addInt ("TabHeight", TabHeight); out->addInt ("TabMaxWidth", TabMaxWidth); out->addEnum("TabVerticalAlignment", s32(VerticalAlignment), GUIAlignmentNames); } //! Reads attributes of the element void CGUITabControl::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { Border = in->getAttributeAsBool("Border"); FillBackground = in->getAttributeAsBool("FillBackground"); ActiveTab = -1; setTabHeight(in->getAttributeAsInt("TabHeight")); TabMaxWidth = in->getAttributeAsInt("TabMaxWidth"); IGUITabControl::deserializeAttributes(in,options); setActiveTab(in->getAttributeAsInt("ActiveTab")); setTabVerticalAlignment( static_cast(in->getAttributeAsEnumeration("TabVerticalAlignment" , GUIAlignmentNames)) ); } } // end namespace irr } // end namespace gui #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIStaticText.h0000644000000000000000000001064712574354552020062 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_STATIC_TEXT_H_INCLUDED__ #define __C_GUI_STATIC_TEXT_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIStaticText.h" #include "irrArray.h" namespace irr { namespace gui { class CGUIStaticText : public IGUIStaticText { public: //! constructor CGUIStaticText(const wchar_t* text, bool border, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle, bool background = false); //! destructor virtual ~CGUIStaticText(); //! draws the element and its children virtual void draw(); //! Sets another skin independent font. virtual void setOverrideFont(IGUIFont* font=0); //! Gets the override font (if any) virtual IGUIFont* getOverrideFont() const; //! Get the font which is used right now for drawing virtual IGUIFont* getActiveFont() const; //! Sets another color for the text. virtual void setOverrideColor(video::SColor color); //! Sets another color for the background. virtual void setBackgroundColor(video::SColor color); //! Sets whether to draw the background virtual void setDrawBackground(bool draw); //! Gets the background color virtual video::SColor getBackgroundColor() const; //! Checks if background drawing is enabled virtual bool isDrawBackgroundEnabled() const; //! Sets whether to draw the border virtual void setDrawBorder(bool draw); //! Checks if border drawing is enabled virtual bool isDrawBorderEnabled() const; //! Sets alignment mode for text virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical); //! Gets the override color virtual video::SColor getOverrideColor() const; //! Sets if the static text should use the overide color or the //! color in the gui skin. virtual void enableOverrideColor(bool enable); //! Checks if an override color is enabled virtual bool isOverrideColorEnabled() const; //! Set whether the text in this label should be clipped if it goes outside bounds virtual void setTextRestrainedInside(bool restrainedInside); //! Checks if the text in this label should be clipped if it goes outside bounds virtual bool isTextRestrainedInside() const; //! Enables or disables word wrap for using the static text as //! multiline text control. virtual void setWordWrap(bool enable); //! Checks if word wrap is enabled virtual bool isWordWrapEnabled() const; //! Sets the new caption of this element. virtual void setText(const wchar_t* text); //! Returns the height of the text in pixels when it is drawn. virtual s32 getTextHeight() const; //! Returns the width of the current text, in the current font virtual s32 getTextWidth() const; //! Updates the absolute position, splits text if word wrap is enabled virtual void updateAbsolutePosition(); //! Set whether the string should be interpreted as right-to-left (RTL) text /** \note This component does not implement the Unicode bidi standard, the text of the component should be already RTL if you call this. The main difference when RTL is enabled is that the linebreaks for multiline elements are performed starting from the end. */ virtual void setRightToLeft(bool rtl); //! Checks if the text should be interpreted as right-to-left text virtual bool isRightToLeft() const; //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: //! Breaks the single text line. void breakText(); EGUI_ALIGNMENT HAlign, VAlign; bool Border; bool OverrideColorEnabled; bool OverrideBGColorEnabled; bool WordWrap; bool Background; bool RestrainTextInside; bool RightToLeft; video::SColor OverrideColor, BGColor; gui::IGUIFont* OverrideFont; gui::IGUIFont* LastBreakFont; // stored because: if skin changes, line break must be recalculated. core::array< core::stringw > BrokenText; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif irrlicht-1.8.3/source/Irrlicht/CGUIStaticText.cpp0000644000000000000000000003524112574354552020412 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIStaticText.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IGUIFont.h" #include "IVideoDriver.h" #include "rect.h" namespace irr { namespace gui { //! constructor CGUIStaticText::CGUIStaticText(const wchar_t* text, bool border, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle, bool background) : IGUIStaticText(environment, parent, id, rectangle), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT), Border(border), OverrideColorEnabled(false), OverrideBGColorEnabled(false), WordWrap(false), Background(background), RestrainTextInside(true), RightToLeft(false), OverrideColor(video::SColor(101,255,255,255)), BGColor(video::SColor(101,210,210,210)), OverrideFont(0), LastBreakFont(0) { #ifdef _DEBUG setDebugName("CGUIStaticText"); #endif Text = text; if (environment && environment->getSkin()) { BGColor = environment->getSkin()->getColor(gui::EGDC_3D_FACE); } } //! destructor CGUIStaticText::~CGUIStaticText() { if (OverrideFont) OverrideFont->drop(); } //! draws the element and its children void CGUIStaticText::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); if (!skin) return; video::IVideoDriver* driver = Environment->getVideoDriver(); core::rect frameRect(AbsoluteRect); // draw background if (Background) { if ( !OverrideBGColorEnabled ) // skin-colors can change BGColor = skin->getColor(gui::EGDC_3D_FACE); driver->draw2DRectangle(BGColor, frameRect, &AbsoluteClippingRect); } // draw the border if (Border) { skin->draw3DSunkenPane(this, 0, true, false, frameRect, &AbsoluteClippingRect); frameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X); } // draw the text if (Text.size()) { IGUIFont* font = getActiveFont(); if (font) { if (!WordWrap) { if (VAlign == EGUIA_LOWERRIGHT) { frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - font->getDimension(L"A").Height - font->getKerningHeight(); } if (HAlign == EGUIA_LOWERRIGHT) { frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X - font->getDimension(Text.c_str()).Width; } font->draw(Text.c_str(), frameRect, OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, (RestrainTextInside ? &AbsoluteClippingRect : NULL)); } else { if (font != LastBreakFont) breakText(); core::rect r = frameRect; s32 height = font->getDimension(L"A").Height + font->getKerningHeight(); s32 totalHeight = height * BrokenText.size(); if (VAlign == EGUIA_CENTER) { r.UpperLeftCorner.Y = r.getCenter().Y - (totalHeight / 2); } else if (VAlign == EGUIA_LOWERRIGHT) { r.UpperLeftCorner.Y = r.LowerRightCorner.Y - totalHeight; } for (u32 i=0; igetDimension(BrokenText[i].c_str()).Width; } font->draw(BrokenText[i].c_str(), r, OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), HAlign == EGUIA_CENTER, false, (RestrainTextInside ? &AbsoluteClippingRect : NULL)); r.LowerRightCorner.Y += height; r.UpperLeftCorner.Y += height; } } } } IGUIElement::draw(); } //! Sets another skin independent font. void CGUIStaticText::setOverrideFont(IGUIFont* font) { if (OverrideFont == font) return; if (OverrideFont) OverrideFont->drop(); OverrideFont = font; if (OverrideFont) OverrideFont->grab(); breakText(); } //! Gets the override font (if any) IGUIFont * CGUIStaticText::getOverrideFont() const { return OverrideFont; } //! Get the font which is used right now for drawing IGUIFont* CGUIStaticText::getActiveFont() const { if ( OverrideFont ) return OverrideFont; IGUISkin* skin = Environment->getSkin(); if (skin) return skin->getFont(); return 0; } //! Sets another color for the text. void CGUIStaticText::setOverrideColor(video::SColor color) { OverrideColor = color; OverrideColorEnabled = true; } //! Sets another color for the text. void CGUIStaticText::setBackgroundColor(video::SColor color) { BGColor = color; OverrideBGColorEnabled = true; Background = true; } //! Sets whether to draw the background void CGUIStaticText::setDrawBackground(bool draw) { Background = draw; } //! Gets the background color video::SColor CGUIStaticText::getBackgroundColor() const { return BGColor; } //! Checks if background drawing is enabled bool CGUIStaticText::isDrawBackgroundEnabled() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Background; } //! Sets whether to draw the border void CGUIStaticText::setDrawBorder(bool draw) { Border = draw; } //! Checks if border drawing is enabled bool CGUIStaticText::isDrawBorderEnabled() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Border; } void CGUIStaticText::setTextRestrainedInside(bool restrainTextInside) { RestrainTextInside = restrainTextInside; } bool CGUIStaticText::isTextRestrainedInside() const { return RestrainTextInside; } void CGUIStaticText::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) { HAlign = horizontal; VAlign = vertical; } video::SColor CGUIStaticText::getOverrideColor() const { return OverrideColor; } //! Sets if the static text should use the overide color or the //! color in the gui skin. void CGUIStaticText::enableOverrideColor(bool enable) { OverrideColorEnabled = enable; } bool CGUIStaticText::isOverrideColorEnabled() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return OverrideColorEnabled; } //! Enables or disables word wrap for using the static text as //! multiline text control. void CGUIStaticText::setWordWrap(bool enable) { WordWrap = enable; breakText(); } bool CGUIStaticText::isWordWrapEnabled() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return WordWrap; } void CGUIStaticText::setRightToLeft(bool rtl) { if (RightToLeft != rtl) { RightToLeft = rtl; breakText(); } } bool CGUIStaticText::isRightToLeft() const { return RightToLeft; } //! Breaks the single text line. void CGUIStaticText::breakText() { if (!WordWrap) return; BrokenText.clear(); IGUISkin* skin = Environment->getSkin(); IGUIFont* font = getActiveFont(); if (!font) return; LastBreakFont = font; core::stringw line; core::stringw word; core::stringw whitespace; s32 size = Text.size(); s32 length = 0; s32 elWidth = RelativeRect.getWidth(); if (Border) elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X); wchar_t c; // We have to deal with right-to-left and left-to-right differently // However, most parts of the following code is the same, it's just // some order and boundaries which change. if (!RightToLeft) { // regular (left-to-right) for (s32 i=0; igetDimension(whitespace.c_str()).Width; const s32 wordlgth = font->getDimension(word.c_str()).Width; if (wordlgth > elWidth) { // This word is too long to fit in the available space, look for // the Unicode Soft HYphen (SHY / 00AD) character for a place to // break the word at int where = word.findFirst( wchar_t(0x00AD) ); if (where != -1) { core::stringw first = word.subString(0, where); core::stringw second = word.subString(where, word.size() - where); BrokenText.push_back(line + first + L"-"); const s32 secondLength = font->getDimension(second.c_str()).Width; length = secondLength; line = second; } else { // No soft hyphen found, so there's nothing more we can do // break to next line if (length) BrokenText.push_back(line); length = wordlgth; line = word; } } else if (length && (length + wordlgth + whitelgth > elWidth)) { // break to next line BrokenText.push_back(line); length = wordlgth; line = word; } else { // add word to line line += whitespace; line += word; length += whitelgth + wordlgth; } word = L""; whitespace = L""; } if ( isWhitespace ) { whitespace += c; } // compute line break if (lineBreak) { line += whitespace; line += word; BrokenText.push_back(line); line = L""; word = L""; whitespace = L""; length = 0; } } } line += whitespace; line += word; BrokenText.push_back(line); } else { // right-to-left for (s32 i=size; i>=0; --i) { c = Text[i]; bool lineBreak = false; if (c == L'\r') // Mac or Windows breaks { lineBreak = true; if ((i>0) && Text[i-1] == L'\n') // Windows breaks { Text.erase(i-1); --size; } c = '\0'; } else if (c == L'\n') // Unix breaks { lineBreak = true; c = '\0'; } if (c==L' ' || c==0 || i==0) { if (word.size()) { // here comes the next whitespace, look if // we must break the last word to the next line. const s32 whitelgth = font->getDimension(whitespace.c_str()).Width; const s32 wordlgth = font->getDimension(word.c_str()).Width; if (length && (length + wordlgth + whitelgth > elWidth)) { // break to next line BrokenText.push_back(line); length = wordlgth; line = word; } else { // add word to line line = whitespace + line; line = word + line; length += whitelgth + wordlgth; } word = L""; whitespace = L""; } if (c != 0) whitespace = core::stringw(&c, 1) + whitespace; // compute line break if (lineBreak) { line = whitespace + line; line = word + line; BrokenText.push_back(line); line = L""; word = L""; whitespace = L""; length = 0; } } else { // yippee this is a word.. word = core::stringw(&c, 1) + word; } } line = whitespace + line; line = word + line; BrokenText.push_back(line); } } //! Sets the new caption of this element. void CGUIStaticText::setText(const wchar_t* text) { IGUIElement::setText(text); breakText(); } void CGUIStaticText::updateAbsolutePosition() { IGUIElement::updateAbsolutePosition(); breakText(); } //! Returns the height of the text in pixels when it is drawn. s32 CGUIStaticText::getTextHeight() const { IGUIFont* font = getActiveFont(); if (!font) return 0; if (WordWrap) { s32 height = font->getDimension(L"A").Height + font->getKerningHeight(); return height* BrokenText.size(); } else { // TODO: Text can have multiple lines which are not in BrokenText // This is likely not correct. But as I have no time for further // investigation I just fix it for now by return the true height here. return font->getDimension(Text.c_str()).Height; } } s32 CGUIStaticText::getTextWidth() const { IGUIFont * font = getActiveFont(); if(!font) return 0; if(WordWrap) { s32 widest = 0; for(u32 line = 0; line < BrokenText.size(); ++line) { s32 width = font->getDimension(BrokenText[line].c_str()).Width; if(width > widest) widest = width; } return widest; } else { return font->getDimension(Text.c_str()).Width; } } //! Writes attributes of the element. //! Implement this to expose the attributes of your element for //! scripting languages, editors, debuggers or xml serialization purposes. void CGUIStaticText::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUIStaticText::serializeAttributes(out,options); out->addBool ("Border", Border); out->addBool ("OverrideColorEnabled",OverrideColorEnabled); out->addBool ("OverrideBGColorEnabled",OverrideBGColorEnabled); out->addBool ("WordWrap", WordWrap); out->addBool ("Background", Background); out->addBool ("RightToLeft", RightToLeft); out->addBool ("RestrainTextInside", RestrainTextInside); out->addColor ("OverrideColor", OverrideColor); out->addColor ("BGColor", BGColor); out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); // out->addFont ("OverrideFont", OverrideFont); } //! Reads attributes of the element void CGUIStaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUIStaticText::deserializeAttributes(in,options); Border = in->getAttributeAsBool("Border"); enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled")); OverrideBGColorEnabled = in->getAttributeAsBool("OverrideBGColorEnabled"); setWordWrap(in->getAttributeAsBool("WordWrap")); Background = in->getAttributeAsBool("Background"); RightToLeft = in->getAttributeAsBool("RightToLeft"); RestrainTextInside = in->getAttributeAsBool("RestrainTextInside"); OverrideColor = in->getAttributeAsColor("OverrideColor"); BGColor = in->getAttributeAsColor("BGColor"); setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames), (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames)); // OverrideFont = in->getAttributeAsFont("OverrideFont"); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUISpriteBank.h0000644000000000000000000000440512574354552020023 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_SPRITE_BANK_H_INCLUDED__ #define __C_GUI_SPRITE_BANK_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISpriteBank.h" namespace irr { namespace video { class IVideoDriver; class ITexture; } namespace gui { class IGUIEnvironment; //! Sprite bank interface. class CGUISpriteBank : public IGUISpriteBank { public: CGUISpriteBank(IGUIEnvironment* env); virtual ~CGUISpriteBank(); virtual core::array< core::rect >& getPositions(); virtual core::array< SGUISprite >& getSprites(); virtual u32 getTextureCount() const; virtual video::ITexture* getTexture(u32 index) const; virtual void addTexture(video::ITexture* texture); virtual void setTexture(u32 index, video::ITexture* texture); //! Add the texture and use it for a single non-animated sprite. virtual s32 addTextureAsSprite(video::ITexture* texture); //! clears sprites, rectangles and textures virtual void clear(); //! Draws a sprite in 2d with position and color virtual void draw2DSprite(u32 index, const core::position2di& pos, const core::rect* clip=0, const video::SColor& color= video::SColor(255,255,255,255), u32 starttime=0, u32 currenttime=0, bool loop=true, bool center=false); //! Draws a sprite batch in 2d using an array of positions and a color virtual void draw2DSpriteBatch(const core::array& indices, const core::array& pos, const core::rect* clip=0, const video::SColor& color= video::SColor(255,255,255,255), u32 starttime=0, u32 currenttime=0, bool loop=true, bool center=false); protected: struct SDrawBatch { core::array positions; core::array sourceRects; u32 textureNumber; }; core::array Sprites; core::array< core::rect > Rectangles; core::array Textures; IGUIEnvironment* Environment; video::IVideoDriver* Driver; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_SPRITE_BANK_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUISpriteBank.cpp0000644000000000000000000001277212574354552020364 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUISpriteBank.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "ITexture.h" namespace irr { namespace gui { CGUISpriteBank::CGUISpriteBank(IGUIEnvironment* env) : Environment(env), Driver(0) { #ifdef _DEBUG setDebugName("CGUISpriteBank"); #endif if (Environment) { Driver = Environment->getVideoDriver(); if (Driver) Driver->grab(); } } CGUISpriteBank::~CGUISpriteBank() { // drop textures for (u32 i=0; idrop(); // drop video driver if (Driver) Driver->drop(); } core::array< core::rect >& CGUISpriteBank::getPositions() { return Rectangles; } core::array< SGUISprite >& CGUISpriteBank::getSprites() { return Sprites; } u32 CGUISpriteBank::getTextureCount() const { return Textures.size(); } video::ITexture* CGUISpriteBank::getTexture(u32 index) const { if (index < Textures.size()) return Textures[index]; else return 0; } void CGUISpriteBank::addTexture(video::ITexture* texture) { if (texture) texture->grab(); Textures.push_back(texture); } void CGUISpriteBank::setTexture(u32 index, video::ITexture* texture) { while (index >= Textures.size()) Textures.push_back(0); if (texture) texture->grab(); if (Textures[index]) Textures[index]->drop(); Textures[index] = texture; } //! clear everything void CGUISpriteBank::clear() { // drop textures for (u32 i=0; idrop(); Textures.clear(); Sprites.clear(); Rectangles.clear(); } //! Add the texture and use it for a single non-animated sprite. s32 CGUISpriteBank::addTextureAsSprite(video::ITexture* texture) { if ( !texture ) return -1; addTexture(texture); u32 textureIndex = getTextureCount() - 1; u32 rectangleIndex = Rectangles.size(); Rectangles.push_back( core::rect(0,0, texture->getOriginalSize().Width, texture->getOriginalSize().Height) ); SGUISprite sprite; sprite.frameTime = 0; SGUISpriteFrame frame; frame.textureNumber = textureIndex; frame.rectNumber = rectangleIndex; sprite.Frames.push_back( frame ); Sprites.push_back( sprite ); return Sprites.size() - 1; } //! draws a sprite in 2d with scale and color void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di& pos, const core::rect* clip, const video::SColor& color, u32 starttime, u32 currenttime, bool loop, bool center) { if (index >= Sprites.size() || Sprites[index].Frames.empty() ) return; // work out frame number u32 frame = 0; if (Sprites[index].frameTime) { u32 f = ((currenttime - starttime) / Sprites[index].frameTime); if (loop) frame = f % Sprites[index].Frames.size(); else frame = (f >= Sprites[index].Frames.size()) ? Sprites[index].Frames.size()-1 : f; } const video::ITexture* tex = Textures[Sprites[index].Frames[frame].textureNumber]; if (!tex) return; const u32 rn = Sprites[index].Frames[frame].rectNumber; if (rn >= Rectangles.size()) return; const core::rect& r = Rectangles[rn]; if (center) { core::position2di p = pos; p -= r.getSize() / 2; Driver->draw2DImage(tex, p, r, clip, color, true); } else { Driver->draw2DImage(tex, pos, r, clip, color, true); } } void CGUISpriteBank::draw2DSpriteBatch( const core::array& indices, const core::array& pos, const core::rect* clip, const video::SColor& color, u32 starttime, u32 currenttime, bool loop, bool center) { const irr::u32 drawCount = core::min_(indices.size(), pos.size()); if( Textures.empty() ) return; core::array drawBatches(Textures.size()); for(u32 i = 0;i < Textures.size();i++) { drawBatches.push_back(SDrawBatch()); drawBatches[i].positions.reallocate(drawCount); drawBatches[i].sourceRects.reallocate(drawCount); } for(u32 i = 0;i < drawCount;i++) { const u32 index = indices[i]; if (index >= Sprites.size() || Sprites[index].Frames.empty() ) continue; // work out frame number u32 frame = 0; if (Sprites[index].frameTime) { u32 f = ((currenttime - starttime) / Sprites[index].frameTime); if (loop) frame = f % Sprites[index].Frames.size(); else frame = (f >= Sprites[index].Frames.size()) ? Sprites[index].Frames.size()-1 : f; } const u32 texNum = Sprites[index].Frames[frame].textureNumber; SDrawBatch& currentBatch = drawBatches[texNum]; const u32 rn = Sprites[index].Frames[frame].rectNumber; if (rn >= Rectangles.size()) return; const core::rect& r = Rectangles[rn]; if (center) { core::position2di p = pos[i]; p -= r.getSize() / 2; currentBatch.positions.push_back(p); currentBatch.sourceRects.push_back(r); } else { currentBatch.positions.push_back(pos[i]); currentBatch.sourceRects.push_back(r); } } for(u32 i = 0;i < drawBatches.size();i++) { if(!drawBatches[i].positions.empty() && !drawBatches[i].sourceRects.empty()) Driver->draw2DImageBatch(Textures[i], drawBatches[i].positions, drawBatches[i].sourceRects, clip, color, true); } } } // namespace gui } // namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUISpinBox.h0000644000000000000000000000612012574354552017337 0ustar rootroot// Copyright (C) 2006-2012 Michael Zeilfelder // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_SPIN_BOX_H_INCLUDED__ #define __C_GUI_SPIN_BOX_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISpinBox.h" namespace irr { namespace gui { class IGUIEditBox; class IGUIButton; class CGUISpinBox : public IGUISpinBox { public: //! constructor CGUISpinBox(const wchar_t* text, bool border, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle); //! destructor virtual ~CGUISpinBox(); //! Access the edit box used in the spin control /** \param enable: If set to true, the override color, which can be set with IGUIEditBox::setOverrideColor is used, otherwise the EGDC_BUTTON_TEXT color of the skin. */ virtual IGUIEditBox* getEditBox() const; //! set the current value of the spinbox /** \param val: value to be set in the spinbox */ virtual void setValue(f32 val); //! Get the current value of the spinbox virtual f32 getValue() const; //! set the range of values which can be used in the spinbox /** \param min: minimum value \param max: maximum value */ virtual void setRange(f32 min, f32 max); //! get the minimum value which can be used in the spinbox virtual f32 getMin() const; //! get the maximum value which can be used in the spinbox virtual f32 getMax() const; //! step size by which values are changed when pressing the spin buttons /** \param step: stepsize used for value changes when pressing spin buttons */ virtual void setStepSize(f32 step=1.f); //! returns the step size virtual f32 getStepSize() const; //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! Draws the element and its children. virtual void draw(); //! Sets the new caption of the element virtual void setText(const wchar_t* text); //! Returns caption of this element. virtual const wchar_t* getText() const; //! Sets the number of decimal places to display. //! Note that this also rounds the range to the same number of decimal places. /** \param places: The number of decimal places to display, use -1 to reset */ virtual void setDecimalPlaces(s32 places); //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); protected: virtual void verifyValueRange(); void refreshSprites(); IGUIEditBox * EditBox; IGUIButton * ButtonSpinUp; IGUIButton * ButtonSpinDown; video::SColor CurrentIconColor; f32 StepSize; f32 RangeMin; f32 RangeMax; core::stringw FormatString; s32 DecimalPlaces; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_SPIN_BOX_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUISpinBox.cpp0000644000000000000000000001701312574354552017675 0ustar rootroot// Copyright (C) 2006-2012 Michael Zeilfelder // This file uses the licence of the Irrlicht Engine. #include "CGUISpinBox.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "CGUIEditBox.h" #include "CGUIButton.h" #include "IGUIEnvironment.h" #include "IEventReceiver.h" #include "fast_atof.h" #include namespace irr { namespace gui { //! constructor CGUISpinBox::CGUISpinBox(const wchar_t* text, bool border,IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle) : IGUISpinBox(environment, parent, id, rectangle), EditBox(0), ButtonSpinUp(0), ButtonSpinDown(0), StepSize(1.f), RangeMin(-FLT_MAX), RangeMax(FLT_MAX), FormatString(L"%f"), DecimalPlaces(-1) { #ifdef _DEBUG setDebugName("CGUISpinBox"); #endif CurrentIconColor = video::SColor(255,255,255,255); s32 ButtonWidth = 16; ButtonSpinDown = Environment->addButton( core::rect(rectangle.getWidth() - ButtonWidth, rectangle.getHeight()/2 +1, rectangle.getWidth(), rectangle.getHeight()), this); ButtonSpinDown->grab(); ButtonSpinDown->setSubElement(true); ButtonSpinDown->setTabStop(false); ButtonSpinDown->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_CENTER, EGUIA_LOWERRIGHT); ButtonSpinUp = Environment->addButton( core::rect(rectangle.getWidth() - ButtonWidth, 0, rectangle.getWidth(), rectangle.getHeight()/2), this); ButtonSpinUp->grab(); ButtonSpinUp->setSubElement(true); ButtonSpinUp->setTabStop(false); ButtonSpinUp->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_CENTER); const core::rect rectEdit(0, 0, rectangle.getWidth() - ButtonWidth - 1, rectangle.getHeight()); EditBox = Environment->addEditBox(text, rectEdit, border, this, -1); EditBox->grab(); EditBox->setSubElement(true); EditBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); refreshSprites(); } //! destructor CGUISpinBox::~CGUISpinBox() { if (ButtonSpinUp) ButtonSpinUp->drop(); if (ButtonSpinDown) ButtonSpinDown->drop(); if (EditBox) EditBox->drop(); } void CGUISpinBox::refreshSprites() { IGUISpriteBank *sb = 0; if (Environment && Environment->getSkin()) { sb = Environment->getSkin()->getSpriteBank(); } if (sb) { IGUISkin * skin = Environment->getSkin(); CurrentIconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL); ButtonSpinDown->setSpriteBank(sb); ButtonSpinDown->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_SMALL_CURSOR_DOWN), CurrentIconColor); ButtonSpinDown->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_SMALL_CURSOR_DOWN), CurrentIconColor); ButtonSpinUp->setSpriteBank(sb); ButtonSpinUp->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_SMALL_CURSOR_UP), CurrentIconColor); ButtonSpinUp->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_SMALL_CURSOR_UP), CurrentIconColor); } else { ButtonSpinDown->setText(L"-"); ButtonSpinUp->setText(L"+"); } } IGUIEditBox* CGUISpinBox::getEditBox() const { return EditBox; } void CGUISpinBox::setValue(f32 val) { wchar_t str[100]; swprintf(str, 99, FormatString.c_str(), val); EditBox->setText(str); verifyValueRange(); } f32 CGUISpinBox::getValue() const { const wchar_t* val = EditBox->getText(); if ( !val ) return 0.f; core::stringc tmp(val); return core::fast_atof(tmp.c_str()); } void CGUISpinBox::setRange(f32 min, f32 max) { if (maxOnEvent(e); return true; } } return IGUIElement::OnEvent(event); } void CGUISpinBox::draw() { if ( !isVisible() ) return; IGUISkin* skin = Environment->getSkin(); if (!skin) return; video::SColor iconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL); if ( iconColor != CurrentIconColor ) { refreshSprites(); } IGUISpinBox::draw(); } void CGUISpinBox::verifyValueRange() { f32 val = getValue(); if ( val+core::ROUNDING_ERROR_f32 < RangeMin ) val = RangeMin; else if ( val-core::ROUNDING_ERROR_f32 > RangeMax ) val = RangeMax; else return; setValue(val); } //! Sets the new caption of the element void CGUISpinBox::setText(const wchar_t* text) { EditBox->setText(text); setValue(getValue()); verifyValueRange(); } //! Returns caption of this element. const wchar_t* CGUISpinBox::getText() const { return EditBox->getText(); } //! Writes attributes of the element. void CGUISpinBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { IGUIElement::serializeAttributes(out, options); out->addFloat("Min", getMin()); out->addFloat("Max", getMax()); out->addFloat("Step", getStepSize()); out->addInt("DecimalPlaces", DecimalPlaces); } //! Reads attributes of the element void CGUISpinBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { IGUIElement::deserializeAttributes(in, options); setRange(in->getAttributeAsFloat("Min"), in->getAttributeAsFloat("Max")); setStepSize(in->getAttributeAsFloat("Step")); setDecimalPlaces(in->getAttributeAsInt("DecimalPlaces")); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUISkin.h0000644000000000000000000002444512574354552016673 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_SKIN_H_INCLUDED__ #define __C_GUI_SKIN_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "irrString.h" namespace irr { namespace video { class IVideoDriver; } namespace gui { class CGUISkin : public IGUISkin { public: CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver); //! destructor virtual ~CGUISkin(); //! returns default color virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const; //! sets a default color virtual void setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor); //! returns size for the given size type virtual s32 getSize(EGUI_DEFAULT_SIZE size) const; //! sets a default size virtual void setSize(EGUI_DEFAULT_SIZE which, s32 size); //! returns the default font virtual IGUIFont* getFont(EGUI_DEFAULT_FONT which=EGDF_DEFAULT) const; //! sets a default font virtual void setFont(IGUIFont* font, EGUI_DEFAULT_FONT which=EGDF_DEFAULT); //! sets the sprite bank used for drawing icons virtual void setSpriteBank(IGUISpriteBank* bank); //! gets the sprite bank used for drawing icons virtual IGUISpriteBank* getSpriteBank() const; //! Returns a default icon /** Returns the sprite index within the sprite bank */ virtual u32 getIcon(EGUI_DEFAULT_ICON icon) const; //! Sets a default icon /** Sets the sprite index used for drawing icons like arrows, close buttons and ticks in checkboxes \param icon: Enum specifying which icon to change \param index: The sprite index used to draw this icon */ virtual void setIcon(EGUI_DEFAULT_ICON icon, u32 index); //! Returns a default text. /** For example for Message box button captions: "OK", "Cancel", "Yes", "No" and so on. */ virtual const wchar_t* getDefaultText(EGUI_DEFAULT_TEXT text) const; //! Sets a default text. /** For example for Message box button captions: "OK", "Cancel", "Yes", "No" and so on. */ virtual void setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText); //! draws a standard 3d button pane /** Used for drawing for example buttons in normal state. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. \param rect: Defining area where to draw. \param clip: Clip area. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. */ virtual void draw3DButtonPaneStandard(IGUIElement* element, const core::rect& rect, const core::rect* clip=0); //! draws a pressed 3d button pane /** Used for drawing for example buttons in pressed state. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. \param rect: Defining area where to draw. \param clip: Clip area. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. */ virtual void draw3DButtonPanePressed(IGUIElement* element, const core::rect& rect, const core::rect* clip=0); //! draws a sunken 3d pane /** Used for drawing the background of edit, combo or check boxes. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param bgcolor: Background color. \param flat: Specifies if the sunken pane should be flat or displayed as sunken deep into the ground. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DSunkenPane(IGUIElement* element, video::SColor bgcolor, bool flat, bool fillBackGround, const core::rect& rect, const core::rect* clip=0); //! draws a window background /** Used for drawing the background of dialogs and windows. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param titleBarColor: Title color. \param drawTitleBar: True to enable title drawing. \param rect: Defining area where to draw. \param clip: Clip area. \param checkClientArea: When set to non-null the function will not draw anything, but will instead return the clientArea which can be used for drawing by the calling window. That is the area without borders and without titlebar. \return Returns rect where it would be good to draw title bar text. This will work even when checkClientArea is set to a non-null value.*/ virtual core::rect draw3DWindowBackground(IGUIElement* element, bool drawTitleBar, video::SColor titleBarColor, const core::rect& rect, const core::rect* clip, core::rect* checkClientArea); //! draws a standard 3d menu pane /** Used for drawing for menus and context menus. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DMenuPane(IGUIElement* element, const core::rect& rect, const core::rect* clip=0); //! draws a standard 3d tool bar /** Used for drawing for toolbars and menus. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DToolBar(IGUIElement* element, const core::rect& rect, const core::rect* clip=0); //! draws a tab button /** Used for drawing for tab buttons on top of tabs. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param active: Specifies if the tab is currently active. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DTabButton(IGUIElement* element, bool active, const core::rect& rect, const core::rect* clip=0, EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT); //! draws a tab control body /** \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param border: Specifies if the border should be drawn. \param background: Specifies if the background should be drawn. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DTabBody(IGUIElement* element, bool border, bool background, const core::rect& rect, const core::rect* clip=0, s32 tabHeight=-1, EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT); //! draws an icon, usually from the skin's sprite bank /** \param element: Pointer to the element which wishes to draw this icon. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param icon: Specifies the icon to be drawn. \param position: The position to draw the icon \param starttime: The time at the start of the animation \param currenttime: The present time, used to calculate the frame number \param loop: Whether the animation should loop or not \param clip: Clip area. */ virtual void drawIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon, const core::position2di position, u32 starttime=0, u32 currenttime=0, bool loop=false, const core::rect* clip=0); //! draws a 2d rectangle. /** \param element: Pointer to the element which wishes to draw this icon. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param color: Color of the rectangle to draw. The alpha component specifies how transparent the rectangle will be. \param pos: Position of the rectangle. \param clip: Pointer to rectangle against which the rectangle will be clipped. If the pointer is null, no clipping will be performed. */ virtual void draw2DRectangle(IGUIElement* element, const video::SColor &color, const core::rect& pos, const core::rect* clip = 0); //! get the type of this skin virtual EGUI_SKIN_TYPE getType() const; //! Writes attributes of the object. //! Implement this to expose the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml serialization purposes. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the object. //! Implement this to set the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml deserialization purposes. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); private: video::SColor Colors[EGDC_COUNT]; s32 Sizes[EGDS_COUNT]; u32 Icons[EGDI_COUNT]; IGUIFont* Fonts[EGDF_COUNT]; IGUISpriteBank* SpriteBank; core::stringw Texts[EGDT_COUNT]; video::IVideoDriver* Driver; bool UseGradient; EGUI_SKIN_TYPE Type; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif irrlicht-1.8.3/source/Irrlicht/CGUISkin.cpp0000644000000000000000000007533012574354552017225 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUISkin.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIFont.h" #include "IGUISpriteBank.h" #include "IGUIElement.h" #include "IVideoDriver.h" #include "IAttributes.h" namespace irr { namespace gui { CGUISkin::CGUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver) : SpriteBank(0), Driver(driver), Type(type) { #ifdef _DEBUG setDebugName("CGUISkin"); #endif if ((Type == EGST_WINDOWS_CLASSIC) || (Type == EGST_WINDOWS_METALLIC)) { Colors[EGDC_3D_DARK_SHADOW] = video::SColor(101,50,50,50); Colors[EGDC_3D_SHADOW] = video::SColor(101,130,130,130); Colors[EGDC_3D_FACE] = video::SColor(101,210,210,210); Colors[EGDC_3D_HIGH_LIGHT] = video::SColor(101,255,255,255); Colors[EGDC_3D_LIGHT] = video::SColor(101,210,210,210); Colors[EGDC_ACTIVE_BORDER] = video::SColor(101,16,14,115); Colors[EGDC_ACTIVE_CAPTION] = video::SColor(255,255,255,255); Colors[EGDC_APP_WORKSPACE] = video::SColor(101,100,100,100); Colors[EGDC_BUTTON_TEXT] = video::SColor(240,10,10,10); Colors[EGDC_GRAY_TEXT] = video::SColor(240,130,130,130); Colors[EGDC_HIGH_LIGHT] = video::SColor(101,8,36,107); Colors[EGDC_HIGH_LIGHT_TEXT] = video::SColor(240,255,255,255); Colors[EGDC_INACTIVE_BORDER] = video::SColor(101,165,165,165); Colors[EGDC_INACTIVE_CAPTION] = video::SColor(255,30,30,30); Colors[EGDC_TOOLTIP] = video::SColor(200,0,0,0); Colors[EGDC_TOOLTIP_BACKGROUND] = video::SColor(200,255,255,225); Colors[EGDC_SCROLLBAR] = video::SColor(101,230,230,230); Colors[EGDC_WINDOW] = video::SColor(101,255,255,255); Colors[EGDC_WINDOW_SYMBOL] = video::SColor(200,10,10,10); Colors[EGDC_ICON] = video::SColor(200,255,255,255); Colors[EGDC_ICON_HIGH_LIGHT] = video::SColor(200,8,36,107); Colors[EGDC_GRAY_WINDOW_SYMBOL] = video::SColor(240,100,100,100); Colors[EGDC_EDITABLE] = video::SColor(255,255,255,255); Colors[EGDC_GRAY_EDITABLE] = video::SColor(255,120,120,120); Colors[EGDC_FOCUSED_EDITABLE] = video::SColor(255,240,240,255); Sizes[EGDS_SCROLLBAR_SIZE] = 14; Sizes[EGDS_MENU_HEIGHT] = 30; Sizes[EGDS_WINDOW_BUTTON_WIDTH] = 15; Sizes[EGDS_CHECK_BOX_WIDTH] = 18; Sizes[EGDS_MESSAGE_BOX_WIDTH] = 500; Sizes[EGDS_MESSAGE_BOX_HEIGHT] = 200; Sizes[EGDS_BUTTON_WIDTH] = 80; Sizes[EGDS_BUTTON_HEIGHT] = 30; Sizes[EGDS_TEXT_DISTANCE_X] = 2; Sizes[EGDS_TEXT_DISTANCE_Y] = 0; Sizes[EGDS_TITLEBARTEXT_DISTANCE_X] = 2; Sizes[EGDS_TITLEBARTEXT_DISTANCE_Y] = 0; } else { //0x80a6a8af Colors[EGDC_3D_DARK_SHADOW] = 0x60767982; //Colors[EGDC_3D_FACE] = 0xc0c9ccd4; // tab background Colors[EGDC_3D_FACE] = 0xc0cbd2d9; // tab background Colors[EGDC_3D_SHADOW] = 0x50e4e8f1; // tab background, and left-top highlight Colors[EGDC_3D_HIGH_LIGHT] = 0x40c7ccdc; Colors[EGDC_3D_LIGHT] = 0x802e313a; Colors[EGDC_ACTIVE_BORDER] = 0x80404040; // window title Colors[EGDC_ACTIVE_CAPTION] = 0xffd0d0d0; Colors[EGDC_APP_WORKSPACE] = 0xc0646464; // unused Colors[EGDC_BUTTON_TEXT] = 0xd0161616; Colors[EGDC_GRAY_TEXT] = 0x3c141414; Colors[EGDC_HIGH_LIGHT] = 0x6c606060; Colors[EGDC_HIGH_LIGHT_TEXT] = 0xd0e0e0e0; Colors[EGDC_INACTIVE_BORDER] = 0xf0a5a5a5; Colors[EGDC_INACTIVE_CAPTION] = 0xffd2d2d2; Colors[EGDC_TOOLTIP] = 0xf00f2033; Colors[EGDC_TOOLTIP_BACKGROUND] = 0xc0cbd2d9; Colors[EGDC_SCROLLBAR] = 0xf0e0e0e0; Colors[EGDC_WINDOW] = 0xf0f0f0f0; Colors[EGDC_WINDOW_SYMBOL] = 0xd0161616; Colors[EGDC_ICON] = 0xd0161616; Colors[EGDC_ICON_HIGH_LIGHT] = 0xd0606060; Colors[EGDC_GRAY_WINDOW_SYMBOL] = 0x3c101010; Colors[EGDC_EDITABLE] = 0xf0ffffff; Colors[EGDC_GRAY_EDITABLE] = 0xf0cccccc; Colors[EGDC_FOCUSED_EDITABLE] = 0xf0fffff0; Sizes[EGDS_SCROLLBAR_SIZE] = 14; Sizes[EGDS_MENU_HEIGHT] = 48; Sizes[EGDS_WINDOW_BUTTON_WIDTH] = 15; Sizes[EGDS_CHECK_BOX_WIDTH] = 18; Sizes[EGDS_MESSAGE_BOX_WIDTH] = 500; Sizes[EGDS_MESSAGE_BOX_HEIGHT] = 200; Sizes[EGDS_BUTTON_WIDTH] = 80; Sizes[EGDS_BUTTON_HEIGHT] = 30; Sizes[EGDS_TEXT_DISTANCE_X] = 3; Sizes[EGDS_TEXT_DISTANCE_Y] = 2; Sizes[EGDS_TITLEBARTEXT_DISTANCE_X] = 3; Sizes[EGDS_TITLEBARTEXT_DISTANCE_Y] = 2; } Sizes[EGDS_MESSAGE_BOX_GAP_SPACE] = 15; Sizes[EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH] = 0; Sizes[EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH] = 500; Sizes[EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT] = 0; Sizes[EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT] = 99999; Sizes[EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X] = 1; Sizes[EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y] = 1; Sizes[EGDS_BUTTON_PRESSED_TEXT_OFFSET_X] = 0; Sizes[EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y] = 2; Texts[EGDT_MSG_BOX_OK] = L"OK"; Texts[EGDT_MSG_BOX_CANCEL] = L"Cancel"; Texts[EGDT_MSG_BOX_YES] = L"Yes"; Texts[EGDT_MSG_BOX_NO] = L"No"; Texts[EGDT_WINDOW_CLOSE] = L"Close"; Texts[EGDT_WINDOW_RESTORE] = L"Restore"; Texts[EGDT_WINDOW_MINIMIZE] = L"Minimize"; Texts[EGDT_WINDOW_MAXIMIZE] = L"Maximize"; Icons[EGDI_WINDOW_MAXIMIZE] = 225; Icons[EGDI_WINDOW_RESTORE] = 226; Icons[EGDI_WINDOW_CLOSE] = 227; Icons[EGDI_WINDOW_MINIMIZE] = 228; Icons[EGDI_CURSOR_UP] = 229; Icons[EGDI_CURSOR_DOWN] = 230; Icons[EGDI_CURSOR_LEFT] = 231; Icons[EGDI_CURSOR_RIGHT] = 232; Icons[EGDI_MENU_MORE] = 232; Icons[EGDI_CHECK_BOX_CHECKED] = 233; Icons[EGDI_DROP_DOWN] = 234; Icons[EGDI_SMALL_CURSOR_UP] = 235; Icons[EGDI_SMALL_CURSOR_DOWN] = 236; Icons[EGDI_RADIO_BUTTON_CHECKED] = 237; Icons[EGDI_MORE_LEFT] = 238; Icons[EGDI_MORE_RIGHT] = 239; Icons[EGDI_MORE_UP] = 240; Icons[EGDI_MORE_DOWN] = 241; Icons[EGDI_WINDOW_RESIZE] = 242; Icons[EGDI_EXPAND] = 243; Icons[EGDI_COLLAPSE] = 244; Icons[EGDI_FILE] = 245; Icons[EGDI_DIRECTORY] = 246; for (u32 i=0; idrop(); } if (SpriteBank) SpriteBank->drop(); } //! returns default color video::SColor CGUISkin::getColor(EGUI_DEFAULT_COLOR color) const { if ((u32)color < EGDC_COUNT) return Colors[color]; else return video::SColor(); } //! sets a default color void CGUISkin::setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor) { if ((u32)which < EGDC_COUNT) Colors[which] = newColor; } //! returns size for the given size type s32 CGUISkin::getSize(EGUI_DEFAULT_SIZE size) const { if ((u32)size < EGDS_COUNT) return Sizes[size]; else return 0; } //! sets a default size void CGUISkin::setSize(EGUI_DEFAULT_SIZE which, s32 size) { if ((u32)which < EGDS_COUNT) Sizes[which] = size; } //! returns the default font IGUIFont* CGUISkin::getFont(EGUI_DEFAULT_FONT which) const { if (((u32)which < EGDF_COUNT) && Fonts[which]) return Fonts[which]; else return Fonts[EGDF_DEFAULT]; } //! sets a default font void CGUISkin::setFont(IGUIFont* font, EGUI_DEFAULT_FONT which) { if ((u32)which >= EGDF_COUNT) return; if (font) { font->grab(); if (Fonts[which]) Fonts[which]->drop(); Fonts[which] = font; } } //! gets the sprite bank stored IGUISpriteBank* CGUISkin::getSpriteBank() const { return SpriteBank; } //! set a new sprite bank or remove one by passing 0 void CGUISkin::setSpriteBank(IGUISpriteBank* bank) { if (bank) bank->grab(); if (SpriteBank) SpriteBank->drop(); SpriteBank = bank; } //! Returns a default icon u32 CGUISkin::getIcon(EGUI_DEFAULT_ICON icon) const { if ((u32)icon < EGDI_COUNT) return Icons[icon]; else return 0; } //! Sets a default icon void CGUISkin::setIcon(EGUI_DEFAULT_ICON icon, u32 index) { if ((u32)icon < EGDI_COUNT) Icons[icon] = index; } //! Returns a default text. For example for Message box button captions: //! "OK", "Cancel", "Yes", "No" and so on. const wchar_t* CGUISkin::getDefaultText(EGUI_DEFAULT_TEXT text) const { if ((u32)text < EGDT_COUNT) return Texts[text].c_str(); else return Texts[0].c_str(); } //! Sets a default text. For example for Message box button captions: //! "OK", "Cancel", "Yes", "No" and so on. void CGUISkin::setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText) { if ((u32)which < EGDT_COUNT) Texts[which] = newText; } //! draws a standard 3d button pane /** Used for drawing for example buttons in normal state. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. \param rect: Defining area where to draw. \param clip: Clip area. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. */ void CGUISkin::draw3DButtonPaneStandard(IGUIElement* element, const core::rect& r, const core::rect* clip) { if (!Driver) return; core::rect rect = r; if ( Type == EGST_BURNING_SKIN ) { rect.UpperLeftCorner.X -= 1; rect.UpperLeftCorner.Y -= 1; rect.LowerRightCorner.X += 1; rect.LowerRightCorner.Y += 1; draw3DSunkenPane(element, getColor( EGDC_WINDOW ).getInterpolated( 0xFFFFFFFF, 0.9f ) ,false, true, rect, clip); return; } Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip); rect.LowerRightCorner.X -= 1; rect.LowerRightCorner.Y -= 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); rect.UpperLeftCorner.X += 1; rect.UpperLeftCorner.Y += 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); rect.LowerRightCorner.X -= 1; rect.LowerRightCorner.Y -= 1; if (!UseGradient) { Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, clip); } else { const video::SColor c1 = getColor(EGDC_3D_FACE); const video::SColor c2 = c1.getInterpolated(getColor(EGDC_3D_DARK_SHADOW), 0.4f); Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip); } } //! draws a pressed 3d button pane /** Used for drawing for example buttons in pressed state. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. \param rect: Defining area where to draw. \param clip: Clip area. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. */ void CGUISkin::draw3DButtonPanePressed(IGUIElement* element, const core::rect& r, const core::rect* clip) { if (!Driver) return; core::rect rect = r; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); rect.LowerRightCorner.X -= 1; rect.LowerRightCorner.Y -= 1; Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip); rect.UpperLeftCorner.X += 1; rect.UpperLeftCorner.Y += 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); rect.UpperLeftCorner.X += 1; rect.UpperLeftCorner.Y += 1; if (!UseGradient) { Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, clip); } else { const video::SColor c1 = getColor(EGDC_3D_FACE); const video::SColor c2 = c1.getInterpolated(getColor(EGDC_3D_DARK_SHADOW), 0.4f); Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip); } } //! draws a sunken 3d pane /** Used for drawing the background of edit, combo or check boxes. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param bgcolor: Background color. \param flat: Specifies if the sunken pane should be flat or displayed as sunken deep into the ground. \param rect: Defining area where to draw. \param clip: Clip area. */ void CGUISkin::draw3DSunkenPane(IGUIElement* element, video::SColor bgcolor, bool flat, bool fillBackGround, const core::rect& r, const core::rect* clip) { if (!Driver) return; core::rect rect = r; if (fillBackGround) Driver->draw2DRectangle(bgcolor, rect, clip); if (flat) { // draw flat sunken pane rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // top ++rect.UpperLeftCorner.Y; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // left rect = r; ++rect.UpperLeftCorner.Y; rect.UpperLeftCorner.X = rect.LowerRightCorner.X - 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // right rect = r; ++rect.UpperLeftCorner.X; rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1; --rect.LowerRightCorner.X; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // bottom } else { // draw deep sunken pane rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // top ++rect.UpperLeftCorner.X; ++rect.UpperLeftCorner.Y; --rect.LowerRightCorner.X; ++rect.LowerRightCorner.Y; Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip); rect.UpperLeftCorner.X = r.UpperLeftCorner.X; rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y+1; rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); // left ++rect.UpperLeftCorner.X; ++rect.UpperLeftCorner.Y; ++rect.LowerRightCorner.X; --rect.LowerRightCorner.Y; Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip); rect = r; rect.UpperLeftCorner.X = rect.LowerRightCorner.X - 1; ++rect.UpperLeftCorner.Y; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // right --rect.UpperLeftCorner.X; ++rect.UpperLeftCorner.Y; --rect.LowerRightCorner.X; --rect.LowerRightCorner.Y; Driver->draw2DRectangle(getColor(EGDC_3D_LIGHT), rect, clip); rect = r; ++rect.UpperLeftCorner.X; rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1; --rect.LowerRightCorner.X; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); // bottom ++rect.UpperLeftCorner.X; --rect.UpperLeftCorner.Y; --rect.LowerRightCorner.X; --rect.LowerRightCorner.Y; Driver->draw2DRectangle(getColor(EGDC_3D_LIGHT), rect, clip); } } //! draws a window background // return where to draw title bar text. core::rect CGUISkin::draw3DWindowBackground(IGUIElement* element, bool drawTitleBar, video::SColor titleBarColor, const core::rect& r, const core::rect* clip, core::rect* checkClientArea) { if (!Driver) { if ( checkClientArea ) { *checkClientArea = r; } return r; } core::rect rect = r; // top border rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1; if ( !checkClientArea ) { Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); } // left border rect.LowerRightCorner.Y = r.LowerRightCorner.Y; rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1; if ( !checkClientArea ) { Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); } // right border dark outer line rect.UpperLeftCorner.X = r.LowerRightCorner.X - 1; rect.LowerRightCorner.X = r.LowerRightCorner.X; rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; if ( !checkClientArea ) { Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip); } // right border bright innner line rect.UpperLeftCorner.X -= 1; rect.LowerRightCorner.X -= 1; rect.UpperLeftCorner.Y += 1; rect.LowerRightCorner.Y -= 1; if ( !checkClientArea ) { Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); } // bottom border dark outer line rect.UpperLeftCorner.X = r.UpperLeftCorner.X; rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; rect.LowerRightCorner.X = r.LowerRightCorner.X; if ( !checkClientArea ) { Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip); } // bottom border bright inner line rect.UpperLeftCorner.X += 1; rect.LowerRightCorner.X -= 1; rect.UpperLeftCorner.Y -= 1; rect.LowerRightCorner.Y -= 1; if ( !checkClientArea ) { Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); } // client area for background rect = r; rect.UpperLeftCorner.X +=1; rect.UpperLeftCorner.Y +=1; rect.LowerRightCorner.X -= 2; rect.LowerRightCorner.Y -= 2; if (checkClientArea) { *checkClientArea = rect; } if ( !checkClientArea ) { if (!UseGradient) { Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, clip); } else if ( Type == EGST_BURNING_SKIN ) { const video::SColor c1 = getColor(EGDC_WINDOW).getInterpolated ( 0xFFFFFFFF, 0.9f ); const video::SColor c2 = getColor(EGDC_WINDOW).getInterpolated ( 0xFFFFFFFF, 0.8f ); Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip); } else { const video::SColor c2 = getColor(EGDC_3D_SHADOW); const video::SColor c1 = getColor(EGDC_3D_FACE); Driver->draw2DRectangle(rect, c1, c1, c1, c2, clip); } } // title bar rect = r; rect.UpperLeftCorner.X += 2; rect.UpperLeftCorner.Y += 2; rect.LowerRightCorner.X -= 2; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + getSize(EGDS_WINDOW_BUTTON_WIDTH) + 2; if (drawTitleBar ) { if (checkClientArea) { (*checkClientArea).UpperLeftCorner.Y = rect.LowerRightCorner.Y; } else { // draw title bar //if (!UseGradient) // Driver->draw2DRectangle(titleBarColor, rect, clip); //else if ( Type == EGST_BURNING_SKIN ) { const video::SColor c = titleBarColor.getInterpolated( video::SColor(titleBarColor.getAlpha(),255,255,255), 0.8f); Driver->draw2DRectangle(rect, titleBarColor, titleBarColor, c, c, clip); } else { const video::SColor c = titleBarColor.getInterpolated(video::SColor(titleBarColor.getAlpha(),0,0,0), 0.2f); Driver->draw2DRectangle(rect, titleBarColor, c, titleBarColor, c, clip); } } } return rect; } //! draws a standard 3d menu pane /** Used for drawing for menus and context menus. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param rect: Defining area where to draw. \param clip: Clip area. */ void CGUISkin::draw3DMenuPane(IGUIElement* element, const core::rect& r, const core::rect* clip) { if (!Driver) return; core::rect rect = r; if ( Type == EGST_BURNING_SKIN ) { rect.UpperLeftCorner.Y -= 3; draw3DButtonPaneStandard(element, rect, clip); return; } // in this skin, this is exactly what non pressed buttons look like, // so we could simply call // draw3DButtonPaneStandard(element, rect, clip); // here. // but if the skin is transparent, this doesn't look that nice. So // We draw it a little bit better, with some more draw2DRectangle calls, // but there aren't that much menus visible anyway. rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); rect.LowerRightCorner.Y = r.LowerRightCorner.Y; rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, clip); rect.UpperLeftCorner.X = r.LowerRightCorner.X - 1; rect.LowerRightCorner.X = r.LowerRightCorner.X; rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip); rect.UpperLeftCorner.X -= 1; rect.LowerRightCorner.X -= 1; rect.UpperLeftCorner.Y += 1; rect.LowerRightCorner.Y -= 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); rect.UpperLeftCorner.X = r.UpperLeftCorner.X; rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; rect.LowerRightCorner.X = r.LowerRightCorner.X; Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, clip); rect.UpperLeftCorner.X += 1; rect.LowerRightCorner.X -= 1; rect.UpperLeftCorner.Y -= 1; rect.LowerRightCorner.Y -= 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); rect = r; rect.UpperLeftCorner.X +=1; rect.UpperLeftCorner.Y +=1; rect.LowerRightCorner.X -= 2; rect.LowerRightCorner.Y -= 2; if (!UseGradient) Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, clip); else { const video::SColor c1 = getColor(EGDC_3D_FACE); const video::SColor c2 = getColor(EGDC_3D_SHADOW); Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip); } } //! draws a standard 3d tool bar /** Used for drawing for toolbars and menus. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param rect: Defining area where to draw. \param clip: Clip area. */ void CGUISkin::draw3DToolBar(IGUIElement* element, const core::rect& r, const core::rect* clip) { if (!Driver) return; core::rect rect = r; rect.UpperLeftCorner.X = r.UpperLeftCorner.X; rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; rect.LowerRightCorner.X = r.LowerRightCorner.X; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, clip); rect = r; rect.LowerRightCorner.Y -= 1; if (!UseGradient) { Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, clip); } else if ( Type == EGST_BURNING_SKIN ) { const video::SColor c1 = 0xF0000000 | getColor(EGDC_3D_FACE).color; const video::SColor c2 = 0xF0000000 | getColor(EGDC_3D_SHADOW).color; rect.LowerRightCorner.Y += 1; Driver->draw2DRectangle(rect, c1, c2, c1, c2, clip); } else { const video::SColor c1 = getColor(EGDC_3D_FACE); const video::SColor c2 = getColor(EGDC_3D_SHADOW); Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip); } } //! draws a tab button /** Used for drawing for tab buttons on top of tabs. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param active: Specifies if the tab is currently active. \param rect: Defining area where to draw. \param clip: Clip area. */ void CGUISkin::draw3DTabButton(IGUIElement* element, bool active, const core::rect& frameRect, const core::rect* clip, EGUI_ALIGNMENT alignment) { if (!Driver) return; core::rect tr = frameRect; if ( alignment == EGUIA_UPPERLEFT ) { tr.LowerRightCorner.X -= 2; tr.LowerRightCorner.Y = tr.UpperLeftCorner.Y + 1; tr.UpperLeftCorner.X += 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), tr, clip); // draw left highlight tr = frameRect; tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1; tr.UpperLeftCorner.Y += 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), tr, clip); // draw grey background tr = frameRect; tr.UpperLeftCorner.X += 1; tr.UpperLeftCorner.Y += 1; tr.LowerRightCorner.X -= 2; Driver->draw2DRectangle(getColor(EGDC_3D_FACE), tr, clip); // draw right middle gray shadow tr.LowerRightCorner.X += 1; tr.UpperLeftCorner.X = tr.LowerRightCorner.X - 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), tr, clip); tr.LowerRightCorner.X += 1; tr.UpperLeftCorner.X += 1; tr.UpperLeftCorner.Y += 1; Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), tr, clip); } else { tr.LowerRightCorner.X -= 2; tr.UpperLeftCorner.Y = tr.LowerRightCorner.Y - 1; tr.UpperLeftCorner.X += 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), tr, clip); // draw left highlight tr = frameRect; tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1; tr.LowerRightCorner.Y -= 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), tr, clip); // draw grey background tr = frameRect; tr.UpperLeftCorner.X += 1; tr.UpperLeftCorner.Y -= 1; tr.LowerRightCorner.X -= 2; tr.LowerRightCorner.Y -= 1; Driver->draw2DRectangle(getColor(EGDC_3D_FACE), tr, clip); // draw right middle gray shadow tr.LowerRightCorner.X += 1; tr.UpperLeftCorner.X = tr.LowerRightCorner.X - 1; //tr.LowerRightCorner.Y -= 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), tr, clip); tr.LowerRightCorner.X += 1; tr.UpperLeftCorner.X += 1; tr.LowerRightCorner.Y -= 1; Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), tr, clip); } } //! draws a tab control body /** \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by ISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param border: Specifies if the border should be drawn. \param background: Specifies if the background should be drawn. \param rect: Defining area where to draw. \param clip: Clip area. */ void CGUISkin::draw3DTabBody(IGUIElement* element, bool border, bool background, const core::rect& rect, const core::rect* clip, s32 tabHeight, EGUI_ALIGNMENT alignment) { if (!Driver) return; core::rect tr = rect; if ( tabHeight == -1 ) tabHeight = getSize(gui::EGDS_BUTTON_HEIGHT); // draw border. if (border) { if ( alignment == EGUIA_UPPERLEFT ) { // draw left hightlight tr.UpperLeftCorner.Y += tabHeight + 2; tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), tr, clip); // draw right shadow tr.UpperLeftCorner.X = rect.LowerRightCorner.X - 1; tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), tr, clip); // draw lower shadow tr = rect; tr.UpperLeftCorner.Y = tr.LowerRightCorner.Y - 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), tr, clip); } else { // draw left hightlight tr.LowerRightCorner.Y -= tabHeight + 2; tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), tr, clip); // draw right shadow tr.UpperLeftCorner.X = rect.LowerRightCorner.X - 1; tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1; Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), tr, clip); // draw lower shadow tr = rect; tr.LowerRightCorner.Y = tr.UpperLeftCorner.Y + 1; Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), tr, clip); } } if (background) { if ( alignment == EGUIA_UPPERLEFT ) { tr = rect; tr.UpperLeftCorner.Y += tabHeight + 2; tr.LowerRightCorner.X -= 1; tr.UpperLeftCorner.X += 1; tr.LowerRightCorner.Y -= 1; } else { tr = rect; tr.UpperLeftCorner.X += 1; tr.UpperLeftCorner.Y -= 1; tr.LowerRightCorner.X -= 1; tr.LowerRightCorner.Y -= tabHeight + 2; //tr.UpperLeftCorner.X += 1; } if (!UseGradient) Driver->draw2DRectangle(getColor(EGDC_3D_FACE), tr, clip); else { video::SColor c1 = getColor(EGDC_3D_FACE); video::SColor c2 = getColor(EGDC_3D_SHADOW); Driver->draw2DRectangle(tr, c1, c1, c2, c2, clip); } } } //! draws an icon, usually from the skin's sprite bank /** \param parent: Pointer to the element which wishes to draw this icon. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param icon: Specifies the icon to be drawn. \param position: The position to draw the icon \param starttime: The time at the start of the animation \param currenttime: The present time, used to calculate the frame number \param loop: Whether the animation should loop or not \param clip: Clip area. */ void CGUISkin::drawIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon, const core::position2di position, u32 starttime, u32 currenttime, bool loop, const core::rect* clip) { if (!SpriteBank) return; bool gray = element && !element->isEnabled(); SpriteBank->draw2DSprite(Icons[icon], position, clip, Colors[gray? EGDC_GRAY_WINDOW_SYMBOL : EGDC_WINDOW_SYMBOL], starttime, currenttime, loop, true); } EGUI_SKIN_TYPE CGUISkin::getType() const { return Type; } //! draws a 2d rectangle. void CGUISkin::draw2DRectangle(IGUIElement* element, const video::SColor &color, const core::rect& pos, const core::rect* clip) { Driver->draw2DRectangle(color, pos, clip); } //! Writes attributes of the object. //! Implement this to expose the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml serialization purposes. void CGUISkin::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { u32 i; for (i=0; iaddColor(GUISkinColorNames[i], Colors[i]); for (i=0; iaddInt(GUISkinSizeNames[i], Sizes[i]); for (i=0; iaddString(GUISkinTextNames[i], Texts[i].c_str()); for (i=0; iaddInt(GUISkinIconNames[i], Icons[i]); } //! Reads attributes of the object. //! Implement this to set the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml deserialization purposes. void CGUISkin::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { // TODO: This is not nice code for downward compatibility, whenever new values are added and users // load an old skin the corresponding values will be set to 0. u32 i; for (i=0; igetAttributeAsColor(GUISkinColorNames[i]); for (i=0; igetAttributeAsInt(GUISkinSizeNames[i]); for (i=0; igetAttributeAsStringW(GUISkinTextNames[i]); for (i=0; igetAttributeAsInt(GUISkinIconNames[i]); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIScrollBar.h0000644000000000000000000000513212574354552017642 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_SCROLL_BAR_H_INCLUDED__ #define __C_GUI_SCROLL_BAR_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIScrollBar.h" #include "IGUIButton.h" namespace irr { namespace gui { class CGUIScrollBar : public IGUIScrollBar { public: //! constructor CGUIScrollBar(bool horizontal, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool noclip=false); //! destructor virtual ~CGUIScrollBar(); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! draws the element and its children virtual void draw(); virtual void OnPostRender(u32 timeMs); //! gets the maximum value of the scrollbar. virtual s32 getMax() const; //! sets the maximum value of the scrollbar. virtual void setMax(s32 max); //! gets the minimum value of the scrollbar. virtual s32 getMin() const; //! sets the minimum value of the scrollbar. virtual void setMin(s32 min); //! gets the small step value virtual s32 getSmallStep() const; //! sets the small step value virtual void setSmallStep(s32 step); //! gets the large step value virtual s32 getLargeStep() const; //! sets the large step value virtual void setLargeStep(s32 step); //! gets the current position of the scrollbar virtual s32 getPos() const; //! sets the position of the scrollbar virtual void setPos(s32 pos); //! updates the rectangle virtual void updateAbsolutePosition(); //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: void refreshControls(); s32 getPosFromMousePos(const core::position2di &p) const; IGUIButton* UpButton; IGUIButton* DownButton; core::rect SliderRect; bool Dragging; bool Horizontal; bool DraggedBySlider; bool TrayClick; s32 Pos; s32 DrawPos; s32 DrawHeight; s32 Min; s32 Max; s32 SmallStep; s32 LargeStep; s32 DesiredPos; u32 LastChange; video::SColor CurrentIconColor; f32 range () const { return (f32) ( Max - Min ); } }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif irrlicht-1.8.3/source/Irrlicht/CGUIScrollBar.cpp0000644000000000000000000003354112574354552020202 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIScrollBar.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "CGUIButton.h" #include "IGUIFont.h" #include "IGUIFontBitmap.h" #include "os.h" namespace irr { namespace gui { //! constructor CGUIScrollBar::CGUIScrollBar(bool horizontal, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool noclip) : IGUIScrollBar(environment, parent, id, rectangle), UpButton(0), DownButton(0), Dragging(false), Horizontal(horizontal), DraggedBySlider(false), TrayClick(false), Pos(0), DrawPos(0), DrawHeight(0), Min(0), Max(100), SmallStep(10), LargeStep(50), DesiredPos(0), LastChange(0) { #ifdef _DEBUG setDebugName("CGUIScrollBar"); #endif refreshControls(); setNotClipped(noclip); // this element can be tabbed to setTabStop(true); setTabOrder(-1); setPos(0); } //! destructor CGUIScrollBar::~CGUIScrollBar() { if (UpButton) UpButton->drop(); if (DownButton) DownButton->drop(); } //! called if an event happened. bool CGUIScrollBar::OnEvent(const SEvent& event) { if (isEnabled()) { switch(event.EventType) { case EET_KEY_INPUT_EVENT: if (event.KeyInput.PressedDown) { const s32 oldPos = Pos; bool absorb = true; switch (event.KeyInput.Key) { case KEY_LEFT: case KEY_UP: setPos(Pos-SmallStep); break; case KEY_RIGHT: case KEY_DOWN: setPos(Pos+SmallStep); break; case KEY_HOME: setPos(Min); break; case KEY_PRIOR: setPos(Pos-LargeStep); break; case KEY_END: setPos(Max); break; case KEY_NEXT: setPos(Pos+LargeStep); break; default: absorb = false; } if (Pos != oldPos) { SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; newEvent.GUIEvent.Element = 0; newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED; Parent->OnEvent(newEvent); } if (absorb) return true; } break; case EET_GUI_EVENT: if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) { if (event.GUIEvent.Caller == UpButton) setPos(Pos-SmallStep); else if (event.GUIEvent.Caller == DownButton) setPos(Pos+SmallStep); SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; newEvent.GUIEvent.Element = 0; newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED; Parent->OnEvent(newEvent); return true; } else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) { if (event.GUIEvent.Caller == this) Dragging = false; } break; case EET_MOUSE_INPUT_EVENT: { const core::position2di p(event.MouseInput.X, event.MouseInput.Y); bool isInside = isPointInside ( p ); switch(event.MouseInput.Event) { case EMIE_MOUSE_WHEEL: if (Environment->hasFocus(this)) { // thanks to a bug report by REAPER // thanks to tommi by tommi for another bugfix // everybody needs a little thanking. hallo niko!;-) setPos( getPos() + ( (event.MouseInput.Wheel < 0 ? -1 : 1) * SmallStep * (Horizontal ? 1 : -1 ) ) ); SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; newEvent.GUIEvent.Element = 0; newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED; Parent->OnEvent(newEvent); return true; } break; case EMIE_LMOUSE_PRESSED_DOWN: { if (isInside) { Dragging = true; DraggedBySlider = SliderRect.isPointInside(p); TrayClick = !DraggedBySlider; DesiredPos = getPosFromMousePos(p); Environment->setFocus ( this ); return true; } break; } case EMIE_LMOUSE_LEFT_UP: case EMIE_MOUSE_MOVED: { if ( !event.MouseInput.isLeftPressed () ) Dragging = false; if ( !Dragging ) { if ( event.MouseInput.Event == EMIE_MOUSE_MOVED ) break; return isInside; } if ( event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP ) Dragging = false; const s32 newPos = getPosFromMousePos(p); const s32 oldPos = Pos; if (!DraggedBySlider) { if ( isInside ) { DraggedBySlider = SliderRect.isPointInside(p); TrayClick = !DraggedBySlider; } if (DraggedBySlider) { setPos(newPos); } else { TrayClick = false; if (event.MouseInput.Event == EMIE_MOUSE_MOVED) return isInside; } } if (DraggedBySlider) { setPos(newPos); } else { DesiredPos = newPos; } if (Pos != oldPos && Parent) { SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; newEvent.GUIEvent.Element = 0; newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED; Parent->OnEvent(newEvent); } return isInside; } break; default: break; } } break; default: break; } } return IGUIElement::OnEvent(event); } void CGUIScrollBar::OnPostRender(u32 timeMs) { if (Dragging && !DraggedBySlider && TrayClick && timeMs > LastChange + 200) { LastChange = timeMs; const s32 oldPos = Pos; if (DesiredPos >= Pos + LargeStep) setPos(Pos + LargeStep); else if (DesiredPos <= Pos - LargeStep) setPos(Pos - LargeStep); else if (DesiredPos >= Pos - LargeStep && DesiredPos <= Pos + LargeStep) setPos(DesiredPos); if (Pos != oldPos && Parent) { SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; newEvent.GUIEvent.Element = 0; newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED; Parent->OnEvent(newEvent); } } } //! draws the element and its children void CGUIScrollBar::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); if (!skin) return; video::SColor iconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL); if ( iconColor != CurrentIconColor ) { refreshControls(); } SliderRect = AbsoluteRect; // draws the background skin->draw2DRectangle(this, skin->getColor(EGDC_SCROLLBAR), SliderRect, &AbsoluteClippingRect); if ( core::isnotzero ( range() ) ) { // recalculate slider rectangle if (Horizontal) { SliderRect.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X + DrawPos + RelativeRect.getHeight() - DrawHeight/2; SliderRect.LowerRightCorner.X = SliderRect.UpperLeftCorner.X + DrawHeight; } else { SliderRect.UpperLeftCorner.Y = AbsoluteRect.UpperLeftCorner.Y + DrawPos + RelativeRect.getWidth() - DrawHeight/2; SliderRect.LowerRightCorner.Y = SliderRect.UpperLeftCorner.Y + DrawHeight; } skin->draw3DButtonPaneStandard(this, SliderRect, &AbsoluteClippingRect); } // draw buttons IGUIElement::draw(); } void CGUIScrollBar::updateAbsolutePosition() { IGUIElement::updateAbsolutePosition(); // todo: properly resize refreshControls(); setPos ( Pos ); } //! s32 CGUIScrollBar::getPosFromMousePos(const core::position2di &pos) const { f32 w, p; if (Horizontal) { w = RelativeRect.getWidth() - f32(RelativeRect.getHeight())*3.0f; p = pos.X - AbsoluteRect.UpperLeftCorner.X - RelativeRect.getHeight()*1.5f; } else { w = RelativeRect.getHeight() - f32(RelativeRect.getWidth())*3.0f; p = pos.Y - AbsoluteRect.UpperLeftCorner.Y - RelativeRect.getWidth()*1.5f; } return (s32) ( p/w * range() ) + Min; } //! sets the position of the scrollbar void CGUIScrollBar::setPos(s32 pos) { Pos = core::s32_clamp ( pos, Min, Max ); if (Horizontal) { f32 f = (RelativeRect.getWidth() - ((f32)RelativeRect.getHeight()*3.0f)) / range(); DrawPos = (s32)( ( ( Pos - Min ) * f) + ((f32)RelativeRect.getHeight() * 0.5f)); DrawHeight = RelativeRect.getHeight(); } else { f32 f = (RelativeRect.getHeight() - ((f32)RelativeRect.getWidth()*3.0f)) / range(); DrawPos = (s32)( ( ( Pos - Min ) * f) + ((f32)RelativeRect.getWidth() * 0.5f)); DrawHeight = RelativeRect.getWidth(); } } //! gets the small step value s32 CGUIScrollBar::getSmallStep() const { return SmallStep; } //! sets the small step value void CGUIScrollBar::setSmallStep(s32 step) { if (step > 0) SmallStep = step; else SmallStep = 10; } //! gets the small step value s32 CGUIScrollBar::getLargeStep() const { return LargeStep; } //! sets the small step value void CGUIScrollBar::setLargeStep(s32 step) { if (step > 0) LargeStep = step; else LargeStep = 50; } //! gets the maximum value of the scrollbar. s32 CGUIScrollBar::getMax() const { return Max; } //! sets the maximum value of the scrollbar. void CGUIScrollBar::setMax(s32 max) { Max = max; if ( Min > Max ) Min = Max; bool enable = core::isnotzero ( range() ); UpButton->setEnabled(enable); DownButton->setEnabled(enable); setPos(Pos); } //! gets the minimum value of the scrollbar. s32 CGUIScrollBar::getMin() const { return Min; } //! sets the minimum value of the scrollbar. void CGUIScrollBar::setMin(s32 min) { Min = min; if ( Max < Min ) Max = Min; bool enable = core::isnotzero ( range() ); UpButton->setEnabled(enable); DownButton->setEnabled(enable); setPos(Pos); } //! gets the current position of the scrollbar s32 CGUIScrollBar::getPos() const { return Pos; } //! refreshes the position and text on child buttons void CGUIScrollBar::refreshControls() { CurrentIconColor = video::SColor(255,255,255,255); IGUISkin* skin = Environment->getSkin(); IGUISpriteBank* sprites = 0; if (skin) { sprites = skin->getSpriteBank(); CurrentIconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL); } if (Horizontal) { s32 h = RelativeRect.getHeight(); if (!UpButton) { UpButton = new CGUIButton(Environment, this, -1, core::rect(0,0, h, h), NoClip); UpButton->setSubElement(true); UpButton->setTabStop(false); } if (sprites) { UpButton->setSpriteBank(sprites); UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_LEFT), CurrentIconColor); UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_LEFT), CurrentIconColor); } UpButton->setRelativePosition(core::rect(0,0, h, h)); UpButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); if (!DownButton) { DownButton = new CGUIButton(Environment, this, -1, core::rect(RelativeRect.getWidth()-h, 0, RelativeRect.getWidth(), h), NoClip); DownButton->setSubElement(true); DownButton->setTabStop(false); } if (sprites) { DownButton->setSpriteBank(sprites); DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_RIGHT), CurrentIconColor); DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_RIGHT), CurrentIconColor); } DownButton->setRelativePosition(core::rect(RelativeRect.getWidth()-h, 0, RelativeRect.getWidth(), h)); DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); } else { s32 w = RelativeRect.getWidth(); if (!UpButton) { UpButton = new CGUIButton(Environment, this, -1, core::rect(0,0, w, w), NoClip); UpButton->setSubElement(true); UpButton->setTabStop(false); } if (sprites) { UpButton->setSpriteBank(sprites); UpButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_UP), CurrentIconColor); UpButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_UP), CurrentIconColor); } UpButton->setRelativePosition(core::rect(0,0, w, w)); UpButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); if (!DownButton) { DownButton = new CGUIButton(Environment, this, -1, core::rect(0,RelativeRect.getHeight()-w, w, RelativeRect.getHeight()), NoClip); DownButton->setSubElement(true); DownButton->setTabStop(false); } if (sprites) { DownButton->setSpriteBank(sprites); DownButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), CurrentIconColor); DownButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), CurrentIconColor); } DownButton->setRelativePosition(core::rect(0,RelativeRect.getHeight()-w, w, RelativeRect.getHeight())); DownButton->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); } } //! Writes attributes of the element. void CGUIScrollBar::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUIScrollBar::serializeAttributes(out,options); out->addBool("Horizontal", Horizontal); out->addInt ("Value", Pos); out->addInt ("Min", Min); out->addInt ("Max", Max); out->addInt ("SmallStep", SmallStep); out->addInt ("LargeStep", LargeStep); // CurrentIconColor - not serialized as continuiously updated } //! Reads attributes of the element void CGUIScrollBar::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUIScrollBar::deserializeAttributes(in,options); Horizontal = in->getAttributeAsBool("Horizontal"); setMin(in->getAttributeAsInt("Min")); setMax(in->getAttributeAsInt("Max")); setPos(in->getAttributeAsInt("Value")); setSmallStep(in->getAttributeAsInt("SmallStep")); setLargeStep(in->getAttributeAsInt("LargeStep")); // CurrentIconColor - not serialized as continuiously updated refreshControls(); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIModalScreen.h0000644000000000000000000000354612574354552020162 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_MODAL_SCREEN_H_INCLUDED__ #define __C_GUI_MODAL_SCREEN_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIElement.h" namespace irr { namespace gui { class CGUIModalScreen : public IGUIElement { public: //! constructor CGUIModalScreen(IGUIEnvironment* environment, IGUIElement* parent, s32 id); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! Removes a child. virtual void removeChild(IGUIElement* child); //! Adds a child virtual void addChild(IGUIElement* child); //! draws the element and its children virtual void draw(); //! Updates the absolute position. virtual void updateAbsolutePosition(); //! Modalscreen is not a typical element, but rather acts like a state for it's children. //! isVisible is overriden to give this a useful behavior, so that a modal will no longer //! be active when its parent is invisible or all its children are invisible. virtual bool isVisible() const; //! Modals are infinite so every point is inside virtual bool isPointInside(const core::position2d& point) const; //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); protected: virtual bool canTakeFocus(IGUIElement* target) const; private: u32 MouseDownTime; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif irrlicht-1.8.3/source/Irrlicht/CGUIModalScreen.cpp0000644000000000000000000001366012574354552020513 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIModalScreen.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIEnvironment.h" #include "os.h" #include "IVideoDriver.h" #include "IGUISkin.h" namespace irr { namespace gui { //! constructor CGUIModalScreen::CGUIModalScreen(IGUIEnvironment* environment, IGUIElement* parent, s32 id) : IGUIElement(EGUIET_MODAL_SCREEN, environment, parent, id, core::recti(0, 0, parent->getAbsolutePosition().getWidth(), parent->getAbsolutePosition().getHeight()) ), MouseDownTime(0) { #ifdef _DEBUG setDebugName("CGUIModalScreen"); #endif setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); // this element is a tab group setTabGroup(true); } bool CGUIModalScreen::canTakeFocus(IGUIElement* target) const { return (target && ((const IGUIElement*)target == this // this element can take it || isMyChild(target) // own children also || (target->getType() == EGUIET_MODAL_SCREEN ) // other modals also fine (is now on top or explicitely requested) || (target->getParent() && target->getParent()->getType() == EGUIET_MODAL_SCREEN ))) // children of other modals will do ; } bool CGUIModalScreen::isVisible() const { // any parent invisible? IGUIElement * parentElement = getParent(); while ( parentElement ) { if ( !parentElement->isVisible() ) return false; parentElement = parentElement->getParent(); } // if we have no children then the modal is probably abused as a way to block input if ( Children.empty() ) { return IGUIElement::isVisible(); } // any child visible? bool visible = false; core::list::ConstIterator it = Children.begin(); for (; it != Children.end(); ++it) { if ( (*it)->isVisible() ) { visible = true; break; } } return visible; } bool CGUIModalScreen::isPointInside(const core::position2d& point) const { return true; } //! called if an event happened. bool CGUIModalScreen::OnEvent(const SEvent& event) { if (!isEnabled() || !isVisible() ) return IGUIElement::OnEvent(event); switch(event.EventType) { case EET_GUI_EVENT: switch(event.GUIEvent.EventType) { case EGET_ELEMENT_FOCUSED: if ( event.GUIEvent.Caller == this && isMyChild(event.GUIEvent.Element) ) { Environment->removeFocus(0); // can't setFocus otherwise at it still has focus here Environment->setFocus(event.GUIEvent.Element); MouseDownTime = os::Timer::getTime(); return true; } if ( !canTakeFocus(event.GUIEvent.Caller)) { if ( !Children.empty() ) Environment->setFocus(*(Children.begin())); else Environment->setFocus(this); } IGUIElement::OnEvent(event); return false; case EGET_ELEMENT_FOCUS_LOST: if ( !canTakeFocus(event.GUIEvent.Element)) { if ( isMyChild(event.GUIEvent.Caller) ) { if ( !Children.empty() ) Environment->setFocus(*(Children.begin())); else Environment->setFocus(this); } else { MouseDownTime = os::Timer::getTime(); } return true; } else { return IGUIElement::OnEvent(event); } case EGET_ELEMENT_CLOSED: // do not interfere with children being removed return IGUIElement::OnEvent(event); default: break; } break; case EET_MOUSE_INPUT_EVENT: if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { MouseDownTime = os::Timer::getTime(); } default: break; } IGUIElement::OnEvent(event); // anyone knows why events are passed on here? Causes p.e. problems when this is child of a CGUIWindow. return true; // absorb everything else } //! draws the element and its children void CGUIModalScreen::draw() { IGUISkin *skin = Environment->getSkin(); if (!skin) return; u32 now = os::Timer::getTime(); if (now - MouseDownTime < 300 && (now / 70)%2) { core::list::Iterator it = Children.begin(); core::rect r; video::SColor c = Environment->getSkin()->getColor(gui::EGDC_3D_HIGH_LIGHT); for (; it != Children.end(); ++it) { if ((*it)->isVisible()) { r = (*it)->getAbsolutePosition(); r.LowerRightCorner.X += 1; r.LowerRightCorner.Y += 1; r.UpperLeftCorner.X -= 1; r.UpperLeftCorner.Y -= 1; skin->draw2DRectangle(this, c, r, &AbsoluteClippingRect); } } } IGUIElement::draw(); } //! Removes a child. void CGUIModalScreen::removeChild(IGUIElement* child) { IGUIElement::removeChild(child); if (Children.empty()) { remove(); } } //! adds a child void CGUIModalScreen::addChild(IGUIElement* child) { IGUIElement::addChild(child); Environment->setFocus(child); } void CGUIModalScreen::updateAbsolutePosition() { core::rect parentRect(0,0,0,0); if (Parent) { parentRect = Parent->getAbsolutePosition(); RelativeRect.UpperLeftCorner.X = 0; RelativeRect.UpperLeftCorner.Y = 0; RelativeRect.LowerRightCorner.X = parentRect.getWidth(); RelativeRect.LowerRightCorner.Y = parentRect.getHeight(); } IGUIElement::updateAbsolutePosition(); } //! Writes attributes of the element. void CGUIModalScreen::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUIElement::serializeAttributes(out,options); } //! Reads attributes of the element void CGUIModalScreen::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUIElement::deserializeAttributes(in, options); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIMessageBox.h0000644000000000000000000000324012574354552020012 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_MESSAGE_BOX_H_INCLUDED__ #define __C_GUI_MESSAGE_BOX_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "CGUIWindow.h" #include "IGUIStaticText.h" #include "IGUIImage.h" #include "irrArray.h" namespace irr { namespace gui { class CGUIMessageBox : public CGUIWindow { public: //! constructor CGUIMessageBox(IGUIEnvironment* environment, const wchar_t* caption, const wchar_t* text, s32 flag, IGUIElement* parent, s32 id, core::rect rectangle, video::ITexture* image=0); //! destructor virtual ~CGUIMessageBox(); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: void refreshControls(); void setButton(IGUIButton*& button, bool isAvailable, const core::rect & btnRect, const wchar_t * text, IGUIElement*& focusMe); IGUIButton* OkButton; IGUIButton* CancelButton; IGUIButton* YesButton; IGUIButton* NoButton; IGUIStaticText* StaticText; IGUIImage * Icon; video::ITexture * IconTexture; s32 Flags; core::stringw MessageText; bool Pressed; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif irrlicht-1.8.3/source/Irrlicht/CGUIMessageBox.cpp0000644000000000000000000003316712574354552020360 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIMessageBox.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IGUIButton.h" #include "IGUIFont.h" #include "ITexture.h" namespace irr { namespace gui { //! constructor CGUIMessageBox::CGUIMessageBox(IGUIEnvironment* environment, const wchar_t* caption, const wchar_t* text, s32 flags, IGUIElement* parent, s32 id, core::rect rectangle, video::ITexture* image) : CGUIWindow(environment, parent, id, rectangle), OkButton(0), CancelButton(0), YesButton(0), NoButton(0), StaticText(0), Icon(0), IconTexture(image), Flags(flags), MessageText(text), Pressed(false) { #ifdef _DEBUG setDebugName("CGUIMessageBox"); #endif // set element type Type = EGUIET_MESSAGE_BOX; // remove focus Environment->setFocus(0); // remove buttons getMaximizeButton()->remove(); getMinimizeButton()->remove(); if (caption) setText(caption); Environment->setFocus(this); if ( IconTexture ) IconTexture->grab(); refreshControls(); } //! destructor CGUIMessageBox::~CGUIMessageBox() { if (StaticText) StaticText->drop(); if (OkButton) OkButton->drop(); if (CancelButton) CancelButton->drop(); if (YesButton) YesButton->drop(); if (NoButton) NoButton->drop(); if (Icon) Icon->drop(); if ( IconTexture ) IconTexture->drop(); } void CGUIMessageBox::setButton(IGUIButton*& button, bool isAvailable, const core::rect & btnRect, const wchar_t * text, IGUIElement*& focusMe) { // add/remove ok button if (isAvailable) { if (!button) { button = Environment->addButton(btnRect, this); button->setSubElement(true); button->grab(); } else button->setRelativePosition(btnRect); button->setText(text); focusMe = button; } else if (button) { button->drop(); button->remove(); button =0; } } void CGUIMessageBox::refreshControls() { // Layout can be seen as 4 boxes (a layoutmanager would be nice) // One box at top over the whole width for title // Two boxes with same height at the middle beside each other for icon and for text // One box at the bottom for the buttons const IGUISkin* skin = Environment->getSkin(); const s32 buttonHeight = skin->getSize(EGDS_BUTTON_HEIGHT); const s32 buttonWidth = skin->getSize(EGDS_BUTTON_WIDTH); const s32 titleHeight = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH)+2; // titlebar has no own constant const s32 buttonDistance = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); const s32 borderWidth = skin->getSize(EGDS_MESSAGE_BOX_GAP_SPACE); // add the static text for the message core::rect staticRect; staticRect.UpperLeftCorner.X = borderWidth; staticRect.UpperLeftCorner.Y = titleHeight + borderWidth; staticRect.LowerRightCorner.X = staticRect.UpperLeftCorner.X + skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH); staticRect.LowerRightCorner.Y = staticRect.UpperLeftCorner.Y + skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT); if (!StaticText) { StaticText = Environment->addStaticText(MessageText.c_str(), staticRect, false, false, this); StaticText->setWordWrap(true); StaticText->setSubElement(true); StaticText->grab(); } else { StaticText->setRelativePosition(staticRect); StaticText->setText(MessageText.c_str()); } s32 textHeight = StaticText->getTextHeight(); s32 textWidth = StaticText->getTextWidth() + 6; // +6 because the static itself needs that const s32 iconHeight = IconTexture ? IconTexture->getOriginalSize().Height : 0; if ( textWidth < skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH) ) textWidth = skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH) + 6; // no neeed to check for max because it couldn't get larger due to statictextbox. if ( textHeight < skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT) ) textHeight = skin->getSize(EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT); if ( textHeight > skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT) ) textHeight = skin->getSize(EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT); // content is text + icons + borders (but not titlebar) s32 contentHeight = textHeight > iconHeight ? textHeight : iconHeight; contentHeight += borderWidth; s32 contentWidth = 0; // add icon if ( IconTexture ) { core::position2d iconPos; iconPos.Y = titleHeight + borderWidth; if ( iconHeight < textHeight ) iconPos.Y += (textHeight-iconHeight) / 2; iconPos.X = borderWidth; if (!Icon) { Icon = Environment->addImage(IconTexture, iconPos, true, this); Icon->setSubElement(true); Icon->grab(); } else { core::rect iconRect( iconPos.X, iconPos.Y, iconPos.X + IconTexture->getOriginalSize().Width, iconPos.Y + IconTexture->getOriginalSize().Height ); Icon->setRelativePosition(iconRect); } contentWidth += borderWidth + IconTexture->getOriginalSize().Width; } else if ( Icon ) { Icon->drop(); Icon->remove(); Icon = 0; } // position text core::rect textRect; textRect.UpperLeftCorner.X = contentWidth + borderWidth; textRect.UpperLeftCorner.Y = titleHeight + borderWidth; if ( textHeight < iconHeight ) textRect.UpperLeftCorner.Y += (iconHeight-textHeight) / 2; textRect.LowerRightCorner.X = textRect.UpperLeftCorner.X + textWidth; textRect.LowerRightCorner.Y = textRect.UpperLeftCorner.Y + textHeight; contentWidth += 2*borderWidth + textWidth; StaticText->setRelativePosition( textRect ); // find out button size needs s32 countButtons = 0; if (Flags & EMBF_OK) ++countButtons; if (Flags & EMBF_CANCEL) ++countButtons; if (Flags & EMBF_YES) ++countButtons; if (Flags & EMBF_NO) ++countButtons; s32 buttonBoxWidth = countButtons * buttonWidth + 2 * borderWidth; if ( countButtons > 1 ) buttonBoxWidth += (countButtons-1) * buttonDistance; s32 buttonBoxHeight = buttonHeight + 2 * borderWidth; // calc new message box sizes core::rect tmp = getRelativePosition(); s32 msgBoxHeight = titleHeight + contentHeight + buttonBoxHeight; s32 msgBoxWidth = contentWidth > buttonBoxWidth ? contentWidth : buttonBoxWidth; // adjust message box position tmp.UpperLeftCorner.Y = (Parent->getAbsolutePosition().getHeight() - msgBoxHeight) / 2; tmp.LowerRightCorner.Y = tmp.UpperLeftCorner.Y + msgBoxHeight; tmp.UpperLeftCorner.X = (Parent->getAbsolutePosition().getWidth() - msgBoxWidth) / 2; tmp.LowerRightCorner.X = tmp.UpperLeftCorner.X + msgBoxWidth; setRelativePosition(tmp); // add buttons core::rect btnRect; btnRect.UpperLeftCorner.Y = titleHeight + contentHeight + borderWidth; btnRect.LowerRightCorner.Y = btnRect.UpperLeftCorner.Y + buttonHeight; btnRect.UpperLeftCorner.X = borderWidth; if ( contentWidth > buttonBoxWidth ) btnRect.UpperLeftCorner.X += (contentWidth - buttonBoxWidth) / 2; // center buttons btnRect.LowerRightCorner.X = btnRect.UpperLeftCorner.X + buttonWidth; IGUIElement* focusMe = 0; setButton(OkButton, (Flags & EMBF_OK) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_OK), focusMe); if ( Flags & EMBF_OK ) btnRect += core::position2d(buttonWidth + buttonDistance, 0); setButton(CancelButton, (Flags & EMBF_CANCEL) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_CANCEL), focusMe); if ( Flags & EMBF_CANCEL ) btnRect += core::position2d(buttonWidth + buttonDistance, 0); setButton(YesButton, (Flags & EMBF_YES) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_YES), focusMe); if ( Flags & EMBF_YES ) btnRect += core::position2d(buttonWidth + buttonDistance, 0); setButton(NoButton, (Flags & EMBF_NO) != 0, btnRect, skin->getDefaultText(EGDT_MSG_BOX_NO), focusMe); if (Environment->hasFocus(this) && focusMe) Environment->setFocus(focusMe); } //! called if an event happened. bool CGUIMessageBox::OnEvent(const SEvent& event) { if (isEnabled()) { SEvent outevent; outevent.EventType = EET_GUI_EVENT; outevent.GUIEvent.Caller = this; outevent.GUIEvent.Element = 0; switch(event.EventType) { case EET_KEY_INPUT_EVENT: if (event.KeyInput.PressedDown) { switch (event.KeyInput.Key) { case KEY_RETURN: if (OkButton) { OkButton->setPressed(true); Pressed = true; } break; case KEY_KEY_Y: if (YesButton) { YesButton->setPressed(true); Pressed = true; } break; case KEY_KEY_N: if (NoButton) { NoButton->setPressed(true); Pressed = true; } break; case KEY_ESCAPE: if (Pressed) { // cancel press if (OkButton) OkButton->setPressed(false); if (YesButton) YesButton->setPressed(false); if (NoButton) NoButton->setPressed(false); Pressed = false; } else if (CancelButton) { CancelButton->setPressed(true); Pressed = true; } else if (CloseButton && CloseButton->isVisible()) { CloseButton->setPressed(true); Pressed = true; } break; default: // no other key is handled here break; } } else if (Pressed) { if (OkButton && event.KeyInput.Key == KEY_RETURN) { setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_OK; Parent->OnEvent(outevent); remove(); return true; } else if ((CancelButton || CloseButton) && event.KeyInput.Key == KEY_ESCAPE) { setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_CANCEL; Parent->OnEvent(outevent); remove(); return true; } else if (YesButton && event.KeyInput.Key == KEY_KEY_Y) { setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_YES; Parent->OnEvent(outevent); remove(); return true; } else if (NoButton && event.KeyInput.Key == KEY_KEY_N) { setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_NO; Parent->OnEvent(outevent); remove(); return true; } } break; case EET_GUI_EVENT: if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) { if (event.GUIEvent.Caller == OkButton) { setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_OK; Parent->OnEvent(outevent); remove(); return true; } else if (event.GUIEvent.Caller == CancelButton || event.GUIEvent.Caller == CloseButton) { setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_CANCEL; Parent->OnEvent(outevent); remove(); return true; } else if (event.GUIEvent.Caller == YesButton) { setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_YES; Parent->OnEvent(outevent); remove(); return true; } else if (event.GUIEvent.Caller == NoButton) { setVisible(false); // this is a workaround to make sure it's no longer the hovered element, crashes on pressing 1-2 times ESC Environment->setFocus(0); outevent.GUIEvent.EventType = EGET_MESSAGEBOX_NO; Parent->OnEvent(outevent); remove(); return true; } } break; default: break; } } return CGUIWindow::OnEvent(event); } //! Writes attributes of the element. void CGUIMessageBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { CGUIWindow::serializeAttributes(out,options); out->addBool ("OkayButton", (Flags & EMBF_OK) != 0 ); out->addBool ("CancelButton", (Flags & EMBF_CANCEL) != 0 ); out->addBool ("YesButton", (Flags & EMBF_YES) != 0 ); out->addBool ("NoButton", (Flags & EMBF_NO) != 0 ); out->addTexture ("Texture", IconTexture); out->addString ("MessageText", MessageText.c_str()); } //! Reads attributes of the element void CGUIMessageBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { Flags = 0; Flags = in->getAttributeAsBool("OkayButton") ? EMBF_OK : 0; Flags |= in->getAttributeAsBool("CancelButton")? EMBF_CANCEL : 0; Flags |= in->getAttributeAsBool("YesButton") ? EMBF_YES : 0; Flags |= in->getAttributeAsBool("NoButton") ? EMBF_NO : 0; if ( IconTexture ) { IconTexture->drop(); IconTexture = NULL; } IconTexture = in->getAttributeAsTexture("Texture"); if ( IconTexture ) IconTexture->grab(); MessageText = in->getAttributeAsStringW("MessageText").c_str(); CGUIWindow::deserializeAttributes(in,options); refreshControls(); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIMeshViewer.h0000644000000000000000000000253212574354552020036 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_MESH_VIEWER_H_INCLUDED__ #define __C_GUI_MESH_VIEWER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIMeshViewer.h" #include "SMaterial.h" namespace irr { namespace gui { class CGUIMeshViewer : public IGUIMeshViewer { public: //! constructor CGUIMeshViewer(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle); //! destructor virtual ~CGUIMeshViewer(); //! sets the mesh to be shown virtual void setMesh(scene::IAnimatedMesh* mesh); //! Gets the displayed mesh virtual scene::IAnimatedMesh* getMesh() const; //! sets the material virtual void setMaterial(const video::SMaterial& material); //! gets the material virtual const video::SMaterial& getMaterial() const; //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! draws the element and its children virtual void draw(); private: video::SMaterial Material; scene::IAnimatedMesh* Mesh; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_MESH_VIEWER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUIMeshViewer.cpp0000644000000000000000000001020512574354552020365 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIMeshViewer.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IAnimatedMesh.h" #include "IMesh.h" #include "os.h" #include "IGUISkin.h" namespace irr { namespace gui { //! constructor CGUIMeshViewer::CGUIMeshViewer(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIMeshViewer(environment, parent, id, rectangle), Mesh(0) { #ifdef _DEBUG setDebugName("CGUIMeshViewer"); #endif } //! destructor CGUIMeshViewer::~CGUIMeshViewer() { if (Mesh) Mesh->drop(); } //! sets the mesh to be shown void CGUIMeshViewer::setMesh(scene::IAnimatedMesh* mesh) { if (mesh) mesh->grab(); if (Mesh) Mesh->drop(); Mesh = mesh; /* This might be used for proper transformation etc. core::vector3df center(0.0f,0.0f,0.0f); core::aabbox3d box; box = Mesh->getMesh(0)->getBoundingBox(); center = (box.MaxEdge + box.MinEdge) / 2; */ } //! Gets the displayed mesh scene::IAnimatedMesh* CGUIMeshViewer::getMesh() const { return Mesh; } //! sets the material void CGUIMeshViewer::setMaterial(const video::SMaterial& material) { Material = material; } //! gets the material const video::SMaterial& CGUIMeshViewer::getMaterial() const { return Material; } //! called if an event happened. bool CGUIMeshViewer::OnEvent(const SEvent& event) { return IGUIElement::OnEvent(event); } //! draws the element and its children void CGUIMeshViewer::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); video::IVideoDriver* driver = Environment->getVideoDriver(); core::rect viewPort = AbsoluteRect; viewPort.LowerRightCorner.X -= 1; viewPort.LowerRightCorner.Y -= 1; viewPort.UpperLeftCorner.X += 1; viewPort.UpperLeftCorner.Y += 1; viewPort.clipAgainst(AbsoluteClippingRect); // draw the frame core::rect frameRect(AbsoluteRect); frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), frameRect, &AbsoluteClippingRect); frameRect.LowerRightCorner.Y = AbsoluteRect.LowerRightCorner.Y; frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), frameRect, &AbsoluteClippingRect); frameRect = AbsoluteRect; frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X - 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect); frameRect = AbsoluteRect; frameRect.UpperLeftCorner.Y = AbsoluteRect.LowerRightCorner.Y - 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect); // draw the mesh if (Mesh) { //TODO: if outside of screen, dont draw. // - why is the absolute clipping rect not already the screen? core::rect oldViewPort = driver->getViewPort(); driver->setViewPort(viewPort); core::matrix4 mat; //CameraControl->calculateProjectionMatrix(mat); //driver->setTransform(video::TS_PROJECTION, mat); mat.makeIdentity(); mat.setTranslation(core::vector3df(0,0,0)); driver->setTransform(video::ETS_WORLD, mat); //CameraControl->calculateViewMatrix(mat); //driver->setTransform(video::TS_VIEW, mat); driver->setMaterial(Material); u32 frame = 0; if(Mesh->getFrameCount()) frame = (os::Timer::getTime()/20)%Mesh->getFrameCount(); const scene::IMesh* const m = Mesh->getMesh(frame); for (u32 i=0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = m->getMeshBuffer(i); driver->drawVertexPrimitiveList(mb->getVertices(), mb->getVertexCount(), mb->getIndices(), mb->getIndexCount()/ 3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType()); } driver->setViewPort(oldViewPort); } IGUIElement::draw(); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIMenu.h0000644000000000000000000000235512574354552016667 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_MENU_H_INCLUDED__ #define __C_GUI_MENU_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "CGUIContextMenu.h" namespace irr { namespace gui { //! GUI menu interface. class CGUIMenu : public CGUIContextMenu { public: //! constructor CGUIMenu(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle); //! draws the element and its children virtual void draw(); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! Updates the absolute position. virtual void updateAbsolutePosition(); protected: virtual void recalculateSize(); //! returns the item highlight-area virtual core::rect getHRect(const SItem& i, const core::rect& absolute) const; //! Gets drawing rect of Item virtual core::rect getRect(const SItem& i, const core::rect& absolute) const; }; } // end namespace gui } // end namespace irr #endif // __C_GUI_MENU_H_INCLUDED__ #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIMenu.cpp0000644000000000000000000001504712574354552017224 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIMenu.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIFont.h" #include "IGUIWindow.h" #include "os.h" namespace irr { namespace gui { //! constructor CGUIMenu::CGUIMenu(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : CGUIContextMenu(environment, parent, id, rectangle, false, true) { #ifdef _DEBUG setDebugName("CGUIMenu"); #endif Type = EGUIET_MENU; setNotClipped(false); recalculateSize(); } //! draws the element and its children void CGUIMenu::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); IGUIFont* font = skin->getFont(EGDF_MENU); if (font != LastFont) { if (LastFont) LastFont->drop(); LastFont = font; if (LastFont) LastFont->grab(); recalculateSize(); } core::rect rect = AbsoluteRect; // draw frame skin->draw3DToolBar(this, rect, &AbsoluteClippingRect); // loop through all menu items rect = AbsoluteRect; for (s32 i=0; i<(s32)Items.size(); ++i) { if (!Items[i].IsSeparator) { rect = getRect(Items[i], AbsoluteRect); // draw highlighted if (i == HighLighted && Items[i].Enabled) { skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_DARK_SHADOW), true, true, rect, &AbsoluteClippingRect); } // draw text EGUI_DEFAULT_COLOR c = EGDC_BUTTON_TEXT; if (i == HighLighted) c = EGDC_HIGH_LIGHT_TEXT; if (!Items[i].Enabled) c = EGDC_GRAY_TEXT; if (font) font->draw(Items[i].Text.c_str(), rect, skin->getColor(c), true, true, &AbsoluteClippingRect); } } IGUIElement::draw(); } //! called if an event happened. bool CGUIMenu::OnEvent(const SEvent& event) { if (isEnabled()) { switch(event.EventType) { case EET_GUI_EVENT: switch(event.GUIEvent.EventType) { case gui::EGET_ELEMENT_FOCUS_LOST: if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element)) { closeAllSubMenus(); HighLighted = -1; } break; case gui::EGET_ELEMENT_FOCUSED: if (event.GUIEvent.Caller == this && Parent) { Parent->bringToFront(this); } break; default: break; } break; case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: { if (!Environment->hasFocus(this)) { Environment->setFocus(this); } if (Parent) Parent->bringToFront(this); core::position2d p(event.MouseInput.X, event.MouseInput.Y); bool shouldCloseSubMenu = hasOpenSubMenu(); if (!AbsoluteClippingRect.isPointInside(p)) { shouldCloseSubMenu = false; } highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), true); if ( shouldCloseSubMenu ) { Environment->removeFocus(this); } return true; } case EMIE_LMOUSE_LEFT_UP: { core::position2d p(event.MouseInput.X, event.MouseInput.Y); if (!AbsoluteClippingRect.isPointInside(p)) { s32 t = sendClick(p); if ((t==0 || t==1) && Environment->hasFocus(this)) Environment->removeFocus(this); } return true; } case EMIE_MOUSE_MOVED: if (Environment->hasFocus(this) && HighLighted >= 0) { s32 oldHighLighted = HighLighted; highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), true); if ( HighLighted < 0 ) HighLighted = oldHighLighted; // keep last hightlight active when moving outside the area } return true; default: break; } break; default: break; } } return IGUIElement::OnEvent(event); } void CGUIMenu::recalculateSize() { core::rect clientRect; // client rect of parent if ( Parent && Parent->hasType(EGUIET_WINDOW) ) { clientRect = static_cast(Parent)->getClientRect(); } else if ( Parent ) { clientRect = core::rect(0,0, Parent->getAbsolutePosition().getWidth(), Parent->getAbsolutePosition().getHeight()); } else { clientRect = RelativeRect; } IGUISkin* skin = Environment->getSkin(); IGUIFont* font = skin->getFont(EGDF_MENU); if (!font) { if (Parent && skin) RelativeRect = core::rect(clientRect.UpperLeftCorner.X, clientRect.UpperLeftCorner.Y, clientRect.LowerRightCorner.X, clientRect.UpperLeftCorner.Y+skin->getSize(EGDS_MENU_HEIGHT)); return; } core::rect rect; rect.UpperLeftCorner = clientRect.UpperLeftCorner; s32 height = font->getDimension(L"A").Height + 5; //if (skin && height < skin->getSize ( EGDS_MENU_HEIGHT )) // height = skin->getSize(EGDS_MENU_HEIGHT); s32 width = rect.UpperLeftCorner.X; s32 i; for (i=0; i<(s32)Items.size(); ++i) { if (Items[i].IsSeparator) { Items[i].Dim.Width = 0; Items[i].Dim.Height = height; } else { Items[i].Dim = font->getDimension(Items[i].Text.c_str()); Items[i].Dim.Width += 20; } Items[i].PosY = width; width += Items[i].Dim.Width; } width = clientRect.getWidth(); rect.LowerRightCorner.X = rect.UpperLeftCorner.X + width; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + height; setRelativePosition(rect); // recalculate submenus for (i=0; i<(s32)Items.size(); ++i) if (Items[i].SubMenu) { // move submenu s32 w = Items[i].SubMenu->getAbsolutePosition().getWidth(); s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight(); Items[i].SubMenu->setRelativePosition( core::rect(Items[i].PosY, height , Items[i].PosY+w-5, height+h)); } } //! returns the item highlight-area core::rect CGUIMenu::getHRect(const SItem& i, const core::rect& absolute) const { core::rect r = absolute; r.UpperLeftCorner.X += i.PosY; r.LowerRightCorner.X = r.UpperLeftCorner.X + i.Dim.Width; return r; } //! Gets drawing rect of Item core::rect CGUIMenu::getRect(const SItem& i, const core::rect& absolute) const { return getHRect(i, absolute); } void CGUIMenu::updateAbsolutePosition() { if (Parent) DesiredRect.LowerRightCorner.X = Parent->getAbsolutePosition().getWidth(); IGUIElement::updateAbsolutePosition(); } } // end namespace } // end namespace #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIListBox.h0000644000000000000000000001352512574354552017350 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_LIST_BOX_H_INCLUDED__ #define __C_GUI_LIST_BOX_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIListBox.h" #include "irrArray.h" namespace irr { namespace gui { class IGUIFont; class IGUIScrollBar; class CGUIListBox : public IGUIListBox { public: //! constructor CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool clip=true, bool drawBack=false, bool moveOverSelect=false); //! destructor virtual ~CGUIListBox(); //! returns amount of list items virtual u32 getItemCount() const; //! returns string of a list item. the id may be a value from 0 to itemCount-1 virtual const wchar_t* getListItem(u32 id) const; //! adds an list item, returns id of item virtual u32 addItem(const wchar_t* text); //! clears the list virtual void clear(); //! returns id of selected item. returns -1 if no item is selected. virtual s32 getSelected() const; //! sets the selected item. Set this to -1 if no item should be selected virtual void setSelected(s32 id); //! sets the selected item. Set this to -1 if no item should be selected virtual void setSelected(const wchar_t *item); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! draws the element and its children virtual void draw(); //! adds an list item with an icon //! \param text Text of list entry //! \param icon Sprite index of the Icon within the current sprite bank. Set it to -1 if you want no icon //! \return //! returns the id of the new created item virtual u32 addItem(const wchar_t* text, s32 icon); //! Returns the icon of an item virtual s32 getIcon(u32 id) const; //! removes an item from the list virtual void removeItem(u32 id); //! get the the id of the item at the given absolute coordinates virtual s32 getItemAt(s32 xpos, s32 ypos) const; //! Sets the sprite bank which should be used to draw list icons. This font is set to the sprite bank of //! the built-in-font by default. A sprite can be displayed in front of every list item. //! An icon is an index within the icon sprite bank. Several default icons are available in the //! skin through getIcon virtual void setSpriteBank(IGUISpriteBank* bank); //! set whether the listbox should scroll to newly selected items virtual void setAutoScrollEnabled(bool scroll); //! returns true if automatic scrolling is enabled, false if not. virtual bool isAutoScrollEnabled() const; //! Update the position and size of the listbox, and update the scrollbar virtual void updateAbsolutePosition(); //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); //! set all item colors at given index to color virtual void setItemOverrideColor(u32 index, video::SColor color); //! set all item colors of specified type at given index to color virtual void setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color); //! clear all item colors at index virtual void clearItemOverrideColor(u32 index); //! clear item color at index for given colortype virtual void clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType); //! has the item at index its color overwritten? virtual bool hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const; //! return the overwrite color at given item index. virtual video::SColor getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const; //! return the default color which is used for the given colorType virtual video::SColor getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const; //! set the item at the given index virtual void setItem(u32 index, const wchar_t* text, s32 icon); //! Insert the item at the given index //! Return the index on success or -1 on failure. virtual s32 insertItem(u32 index, const wchar_t* text, s32 icon); //! Swap the items at the given indices virtual void swapItems(u32 index1, u32 index2); //! set global itemHeight virtual void setItemHeight( s32 height ); //! Sets whether to draw the background virtual void setDrawBackground(bool draw); private: struct ListItem { ListItem() : icon(-1) {} core::stringw text; s32 icon; // A multicolor extension struct ListItemOverrideColor { ListItemOverrideColor() : Use(false) {} bool Use; video::SColor Color; }; ListItemOverrideColor OverrideColors[EGUI_LBC_COUNT]; }; void recalculateItemHeight(); void selectNew(s32 ypos, bool onlyHover=false); void recalculateScrollPos(); // extracted that function to avoid copy&paste code void recalculateItemWidth(s32 icon); // get labels used for serialization bool getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc & useColorLabel, core::stringc & colorLabel) const; core::array< ListItem > Items; s32 Selected; s32 ItemHeight; s32 ItemHeightOverride; s32 TotalItemHeight; s32 ItemsIconWidth; gui::IGUIFont* Font; gui::IGUISpriteBank* IconBank; gui::IGUIScrollBar* ScrollBar; u32 selectTime; u32 LastKeyTime; core::stringw KeyBuffer; bool Selecting; bool DrawBack; bool MoveOverSelect; bool AutoScroll; bool HighlightWhenNotFocused; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif irrlicht-1.8.3/source/Irrlicht/CGUIListBox.cpp0000644000000000000000000005336012574354552017704 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIListBox.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "CGUIListBox.h" #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIFont.h" #include "IGUISpriteBank.h" #include "CGUIScrollBar.h" #include "os.h" namespace irr { namespace gui { //! constructor CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool clip, bool drawBack, bool moveOverSelect) : IGUIListBox(environment, parent, id, rectangle), Selected(-1), ItemHeight(0),ItemHeightOverride(0), TotalItemHeight(0), ItemsIconWidth(0), Font(0), IconBank(0), ScrollBar(0), selectTime(0), LastKeyTime(0), Selecting(false), DrawBack(drawBack), MoveOverSelect(moveOverSelect), AutoScroll(true), HighlightWhenNotFocused(true) { #ifdef _DEBUG setDebugName("CGUIListBox"); #endif IGUISkin* skin = Environment->getSkin(); const s32 s = skin->getSize(EGDS_SCROLLBAR_SIZE); ScrollBar = new CGUIScrollBar(false, Environment, this, -1, core::rect(RelativeRect.getWidth() - s, 0, RelativeRect.getWidth(), RelativeRect.getHeight()), !clip); ScrollBar->setSubElement(true); ScrollBar->setTabStop(false); ScrollBar->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); ScrollBar->setVisible(false); ScrollBar->setPos(0); setNotClipped(!clip); // this element can be tabbed to setTabStop(true); setTabOrder(-1); updateAbsolutePosition(); } //! destructor CGUIListBox::~CGUIListBox() { if (ScrollBar) ScrollBar->drop(); if (Font) Font->drop(); if (IconBank) IconBank->drop(); } //! returns amount of list items u32 CGUIListBox::getItemCount() const { return Items.size(); } //! returns string of a list item. the may be a value from 0 to itemCount-1 const wchar_t* CGUIListBox::getListItem(u32 id) const { if (id>=Items.size()) return 0; return Items[id].text.c_str(); } //! Returns the icon of an item s32 CGUIListBox::getIcon(u32 id) const { if (id>=Items.size()) return -1; return Items[id].icon; } //! adds a list item, returns id of item u32 CGUIListBox::addItem(const wchar_t* text) { return addItem(text, -1); } //! adds a list item, returns id of item void CGUIListBox::removeItem(u32 id) { if (id >= Items.size()) return; if ((u32)Selected==id) { Selected = -1; } else if ((u32)Selected > id) { Selected -= 1; selectTime = os::Timer::getTime(); } Items.erase(id); recalculateItemHeight(); } s32 CGUIListBox::getItemAt(s32 xpos, s32 ypos) const { if ( xpos < AbsoluteRect.UpperLeftCorner.X || xpos >= AbsoluteRect.LowerRightCorner.X || ypos < AbsoluteRect.UpperLeftCorner.Y || ypos >= AbsoluteRect.LowerRightCorner.Y ) return -1; if ( ItemHeight == 0 ) return -1; s32 item = ((ypos - AbsoluteRect.UpperLeftCorner.Y - 1) + ScrollBar->getPos()) / ItemHeight; if ( item < 0 || item >= (s32)Items.size()) return -1; return item; } //! clears the list void CGUIListBox::clear() { Items.clear(); ItemsIconWidth = 0; Selected = -1; if (ScrollBar) ScrollBar->setPos(0); recalculateItemHeight(); } void CGUIListBox::recalculateItemHeight() { IGUISkin* skin = Environment->getSkin(); if (Font != skin->getFont()) { if (Font) Font->drop(); Font = skin->getFont(); if ( 0 == ItemHeightOverride ) ItemHeight = 0; if (Font) { if ( 0 == ItemHeightOverride ) ItemHeight = Font->getDimension(L"A").Height + 4; Font->grab(); } } TotalItemHeight = ItemHeight * Items.size(); ScrollBar->setMax( core::max_(0, TotalItemHeight - AbsoluteRect.getHeight()) ); s32 minItemHeight = ItemHeight > 0 ? ItemHeight : 1; ScrollBar->setSmallStep ( minItemHeight ); ScrollBar->setLargeStep ( 2*minItemHeight ); if ( TotalItemHeight <= AbsoluteRect.getHeight() ) ScrollBar->setVisible(false); else ScrollBar->setVisible(true); } //! returns id of selected item. returns -1 if no item is selected. s32 CGUIListBox::getSelected() const { return Selected; } //! sets the selected item. Set this to -1 if no item should be selected void CGUIListBox::setSelected(s32 id) { if ((u32)id>=Items.size()) Selected = -1; else Selected = id; selectTime = os::Timer::getTime(); recalculateScrollPos(); } //! sets the selected item. Set this to -1 if no item should be selected void CGUIListBox::setSelected(const wchar_t *item) { s32 index = -1; if ( item ) { for ( index = 0; index < (s32) Items.size(); ++index ) { if ( Items[index].text == item ) break; } } setSelected ( index ); } //! called if an event happened. bool CGUIListBox::OnEvent(const SEvent& event) { if (isEnabled()) { switch(event.EventType) { case EET_KEY_INPUT_EVENT: if (event.KeyInput.PressedDown && (event.KeyInput.Key == KEY_DOWN || event.KeyInput.Key == KEY_UP || event.KeyInput.Key == KEY_HOME || event.KeyInput.Key == KEY_END || event.KeyInput.Key == KEY_NEXT || event.KeyInput.Key == KEY_PRIOR ) ) { s32 oldSelected = Selected; switch (event.KeyInput.Key) { case KEY_DOWN: Selected += 1; break; case KEY_UP: Selected -= 1; break; case KEY_HOME: Selected = 0; break; case KEY_END: Selected = (s32)Items.size()-1; break; case KEY_NEXT: Selected += AbsoluteRect.getHeight() / ItemHeight; break; case KEY_PRIOR: Selected -= AbsoluteRect.getHeight() / ItemHeight; break; default: break; } if (Selected<0) Selected = 0; if (Selected >= (s32)Items.size()) Selected = Items.size() - 1; // will set Selected to -1 for empty listboxes which is correct recalculateScrollPos(); // post the news if (oldSelected != Selected && Parent && !Selecting && !MoveOverSelect) { SEvent e; e.EventType = EET_GUI_EVENT; e.GUIEvent.Caller = this; e.GUIEvent.Element = 0; e.GUIEvent.EventType = EGET_LISTBOX_CHANGED; Parent->OnEvent(e); } return true; } else if (!event.KeyInput.PressedDown && ( event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE ) ) { if (Parent) { SEvent e; e.EventType = EET_GUI_EVENT; e.GUIEvent.Caller = this; e.GUIEvent.Element = 0; e.GUIEvent.EventType = EGET_LISTBOX_SELECTED_AGAIN; Parent->OnEvent(e); } return true; } else if (event.KeyInput.PressedDown && event.KeyInput.Char) { // change selection based on text as it is typed. u32 now = os::Timer::getTime(); if (now - LastKeyTime < 500) { // add to key buffer if it isn't a key repeat if (!(KeyBuffer.size() == 1 && KeyBuffer[0] == event.KeyInput.Char)) { KeyBuffer += L" "; KeyBuffer[KeyBuffer.size()-1] = event.KeyInput.Char; } } else { KeyBuffer = L" "; KeyBuffer[0] = event.KeyInput.Char; } LastKeyTime = now; // find the selected item, starting at the current selection s32 start = Selected; // dont change selection if the key buffer matches the current item if (Selected > -1 && KeyBuffer.size() > 1) { if (Items[Selected].text.size() >= KeyBuffer.size() && KeyBuffer.equals_ignore_case(Items[Selected].text.subString(0,KeyBuffer.size()))) return true; } s32 current; for (current = start+1; current < (s32)Items.size(); ++current) { if (Items[current].text.size() >= KeyBuffer.size()) { if (KeyBuffer.equals_ignore_case(Items[current].text.subString(0,KeyBuffer.size()))) { if (Parent && Selected != current && !Selecting && !MoveOverSelect) { SEvent e; e.EventType = EET_GUI_EVENT; e.GUIEvent.Caller = this; e.GUIEvent.Element = 0; e.GUIEvent.EventType = EGET_LISTBOX_CHANGED; Parent->OnEvent(e); } setSelected(current); return true; } } } for (current = 0; current <= start; ++current) { if (Items[current].text.size() >= KeyBuffer.size()) { if (KeyBuffer.equals_ignore_case(Items[current].text.subString(0,KeyBuffer.size()))) { if (Parent && Selected != current && !Selecting && !MoveOverSelect) { Selected = current; SEvent e; e.EventType = EET_GUI_EVENT; e.GUIEvent.Caller = this; e.GUIEvent.Element = 0; e.GUIEvent.EventType = EGET_LISTBOX_CHANGED; Parent->OnEvent(e); } setSelected(current); return true; } } } return true; } break; case EET_GUI_EVENT: switch(event.GUIEvent.EventType) { case gui::EGET_SCROLL_BAR_CHANGED: if (event.GUIEvent.Caller == ScrollBar) return true; break; case gui::EGET_ELEMENT_FOCUS_LOST: { if (event.GUIEvent.Caller == this) Selecting = false; } default: break; } break; case EET_MOUSE_INPUT_EVENT: { core::position2d p(event.MouseInput.X, event.MouseInput.Y); switch(event.MouseInput.Event) { case EMIE_MOUSE_WHEEL: ScrollBar->setPos(ScrollBar->getPos() + (event.MouseInput.Wheel < 0 ? -1 : 1)*-ItemHeight/2); return true; case EMIE_LMOUSE_PRESSED_DOWN: { Selecting = true; return true; } case EMIE_LMOUSE_LEFT_UP: { Selecting = false; if (isPointInside(p)) selectNew(event.MouseInput.Y); return true; } case EMIE_MOUSE_MOVED: if (Selecting || MoveOverSelect) { if (isPointInside(p)) { selectNew(event.MouseInput.Y, true); return true; } } default: break; } } break; case EET_LOG_TEXT_EVENT: case EET_USER_EVENT: case EET_JOYSTICK_INPUT_EVENT: case EGUIET_FORCE_32_BIT: break; } } return IGUIElement::OnEvent(event); } void CGUIListBox::selectNew(s32 ypos, bool onlyHover) { u32 now = os::Timer::getTime(); s32 oldSelected = Selected; Selected = getItemAt(AbsoluteRect.UpperLeftCorner.X, ypos); if (Selected<0 && !Items.empty()) Selected = 0; recalculateScrollPos(); gui::EGUI_EVENT_TYPE eventType = (Selected == oldSelected && now < selectTime + 500) ? EGET_LISTBOX_SELECTED_AGAIN : EGET_LISTBOX_CHANGED; selectTime = now; // post the news if (Parent && !onlyHover) { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = eventType; Parent->OnEvent(event); } } //! Update the position and size of the listbox, and update the scrollbar void CGUIListBox::updateAbsolutePosition() { IGUIElement::updateAbsolutePosition(); recalculateItemHeight(); } //! draws the element and its children void CGUIListBox::draw() { if (!IsVisible) return; recalculateItemHeight(); // if the font changed IGUISkin* skin = Environment->getSkin(); core::rect* clipRect = 0; // draw background core::rect frameRect(AbsoluteRect); // draw items core::rect clientClip(AbsoluteRect); clientClip.UpperLeftCorner.Y += 1; clientClip.UpperLeftCorner.X += 1; if (ScrollBar->isVisible()) clientClip.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize(EGDS_SCROLLBAR_SIZE); clientClip.LowerRightCorner.Y -= 1; clientClip.clipAgainst(AbsoluteClippingRect); skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT), true, DrawBack, frameRect, &AbsoluteClippingRect); if (clipRect) clientClip.clipAgainst(*clipRect); frameRect = AbsoluteRect; frameRect.UpperLeftCorner.X += 1; if (ScrollBar->isVisible()) frameRect.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize(EGDS_SCROLLBAR_SIZE); frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight; frameRect.UpperLeftCorner.Y -= ScrollBar->getPos(); frameRect.LowerRightCorner.Y -= ScrollBar->getPos(); bool hl = (HighlightWhenNotFocused || Environment->hasFocus(this) || Environment->hasFocus(ScrollBar)); for (s32 i=0; i<(s32)Items.size(); ++i) { if (frameRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y && frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y) { if (i == Selected && hl) skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), frameRect, &clientClip); core::rect textRect = frameRect; textRect.UpperLeftCorner.X += 3; if (Font) { if (IconBank && (Items[i].icon > -1)) { core::position2di iconPos = textRect.UpperLeftCorner; iconPos.Y += textRect.getHeight() / 2; iconPos.X += ItemsIconWidth/2; if ( i==Selected && hl ) { IconBank->draw2DSprite( (u32)Items[i].icon, iconPos, &clientClip, hasItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) ? getItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_ICON_HIGHLIGHT), selectTime, os::Timer::getTime(), false, true); } else { IconBank->draw2DSprite( (u32)Items[i].icon, iconPos, &clientClip, hasItemOverrideColor(i, EGUI_LBC_ICON) ? getItemOverrideColor(i, EGUI_LBC_ICON) : getItemDefaultColor(EGUI_LBC_ICON), 0 , (i==Selected) ? os::Timer::getTime() : 0, false, true); } } textRect.UpperLeftCorner.X += ItemsIconWidth+3; if ( i==Selected && hl ) { Font->draw(Items[i].text.c_str(), textRect, hasItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) ? getItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_TEXT_HIGHLIGHT), false, true, &clientClip); } else { Font->draw(Items[i].text.c_str(), textRect, hasItemOverrideColor(i, EGUI_LBC_TEXT) ? getItemOverrideColor(i, EGUI_LBC_TEXT) : getItemDefaultColor(EGUI_LBC_TEXT), false, true, &clientClip); } textRect.UpperLeftCorner.X -= ItemsIconWidth+3; } } frameRect.UpperLeftCorner.Y += ItemHeight; frameRect.LowerRightCorner.Y += ItemHeight; } IGUIElement::draw(); } //! adds an list item with an icon u32 CGUIListBox::addItem(const wchar_t* text, s32 icon) { ListItem i; i.text = text; i.icon = icon; Items.push_back(i); recalculateItemHeight(); recalculateItemWidth(icon); return Items.size() - 1; } void CGUIListBox::setSpriteBank(IGUISpriteBank* bank) { if ( bank == IconBank ) return; if (IconBank) IconBank->drop(); IconBank = bank; if (IconBank) IconBank->grab(); } void CGUIListBox::recalculateScrollPos() { if (!AutoScroll) return; const s32 selPos = (Selected == -1 ? TotalItemHeight : Selected * ItemHeight) - ScrollBar->getPos(); if (selPos < 0) { ScrollBar->setPos(ScrollBar->getPos() + selPos); } else if (selPos > AbsoluteRect.getHeight() - ItemHeight) { ScrollBar->setPos(ScrollBar->getPos() + selPos - AbsoluteRect.getHeight() + ItemHeight); } } void CGUIListBox::setAutoScrollEnabled(bool scroll) { AutoScroll = scroll; } bool CGUIListBox::isAutoScrollEnabled() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return AutoScroll; } bool CGUIListBox::getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc & useColorLabel, core::stringc & colorLabel) const { switch ( colorType ) { case EGUI_LBC_TEXT: useColorLabel = "UseColText"; colorLabel = "ColText"; break; case EGUI_LBC_TEXT_HIGHLIGHT: useColorLabel = "UseColTextHl"; colorLabel = "ColTextHl"; break; case EGUI_LBC_ICON: useColorLabel = "UseColIcon"; colorLabel = "ColIcon"; break; case EGUI_LBC_ICON_HIGHLIGHT: useColorLabel = "UseColIconHl"; colorLabel = "ColIconHl"; break; default: return false; } return true; } //! Writes attributes of the element. void CGUIListBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUIListBox::serializeAttributes(out,options); // todo: out->addString ("IconBank", IconBank->getName?); out->addBool ("DrawBack", DrawBack); out->addBool ("MoveOverSelect", MoveOverSelect); out->addBool ("AutoScroll", AutoScroll); out->addInt("ItemCount", Items.size()); for (u32 i=0;iaddString(label.c_str(), Items[i].text.c_str() ); for ( s32 c=0; c < (s32)EGUI_LBC_COUNT; ++c ) { core::stringc useColorLabel, colorLabel; if ( !getSerializationLabels((EGUI_LISTBOX_COLOR)c, useColorLabel, colorLabel) ) return; label = useColorLabel; label += i; if ( Items[i].OverrideColors[c].Use ) { out->addBool(label.c_str(), true ); label = colorLabel; label += i; out->addColor(label.c_str(), Items[i].OverrideColors[c].Color); } else { out->addBool(label.c_str(), false ); } } } } //! Reads attributes of the element void CGUIListBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { clear(); DrawBack = in->getAttributeAsBool("DrawBack"); MoveOverSelect = in->getAttributeAsBool("MoveOverSelect"); AutoScroll = in->getAttributeAsBool("AutoScroll"); IGUIListBox::deserializeAttributes(in,options); const s32 count = in->getAttributeAsInt("ItemCount"); for (s32 i=0; igetAttributeAsStringW(label.c_str()); addItem(item.text.c_str(), item.icon); for ( u32 c=0; c < EGUI_LBC_COUNT; ++c ) { core::stringc useColorLabel, colorLabel; if ( !getSerializationLabels((EGUI_LISTBOX_COLOR)c, useColorLabel, colorLabel) ) return; label = useColorLabel; label += i; Items[i].OverrideColors[c].Use = in->getAttributeAsBool(label.c_str()); if ( Items[i].OverrideColors[c].Use ) { label = colorLabel; label += i; Items[i].OverrideColors[c].Color = in->getAttributeAsColor(label.c_str()); } } } } void CGUIListBox::recalculateItemWidth(s32 icon) { if (IconBank && icon > -1 && IconBank->getSprites().size() > (u32)icon && IconBank->getSprites()[(u32)icon].Frames.size()) { u32 rno = IconBank->getSprites()[(u32)icon].Frames[0].rectNumber; if (IconBank->getPositions().size() > rno) { const s32 w = IconBank->getPositions()[rno].getWidth(); if (w > ItemsIconWidth) ItemsIconWidth = w; } } } void CGUIListBox::setItem(u32 index, const wchar_t* text, s32 icon) { if ( index >= Items.size() ) return; Items[index].text = text; Items[index].icon = icon; recalculateItemHeight(); recalculateItemWidth(icon); } //! Insert the item at the given index //! Return the index on success or -1 on failure. s32 CGUIListBox::insertItem(u32 index, const wchar_t* text, s32 icon) { ListItem i; i.text = text; i.icon = icon; Items.insert(i, index); recalculateItemHeight(); recalculateItemWidth(icon); return index; } void CGUIListBox::swapItems(u32 index1, u32 index2) { if ( index1 >= Items.size() || index2 >= Items.size() ) return; ListItem dummmy = Items[index1]; Items[index1] = Items[index2]; Items[index2] = dummmy; } void CGUIListBox::setItemOverrideColor(u32 index, video::SColor color) { for ( u32 c=0; c < EGUI_LBC_COUNT; ++c ) { Items[index].OverrideColors[c].Use = true; Items[index].OverrideColors[c].Color = color; } } void CGUIListBox::setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color) { if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT ) return; Items[index].OverrideColors[colorType].Use = true; Items[index].OverrideColors[colorType].Color = color; } void CGUIListBox::clearItemOverrideColor(u32 index) { for (u32 c=0; c < (u32)EGUI_LBC_COUNT; ++c ) { Items[index].OverrideColors[c].Use = false; } } void CGUIListBox::clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) { if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT ) return; Items[index].OverrideColors[colorType].Use = false; } bool CGUIListBox::hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const { if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT ) return false; return Items[index].OverrideColors[colorType].Use; } video::SColor CGUIListBox::getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const { if ( (u32)index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT ) return video::SColor(); return Items[index].OverrideColors[colorType].Color; } video::SColor CGUIListBox::getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const { IGUISkin* skin = Environment->getSkin(); if ( !skin ) return video::SColor(); switch ( colorType ) { case EGUI_LBC_TEXT: return skin->getColor(EGDC_BUTTON_TEXT); case EGUI_LBC_TEXT_HIGHLIGHT: return skin->getColor(EGDC_HIGH_LIGHT_TEXT); case EGUI_LBC_ICON: return skin->getColor(EGDC_ICON); case EGUI_LBC_ICON_HIGHLIGHT: return skin->getColor(EGDC_ICON_HIGH_LIGHT); default: return video::SColor(); } } //! set global itemHeight void CGUIListBox::setItemHeight( s32 height ) { ItemHeight = height; ItemHeightOverride = 1; } //! Sets whether to draw the background void CGUIListBox::setDrawBackground(bool draw) { DrawBack = draw; } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIInOutFader.h0000644000000000000000000000346212574354552017763 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_IN_OUT_FADER_H_INCLUDED__ #define __C_GUI_IN_OUT_FADER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIInOutFader.h" namespace irr { namespace gui { class CGUIInOutFader : public IGUIInOutFader { public: //! constructor CGUIInOutFader(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle); //! draws the element and its children virtual void draw(); //! Gets the color to fade out to or to fade in from. virtual video::SColor getColor() const; //! Sets the color to fade out to or to fade in from. virtual void setColor(video::SColor color ); virtual void setColor(video::SColor source, video::SColor dest); //! Starts the fade in process. virtual void fadeIn(u32 time); //! Starts the fade out process. virtual void fadeOut(u32 time); //! Returns if the fade in or out process is done. virtual bool isReady() const; //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: enum EFadeAction { EFA_NOTHING = 0, EFA_FADE_IN, EFA_FADE_OUT }; u32 StartTime; u32 EndTime; EFadeAction Action; video::SColor Color[2]; video::SColor FullColor; video::SColor TransColor; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_IN_OUT_FADER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUIInOutFader.cpp0000644000000000000000000000703512574354552020316 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIInOutFader.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "os.h" namespace irr { namespace gui { //! constructor CGUIInOutFader::CGUIInOutFader(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIInOutFader(environment, parent, id, rectangle) { #ifdef _DEBUG setDebugName("CGUIInOutFader"); #endif Action = EFA_NOTHING; StartTime = 0; EndTime = 0; setColor(video::SColor(0,0,0,0)); } //! draws the element and its children void CGUIInOutFader::draw() { if (!IsVisible || !Action) return; u32 now = os::Timer::getTime(); if (now > EndTime && Action == EFA_FADE_IN) { Action = EFA_NOTHING; return; } video::IVideoDriver* driver = Environment->getVideoDriver(); if (driver) { f32 d; if (now > EndTime) d = 0.0f; else d = (EndTime - now) / (f32)(EndTime - StartTime); video::SColor newCol = FullColor.getInterpolated(TransColor, d); driver->draw2DRectangle(newCol, AbsoluteRect, &AbsoluteClippingRect); } IGUIElement::draw(); } //! Gets the color to fade out to or to fade in from. video::SColor CGUIInOutFader::getColor() const { return Color[1]; } //! Sets the color to fade out to or to fade in from. void CGUIInOutFader::setColor(video::SColor color) { video::SColor s = color; video::SColor d = color; s.setAlpha ( 255 ); d.setAlpha ( 0 ); setColor ( s,d ); /* Color[0] = color; FullColor = Color[0]; TransColor = Color[0]; if (Action == EFA_FADE_OUT) { FullColor.setAlpha(0); TransColor.setAlpha(255); } else if (Action == EFA_FADE_IN) { FullColor.setAlpha(255); TransColor.setAlpha(0); } */ } void CGUIInOutFader::setColor(video::SColor source, video::SColor dest) { Color[0] = source; Color[1] = dest; if (Action == EFA_FADE_OUT) { FullColor = Color[1]; TransColor = Color[0]; } else if (Action == EFA_FADE_IN) { FullColor = Color[0]; TransColor = Color[1]; } } //! Returns if the fade in or out process is done. bool CGUIInOutFader::isReady() const { u32 now = os::Timer::getTime(); bool ret = (now > EndTime); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! Starts the fade in process. void CGUIInOutFader::fadeIn(u32 time) { StartTime = os::Timer::getTime(); EndTime = StartTime + time; Action = EFA_FADE_IN; setColor(Color[0],Color[1]); } //! Starts the fade out process. void CGUIInOutFader::fadeOut(u32 time) { StartTime = os::Timer::getTime(); EndTime = StartTime + time; Action = EFA_FADE_OUT; setColor(Color[0],Color[1]); } //! Writes attributes of the element. void CGUIInOutFader::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUIInOutFader::serializeAttributes(out,options); out->addColor ("FullColor", FullColor); out->addColor ("TransColor", TransColor); } //! Reads attributes of the element void CGUIInOutFader::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUIInOutFader::deserializeAttributes(in,options); FullColor = in->getAttributeAsColor("FullColor"); TransColor = in->getAttributeAsColor("TransColor"); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIImageList.h0000644000000000000000000000356512574354552017645 0ustar rootroot// This file is part of the "Irrlicht Engine". // written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de #ifndef __C_GUI_IMAGE_LIST_H_INCLUDED__ #define __C_GUI_IMAGE_LIST_H_INCLUDED__ #include "IGUIImageList.h" #include "IVideoDriver.h" namespace irr { namespace gui { class CGUIImageList : public IGUIImageList { public: //! constructor CGUIImageList( video::IVideoDriver* Driver ); //! destructor virtual ~CGUIImageList(); //! Creates the image list from texture. //! \param texture: The texture to use //! \param imageSize: Size of a single image //! \param useAlphaChannel: true if the alpha channel from the texture should be used //! \return //! true if the image list was created bool createImageList( video::ITexture* texture, core::dimension2d imageSize, bool useAlphaChannel ); //! Draws an image and clips it to the specified rectangle if wanted //! \param index: Index of the image //! \param destPos: Position of the image to draw //! \param clip: Optional pointer to a rectalgle against which the text will be clipped. //! If the pointer is null, no clipping will be done. virtual void draw( s32 index, const core::position2d& destPos, const core::rect* clip = 0 ); //! Returns the count of Images in the list. //! \return Returns the count of Images in the list. virtual s32 getImageCount() const { return ImageCount; } //! Returns the size of the images in the list. //! \return Returns the size of the images in the list. virtual core::dimension2d getImageSize() const { return ImageSize; } private: video::IVideoDriver* Driver; video::ITexture* Texture; s32 ImageCount; core::dimension2d ImageSize; s32 ImagesPerRow; bool UseAlphaChannel; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CGUIImageList.cpp0000644000000000000000000000365612574354552020201 0ustar rootroot// This file is part of the "Irrlicht Engine". // written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de // modified by Thomas Alten #include "CGUIImageList.h" namespace irr { namespace gui { //! constructor CGUIImageList::CGUIImageList( video::IVideoDriver* driver ) : Driver( driver ), Texture( 0 ), ImageCount( 0 ), ImageSize( 0, 0 ), ImagesPerRow( 0 ), UseAlphaChannel( false ) { #ifdef _DEBUG setDebugName( "CGUIImageList" ); #endif if( Driver ) { Driver->grab(); } } //! destructor CGUIImageList::~CGUIImageList() { if( Driver ) { Driver->drop(); } if( Texture ) { Texture->drop(); } } //! Creates the image list from texture. bool CGUIImageList::createImageList(video::ITexture* texture, core::dimension2d imageSize, bool useAlphaChannel) { if( !texture ) { return false; } Texture = texture; Texture->grab(); ImageSize = imageSize; ImagesPerRow = Texture->getSize().Width / ImageSize.Width; ImageCount = ImagesPerRow * Texture->getSize().Height / ImageSize.Height; UseAlphaChannel = useAlphaChannel; return true; } //! Draws an image and clips it to the specified rectangle if wanted void CGUIImageList::draw( s32 index, const core::position2d& destPos, const core::rect* clip /*= 0*/ ) { core::rect sourceRect; if( !Driver || index < 0 || index >= ImageCount ) { return; } sourceRect.UpperLeftCorner.X = ( index % ImagesPerRow ) * ImageSize.Width; sourceRect.UpperLeftCorner.Y = ( index / ImagesPerRow ) * ImageSize.Height; sourceRect.LowerRightCorner.X = sourceRect.UpperLeftCorner.X + ImageSize.Width; sourceRect.LowerRightCorner.Y = sourceRect.UpperLeftCorner.Y + ImageSize.Height; Driver->draw2DImage( Texture, destPos, sourceRect, clip, video::SColor( 255, 255, 255, 255 ), UseAlphaChannel ); } } // end namespace gui } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CGUIImage.h0000644000000000000000000000364612574354552017011 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_IMAGE_H_INCLUDED__ #define __C_GUI_IMAGE_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIImage.h" namespace irr { namespace gui { class CGUIImage : public IGUIImage { public: //! constructor CGUIImage(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle); //! destructor virtual ~CGUIImage(); //! sets an image virtual void setImage(video::ITexture* image); //! Gets the image texture virtual video::ITexture* getImage() const; //! sets the color of the image virtual void setColor(video::SColor color); //! sets if the image should scale to fit the element virtual void setScaleImage(bool scale); //! draws the element and its children virtual void draw(); //! sets if the image should use its alpha channel to draw itself virtual void setUseAlphaChannel(bool use); //! Gets the color of the image virtual video::SColor getColor() const; //! Returns true if the image is scaled to fit, false if not virtual bool isImageScaled() const; //! Returns true if the image is using the alpha channel, false if not virtual bool isAlphaChannelUsed() const; //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: video::ITexture* Texture; video::SColor Color; bool UseAlphaChannel; bool ScaleImage; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_IMAGE_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUIImage.cpp0000644000000000000000000000721112574354552017334 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIImage.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" namespace irr { namespace gui { //! constructor CGUIImage::CGUIImage(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIImage(environment, parent, id, rectangle), Texture(0), Color(255,255,255,255), UseAlphaChannel(false), ScaleImage(false) { #ifdef _DEBUG setDebugName("CGUIImage"); #endif } //! destructor CGUIImage::~CGUIImage() { if (Texture) Texture->drop(); } //! sets an image void CGUIImage::setImage(video::ITexture* image) { if (image == Texture) return; if (Texture) Texture->drop(); Texture = image; if (Texture) Texture->grab(); } //! Gets the image texture video::ITexture* CGUIImage::getImage() const { return Texture; } //! sets the color of the image void CGUIImage::setColor(video::SColor color) { Color = color; } //! Gets the color of the image video::SColor CGUIImage::getColor() const { return Color; } //! draws the element and its children void CGUIImage::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); video::IVideoDriver* driver = Environment->getVideoDriver(); if (Texture) { if (ScaleImage) { const video::SColor Colors[] = {Color,Color,Color,Color}; driver->draw2DImage(Texture, AbsoluteRect, core::rect(core::position2d(0,0), core::dimension2di(Texture->getOriginalSize())), &AbsoluteClippingRect, Colors, UseAlphaChannel); } else { driver->draw2DImage(Texture, AbsoluteRect.UpperLeftCorner, core::rect(core::position2d(0,0), core::dimension2di(Texture->getOriginalSize())), &AbsoluteClippingRect, Color, UseAlphaChannel); } } else { skin->draw2DRectangle(this, skin->getColor(EGDC_3D_DARK_SHADOW), AbsoluteRect, &AbsoluteClippingRect); } IGUIElement::draw(); } //! sets if the image should use its alpha channel to draw itself void CGUIImage::setUseAlphaChannel(bool use) { UseAlphaChannel = use; } //! sets if the image should use its alpha channel to draw itself void CGUIImage::setScaleImage(bool scale) { ScaleImage = scale; } //! Returns true if the image is scaled to fit, false if not bool CGUIImage::isImageScaled() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ScaleImage; } //! Returns true if the image is using the alpha channel, false if not bool CGUIImage::isAlphaChannelUsed() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return UseAlphaChannel; } //! Writes attributes of the element. void CGUIImage::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUIImage::serializeAttributes(out,options); out->addTexture ("Texture", Texture); out->addBool ("UseAlphaChannel", UseAlphaChannel); out->addColor ("Color", Color); out->addBool ("ScaleImage", ScaleImage); } //! Reads attributes of the element void CGUIImage::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUIImage::deserializeAttributes(in,options); setImage(in->getAttributeAsTexture("Texture")); setUseAlphaChannel(in->getAttributeAsBool("UseAlphaChannel")); setColor(in->getAttributeAsColor("Color")); setScaleImage(in->getAttributeAsBool("ScaleImage")); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIFont.h0000644000000000000000000000606212574354552016670 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_FONT_H_INCLUDED__ #define __C_GUI_FONT_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIFontBitmap.h" #include "irrString.h" #include "irrMap.h" #include "IXMLReader.h" #include "IReadFile.h" #include "irrArray.h" namespace irr { namespace video { class IVideoDriver; class IImage; } namespace gui { class IGUIEnvironment; class CGUIFont : public IGUIFontBitmap { public: //! constructor CGUIFont(IGUIEnvironment* env, const io::path& filename); //! destructor virtual ~CGUIFont(); //! loads a font from a texture file bool load(const io::path& filename); //! loads a font from a texture file bool load(io::IReadFile* file); //! loads a font from an XML file bool load(io::IXMLReader* xml); //! draws an text and clips it to the specified rectangle if wanted virtual void draw(const core::stringw& text, const core::rect& position, video::SColor color, bool hcenter=false, bool vcenter=false, const core::rect* clip=0); //! returns the dimension of a text virtual core::dimension2d getDimension(const wchar_t* text) const; //! Calculates the index of the character in the text which is on a specific position. virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const; //! Returns the type of this font virtual EGUI_FONT_TYPE getType() const { return EGFT_BITMAP; } //! set an Pixel Offset on Drawing ( scale position on width ) virtual void setKerningWidth (s32 kerning); virtual void setKerningHeight (s32 kerning); //! set an Pixel Offset on Drawing ( scale position on width ) virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const; virtual s32 getKerningHeight() const; //! gets the sprite bank virtual IGUISpriteBank* getSpriteBank() const; //! returns the sprite number from a given character virtual u32 getSpriteNoFromChar(const wchar_t *c) const; virtual void setInvisibleCharacters( const wchar_t *s ); private: struct SFontArea { SFontArea() : underhang(0), overhang(0), width(0), spriteno(0) {} s32 underhang; s32 overhang; s32 width; u32 spriteno; }; //! load & prepare font from ITexture bool loadTexture(video::IImage * image, const io::path& name); void readPositions(video::IImage* texture, s32& lowerRightPositions); s32 getAreaFromCharacter (const wchar_t c) const; void setMaxHeight(); core::array Areas; core::map CharacterMap; video::IVideoDriver* Driver; IGUISpriteBank* SpriteBank; IGUIEnvironment* Environment; u32 WrongCharacter; s32 MaxHeight; s32 GlobalKerningWidth, GlobalKerningHeight; core::stringw Invisible; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_FONT_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUIFont.cpp0000644000000000000000000003444212574354552017226 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIFont.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "os.h" #include "IGUIEnvironment.h" #include "IXMLReader.h" #include "IReadFile.h" #include "IVideoDriver.h" #include "IGUISpriteBank.h" namespace irr { namespace gui { //! constructor CGUIFont::CGUIFont(IGUIEnvironment *env, const io::path& filename) : Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0), MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0) { #ifdef _DEBUG setDebugName("CGUIFont"); #endif if (Environment) { // don't grab environment, to avoid circular references Driver = Environment->getVideoDriver(); SpriteBank = Environment->getSpriteBank(filename); if (!SpriteBank) // could be default-font which has no file SpriteBank = Environment->addEmptySpriteBank(filename); if (SpriteBank) SpriteBank->grab(); } if (Driver) Driver->grab(); setInvisibleCharacters ( L" " ); } //! destructor CGUIFont::~CGUIFont() { if (Driver) Driver->drop(); if (SpriteBank) { SpriteBank->drop(); // TODO: spritebank still exists in gui-environment and should be removed here when it's // reference-count is 1. Just can't do that from here at the moment. // But spritebank would not be able to drop textures anyway because those are in texture-cache // where they can't be removed unless materials start reference-couting 'em. } } //! loads a font file from xml bool CGUIFont::load(io::IXMLReader* xml) { if (!SpriteBank) return false; SpriteBank->clear(); while (xml->read()) { if (io::EXN_ELEMENT == xml->getNodeType()) { if (core::stringw(L"Texture") == xml->getNodeName()) { // add a texture core::stringc fn = xml->getAttributeValue(L"filename"); u32 i = (u32)xml->getAttributeValueAsInt(L"index"); core::stringw alpha = xml->getAttributeValue(L"hasAlpha"); while (i+1 > SpriteBank->getTextureCount()) SpriteBank->addTexture(0); // disable mipmaps+filtering bool mipmap = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); // load texture SpriteBank->setTexture(i, Driver->getTexture(fn)); // set previous mip-map+filter state Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap); // couldn't load texture, abort. if (!SpriteBank->getTexture(i)) { os::Printer::log("Unable to load all textures in the font, aborting", ELL_ERROR); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } else { // colorkey texture rather than alpha channel? if (alpha == core::stringw("false")) Driver->makeColorKeyTexture(SpriteBank->getTexture(i), core::position2di(0,0)); } } else if (core::stringw(L"c") == xml->getNodeName()) { // adding a character to this font SFontArea a; SGUISpriteFrame f; SGUISprite s; core::rect rectangle; a.underhang = xml->getAttributeValueAsInt(L"u"); a.overhang = xml->getAttributeValueAsInt(L"o"); a.spriteno = SpriteBank->getSprites().size(); s32 texno = xml->getAttributeValueAsInt(L"i"); // parse rectangle core::stringc rectstr = xml->getAttributeValue(L"r"); wchar_t ch = xml->getAttributeValue(L"c")[0]; const c8 *c = rectstr.c_str(); s32 val; val = 0; while (*c >= '0' && *c <= '9') { val *= 10; val += *c - '0'; c++; } rectangle.UpperLeftCorner.X = val; while (*c == L' ' || *c == L',') c++; val = 0; while (*c >= '0' && *c <= '9') { val *= 10; val += *c - '0'; c++; } rectangle.UpperLeftCorner.Y = val; while (*c == L' ' || *c == L',') c++; val = 0; while (*c >= '0' && *c <= '9') { val *= 10; val += *c - '0'; c++; } rectangle.LowerRightCorner.X = val; while (*c == L' ' || *c == L',') c++; val = 0; while (*c >= '0' && *c <= '9') { val *= 10; val += *c - '0'; c++; } rectangle.LowerRightCorner.Y = val; CharacterMap.insert(ch,Areas.size()); // make frame f.rectNumber = SpriteBank->getPositions().size(); f.textureNumber = texno; // add frame to sprite s.Frames.push_back(f); s.frameTime = 0; // add rectangle to sprite bank SpriteBank->getPositions().push_back(rectangle); a.width = rectangle.getWidth(); // add sprite to sprite bank SpriteBank->getSprites().push_back(s); // add character to font Areas.push_back(a); } } } // set bad character WrongCharacter = getAreaFromCharacter(L' '); setMaxHeight(); return true; } void CGUIFont::setMaxHeight() { if ( !SpriteBank ) return; MaxHeight = 0; s32 t; core::array< core::rect >& p = SpriteBank->getPositions(); for (u32 i=0; iMaxHeight) MaxHeight = t; } } //! loads a font file, native file needed, for texture parsing bool CGUIFont::load(io::IReadFile* file) { if (!Driver) return false; return loadTexture(Driver->createImageFromFile(file), file->getFileName()); } //! loads a font file, native file needed, for texture parsing bool CGUIFont::load(const io::path& filename) { if (!Driver) return false; return loadTexture(Driver->createImageFromFile( filename ), filename); } //! load & prepare font from ITexture bool CGUIFont::loadTexture(video::IImage* image, const io::path& name) { if (!image || !SpriteBank) return false; s32 lowerRightPositions = 0; video::IImage* tmpImage=image; bool deleteTmpImage=false; switch(image->getColorFormat()) { case video::ECF_R5G6B5: tmpImage = Driver->createImage(video::ECF_A1R5G5B5,image->getDimension()); image->copyTo(tmpImage); deleteTmpImage=true; break; case video::ECF_A1R5G5B5: case video::ECF_A8R8G8B8: break; case video::ECF_R8G8B8: tmpImage = Driver->createImage(video::ECF_A8R8G8B8,image->getDimension()); image->copyTo(tmpImage); deleteTmpImage=true; break; default: os::Printer::log("Unknown texture format provided for CGUIFont::loadTexture", ELL_ERROR); return false; } readPositions(tmpImage, lowerRightPositions); WrongCharacter = getAreaFromCharacter(L' '); // output warnings if (!lowerRightPositions || !SpriteBank->getSprites().size()) os::Printer::log("Either no upper or lower corner pixels in the font file. If this font was made using the new font tool, please load the XML file instead. If not, the font may be corrupted.", ELL_ERROR); else if (lowerRightPositions != (s32)SpriteBank->getPositions().size()) os::Printer::log("The amount of upper corner pixels and the lower corner pixels is not equal, font file may be corrupted.", ELL_ERROR); bool ret = ( !SpriteBank->getSprites().empty() && lowerRightPositions ); if ( ret ) { bool flag[2]; flag[0] = Driver->getTextureCreationFlag ( video::ETCF_ALLOW_NON_POWER_2 ); flag[1] = Driver->getTextureCreationFlag ( video::ETCF_CREATE_MIP_MAPS ); Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, true); Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false ); SpriteBank->addTexture(Driver->addTexture(name, tmpImage)); Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, flag[0] ); Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, flag[1] ); } if (deleteTmpImage) tmpImage->drop(); image->drop(); setMaxHeight(); return ret; } void CGUIFont::readPositions(video::IImage* image, s32& lowerRightPositions) { if (!SpriteBank ) return; const core::dimension2d size = image->getDimension(); video::SColor colorTopLeft = image->getPixel(0,0); colorTopLeft.setAlpha(255); image->setPixel(0,0,colorTopLeft); video::SColor colorLowerRight = image->getPixel(1,0); video::SColor colorBackGround = image->getPixel(2,0); video::SColor colorBackGroundTransparent = 0; image->setPixel(1,0,colorBackGround); // start parsing core::position2d pos(0,0); for (pos.Y=0; pos.Y<(s32)size.Height; ++pos.Y) { for (pos.X=0; pos.X<(s32)size.Width; ++pos.X) { const video::SColor c = image->getPixel(pos.X, pos.Y); if (c == colorTopLeft) { image->setPixel(pos.X, pos.Y, colorBackGroundTransparent); SpriteBank->getPositions().push_back(core::rect(pos, pos)); } else if (c == colorLowerRight) { // too many lower right points if (SpriteBank->getPositions().size()<=(u32)lowerRightPositions) { lowerRightPositions = 0; return; } image->setPixel(pos.X, pos.Y, colorBackGroundTransparent); SpriteBank->getPositions()[lowerRightPositions].LowerRightCorner = pos; // add frame to sprite bank SGUISpriteFrame f; f.rectNumber = lowerRightPositions; f.textureNumber = 0; SGUISprite s; s.Frames.push_back(f); s.frameTime = 0; SpriteBank->getSprites().push_back(s); // add character to font SFontArea a; a.overhang = 0; a.underhang = 0; a.spriteno = lowerRightPositions; a.width = SpriteBank->getPositions()[lowerRightPositions].getWidth(); Areas.push_back(a); // map letter to character wchar_t ch = (wchar_t)(lowerRightPositions + 32); CharacterMap.set(ch, lowerRightPositions); ++lowerRightPositions; } else if (c == colorBackGround) image->setPixel(pos.X, pos.Y, colorBackGroundTransparent); } } } //! set an Pixel Offset on Drawing ( scale position on width ) void CGUIFont::setKerningWidth(s32 kerning) { GlobalKerningWidth = kerning; } //! set an Pixel Offset on Drawing ( scale position on width ) s32 CGUIFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const { s32 ret = GlobalKerningWidth; if (thisLetter) { ret += Areas[getAreaFromCharacter(*thisLetter)].overhang; if (previousLetter) { ret += Areas[getAreaFromCharacter(*previousLetter)].underhang; } } return ret; } //! set an Pixel Offset on Drawing ( scale position on height ) void CGUIFont::setKerningHeight(s32 kerning) { GlobalKerningHeight = kerning; } //! set an Pixel Offset on Drawing ( scale position on height ) s32 CGUIFont::getKerningHeight () const { return GlobalKerningHeight; } //! returns the sprite number from a given character u32 CGUIFont::getSpriteNoFromChar(const wchar_t *c) const { return Areas[getAreaFromCharacter(*c)].spriteno; } s32 CGUIFont::getAreaFromCharacter(const wchar_t c) const { core::map::Node* n = CharacterMap.find(c); if (n) return n->getValue(); else return WrongCharacter; } void CGUIFont::setInvisibleCharacters( const wchar_t *s ) { Invisible = s; } //! returns the dimension of text core::dimension2d CGUIFont::getDimension(const wchar_t* text) const { core::dimension2d dim(0, 0); core::dimension2d thisLine(0, MaxHeight); for (const wchar_t* p = text; *p; ++p) { bool lineBreak=false; if (*p == L'\r') // Mac or Windows breaks { lineBreak = true; if (p[1] == L'\n') // Windows breaks ++p; } else if (*p == L'\n') // Unix breaks { lineBreak = true; } if (lineBreak) { dim.Height += thisLine.Height; if (dim.Width < thisLine.Width) dim.Width = thisLine.Width; thisLine.Width = 0; continue; } const SFontArea &area = Areas[getAreaFromCharacter(*p)]; thisLine.Width += area.underhang; thisLine.Width += area.width + area.overhang + GlobalKerningWidth; } dim.Height += thisLine.Height; if (dim.Width < thisLine.Width) dim.Width = thisLine.Width; return dim; } //! draws some text and clips it to the specified rectangle if wanted void CGUIFont::draw(const core::stringw& text, const core::rect& position, video::SColor color, bool hcenter, bool vcenter, const core::rect* clip ) { if (!Driver || !SpriteBank) return; core::dimension2d textDimension; // NOTE: don't make this u32 or the >> later on can fail when the dimension width is < position width core::position2d offset = position.UpperLeftCorner; if (hcenter || vcenter || clip) textDimension = getDimension(text.c_str()); if (hcenter) offset.X += (position.getWidth() - textDimension.Width) >> 1; if (vcenter) offset.Y += (position.getHeight() - textDimension.Height) >> 1; if (clip) { core::rect clippedRect(offset, textDimension); clippedRect.clipAgainst(*clip); if (!clippedRect.isValid()) return; } core::array indices(text.size()); core::array offsets(text.size()); for(u32 i = 0;i < text.size();i++) { wchar_t c = text[i]; bool lineBreak=false; if ( c == L'\r') // Mac or Windows breaks { lineBreak = true; if ( text[i + 1] == L'\n') // Windows breaks c = text[++i]; } else if ( c == L'\n') // Unix breaks { lineBreak = true; } if (lineBreak) { offset.Y += MaxHeight; offset.X = position.UpperLeftCorner.X; if ( hcenter ) { offset.X += (position.getWidth() - textDimension.Width) >> 1; } continue; } SFontArea& area = Areas[getAreaFromCharacter(c)]; offset.X += area.underhang; if ( Invisible.findFirst ( c ) < 0 ) { indices.push_back(area.spriteno); offsets.push_back(offset); } offset.X += area.width + area.overhang + GlobalKerningWidth; } SpriteBank->draw2DSpriteBatch(indices, offsets, clip, color); } //! Calculates the index of the character in the text which is on a specific position. s32 CGUIFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const { s32 x = 0; s32 idx = 0; while (text[idx]) { const SFontArea& a = Areas[getAreaFromCharacter(text[idx])]; x += a.width + a.overhang + a.underhang + GlobalKerningWidth; if (x >= pixel_x) return idx; ++idx; } return -1; } IGUISpriteBank* CGUIFont::getSpriteBank() const { return SpriteBank; } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIFileOpenDialog.h0000644000000000000000000000437212574354552020605 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_FILE_OPEN_DIALOG_H_INCLUDED__ #define __C_GUI_FILE_OPEN_DIALOG_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIFileOpenDialog.h" #include "IGUIButton.h" #include "IGUIListBox.h" #include "IGUIEditBox.h" #include "IFileSystem.h" namespace irr { namespace gui { class CGUIFileOpenDialog : public IGUIFileOpenDialog { public: //! constructor CGUIFileOpenDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id, bool restoreCWD=false, io::path::char_type* startDir=0); //! destructor virtual ~CGUIFileOpenDialog(); //! returns the filename of the selected file. Returns NULL, if no file was selected. virtual const wchar_t* getFileName() const; //! Returns the directory of the selected file. Returns NULL, if no directory was selected. virtual const io::path& getDirectoryName(); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! draws the element and its children virtual void draw(); virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); protected: //! fills the listbox with files. void fillListBox(); //! sends the event that the file has been selected. void sendSelectedEvent( EGUI_EVENT_TYPE type ); //! sends the event that the file choose process has been canceld void sendCancelEvent(); core::position2d DragStart; core::stringw FileName; io::path FileDirectory; io::path RestoreDirectory; io::path StartDirectory; IGUIButton* CloseButton; IGUIButton* OKButton; IGUIButton* CancelButton; IGUIListBox* FileBox; IGUIEditBox* FileNameText; IGUIElement* EventParent; io::IFileSystem* FileSystem; io::IFileList* FileList; bool Dragging; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_FILE_OPEN_DIALOG_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUIFileOpenDialog.cpp0000644000000000000000000002712512574354552021141 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIFileOpenDialog.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIButton.h" #include "IGUIStaticText.h" #include "IGUIFont.h" #include "IGUIFontBitmap.h" #include "IFileList.h" #include "os.h" namespace irr { namespace gui { const s32 FOD_WIDTH = 350; const s32 FOD_HEIGHT = 250; //! constructor CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id, bool restoreCWD, io::path::char_type* startDir) : IGUIFileOpenDialog(environment, parent, id, core::rect((parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2, (parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2, (parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2+FOD_WIDTH, (parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2+FOD_HEIGHT)), FileNameText(0), FileList(0), Dragging(false) { #ifdef _DEBUG IGUIElement::setDebugName("CGUIFileOpenDialog"); #endif Text = title; FileSystem = Environment?Environment->getFileSystem():0; if (FileSystem) { FileSystem->grab(); if (restoreCWD) RestoreDirectory = FileSystem->getWorkingDirectory(); if (startDir) { StartDirectory = startDir; FileSystem->changeWorkingDirectoryTo(startDir); } } else return; IGUISpriteBank* sprites = 0; video::SColor color(255,255,255,255); IGUISkin* skin = Environment->getSkin(); if (skin) { sprites = skin->getSpriteBank(); color = skin->getColor(EGDC_WINDOW_SYMBOL); } const s32 buttonw = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); const s32 posx = RelativeRect.getWidth() - buttonw - 4; CloseButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close"); CloseButton->setSubElement(true); CloseButton->setTabStop(false); if (sprites) { CloseButton->setSpriteBank(sprites); CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), color); CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), color); } CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); CloseButton->grab(); OKButton = Environment->addButton( core::rect(RelativeRect.getWidth()-80, 30, RelativeRect.getWidth()-10, 50), this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK"); OKButton->setSubElement(true); OKButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); OKButton->grab(); CancelButton = Environment->addButton( core::rect(RelativeRect.getWidth()-80, 55, RelativeRect.getWidth()-10, 75), this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel"); CancelButton->setSubElement(true); CancelButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); CancelButton->grab(); FileBox = Environment->addListBox(core::rect(10, 55, RelativeRect.getWidth()-90, 230), this, -1, true); FileBox->setSubElement(true); FileBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); FileBox->grab(); FileNameText = Environment->addEditBox(0, core::rect(10, 30, RelativeRect.getWidth()-90, 50), true, this); FileNameText->setSubElement(true); FileNameText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); FileNameText->grab(); setTabGroup(true); fillListBox(); } //! destructor CGUIFileOpenDialog::~CGUIFileOpenDialog() { if (CloseButton) CloseButton->drop(); if (OKButton) OKButton->drop(); if (CancelButton) CancelButton->drop(); if (FileBox) FileBox->drop(); if (FileNameText) FileNameText->drop(); if (FileSystem) { // revert to original CWD if path was set in constructor if (RestoreDirectory.size()) FileSystem->changeWorkingDirectoryTo(RestoreDirectory); FileSystem->drop(); } if (FileList) FileList->drop(); } //! returns the filename of the selected file. Returns NULL, if no file was selected. const wchar_t* CGUIFileOpenDialog::getFileName() const { return FileName.c_str(); } //! Returns the directory of the selected file. Returns NULL, if no directory was selected. const io::path& CGUIFileOpenDialog::getDirectoryName() { FileSystem->flattenFilename ( FileDirectory ); return FileDirectory; } //! called if an event happened. bool CGUIFileOpenDialog::OnEvent(const SEvent& event) { if (isEnabled()) { switch(event.EventType) { case EET_GUI_EVENT: switch(event.GUIEvent.EventType) { case EGET_ELEMENT_FOCUS_LOST: Dragging = false; break; case EGET_BUTTON_CLICKED: if (event.GUIEvent.Caller == CloseButton || event.GUIEvent.Caller == CancelButton) { sendCancelEvent(); remove(); return true; } else if (event.GUIEvent.Caller == OKButton ) { if ( FileDirectory != L"" ) { sendSelectedEvent( EGET_DIRECTORY_SELECTED ); } if ( FileName != L"" ) { sendSelectedEvent( EGET_FILE_SELECTED ); remove(); return true; } } break; case EGET_LISTBOX_CHANGED: { s32 selected = FileBox->getSelected(); if (FileList && FileSystem) { if (FileList->isDirectory(selected)) { FileName = L""; FileDirectory = FileList->getFullFileName(selected); } else { FileDirectory = L""; FileName = FileList->getFullFileName(selected); } return true; } } break; case EGET_LISTBOX_SELECTED_AGAIN: { const s32 selected = FileBox->getSelected(); if (FileList && FileSystem) { if (FileList->isDirectory(selected)) { FileDirectory = FileList->getFullFileName(selected); FileSystem->changeWorkingDirectoryTo(FileList->getFileName(selected)); fillListBox(); FileName = ""; } else { FileName = FileList->getFullFileName(selected); } return true; } } break; case EGET_EDITBOX_ENTER: if (event.GUIEvent.Caller == FileNameText) { io::path dir( FileNameText->getText () ); if ( FileSystem->changeWorkingDirectoryTo( dir ) ) { fillListBox(); FileName = L""; } return true; } break; default: break; } break; case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) { case EMIE_MOUSE_WHEEL: return FileBox->OnEvent(event); case EMIE_LMOUSE_PRESSED_DOWN: DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; Dragging = true; Environment->setFocus(this); return true; case EMIE_LMOUSE_LEFT_UP: Dragging = false; return true; case EMIE_MOUSE_MOVED: if ( !event.MouseInput.isLeftPressed () ) Dragging = false; if (Dragging) { // gui window should not be dragged outside its parent if (Parent) if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 || event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 || event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 || event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1) return true; move(core::position2d(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y)); DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; return true; } break; default: break; } default: break; } } return IGUIElement::OnEvent(event); } //! draws the element and its children void CGUIFileOpenDialog::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); core::rect rect = AbsoluteRect; rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER), rect, &AbsoluteClippingRect); if (Text.size()) { rect.UpperLeftCorner.X += 2; rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5; IGUIFont* font = skin->getFont(EGDF_WINDOW); if (font) font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true, &AbsoluteClippingRect); } IGUIElement::draw(); } //! Writes attributes of the element. /* Not sure if this will really work out properly. Saving paths can be rather problematic. */ void CGUIFileOpenDialog::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { IGUIFileOpenDialog::serializeAttributes(out,options); out->addString("StartDirectory", StartDirectory.c_str()); out->addBool("RestoreDirectory", (RestoreDirectory.size()!=0)); } //! Reads attributes of the element /* Note that thiese paths changes will happen at arbitrary places upon load of the gui description. This may be undesired. */ void CGUIFileOpenDialog::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { StartDirectory = in->getAttributeAsString("StartDirectory"); const bool restore = in->getAttributeAsBool("RestoreDirectory"); if (restore) RestoreDirectory = FileSystem->getWorkingDirectory(); else RestoreDirectory = ""; if (StartDirectory.size()) FileSystem->changeWorkingDirectoryTo(StartDirectory); IGUIFileOpenDialog::deserializeAttributes(in,options); } //! fills the listbox with files. void CGUIFileOpenDialog::fillListBox() { IGUISkin *skin = Environment->getSkin(); if (!FileSystem || !FileBox || !skin) return; if (FileList) FileList->drop(); FileBox->clear(); FileList = FileSystem->createFileList(); core::stringw s; #if !defined(_IRR_WINDOWS_CE_PLATFORM_) setlocale(LC_ALL,""); #endif if (FileList) { for (u32 i=0; i < FileList->getFileCount(); ++i) { #ifndef _IRR_WCHAR_FILESYSTEM const c8 *cs = (const c8 *)FileList->getFileName(i).c_str(); wchar_t *ws = new wchar_t[strlen(cs) + 1]; int len = mbstowcs(ws,cs,strlen(cs)); ws[len] = 0; s = ws; delete [] ws; #else s = FileList->getFileName(i).c_str(); #endif FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE)); } } if (FileNameText) { #ifndef _IRR_WCHAR_FILESYSTEM const c8 *cs = (const c8 *)FileSystem->getWorkingDirectory().c_str(); wchar_t *ws = new wchar_t[strlen(cs) + 1]; int len = mbstowcs(ws,cs,strlen(cs)); ws[len] = 0; s = ws; delete [] ws; #else s = FileSystem->getWorkingDirectory(); #endif FileDirectory = s; FileNameText->setText(s.c_str()); } } //! sends the event that the file has been selected. void CGUIFileOpenDialog::sendSelectedEvent( EGUI_EVENT_TYPE type) { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = type; Parent->OnEvent(event); } //! sends the event that the file choose process has been canceld void CGUIFileOpenDialog::sendCancelEvent() { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED; Parent->OnEvent(event); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIEnvironment.h0000644000000000000000000002642312574354552020271 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_ENVIRONMENT_H_INCLUDED__ #define __C_GUI_ENVIRONMENT_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIEnvironment.h" #include "IGUIElement.h" #include "irrArray.h" #include "IFileSystem.h" #include "IOSOperator.h" namespace irr { namespace io { class IXMLWriter; } namespace gui { class CGUIEnvironment : public IGUIEnvironment, public IGUIElement { public: //! constructor CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op); //! destructor virtual ~CGUIEnvironment(); //! draws all gui elements virtual void drawAll(); //! returns the current video driver virtual video::IVideoDriver* getVideoDriver() const; //! returns pointer to the filesystem virtual io::IFileSystem* getFileSystem() const; //! returns a pointer to the OS operator virtual IOSOperator* getOSOperator() const; //! posts an input event to the environment virtual bool postEventFromUser(const SEvent& event); //! This sets a new event receiver for gui events. Usually you do not have to //! use this method, it is used by the internal engine. virtual void setUserEventReceiver(IEventReceiver* evr); //! removes all elements from the environment virtual void clear(); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! returns the current gui skin virtual IGUISkin* getSkin() const; //! Sets a new GUI Skin virtual void setSkin(IGUISkin* skin); //! Creates a new GUI Skin based on a template. /** \return Returns a pointer to the created skin. If you no longer need the skin, you should call IGUISkin::drop(). See IReferenceCounted::drop() for more information. */ virtual IGUISkin* createSkin(EGUI_SKIN_TYPE type); //! Creates the image list from the given texture. virtual IGUIImageList* createImageList( video::ITexture* texture, core::dimension2d imageSize, bool useAlphaChannel ); //! returns the font virtual IGUIFont* getFont(const io::path& filename); //! add an externally loaded font virtual IGUIFont* addFont(const io::path& name, IGUIFont* font); //! remove loaded font virtual void removeFont(IGUIFont* font); //! returns default font virtual IGUIFont* getBuiltInFont() const; //! returns the sprite bank virtual IGUISpriteBank* getSpriteBank(const io::path& filename); //! returns the sprite bank virtual IGUISpriteBank* addEmptySpriteBank(const io::path& name); //! adds an button. The returned pointer must not be dropped. virtual IGUIButton* addButton(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0,const wchar_t* tooltiptext = 0); //! adds a window. The returned pointer must not be dropped. virtual IGUIWindow* addWindow(const core::rect& rectangle, bool modal = false, const wchar_t* text=0, IGUIElement* parent=0, s32 id=-1); //! adds a modal screen. The returned pointer must not be dropped. virtual IGUIElement* addModalScreen(IGUIElement* parent); //! Adds a message box. virtual IGUIWindow* addMessageBox(const wchar_t* caption, const wchar_t* text=0, bool modal = true, s32 flag = EMBF_OK, IGUIElement* parent=0, s32 id=-1, video::ITexture* image=0); //! adds a scrollbar. The returned pointer must not be dropped. virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1); //! Adds an image element. virtual IGUIImage* addImage(video::ITexture* image, core::position2d pos, bool useAlphaChannel=true, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0); //! adds an image. The returned pointer must not be dropped. virtual IGUIImage* addImage(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0, bool useAlphaChannel=true); //! adds a checkbox virtual IGUICheckBox* addCheckBox(bool checked, const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0); //! adds a list box virtual IGUIListBox* addListBox(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, bool drawBackground=false); //! adds a tree view virtual IGUITreeView* addTreeView(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, bool drawBackground=false, bool scrollBarVertical = true, bool scrollBarHorizontal = false); //! adds an mesh viewer. The returned pointer must not be dropped. virtual IGUIMeshViewer* addMeshViewer(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0); //! Adds a file open dialog. virtual IGUIFileOpenDialog* addFileOpenDialog(const wchar_t* title = 0, bool modal=true, IGUIElement* parent=0, s32 id=-1, bool restoreCWD=false, io::path::char_type* startDir=0); //! Adds a color select dialog. virtual IGUIColorSelectDialog* addColorSelectDialog(const wchar_t* title = 0, bool modal=true, IGUIElement* parent=0, s32 id=-1); //! adds a static text. The returned pointer must not be dropped. virtual IGUIStaticText* addStaticText(const wchar_t* text, const core::rect& rectangle, bool border=false, bool wordWrap=true, IGUIElement* parent=0, s32 id=-1, bool drawBackground = false); //! Adds an edit box. The returned pointer must not be dropped. virtual IGUIEditBox* addEditBox(const wchar_t* text, const core::rect& rectangle, bool border=false, IGUIElement* parent=0, s32 id=-1); //! Adds a spin box to the environment virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect& rectangle, bool border=false,IGUIElement* parent=0, s32 id=-1); //! Adds a tab control to the environment. virtual IGUITabControl* addTabControl(const core::rect& rectangle, IGUIElement* parent=0, bool fillbackground=false, bool border=true, s32 id=-1); //! Adds tab to the environment. virtual IGUITab* addTab(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1); //! Adds a context menu to the environment. virtual IGUIContextMenu* addContextMenu(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1); //! Adds a menu to the environment. virtual IGUIContextMenu* addMenu(IGUIElement* parent=0, s32 id=-1); //! Adds a toolbar to the environment. It is like a menu is always placed on top //! in its parent, and contains buttons. virtual IGUIToolBar* addToolBar(IGUIElement* parent=0, s32 id=-1); //! Adds a combo box to the environment. virtual IGUIComboBox* addComboBox(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1); //! Adds a table element. virtual IGUITable* addTable(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, bool drawBackground=false); //! sets the focus to an element virtual bool setFocus(IGUIElement* element); //! removes the focus from an element virtual bool removeFocus(IGUIElement* element); //! Returns if the element has focus virtual bool hasFocus(IGUIElement* element) const; //! Returns the element with the focus virtual IGUIElement* getFocus() const; //! Returns the element last known to be under the mouse virtual IGUIElement* getHovered() const; //! Adds an element for fading in or out. virtual IGUIInOutFader* addInOutFader(const core::rect* rectangle=0, IGUIElement* parent=0, s32 id=-1); //! Returns the root gui element. virtual IGUIElement* getRootGUIElement(); virtual void OnPostRender( u32 time ); //! Returns the default element factory which can create all built in elements virtual IGUIElementFactory* getDefaultGUIElementFactory() const; //! Adds an element factory to the gui environment. /** Use this to extend the gui environment with new element types which it should be able to create automaticly, for example when loading data from xml files. */ virtual void registerGUIElementFactory(IGUIElementFactory* factoryToAdd); //! Returns amount of registered scene node factories. virtual u32 getRegisteredGUIElementFactoryCount() const; //! Returns a scene node factory by index virtual IGUIElementFactory* getGUIElementFactory(u32 index) const; //! Adds a GUI Element by its name virtual IGUIElement* addGUIElement(const c8* elementName, IGUIElement* parent=0); //! Saves the current gui into a file. /** \param filename: Name of the file. \param start: The element to start saving from. if not specified, the root element will be used */ virtual bool saveGUI( const io::path& filename, IGUIElement* start=0); //! Saves the current gui into a file. /** \param file: The file to save the GUI to. \param start: The element to start saving from. if not specified, the root element will be used */ virtual bool saveGUI(io::IWriteFile* file, IGUIElement* start=0); //! Loads the gui. Note that the current gui is not cleared before. /** \param filename: Name of the file. \param parent: The parent of all loaded GUI elements, if not specified, the root element will be used */ virtual bool loadGUI(const io::path& filename, IGUIElement* parent=0); //! Loads the gui. Note that the current gui is not cleared before. /** \param file: IReadFile to load the GUI from \param parent: The parent of all loaded GUI elements, if not specified, the root element will be used */ virtual bool loadGUI(io::IReadFile* file, IGUIElement* parent=0); //! Writes attributes of the environment virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the environment. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! writes an element virtual void writeGUIElement(io::IXMLWriter* writer, IGUIElement* node); //! reads an element virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* node); private: IGUIElement* getNextElement(bool reverse=false, bool group=false); void updateHoveredElement(core::position2d mousePos); void loadBuiltInFont(); struct SFont { io::SNamedPath NamedPath; IGUIFont* Font; bool operator < (const SFont& other) const { return (NamedPath < other.NamedPath); } }; struct SSpriteBank { io::SNamedPath NamedPath; IGUISpriteBank* Bank; bool operator < (const SSpriteBank& other) const { return (NamedPath < other.NamedPath); } }; struct SToolTip { IGUIStaticText* Element; u32 LastTime; u32 EnterTime; u32 LaunchTime; u32 RelaunchTime; }; SToolTip ToolTip; core::array GUIElementFactoryList; core::array Fonts; core::array Banks; video::IVideoDriver* Driver; IGUIElement* Hovered; IGUIElement* HoveredNoSubelement; // subelements replaced by their parent, so you only have 'real' elements here IGUIElement* Focus; core::position2d LastHoveredMousePos; IGUISkin* CurrentSkin; io::IFileSystem* FileSystem; IEventReceiver* UserReceiver; IOSOperator* Operator; static const io::path DefaultFontName; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_ENVIRONMENT_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUIEnvironment.cpp0000644000000000000000000011650012574354552020620 0ustar rootroot // Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIEnvironment.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IVideoDriver.h" #include "CGUISkin.h" #include "CGUIButton.h" #include "CGUIWindow.h" #include "CGUIScrollBar.h" #include "CGUIFont.h" #include "CGUISpriteBank.h" #include "CGUIImage.h" #include "CGUIMeshViewer.h" #include "CGUICheckBox.h" #include "CGUIListBox.h" #include "CGUITreeView.h" #include "CGUIImageList.h" #include "CGUIFileOpenDialog.h" #include "CGUIColorSelectDialog.h" #include "CGUIStaticText.h" #include "CGUIEditBox.h" #include "CGUISpinBox.h" #include "CGUIInOutFader.h" #include "CGUIMessageBox.h" #include "CGUIModalScreen.h" #include "CGUITabControl.h" #include "CGUIContextMenu.h" #include "CGUIComboBox.h" #include "CGUIMenu.h" #include "CGUIToolBar.h" #include "CGUITable.h" #include "CDefaultGUIElementFactory.h" #include "IWriteFile.h" #include "IXMLWriter.h" #include "BuiltInFont.h" #include "os.h" namespace irr { namespace gui { const wchar_t* IRR_XML_FORMAT_GUI_ENV = L"irr_gui"; const wchar_t* IRR_XML_FORMAT_GUI_ELEMENT = L"element"; const wchar_t* IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE = L"type"; const io::path CGUIEnvironment::DefaultFontName = "#DefaultFont"; //! constructor CGUIEnvironment::CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op) : IGUIElement(EGUIET_ROOT, 0, 0, 0, core::rect(core::position2d(0,0), driver ? core::dimension2d(driver->getScreenSize()) : core::dimension2d(0,0))), Driver(driver), Hovered(0), HoveredNoSubelement(0), Focus(0), LastHoveredMousePos(0,0), CurrentSkin(0), FileSystem(fs), UserReceiver(0), Operator(op) { if (Driver) Driver->grab(); if (FileSystem) FileSystem->grab(); if (Operator) Operator->grab(); #ifdef _DEBUG IGUIEnvironment::setDebugName("CGUIEnvironment"); #endif // gui factory IGUIElementFactory* factory = new CDefaultGUIElementFactory(this); registerGUIElementFactory(factory); factory->drop(); loadBuiltInFont(); IGUISkin* skin = createSkin( gui::EGST_WINDOWS_METALLIC ); setSkin(skin); skin->drop(); //set tooltip default ToolTip.LastTime = 0; ToolTip.EnterTime = 0; ToolTip.LaunchTime = 1000; ToolTip.RelaunchTime = 500; ToolTip.Element = 0; // environment is root tab group Environment = this; setTabGroup(true); } //! destructor CGUIEnvironment::~CGUIEnvironment() { if ( HoveredNoSubelement && HoveredNoSubelement != this ) { HoveredNoSubelement->drop(); HoveredNoSubelement = 0; } if (Hovered && Hovered != this) { Hovered->drop(); Hovered = 0; } if (Focus) { Focus->drop(); Focus = 0; } if (ToolTip.Element) { ToolTip.Element->drop(); ToolTip.Element = 0; } // drop skin if (CurrentSkin) { CurrentSkin->drop(); CurrentSkin = 0; } u32 i; // delete all sprite banks for (i=0; idrop(); // delete all fonts for (i=0; idrop(); // remove all factories for (i=0; idrop(); if (Operator) { Operator->drop(); Operator = 0; } if (FileSystem) { FileSystem->drop(); FileSystem = 0; } if (Driver) { Driver->drop(); Driver = 0; } } void CGUIEnvironment::loadBuiltInFont() { io::IReadFile* file = io::createMemoryReadFile(BuiltInFontData, BuiltInFontDataSize, DefaultFontName, false); CGUIFont* font = new CGUIFont(this, DefaultFontName ); if (!font->load(file)) { os::Printer::log("Error: Could not load built-in Font. Did you compile without the BMP loader?", ELL_ERROR); font->drop(); file->drop(); return; } SFont f; f.NamedPath.setPath(DefaultFontName); f.Font = font; Fonts.push_back(f); file->drop(); } //! draws all gui elements void CGUIEnvironment::drawAll() { if (Driver) { core::dimension2d dim(Driver->getScreenSize()); if (AbsoluteRect.LowerRightCorner.X != dim.Width || AbsoluteRect.LowerRightCorner.Y != dim.Height) { // resize gui environment DesiredRect.LowerRightCorner = dim; AbsoluteClippingRect = DesiredRect; AbsoluteRect = DesiredRect; updateAbsolutePosition(); } } // make sure tooltip is always on top if (ToolTip.Element) bringToFront(ToolTip.Element); draw(); OnPostRender ( os::Timer::getTime () ); } //! sets the focus to an element bool CGUIEnvironment::setFocus(IGUIElement* element) { if (Focus == element) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } // GUI Environment should not get the focus if (element == this) element = 0; // stop element from being deleted if (element) element->grab(); // focus may change or be removed in this call IGUIElement *currentFocus = 0; if (Focus) { currentFocus = Focus; currentFocus->grab(); SEvent e; e.EventType = EET_GUI_EVENT; e.GUIEvent.Caller = Focus; e.GUIEvent.Element = element; e.GUIEvent.EventType = EGET_ELEMENT_FOCUS_LOST; if (Focus->OnEvent(e)) { if (element) element->drop(); currentFocus->drop(); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } currentFocus->drop(); currentFocus = 0; } if (element) { currentFocus = Focus; if (currentFocus) currentFocus->grab(); // send focused event SEvent e; e.EventType = EET_GUI_EVENT; e.GUIEvent.Caller = element; e.GUIEvent.Element = Focus; e.GUIEvent.EventType = EGET_ELEMENT_FOCUSED; if (element->OnEvent(e)) { if (element) element->drop(); if (currentFocus) currentFocus->drop(); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } } if (currentFocus) currentFocus->drop(); if (Focus) Focus->drop(); // element is the new focus so it doesn't have to be dropped Focus = element; return true; } //! returns the element with the focus IGUIElement* CGUIEnvironment::getFocus() const { return Focus; } //! returns the element last known to be under the mouse cursor IGUIElement* CGUIEnvironment::getHovered() const { return Hovered; } //! removes the focus from an element bool CGUIEnvironment::removeFocus(IGUIElement* element) { if (Focus && Focus==element) { SEvent e; e.EventType = EET_GUI_EVENT; e.GUIEvent.Caller = Focus; e.GUIEvent.Element = 0; e.GUIEvent.EventType = EGET_ELEMENT_FOCUS_LOST; if (Focus->OnEvent(e)) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } } if (Focus) { Focus->drop(); Focus = 0; } return true; } //! Returns if the element has focus bool CGUIEnvironment::hasFocus(IGUIElement* element) const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return (element == Focus); } //! returns the current video driver video::IVideoDriver* CGUIEnvironment::getVideoDriver() const { return Driver; } //! returns the current file system io::IFileSystem* CGUIEnvironment::getFileSystem() const { return FileSystem; } //! returns a pointer to the OS operator IOSOperator* CGUIEnvironment::getOSOperator() const { return Operator; } //! clear all GUI elements void CGUIEnvironment::clear() { // Remove the focus if (Focus) { Focus->drop(); Focus = 0; } if (Hovered && Hovered != this) { Hovered->drop(); Hovered = 0; } if ( HoveredNoSubelement && HoveredNoSubelement != this) { HoveredNoSubelement->drop(); HoveredNoSubelement = 0; } // get the root's children in case the root changes in future const core::list& children = getRootGUIElement()->getChildren(); while (!children.empty()) (*children.getLast())->remove(); } //! called by ui if an event happened. bool CGUIEnvironment::OnEvent(const SEvent& event) { bool ret = false; if (UserReceiver && (event.EventType != EET_MOUSE_INPUT_EVENT) && (event.EventType != EET_KEY_INPUT_EVENT) && (event.EventType != EET_GUI_EVENT || event.GUIEvent.Caller != this)) { ret = UserReceiver->OnEvent(event); } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } // void CGUIEnvironment::OnPostRender( u32 time ) { // launch tooltip if ( ToolTip.Element == 0 && HoveredNoSubelement && HoveredNoSubelement != this && (time - ToolTip.EnterTime >= ToolTip.LaunchTime || (time - ToolTip.LastTime >= ToolTip.RelaunchTime && time - ToolTip.LastTime < ToolTip.LaunchTime)) && HoveredNoSubelement->getToolTipText().size() && getSkin() && getSkin()->getFont(EGDF_TOOLTIP) ) { core::rect pos; pos.UpperLeftCorner = LastHoveredMousePos; core::dimension2du dim = getSkin()->getFont(EGDF_TOOLTIP)->getDimension(HoveredNoSubelement->getToolTipText().c_str()); dim.Width += getSkin()->getSize(EGDS_TEXT_DISTANCE_X)*2; dim.Height += getSkin()->getSize(EGDS_TEXT_DISTANCE_Y)*2; pos.UpperLeftCorner.Y -= dim.Height+1; pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + dim.Height-1; pos.LowerRightCorner.X = pos.UpperLeftCorner.X + dim.Width; pos.constrainTo(getAbsolutePosition()); ToolTip.Element = addStaticText(HoveredNoSubelement->getToolTipText().c_str(), pos, true, true, this, -1, true); ToolTip.Element->setOverrideColor(getSkin()->getColor(EGDC_TOOLTIP)); ToolTip.Element->setBackgroundColor(getSkin()->getColor(EGDC_TOOLTIP_BACKGROUND)); ToolTip.Element->setOverrideFont(getSkin()->getFont(EGDF_TOOLTIP)); ToolTip.Element->setSubElement(true); ToolTip.Element->grab(); s32 textHeight = ToolTip.Element->getTextHeight(); pos = ToolTip.Element->getRelativePosition(); pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + textHeight; ToolTip.Element->setRelativePosition(pos); } if (ToolTip.Element && ToolTip.Element->isVisible() ) // (isVisible() check only because we might use visibility for ToolTip one day) { ToolTip.LastTime = time; // got invisible or removed in the meantime? if ( !HoveredNoSubelement || !HoveredNoSubelement->isVisible() || !HoveredNoSubelement->getParent() ) // got invisible or removed in the meantime? { ToolTip.Element->remove(); ToolTip.Element->drop(); ToolTip.Element = 0; } } IGUIElement::OnPostRender ( time ); } // void CGUIEnvironment::updateHoveredElement(core::position2d mousePos) { IGUIElement* lastHovered = Hovered; IGUIElement* lastHoveredNoSubelement = HoveredNoSubelement; LastHoveredMousePos = mousePos; Hovered = getElementFromPoint(mousePos); if ( ToolTip.Element && Hovered == ToolTip.Element ) { // When the mouse is over the ToolTip we remove that so it will be re-created at a new position. // Note that ToolTip.EnterTime does not get changed here, so it will be re-created at once. ToolTip.Element->remove(); ToolTip.Element->drop(); ToolTip.Element = 0; // Get the real Hovered Hovered = getElementFromPoint(mousePos); } // for tooltips we want the element itself and not some of it's subelements HoveredNoSubelement = Hovered; while ( HoveredNoSubelement && HoveredNoSubelement->isSubElement() ) { HoveredNoSubelement = HoveredNoSubelement->getParent(); } if (Hovered && Hovered != this) Hovered->grab(); if ( HoveredNoSubelement && HoveredNoSubelement != this) HoveredNoSubelement->grab(); if (Hovered != lastHovered) { SEvent event; event.EventType = EET_GUI_EVENT; if (lastHovered) { event.GUIEvent.Caller = lastHovered; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_ELEMENT_LEFT; lastHovered->OnEvent(event); } if ( Hovered ) { event.GUIEvent.Caller = Hovered; event.GUIEvent.Element = Hovered; event.GUIEvent.EventType = EGET_ELEMENT_HOVERED; Hovered->OnEvent(event); } } if ( lastHoveredNoSubelement != HoveredNoSubelement ) { if (ToolTip.Element) { ToolTip.Element->remove(); ToolTip.Element->drop(); ToolTip.Element = 0; } if ( HoveredNoSubelement ) { u32 now = os::Timer::getTime(); ToolTip.EnterTime = now; } } if (lastHovered && lastHovered != this) lastHovered->drop(); if (lastHoveredNoSubelement && lastHoveredNoSubelement != this) lastHoveredNoSubelement->drop(); } //! This sets a new event receiver for gui events. Usually you do not have to //! use this method, it is used by the internal engine. void CGUIEnvironment::setUserEventReceiver(IEventReceiver* evr) { UserReceiver = evr; } //! posts an input event to the environment bool CGUIEnvironment::postEventFromUser(const SEvent& event) { switch(event.EventType) { case EET_GUI_EVENT: // hey, why is the user sending gui events..? break; case EET_MOUSE_INPUT_EVENT: updateHoveredElement(core::position2d(event.MouseInput.X, event.MouseInput.Y)); if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) if ( (Hovered && Hovered != Focus) || !Focus ) { setFocus(Hovered); } // sending input to focus if (Focus && Focus->OnEvent(event)) return true; // focus could have died in last call if (!Focus && Hovered) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Hovered->OnEvent(event); } break; case EET_KEY_INPUT_EVENT: { if (Focus && Focus->OnEvent(event)) return true; // For keys we handle the event before changing focus to give elements the chance for catching the TAB // Send focus changing event if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_TAB) { IGUIElement *next = getNextElement(event.KeyInput.Shift, event.KeyInput.Control); if (next && next != Focus) { if (setFocus(next)) return true; } } } break; default: break; } // end switch _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } //! returns the current gui skin IGUISkin* CGUIEnvironment::getSkin() const { return CurrentSkin; } //! Sets a new GUI Skin void CGUIEnvironment::setSkin(IGUISkin* skin) { if (CurrentSkin==skin) return; if (CurrentSkin) CurrentSkin->drop(); CurrentSkin = skin; if (CurrentSkin) CurrentSkin->grab(); } //! Creates a new GUI Skin based on a template. /** \return Returns a pointer to the created skin. If you no longer need the skin, you should call IGUISkin::drop(). See IReferenceCounted::drop() for more information. */ IGUISkin* CGUIEnvironment::createSkin(EGUI_SKIN_TYPE type) { IGUISkin* skin = new CGUISkin(type, Driver); IGUIFont* builtinfont = getBuiltInFont(); IGUIFontBitmap* bitfont = 0; if (builtinfont && builtinfont->getType() == EGFT_BITMAP) bitfont = (IGUIFontBitmap*)builtinfont; IGUISpriteBank* bank = 0; skin->setFont(builtinfont); if (bitfont) bank = bitfont->getSpriteBank(); skin->setSpriteBank(bank); return skin; } //! Returns the default element factory which can create all built in elements IGUIElementFactory* CGUIEnvironment::getDefaultGUIElementFactory() const { return getGUIElementFactory(0); } //! Adds an element factory to the gui environment. /** Use this to extend the gui environment with new element types which it should be able to create automaticly, for example when loading data from xml files. */ void CGUIEnvironment::registerGUIElementFactory(IGUIElementFactory* factoryToAdd) { if (factoryToAdd) { factoryToAdd->grab(); GUIElementFactoryList.push_back(factoryToAdd); } } //! Returns amount of registered scene node factories. u32 CGUIEnvironment::getRegisteredGUIElementFactoryCount() const { return GUIElementFactoryList.size(); } //! Returns a scene node factory by index IGUIElementFactory* CGUIEnvironment::getGUIElementFactory(u32 index) const { if (index < GUIElementFactoryList.size()) return GUIElementFactoryList[index]; else return 0; } //! adds a GUI Element using its name IGUIElement* CGUIEnvironment::addGUIElement(const c8* elementName, IGUIElement* parent) { IGUIElement* node=0; if (!parent) parent = this; for (s32 i=GUIElementFactoryList.size()-1; i>=0 && !node; --i) node = GUIElementFactoryList[i]->addGUIElement(elementName, parent); return node; } //! Saves the current gui into a file. //! \param filename: Name of the file . bool CGUIEnvironment::saveGUI(const io::path& filename, IGUIElement* start) { io::IWriteFile* file = FileSystem->createAndWriteFile(filename); if (!file) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } bool ret = saveGUI(file, start); file->drop(); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! Saves the current gui into a file. bool CGUIEnvironment::saveGUI(io::IWriteFile* file, IGUIElement* start) { if (!file) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } io::IXMLWriter* writer = FileSystem->createXMLWriter(file); if (!writer) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } writer->writeXMLHeader(); writeGUIElement(writer, start ? start : this); writer->drop(); return true; } //! Loads the gui. Note that the current gui is not cleared before. //! \param filename: Name of the file. bool CGUIEnvironment::loadGUI(const io::path& filename, IGUIElement* parent) { io::IReadFile* read = FileSystem->createAndOpenFile(filename); if (!read) { os::Printer::log("Unable to open gui file", filename, ELL_ERROR); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } bool ret = loadGUI(read, parent); read->drop(); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! Loads the gui. Note that the current gui is not cleared before. bool CGUIEnvironment::loadGUI(io::IReadFile* file, IGUIElement* parent) { if (!file) { os::Printer::log("Unable to open GUI file", ELL_ERROR); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } io::IXMLReader* reader = FileSystem->createXMLReader(file); if (!reader) { os::Printer::log("GUI is not a valid XML file", file->getFileName(), ELL_ERROR); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } // read file while(reader->read()) { readGUIElement(reader, parent); } // finish up reader->drop(); return true; } //! reads an element void CGUIEnvironment::readGUIElement(io::IXMLReader* reader, IGUIElement* node) { if (!reader) return; io::EXML_NODE nodeType = reader->getNodeType(); if (nodeType == io::EXN_NONE || nodeType == io::EXN_UNKNOWN || nodeType == io::EXN_ELEMENT_END) return; IGUIElement* deferedNode = 0; if (!wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName())) { // GuiEnvironment always must be this as it would serialize into a wrong element otherwise. // So we use the given node next time if ( node && node != this ) deferedNode = node; node = this; // root } else if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName())) { // find node type and create it const core::stringc attrName = reader->getAttributeValue(IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE); node = addGUIElement(attrName.c_str(), node); if (!node) os::Printer::log("Could not create GUI element of unknown type", attrName.c_str()); } // read attributes while(reader->read()) { bool endreached = false; switch (reader->getNodeType()) { case io::EXN_ELEMENT_END: if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()) || !wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName())) { endreached = true; } break; case io::EXN_ELEMENT: if (!wcscmp(L"attributes", reader->getNodeName())) { // read attributes io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver); attr->read(reader, true); if (node) node->deserializeAttributes(attr); attr->drop(); } else if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()) || !wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName())) { if ( deferedNode ) readGUIElement(reader, deferedNode); else readGUIElement(reader, node); } else { os::Printer::log("Found unknown element in irrlicht GUI file", core::stringc(reader->getNodeName()).c_str()); } break; default: break; } if (endreached) break; } } //! writes an element void CGUIEnvironment::writeGUIElement(io::IXMLWriter* writer, IGUIElement* node) { if (!writer || !node ) return; const wchar_t* name = 0; // write properties io::IAttributes* attr = FileSystem->createEmptyAttributes(); node->serializeAttributes(attr); // all gui elements must have at least one attribute // if they have nothing then we ignore them. if (attr->getAttributeCount() != 0) { if (node == this) { name = IRR_XML_FORMAT_GUI_ENV; writer->writeElement(name, false); } else { name = IRR_XML_FORMAT_GUI_ELEMENT; writer->writeElement(name, false, IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE, core::stringw(node->getTypeName()).c_str()); } writer->writeLineBreak(); writer->writeLineBreak(); attr->write(writer); writer->writeLineBreak(); } // write children core::list::ConstIterator it = node->getChildren().begin(); for (; it != node->getChildren().end(); ++it) { if (!(*it)->isSubElement()) writeGUIElement(writer, (*it)); } // write closing brace if required if (attr->getAttributeCount() != 0) { writer->writeClosingTag(name); writer->writeLineBreak(); writer->writeLineBreak(); } attr->drop(); } //! Writes attributes of the environment void CGUIEnvironment::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { IGUISkin* skin = getSkin(); if (skin) { out->addEnum("Skin", getSkin()->getType(), GUISkinTypeNames); skin->serializeAttributes(out, options); } } //! Reads attributes of the environment void CGUIEnvironment::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { if (in->existsAttribute("Skin")) { IGUISkin *skin = getSkin(); EGUI_SKIN_TYPE t = (EGUI_SKIN_TYPE) in->getAttributeAsEnumeration("Skin",GUISkinTypeNames); if ( !skin || t != skin->getType()) { skin = createSkin(t); setSkin(skin); skin->drop(); } skin = getSkin(); if (skin) { skin->deserializeAttributes(in, options); } } RelativeRect = AbsoluteRect = core::rect(core::position2d(0,0), Driver ? core::dimension2di(Driver->getScreenSize()) : core::dimension2d(0,0)); } //! adds a button. The returned pointer must not be dropped. IGUIButton* CGUIEnvironment::addButton(const core::rect& rectangle, IGUIElement* parent, s32 id, const wchar_t* text, const wchar_t *tooltiptext) { IGUIButton* button = new CGUIButton(this, parent ? parent : this, id, rectangle); if (text) button->setText(text); if ( tooltiptext ) button->setToolTipText ( tooltiptext ); button->drop(); return button; } //! adds a window. The returned pointer must not be dropped. IGUIWindow* CGUIEnvironment::addWindow(const core::rect& rectangle, bool modal, const wchar_t* text, IGUIElement* parent, s32 id) { parent = parent ? parent : this; IGUIWindow* win = new CGUIWindow(this, parent, id, rectangle); if (text) win->setText(text); win->drop(); if (modal) { // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very // careful not to get virtual function call, like OnEvent, in the window. CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); modalScreen->drop(); modalScreen->addChild(win); } return win; } //! adds a modal screen. The returned pointer must not be dropped. IGUIElement* CGUIEnvironment::addModalScreen(IGUIElement* parent) { parent = parent ? parent : this; IGUIElement *win = new CGUIModalScreen(this, parent, -1); win->drop(); return win; } //! Adds a message box. IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t* text, bool modal, s32 flag, IGUIElement* parent, s32 id, video::ITexture* image) { if (!CurrentSkin) return 0; parent = parent ? parent : this; core::rect rect; core::dimension2d screenDim, msgBoxDim; screenDim.Width = parent->getAbsolutePosition().getWidth(); screenDim.Height = parent->getAbsolutePosition().getHeight(); msgBoxDim.Width = 2; msgBoxDim.Height = 2; rect.UpperLeftCorner.X = (screenDim.Width - msgBoxDim.Width) / 2; rect.UpperLeftCorner.Y = (screenDim.Height - msgBoxDim.Height) / 2; rect.LowerRightCorner.X = rect.UpperLeftCorner.X + msgBoxDim.Width; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + msgBoxDim.Height; IGUIWindow* win = new CGUIMessageBox(this, caption, text, flag, parent, id, rect, image); win->drop(); if (modal) { // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very // careful not to get virtual function call, like OnEvent, in the CGUIMessageBox. CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); modalScreen->drop(); modalScreen->addChild( win ); } return win; } //! adds a scrollbar. The returned pointer must not be dropped. IGUIScrollBar* CGUIEnvironment::addScrollBar(bool horizontal, const core::rect& rectangle, IGUIElement* parent, s32 id) { IGUIScrollBar* bar = new CGUIScrollBar(horizontal, this, parent ? parent : this, id, rectangle); bar->drop(); return bar; } //! Adds a table to the environment IGUITable* CGUIEnvironment::addTable(const core::rect& rectangle, IGUIElement* parent, s32 id, bool drawBackground) { CGUITable* b = new CGUITable(this, parent ? parent : this, id, rectangle, true, drawBackground, false); b->drop(); return b; } //! Adds an image element. IGUIImage* CGUIEnvironment::addImage(video::ITexture* image, core::position2d pos, bool useAlphaChannel, IGUIElement* parent, s32 id, const wchar_t* text) { core::dimension2d sz(0,0); if (image) sz = core::dimension2d(image->getOriginalSize()); IGUIImage* img = new CGUIImage(this, parent ? parent : this, id, core::rect(pos, sz)); if (text) img->setText(text); if (useAlphaChannel) img->setUseAlphaChannel(true); if (image) img->setImage(image); img->drop(); return img; } //! adds an image. The returned pointer must not be dropped. IGUIImage* CGUIEnvironment::addImage(const core::rect& rectangle, IGUIElement* parent, s32 id, const wchar_t* text, bool useAlphaChannel) { IGUIImage* img = new CGUIImage(this, parent ? parent : this, id, rectangle); if (text) img->setText(text); if ( useAlphaChannel ) img->setUseAlphaChannel(true); img->drop(); return img; } //! adds an mesh viewer. The returned pointer must not be dropped. IGUIMeshViewer* CGUIEnvironment::addMeshViewer(const core::rect& rectangle, IGUIElement* parent, s32 id, const wchar_t* text) { IGUIMeshViewer* v = new CGUIMeshViewer(this, parent ? parent : this, id, rectangle); if (text) v->setText(text); v->drop(); return v; } //! adds a checkbox IGUICheckBox* CGUIEnvironment::addCheckBox(bool checked, const core::rect& rectangle, IGUIElement* parent, s32 id, const wchar_t* text) { IGUICheckBox* b = new CGUICheckBox(checked, this, parent ? parent : this , id , rectangle); if (text) b->setText(text); b->drop(); return b; } //! adds a list box IGUIListBox* CGUIEnvironment::addListBox(const core::rect& rectangle, IGUIElement* parent, s32 id, bool drawBackground) { IGUIListBox* b = new CGUIListBox(this, parent ? parent : this, id, rectangle, true, drawBackground, false); if (CurrentSkin && CurrentSkin->getSpriteBank()) { b->setSpriteBank(CurrentSkin->getSpriteBank()); } else if (getBuiltInFont() && getBuiltInFont()->getType() == EGFT_BITMAP) { b->setSpriteBank( ((IGUIFontBitmap*)getBuiltInFont())->getSpriteBank()); } b->drop(); return b; } //! adds a tree view IGUITreeView* CGUIEnvironment::addTreeView(const core::rect& rectangle, IGUIElement* parent, s32 id, bool drawBackground, bool scrollBarVertical, bool scrollBarHorizontal) { IGUITreeView* b = new CGUITreeView(this, parent ? parent : this, id, rectangle, true, drawBackground, scrollBarVertical, scrollBarHorizontal); b->setIconFont ( getBuiltInFont () ); b->drop(); return b; } //! adds a file open dialog. The returned pointer must not be dropped. IGUIFileOpenDialog* CGUIEnvironment::addFileOpenDialog(const wchar_t* title, bool modal, IGUIElement* parent, s32 id, bool restoreCWD, io::path::char_type* startDir) { parent = parent ? parent : this; IGUIFileOpenDialog* d = new CGUIFileOpenDialog(title, this, parent, id, restoreCWD, startDir); d->drop(); if (modal) { // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very // careful not to get virtual function call, like OnEvent, in the window. CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); modalScreen->drop(); modalScreen->addChild(d); } return d; } //! adds a color select dialog. The returned pointer must not be dropped. IGUIColorSelectDialog* CGUIEnvironment::addColorSelectDialog(const wchar_t* title, bool modal, IGUIElement* parent, s32 id) { parent = parent ? parent : this; IGUIColorSelectDialog* d = new CGUIColorSelectDialog( title, this, parent, id); d->drop(); if (modal) { // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very // careful not to get virtual function call, like OnEvent, in the window. CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); modalScreen->drop(); modalScreen->addChild(d); } return d; } //! adds a static text. The returned pointer must not be dropped. IGUIStaticText* CGUIEnvironment::addStaticText(const wchar_t* text, const core::rect& rectangle, bool border, bool wordWrap, IGUIElement* parent, s32 id, bool background) { IGUIStaticText* d = new CGUIStaticText(text, border, this, parent ? parent : this, id, rectangle, background); d->setWordWrap(wordWrap); d->drop(); return d; } //! Adds an edit box. The returned pointer must not be dropped. IGUIEditBox* CGUIEnvironment::addEditBox(const wchar_t* text, const core::rect& rectangle, bool border, IGUIElement* parent, s32 id) { IGUIEditBox* d = new CGUIEditBox(text, border, this, parent ? parent : this, id, rectangle); d->drop(); return d; } //! Adds a spin box to the environment IGUISpinBox* CGUIEnvironment::addSpinBox(const wchar_t* text, const core::rect &rectangle, bool border,IGUIElement* parent, s32 id) { IGUISpinBox* d = new CGUISpinBox(text, border,this, parent ? parent : this, id, rectangle); d->drop(); return d; } //! Adds a tab control to the environment. IGUITabControl* CGUIEnvironment::addTabControl(const core::rect& rectangle, IGUIElement* parent, bool fillbackground, bool border, s32 id) { IGUITabControl* t = new CGUITabControl(this, parent ? parent : this, rectangle, fillbackground, border, id); t->drop(); return t; } //! Adds tab to the environment. IGUITab* CGUIEnvironment::addTab(const core::rect& rectangle, IGUIElement* parent, s32 id) { IGUITab* t = new CGUITab(-1, this, parent ? parent : this, rectangle, id); t->drop(); return t; } //! Adds a context menu to the environment. IGUIContextMenu* CGUIEnvironment::addContextMenu(const core::rect& rectangle, IGUIElement* parent, s32 id) { IGUIContextMenu* c = new CGUIContextMenu(this, parent ? parent : this, id, rectangle, true); c->drop(); return c; } //! Adds a menu to the environment. IGUIContextMenu* CGUIEnvironment::addMenu(IGUIElement* parent, s32 id) { if (!parent) parent = this; IGUIContextMenu* c = new CGUIMenu(this, parent, id, core::rect(0,0, parent->getAbsolutePosition().getWidth(), parent->getAbsolutePosition().getHeight())); c->drop(); return c; } //! Adds a toolbar to the environment. It is like a menu is always placed on top //! in its parent, and contains buttons. IGUIToolBar* CGUIEnvironment::addToolBar(IGUIElement* parent, s32 id) { if (!parent) parent = this; IGUIToolBar* b = new CGUIToolBar(this, parent, id, core::rect(0,0,10,10)); b->drop(); return b; } //! Adds an element for fading in or out. IGUIInOutFader* CGUIEnvironment::addInOutFader(const core::rect* rectangle, IGUIElement* parent, s32 id) { core::rect rect; if (rectangle) rect = *rectangle; else if (Driver) rect = core::rect(core::position2d(0,0), core::dimension2di(Driver->getScreenSize())); if (!parent) parent = this; IGUIInOutFader* fader = new CGUIInOutFader(this, parent, id, rect); fader->drop(); return fader; } //! Adds a combo box to the environment. IGUIComboBox* CGUIEnvironment::addComboBox(const core::rect& rectangle, IGUIElement* parent, s32 id) { IGUIComboBox* t = new CGUIComboBox(this, parent ? parent : this, id, rectangle); t->drop(); return t; } //! returns the font IGUIFont* CGUIEnvironment::getFont(const io::path& filename) { // search existing font SFont f; f.NamedPath.setPath(filename); s32 index = Fonts.binary_search(f); if (index != -1) return Fonts[index].Font; // font doesn't exist, attempt to load it // does the file exist? if (!FileSystem->existFile(filename)) { os::Printer::log("Could not load font because the file does not exist", f.NamedPath.getPath(), ELL_ERROR); return 0; } IGUIFont* ifont=0; io::IXMLReader *xml = FileSystem->createXMLReader(filename ); if (xml) { // this is an XML font, but we need to know what type EGUI_FONT_TYPE t = EGFT_CUSTOM; bool found=false; while(!found && xml->read()) { if (xml->getNodeType() == io::EXN_ELEMENT) { if (core::stringw(L"font") == xml->getNodeName()) { if (core::stringw(L"vector") == xml->getAttributeValue(L"type")) { t = EGFT_VECTOR; found=true; } else if (core::stringw(L"bitmap") == xml->getAttributeValue(L"type")) { t = EGFT_BITMAP; found=true; } else found=true; } } } if (t==EGFT_BITMAP) { CGUIFont* font = new CGUIFont(this, filename); ifont = (IGUIFont*)font; // change working directory, for loading textures io::path workingDir = FileSystem->getWorkingDirectory(); FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.NamedPath.getPath())); // load the font if (!font->load(xml)) { font->drop(); font = 0; ifont = 0; } // change working dir back again FileSystem->changeWorkingDirectoryTo( workingDir ); } else if (t==EGFT_VECTOR) { // todo: vector fonts os::Printer::log("Unable to load font, XML vector fonts are not supported yet", f.NamedPath, ELL_ERROR); //CGUIFontVector* font = new CGUIFontVector(Driver); //ifont = (IGUIFont*)font; //if (!font->load(xml)) } xml->drop(); } if (!ifont) { CGUIFont* font = new CGUIFont(this, f.NamedPath.getPath() ); ifont = (IGUIFont*)font; if (!font->load(f.NamedPath.getPath())) { font->drop(); return 0; } } // add to fonts. f.Font = ifont; Fonts.push_back(f); return ifont; } //! add an externally loaded font IGUIFont* CGUIEnvironment::addFont(const io::path& name, IGUIFont* font) { if (font) { SFont f; f.NamedPath.setPath(name); s32 index = Fonts.binary_search(f); if (index != -1) return Fonts[index].Font; f.Font = font; Fonts.push_back(f); font->grab(); } return font; } //! remove loaded font void CGUIEnvironment::removeFont(IGUIFont* font) { if ( !font ) return; for ( u32 i=0; idrop(); Fonts.erase(i); return; } } } //! returns default font IGUIFont* CGUIEnvironment::getBuiltInFont() const { if (Fonts.empty()) return 0; return Fonts[0].Font; } IGUISpriteBank* CGUIEnvironment::getSpriteBank(const io::path& filename) { // search for the file name SSpriteBank b; b.NamedPath.setPath(filename); s32 index = Banks.binary_search(b); if (index != -1) return Banks[index].Bank; // we don't have this sprite bank, we should load it if (!FileSystem->existFile(b.NamedPath.getPath())) { if ( filename != DefaultFontName ) { os::Printer::log("Could not load sprite bank because the file does not exist", b.NamedPath.getPath(), ELL_DEBUG); } return 0; } // todo: load it! return 0; } IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const io::path& name) { // no duplicate names allowed SSpriteBank b; b.NamedPath.setPath(name); const s32 index = Banks.binary_search(b); if (index != -1) return 0; // create a new sprite bank b.Bank = new CGUISpriteBank(this); Banks.push_back(b); return b.Bank; } //! Creates the image list from the given texture. IGUIImageList* CGUIEnvironment::createImageList( video::ITexture* texture, core::dimension2d imageSize, bool useAlphaChannel ) { CGUIImageList* imageList = new CGUIImageList( Driver ); if( !imageList->createImageList( texture, imageSize, useAlphaChannel ) ) { imageList->drop(); return 0; } return imageList; } //! Returns the root gui element. IGUIElement* CGUIEnvironment::getRootGUIElement() { return this; } //! Returns the next element in the tab group starting at the focused element IGUIElement* CGUIEnvironment::getNextElement(bool reverse, bool group) { // start the search at the root of the current tab group IGUIElement *startPos = Focus ? Focus->getTabGroup() : 0; s32 startOrder = -1; // if we're searching for a group if (group && startPos) { startOrder = startPos->getTabOrder(); } else if (!group && Focus && !Focus->isTabGroup()) { startOrder = Focus->getTabOrder(); if (startOrder == -1) { // this element is not part of the tab cycle, // but its parent might be... IGUIElement *el = Focus; while (el && el->getParent() && startOrder == -1) { el = el->getParent(); startOrder = el->getTabOrder(); } } } if (group || !startPos) startPos = this; // start at the root // find the element IGUIElement *closest = 0; IGUIElement *first = 0; startPos->getNextElement(startOrder, reverse, group, first, closest); if (closest) return closest; // we found an element else if (first) return first; // go to the end or the start else if (group) return this; // no group found? root group else return 0; } //! creates an GUI Environment IGUIEnvironment* createGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* Driver, IOSOperator* op) { return new CGUIEnvironment(fs, Driver, op); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIEditBox.h0000644000000000000000000001360012574354552017314 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_EDIT_BOX_H_INCLUDED__ #define __C_GUI_EDIT_BOX_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIEditBox.h" #include "irrArray.h" #include "IOSOperator.h" namespace irr { namespace gui { class CGUIEditBox : public IGUIEditBox { public: //! constructor CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle); //! destructor virtual ~CGUIEditBox(); //! Sets another skin independent font. virtual void setOverrideFont(IGUIFont* font=0); //! Gets the override font (if any) /** \return The override font (may be 0) */ virtual IGUIFont* getOverrideFont() const; //! Get the font which is used right now for drawing /** Currently this is the override font when one is set and the font of the active skin otherwise */ virtual IGUIFont* getActiveFont() const; //! Sets another color for the text. virtual void setOverrideColor(video::SColor color); //! Gets the override color virtual video::SColor getOverrideColor() const; //! Sets if the text should use the overide color or the //! color in the gui skin. virtual void enableOverrideColor(bool enable); //! Checks if an override color is enabled /** \return true if the override color is enabled, false otherwise */ virtual bool isOverrideColorEnabled(void) const; //! Sets whether to draw the background virtual void setDrawBackground(bool draw); //! Turns the border on or off virtual void setDrawBorder(bool border); //! Enables or disables word wrap for using the edit box as multiline text editor. virtual void setWordWrap(bool enable); //! Checks if word wrap is enabled //! \return true if word wrap is enabled, false otherwise virtual bool isWordWrapEnabled() const; //! Enables or disables newlines. /** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired, instead a newline character will be inserted. */ virtual void setMultiLine(bool enable); //! Checks if multi line editing is enabled //! \return true if mult-line is enabled, false otherwise virtual bool isMultiLineEnabled() const; //! Enables or disables automatic scrolling with cursor position //! \param enable: If set to true, the text will move around with the cursor position virtual void setAutoScroll(bool enable); //! Checks to see if automatic scrolling is enabled //! \return true if automatic scrolling is enabled, false if not virtual bool isAutoScrollEnabled() const; //! Gets the size area of the text in the edit box //! \return Returns the size in pixels of the text virtual core::dimension2du getTextDimension(); //! Sets text justification virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! draws the element and its children virtual void draw(); //! Sets the new caption of this element. virtual void setText(const wchar_t* text); //! Sets the maximum amount of characters which may be entered in the box. //! \param max: Maximum amount of characters. If 0, the character amount is //! infinity. virtual void setMax(u32 max); //! Returns maximum amount of characters, previously set by setMax(); virtual u32 getMax() const; //! Sets whether the edit box is a password box. Setting this to true will /** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x \param passwordBox: true to enable password, false to disable \param passwordChar: the character that is displayed instead of letters */ virtual void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*'); //! Returns true if the edit box is currently a password box. virtual bool isPasswordBox() const; //! Updates the absolute position, splits text if required virtual void updateAbsolutePosition(); //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); protected: //! Breaks the single text line. void breakText(); //! sets the area of the given line void setTextRect(s32 line); //! returns the line number that the cursor is on s32 getLineFromPos(s32 pos); //! adds a letter to the edit box void inputChar(wchar_t c); //! calculates the current scroll position void calculateScrollPos(); //! calculated the FrameRect void calculateFrameRect(); //! send some gui event to parent void sendGuiEvent(EGUI_EVENT_TYPE type); //! set text markers void setTextMarkers(s32 begin, s32 end); bool processKey(const SEvent& event); bool processMouse(const SEvent& event); s32 getCursorPos(s32 x, s32 y); bool MouseMarking; bool Border; bool Background; bool OverrideColorEnabled; s32 MarkBegin; s32 MarkEnd; video::SColor OverrideColor; gui::IGUIFont *OverrideFont, *LastBreakFont; IOSOperator* Operator; u32 BlinkStartTime; s32 CursorPos; s32 HScrollPos, VScrollPos; // scroll position in characters u32 Max; bool WordWrap, MultiLine, AutoScroll, PasswordBox; wchar_t PasswordChar; EGUI_ALIGNMENT HAlign, VAlign; core::array< core::stringw > BrokenText; core::array< s32 > BrokenTextPositions; core::rect CurrentTextRect, FrameRect; // temporary values }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_EDIT_BOX_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUIEditBox.cpp0000644000000000000000000011135612574354552017656 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIEditBox.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IGUIFont.h" #include "IVideoDriver.h" #include "rect.h" #include "os.h" #include "Keycodes.h" /* todo: optional scrollbars ctrl+left/right to select word double click/ctrl click: word select + drag to select whole words, triple click to select line optional? dragging selected text numerical */ namespace irr { namespace gui { //! constructor CGUIEditBox::CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle) : IGUIEditBox(environment, parent, id, rectangle), MouseMarking(false), Border(border), Background(true), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0), OverrideColor(video::SColor(101,255,255,255)), OverrideFont(0), LastBreakFont(0), Operator(0), BlinkStartTime(0), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0), WordWrap(false), MultiLine(false), AutoScroll(true), PasswordBox(false), PasswordChar(L'*'), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), CurrentTextRect(0,0,1,1), FrameRect(rectangle) { #ifdef _DEBUG setDebugName("CGUIEditBox"); #endif Text = text; if (Environment) Operator = Environment->getOSOperator(); if (Operator) Operator->grab(); // this element can be tabbed to setTabStop(true); setTabOrder(-1); calculateFrameRect(); breakText(); calculateScrollPos(); } //! destructor CGUIEditBox::~CGUIEditBox() { if (OverrideFont) OverrideFont->drop(); if (Operator) Operator->drop(); } //! Sets another skin independent font. void CGUIEditBox::setOverrideFont(IGUIFont* font) { if (OverrideFont == font) return; if (OverrideFont) OverrideFont->drop(); OverrideFont = font; if (OverrideFont) OverrideFont->grab(); breakText(); } //! Gets the override font (if any) IGUIFont * CGUIEditBox::getOverrideFont() const { return OverrideFont; } //! Get the font which is used right now for drawing IGUIFont* CGUIEditBox::getActiveFont() const { if ( OverrideFont ) return OverrideFont; IGUISkin* skin = Environment->getSkin(); if (skin) return skin->getFont(); return 0; } //! Sets another color for the text. void CGUIEditBox::setOverrideColor(video::SColor color) { OverrideColor = color; OverrideColorEnabled = true; } video::SColor CGUIEditBox::getOverrideColor() const { return OverrideColor; } //! Turns the border on or off void CGUIEditBox::setDrawBorder(bool border) { Border = border; } //! Sets whether to draw the background void CGUIEditBox::setDrawBackground(bool draw) { Background = draw; } //! Sets if the text should use the overide color or the color in the gui skin. void CGUIEditBox::enableOverrideColor(bool enable) { OverrideColorEnabled = enable; } bool CGUIEditBox::isOverrideColorEnabled() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return OverrideColorEnabled; } //! Enables or disables word wrap void CGUIEditBox::setWordWrap(bool enable) { WordWrap = enable; breakText(); } void CGUIEditBox::updateAbsolutePosition() { core::rect oldAbsoluteRect(AbsoluteRect); IGUIElement::updateAbsolutePosition(); if ( oldAbsoluteRect != AbsoluteRect ) { calculateFrameRect(); breakText(); calculateScrollPos(); } } //! Checks if word wrap is enabled bool CGUIEditBox::isWordWrapEnabled() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return WordWrap; } //! Enables or disables newlines. void CGUIEditBox::setMultiLine(bool enable) { MultiLine = enable; breakText(); } //! Checks if multi line editing is enabled bool CGUIEditBox::isMultiLineEnabled() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return MultiLine; } void CGUIEditBox::setPasswordBox(bool passwordBox, wchar_t passwordChar) { PasswordBox = passwordBox; if (PasswordBox) { PasswordChar = passwordChar; setMultiLine(false); setWordWrap(false); BrokenText.clear(); } } bool CGUIEditBox::isPasswordBox() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return PasswordBox; } //! Sets text justification void CGUIEditBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) { HAlign = horizontal; VAlign = vertical; } //! called if an event happened. bool CGUIEditBox::OnEvent(const SEvent& event) { if (isEnabled()) { switch(event.EventType) { case EET_GUI_EVENT: if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) { if (event.GUIEvent.Caller == this) { MouseMarking = false; setTextMarkers(0,0); } } break; case EET_KEY_INPUT_EVENT: if (processKey(event)) return true; break; case EET_MOUSE_INPUT_EVENT: if (processMouse(event)) return true; break; default: break; } } return IGUIElement::OnEvent(event); } bool CGUIEditBox::processKey(const SEvent& event) { if (!event.KeyInput.PressedDown) return false; bool textChanged = false; s32 newMarkBegin = MarkBegin; s32 newMarkEnd = MarkEnd; // control shortcut handling if (event.KeyInput.Control) { // german backlash '\' entered with control + '?' if ( event.KeyInput.Char == '\\' ) { inputChar(event.KeyInput.Char); return true; } switch(event.KeyInput.Key) { case KEY_KEY_A: // select all newMarkBegin = 0; newMarkEnd = Text.size(); break; case KEY_KEY_C: // copy to clipboard if (!PasswordBox && Operator && MarkBegin != MarkEnd) { const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; core::stringc s; s = Text.subString(realmbgn, realmend - realmbgn).c_str(); Operator->copyToClipboard(s.c_str()); } break; case KEY_KEY_X: // cut to the clipboard if (!PasswordBox && Operator && MarkBegin != MarkEnd) { const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; // copy core::stringc sc; sc = Text.subString(realmbgn, realmend - realmbgn).c_str(); Operator->copyToClipboard(sc.c_str()); if (isEnabled()) { // delete core::stringw s; s = Text.subString(0, realmbgn); s.append( Text.subString(realmend, Text.size()-realmend) ); Text = s; CursorPos = realmbgn; newMarkBegin = 0; newMarkEnd = 0; textChanged = true; } } break; case KEY_KEY_V: if ( !isEnabled() ) break; // paste from the clipboard if (Operator) { const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; // add new character const c8* p = Operator->getTextFromClipboard(); if (p) { // TODO: we should have such a function in core::string size_t lenOld = strlen(p); wchar_t *ws = new wchar_t[lenOld + 1]; size_t len = mbstowcs(ws,p,lenOld); ws[len] = 0; irr::core::stringw widep(ws); delete[] ws; if (MarkBegin == MarkEnd) { // insert text core::stringw s = Text.subString(0, CursorPos); s.append(widep); s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); if (!Max || s.size()<=Max) // thx to Fish FH for fix { Text = s; s = widep; CursorPos += s.size(); } } else { // replace text core::stringw s = Text.subString(0, realmbgn); s.append(widep); s.append( Text.subString(realmend, Text.size()-realmend) ); if (!Max || s.size()<=Max) // thx to Fish FH for fix { Text = s; s = widep; CursorPos = realmbgn + s.size(); } } } newMarkBegin = 0; newMarkEnd = 0; textChanged = true; } break; case KEY_HOME: // move/highlight to start of text if (event.KeyInput.Shift) { newMarkEnd = CursorPos; newMarkBegin = 0; CursorPos = 0; } else { CursorPos = 0; newMarkBegin = 0; newMarkEnd = 0; } break; case KEY_END: // move/highlight to end of text if (event.KeyInput.Shift) { newMarkBegin = CursorPos; newMarkEnd = Text.size(); CursorPos = 0; } else { CursorPos = Text.size(); newMarkBegin = 0; newMarkEnd = 0; } break; default: return false; } } // default keyboard handling else switch(event.KeyInput.Key) { case KEY_END: { s32 p = Text.size(); if (WordWrap || MultiLine) { p = getLineFromPos(CursorPos); p = BrokenTextPositions[p] + (s32)BrokenText[p].size(); if (p > 0 && (Text[p-1] == L'\r' || Text[p-1] == L'\n' )) p-=1; } if (event.KeyInput.Shift) { if (MarkBegin == MarkEnd) newMarkBegin = CursorPos; newMarkEnd = p; } else { newMarkBegin = 0; newMarkEnd = 0; } CursorPos = p; BlinkStartTime = os::Timer::getTime(); } break; case KEY_HOME: { s32 p = 0; if (WordWrap || MultiLine) { p = getLineFromPos(CursorPos); p = BrokenTextPositions[p]; } if (event.KeyInput.Shift) { if (MarkBegin == MarkEnd) newMarkBegin = CursorPos; newMarkEnd = p; } else { newMarkBegin = 0; newMarkEnd = 0; } CursorPos = p; BlinkStartTime = os::Timer::getTime(); } break; case KEY_RETURN: if (MultiLine) { inputChar(L'\n'); } else { calculateScrollPos(); sendGuiEvent( EGET_EDITBOX_ENTER ); } return true; case KEY_LEFT: if (event.KeyInput.Shift) { if (CursorPos > 0) { if (MarkBegin == MarkEnd) newMarkBegin = CursorPos; newMarkEnd = CursorPos-1; } } else { newMarkBegin = 0; newMarkEnd = 0; } if (CursorPos > 0) CursorPos--; BlinkStartTime = os::Timer::getTime(); break; case KEY_RIGHT: if (event.KeyInput.Shift) { if (Text.size() > (u32)CursorPos) { if (MarkBegin == MarkEnd) newMarkBegin = CursorPos; newMarkEnd = CursorPos+1; } } else { newMarkBegin = 0; newMarkEnd = 0; } if (Text.size() > (u32)CursorPos) CursorPos++; BlinkStartTime = os::Timer::getTime(); break; case KEY_UP: if (MultiLine || (WordWrap && BrokenText.size() > 1) ) { s32 lineNo = getLineFromPos(CursorPos); s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin > MarkEnd ? MarkBegin : MarkEnd); if (lineNo > 0) { s32 cp = CursorPos - BrokenTextPositions[lineNo]; if ((s32)BrokenText[lineNo-1].size() < cp) CursorPos = BrokenTextPositions[lineNo-1] + core::max_((u32)1, BrokenText[lineNo-1].size())-1; else CursorPos = BrokenTextPositions[lineNo-1] + cp; } if (event.KeyInput.Shift) { newMarkBegin = mb; newMarkEnd = CursorPos; } else { newMarkBegin = 0; newMarkEnd = 0; } } else { return false; } break; case KEY_DOWN: if (MultiLine || (WordWrap && BrokenText.size() > 1) ) { s32 lineNo = getLineFromPos(CursorPos); s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin < MarkEnd ? MarkBegin : MarkEnd); if (lineNo < (s32)BrokenText.size()-1) { s32 cp = CursorPos - BrokenTextPositions[lineNo]; if ((s32)BrokenText[lineNo+1].size() < cp) CursorPos = BrokenTextPositions[lineNo+1] + core::max_((u32)1, BrokenText[lineNo+1].size())-1; else CursorPos = BrokenTextPositions[lineNo+1] + cp; } if (event.KeyInput.Shift) { newMarkBegin = mb; newMarkEnd = CursorPos; } else { newMarkBegin = 0; newMarkEnd = 0; } } else { return false; } break; case KEY_BACK: if ( !isEnabled() ) break; if (Text.size()) { core::stringw s; if (MarkBegin != MarkEnd) { // delete marked text const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; s = Text.subString(0, realmbgn); s.append( Text.subString(realmend, Text.size()-realmend) ); Text = s; CursorPos = realmbgn; } else { // delete text behind cursor if (CursorPos>0) s = Text.subString(0, CursorPos-1); else s = L""; s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); Text = s; --CursorPos; } if (CursorPos < 0) CursorPos = 0; BlinkStartTime = os::Timer::getTime(); newMarkBegin = 0; newMarkEnd = 0; textChanged = true; } break; case KEY_DELETE: if ( !isEnabled() ) break; if (Text.size() != 0) { core::stringw s; if (MarkBegin != MarkEnd) { // delete marked text const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; s = Text.subString(0, realmbgn); s.append( Text.subString(realmend, Text.size()-realmend) ); Text = s; CursorPos = realmbgn; } else { // delete text before cursor s = Text.subString(0, CursorPos); s.append( Text.subString(CursorPos+1, Text.size()-CursorPos-1) ); Text = s; } if (CursorPos > (s32)Text.size()) CursorPos = (s32)Text.size(); BlinkStartTime = os::Timer::getTime(); newMarkBegin = 0; newMarkEnd = 0; textChanged = true; } break; case KEY_ESCAPE: case KEY_TAB: case KEY_SHIFT: case KEY_F1: case KEY_F2: case KEY_F3: case KEY_F4: case KEY_F5: case KEY_F6: case KEY_F7: case KEY_F8: case KEY_F9: case KEY_F10: case KEY_F11: case KEY_F12: case KEY_F13: case KEY_F14: case KEY_F15: case KEY_F16: case KEY_F17: case KEY_F18: case KEY_F19: case KEY_F20: case KEY_F21: case KEY_F22: case KEY_F23: case KEY_F24: // ignore these keys return false; default: inputChar(event.KeyInput.Char); return true; } // Set new text markers setTextMarkers( newMarkBegin, newMarkEnd ); // break the text if it has changed if (textChanged) { breakText(); calculateScrollPos(); sendGuiEvent(EGET_EDITBOX_CHANGED); } else { calculateScrollPos(); } return true; } //! draws the element and its children void CGUIEditBox::draw() { if (!IsVisible) return; const bool focus = Environment->hasFocus(this); IGUISkin* skin = Environment->getSkin(); if (!skin) return; EGUI_DEFAULT_COLOR bgCol = EGDC_GRAY_EDITABLE; if ( isEnabled() ) bgCol = focus ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE; if (!Border && Background) { skin->draw2DRectangle(this, skin->getColor(bgCol), AbsoluteRect, &AbsoluteClippingRect); } if (Border) { // draw the border skin->draw3DSunkenPane(this, skin->getColor(bgCol), false, Background, AbsoluteRect, &AbsoluteClippingRect); calculateFrameRect(); } core::rect localClipRect = FrameRect; localClipRect.clipAgainst(AbsoluteClippingRect); // draw the text IGUIFont* font = getActiveFont(); s32 cursorLine = 0; s32 charcursorpos = 0; if (font) { if (LastBreakFont != font) { breakText(); } // calculate cursor pos core::stringw *txtLine = &Text; s32 startPos = 0; core::stringw s, s2; // get mark position const bool ml = (!PasswordBox && (WordWrap || MultiLine)); const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; const s32 hlineStart = ml ? getLineFromPos(realmbgn) : 0; const s32 hlineCount = ml ? getLineFromPos(realmend) - hlineStart + 1 : 1; const s32 lineCount = ml ? BrokenText.size() : 1; // Save the override color information. // Then, alter it if the edit box is disabled. const bool prevOver = OverrideColorEnabled; const video::SColor prevColor = OverrideColor; if (Text.size()) { if (!isEnabled() && !OverrideColorEnabled) { OverrideColorEnabled = true; OverrideColor = skin->getColor(EGDC_GRAY_TEXT); } for (s32 i=0; i < lineCount; ++i) { setTextRect(i); // clipping test - don't draw anything outside the visible area core::rect c = localClipRect; c.clipAgainst(CurrentTextRect); if (!c.isValid()) continue; // get current line if (PasswordBox) { if (BrokenText.size() != 1) { BrokenText.clear(); BrokenText.push_back(core::stringw()); } if (BrokenText[0].size() != Text.size()) { BrokenText[0] = Text; for (u32 q = 0; q < Text.size(); ++q) { BrokenText[0] [q] = PasswordChar; } } txtLine = &BrokenText[0]; startPos = 0; } else { txtLine = ml ? &BrokenText[i] : &Text; startPos = ml ? BrokenTextPositions[i] : 0; } // draw normal text font->draw(txtLine->c_str(), CurrentTextRect, OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT), false, true, &localClipRect); // draw mark and marked text if (focus && MarkBegin != MarkEnd && i >= hlineStart && i < hlineStart + hlineCount) { s32 mbegin = 0, mend = 0; s32 lineStartPos = 0, lineEndPos = txtLine->size(); if (i == hlineStart) { // highlight start is on this line s = txtLine->subString(0, realmbgn - startPos); mbegin = font->getDimension(s.c_str()).Width; // deal with kerning mbegin += font->getKerningWidth( &((*txtLine)[realmbgn - startPos]), realmbgn - startPos > 0 ? &((*txtLine)[realmbgn - startPos - 1]) : 0); lineStartPos = realmbgn - startPos; } if (i == hlineStart + hlineCount - 1) { // highlight end is on this line s2 = txtLine->subString(0, realmend - startPos); mend = font->getDimension(s2.c_str()).Width; lineEndPos = (s32)s2.size(); } else mend = font->getDimension(txtLine->c_str()).Width; CurrentTextRect.UpperLeftCorner.X += mbegin; CurrentTextRect.LowerRightCorner.X = CurrentTextRect.UpperLeftCorner.X + mend - mbegin; // draw mark skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), CurrentTextRect, &localClipRect); // draw marked text s = txtLine->subString(lineStartPos, lineEndPos - lineStartPos); if (s.size()) font->draw(s.c_str(), CurrentTextRect, OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_HIGH_LIGHT_TEXT), false, true, &localClipRect); } } // Return the override color information to its previous settings. OverrideColorEnabled = prevOver; OverrideColor = prevColor; } // draw cursor if ( IsEnabled ) { if (WordWrap || MultiLine) { cursorLine = getLineFromPos(CursorPos); txtLine = &BrokenText[cursorLine]; startPos = BrokenTextPositions[cursorLine]; } s = txtLine->subString(0,CursorPos-startPos); charcursorpos = font->getDimension(s.c_str()).Width + font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0); if (focus && (os::Timer::getTime() - BlinkStartTime) % 700 < 350) { setTextRect(cursorLine); CurrentTextRect.UpperLeftCorner.X += charcursorpos; font->draw(L"_", CurrentTextRect, OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT), false, true, &localClipRect); } } } // draw children IGUIElement::draw(); } //! Sets the new caption of this element. void CGUIEditBox::setText(const wchar_t* text) { Text = text; if (u32(CursorPos) > Text.size()) CursorPos = Text.size(); HScrollPos = 0; breakText(); } //! Enables or disables automatic scrolling with cursor position //! \param enable: If set to true, the text will move around with the cursor position void CGUIEditBox::setAutoScroll(bool enable) { AutoScroll = enable; } //! Checks to see if automatic scrolling is enabled //! \return true if automatic scrolling is enabled, false if not bool CGUIEditBox::isAutoScrollEnabled() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return AutoScroll; } //! Gets the area of the text in the edit box //! \return Returns the size in pixels of the text core::dimension2du CGUIEditBox::getTextDimension() { core::rect ret; setTextRect(0); ret = CurrentTextRect; for (u32 i=1; i < BrokenText.size(); ++i) { setTextRect(i); ret.addInternalPoint(CurrentTextRect.UpperLeftCorner); ret.addInternalPoint(CurrentTextRect.LowerRightCorner); } return core::dimension2du(ret.getSize()); } //! Sets the maximum amount of characters which may be entered in the box. //! \param max: Maximum amount of characters. If 0, the character amount is //! infinity. void CGUIEditBox::setMax(u32 max) { Max = max; if (Text.size() > Max && Max != 0) Text = Text.subString(0, Max); } //! Returns maximum amount of characters, previously set by setMax(); u32 CGUIEditBox::getMax() const { return Max; } bool CGUIEditBox::processMouse(const SEvent& event) { switch(event.MouseInput.Event) { case irr::EMIE_LMOUSE_LEFT_UP: if (Environment->hasFocus(this)) { CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); if (MouseMarking) { setTextMarkers( MarkBegin, CursorPos ); } MouseMarking = false; calculateScrollPos(); return true; } break; case irr::EMIE_MOUSE_MOVED: { if (MouseMarking) { CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); setTextMarkers( MarkBegin, CursorPos ); calculateScrollPos(); return true; } } break; case EMIE_LMOUSE_PRESSED_DOWN: if (!Environment->hasFocus(this)) { BlinkStartTime = os::Timer::getTime(); MouseMarking = true; CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); setTextMarkers(CursorPos, CursorPos ); calculateScrollPos(); return true; } else { if (!AbsoluteClippingRect.isPointInside( core::position2d(event.MouseInput.X, event.MouseInput.Y))) { return false; } else { // move cursor CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); s32 newMarkBegin = MarkBegin; if (!MouseMarking) newMarkBegin = CursorPos; MouseMarking = true; setTextMarkers( newMarkBegin, CursorPos); calculateScrollPos(); return true; } } default: break; } return false; } s32 CGUIEditBox::getCursorPos(s32 x, s32 y) { IGUIFont* font = getActiveFont(); const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1; core::stringw *txtLine=0; s32 startPos=0; x+=3; for (u32 i=0; i < lineCount; ++i) { setTextRect(i); if (i == 0 && y < CurrentTextRect.UpperLeftCorner.Y) y = CurrentTextRect.UpperLeftCorner.Y; if (i == lineCount - 1 && y > CurrentTextRect.LowerRightCorner.Y ) y = CurrentTextRect.LowerRightCorner.Y; // is it inside this region? if (y >= CurrentTextRect.UpperLeftCorner.Y && y <= CurrentTextRect.LowerRightCorner.Y) { // we've found the clicked line txtLine = (WordWrap || MultiLine) ? &BrokenText[i] : &Text; startPos = (WordWrap || MultiLine) ? BrokenTextPositions[i] : 0; break; } } if (x < CurrentTextRect.UpperLeftCorner.X) x = CurrentTextRect.UpperLeftCorner.X; if ( !txtLine ) return 0; s32 idx = font->getCharacterFromPos(txtLine->c_str(), x - CurrentTextRect.UpperLeftCorner.X); // click was on or left of the line if (idx != -1) return idx + startPos; // click was off the right edge of the line, go to end. return txtLine->size() + startPos; } //! Breaks the single text line. void CGUIEditBox::breakText() { if ((!WordWrap && !MultiLine)) return; BrokenText.clear(); // need to reallocate :/ BrokenTextPositions.set_used(0); IGUIFont* font = getActiveFont(); if (!font) return; LastBreakFont = font; core::stringw line; core::stringw word; core::stringw whitespace; s32 lastLineStart = 0; s32 size = Text.size(); s32 length = 0; s32 elWidth = RelativeRect.getWidth() - 6; wchar_t c; for (s32 i=0; i i ) --CursorPos; } } else if (c == L'\n') // Unix breaks { lineBreak = true; c = 0; } // don't break if we're not a multi-line edit box if (!MultiLine) lineBreak = false; if (c == L' ' || c == 0 || i == (size-1)) { // here comes the next whitespace, look if // we can break the last word to the next line // We also break whitespace, otherwise cursor would vanish beside the right border. s32 whitelgth = font->getDimension(whitespace.c_str()).Width; s32 worldlgth = font->getDimension(word.c_str()).Width; if (WordWrap && length + worldlgth + whitelgth > elWidth && line.size() > 0) { // break to next line length = worldlgth; BrokenText.push_back(line); BrokenTextPositions.push_back(lastLineStart); lastLineStart = i - (s32)word.size(); line = word; } else { // add word to line line += whitespace; line += word; length += whitelgth + worldlgth; } word = L""; whitespace = L""; if ( c ) whitespace += c; // compute line break if (lineBreak) { line += whitespace; line += word; BrokenText.push_back(line); BrokenTextPositions.push_back(lastLineStart); lastLineStart = i+1; line = L""; word = L""; whitespace = L""; length = 0; } } else { // yippee this is a word.. word += c; } } line += whitespace; line += word; BrokenText.push_back(line); BrokenTextPositions.push_back(lastLineStart); } // TODO: that function does interpret VAlign according to line-index (indexed line is placed on top-center-bottom) // but HAlign according to line-width (pixels) and not by row. // Intuitively I suppose HAlign handling is better as VScrollPos should handle the line-scrolling. // But please no one change this without also rewriting (and this time fucking testing!!!) autoscrolling (I noticed this when fixing the old autoscrolling). void CGUIEditBox::setTextRect(s32 line) { if ( line < 0 ) return; IGUIFont* font = getActiveFont(); if (!font) return; core::dimension2du d; // get text dimension const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1; if (WordWrap || MultiLine) { d = font->getDimension(BrokenText[line].c_str()); } else { d = font->getDimension(Text.c_str()); d.Height = AbsoluteRect.getHeight(); } d.Height += font->getKerningHeight(); // justification switch (HAlign) { case EGUIA_CENTER: // align to h centre CurrentTextRect.UpperLeftCorner.X = (FrameRect.getWidth()/2) - (d.Width/2); CurrentTextRect.LowerRightCorner.X = (FrameRect.getWidth()/2) + (d.Width/2); break; case EGUIA_LOWERRIGHT: // align to right edge CurrentTextRect.UpperLeftCorner.X = FrameRect.getWidth() - d.Width; CurrentTextRect.LowerRightCorner.X = FrameRect.getWidth(); break; default: // align to left edge CurrentTextRect.UpperLeftCorner.X = 0; CurrentTextRect.LowerRightCorner.X = d.Width; } switch (VAlign) { case EGUIA_CENTER: // align to v centre CurrentTextRect.UpperLeftCorner.Y = (FrameRect.getHeight()/2) - (lineCount*d.Height)/2 + d.Height*line; break; case EGUIA_LOWERRIGHT: // align to bottom edge CurrentTextRect.UpperLeftCorner.Y = FrameRect.getHeight() - lineCount*d.Height + d.Height*line; break; default: // align to top edge CurrentTextRect.UpperLeftCorner.Y = d.Height*line; break; } CurrentTextRect.UpperLeftCorner.X -= HScrollPos; CurrentTextRect.LowerRightCorner.X -= HScrollPos; CurrentTextRect.UpperLeftCorner.Y -= VScrollPos; CurrentTextRect.LowerRightCorner.Y = CurrentTextRect.UpperLeftCorner.Y + d.Height; CurrentTextRect += FrameRect.UpperLeftCorner; } s32 CGUIEditBox::getLineFromPos(s32 pos) { if (!WordWrap && !MultiLine) return 0; s32 i=0; while (i < (s32)BrokenTextPositions.size()) { if (BrokenTextPositions[i] > pos) return i-1; ++i; } return (s32)BrokenTextPositions.size() - 1; } void CGUIEditBox::inputChar(wchar_t c) { if (!isEnabled()) return; if (c != 0) { if (Text.size() < Max || Max == 0) { core::stringw s; if (MarkBegin != MarkEnd) { // replace marked text const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; s = Text.subString(0, realmbgn); s.append(c); s.append( Text.subString(realmend, Text.size()-realmend) ); Text = s; CursorPos = realmbgn+1; } else { // add new character s = Text.subString(0, CursorPos); s.append(c); s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); Text = s; ++CursorPos; } BlinkStartTime = os::Timer::getTime(); setTextMarkers(0, 0); } } breakText(); calculateScrollPos(); sendGuiEvent(EGET_EDITBOX_CHANGED); } // calculate autoscroll void CGUIEditBox::calculateScrollPos() { if (!AutoScroll) return; IGUISkin* skin = Environment->getSkin(); if (!skin) return; IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont(); if (!font) return; s32 cursLine = getLineFromPos(CursorPos); if ( cursLine < 0 ) return; setTextRect(cursLine); const bool hasBrokenText = MultiLine || WordWrap; // Check horizonal scrolling // NOTE: Calculations different to vertical scrolling because setTextRect interprets VAlign relative to line but HAlign not relative to row { // get cursor position IGUIFont* font = getActiveFont(); if (!font) return; // get cursor area irr::u32 cursorWidth = font->getDimension(L"_").Width; core::stringw *txtLine = hasBrokenText ? &BrokenText[cursLine] : &Text; s32 cPos = hasBrokenText ? CursorPos - BrokenTextPositions[cursLine] : CursorPos; // column s32 cStart = font->getDimension(txtLine->subString(0, cPos).c_str()).Width; // pixels from text-start s32 cEnd = cStart + cursorWidth; s32 txtWidth = font->getDimension(txtLine->c_str()).Width; if ( txtWidth < FrameRect.getWidth() ) { // TODO: Needs a clean left and right gap removal depending on HAlign, similar to vertical scrolling tests for top/bottom. // This check just fixes the case where it was most noticable (text smaller than clipping area). HScrollPos = 0; setTextRect(cursLine); } if ( CurrentTextRect.UpperLeftCorner.X+cStart < FrameRect.UpperLeftCorner.X ) { // cursor to the left of the clipping area HScrollPos -= FrameRect.UpperLeftCorner.X-(CurrentTextRect.UpperLeftCorner.X+cStart); setTextRect(cursLine); // TODO: should show more characters to the left when we're scrolling left // and the cursor reaches the border. } else if ( CurrentTextRect.UpperLeftCorner.X+cEnd > FrameRect.LowerRightCorner.X) { // cursor to the right of the clipping area HScrollPos += (CurrentTextRect.UpperLeftCorner.X+cEnd)-FrameRect.LowerRightCorner.X; setTextRect(cursLine); } } // calculate vertical scrolling if (hasBrokenText) { irr::u32 lineHeight = font->getDimension(L"A").Height + font->getKerningHeight(); // only up to 1 line fits? if ( lineHeight >= (irr::u32)FrameRect.getHeight() ) { VScrollPos = 0; setTextRect(cursLine); s32 unscrolledPos = CurrentTextRect.UpperLeftCorner.Y; s32 pivot = FrameRect.UpperLeftCorner.Y; switch (VAlign) { case EGUIA_CENTER: pivot += FrameRect.getHeight()/2; unscrolledPos += lineHeight/2; break; case EGUIA_LOWERRIGHT: pivot += FrameRect.getHeight(); unscrolledPos += lineHeight; break; default: break; } VScrollPos = unscrolledPos-pivot; setTextRect(cursLine); } else { // First 2 checks are necessary when people delete lines setTextRect(0); if ( CurrentTextRect.UpperLeftCorner.Y > FrameRect.UpperLeftCorner.Y && VAlign != EGUIA_LOWERRIGHT) { // first line is leaving a gap on top VScrollPos = 0; } else if (VAlign != EGUIA_UPPERLEFT) { u32 lastLine = BrokenTextPositions.empty() ? 0 : BrokenTextPositions.size()-1; setTextRect(lastLine); if ( CurrentTextRect.LowerRightCorner.Y < FrameRect.LowerRightCorner.Y) { // last line is leaving a gap on bottom VScrollPos -= FrameRect.LowerRightCorner.Y-CurrentTextRect.LowerRightCorner.Y; } } setTextRect(cursLine); if ( CurrentTextRect.UpperLeftCorner.Y < FrameRect.UpperLeftCorner.Y ) { // text above valid area VScrollPos -= FrameRect.UpperLeftCorner.Y-CurrentTextRect.UpperLeftCorner.Y; setTextRect(cursLine); } else if ( CurrentTextRect.LowerRightCorner.Y > FrameRect.LowerRightCorner.Y) { // text below valid area VScrollPos += CurrentTextRect.LowerRightCorner.Y-FrameRect.LowerRightCorner.Y; setTextRect(cursLine); } } } } void CGUIEditBox::calculateFrameRect() { FrameRect = AbsoluteRect; IGUISkin *skin = 0; if (Environment) skin = Environment->getSkin(); if (Border && skin) { FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1; FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1; FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; } } //! set text markers void CGUIEditBox::setTextMarkers(s32 begin, s32 end) { if ( begin != MarkBegin || end != MarkEnd ) { MarkBegin = begin; MarkEnd = end; sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED); } } //! send some gui event to parent void CGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type) { if ( Parent ) { SEvent e; e.EventType = EET_GUI_EVENT; e.GUIEvent.Caller = this; e.GUIEvent.Element = 0; e.GUIEvent.EventType = type; Parent->OnEvent(e); } } //! Writes attributes of the element. void CGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { // IGUIEditBox::serializeAttributes(out,options); out->addBool ("Border", Border); out->addBool ("Background", Background); out->addBool ("OverrideColorEnabled", OverrideColorEnabled ); out->addColor ("OverrideColor", OverrideColor); // out->addFont("OverrideFont", OverrideFont); out->addInt ("MaxChars", Max); out->addBool ("WordWrap", WordWrap); out->addBool ("MultiLine", MultiLine); out->addBool ("AutoScroll", AutoScroll); out->addBool ("PasswordBox", PasswordBox); core::stringw ch = L" "; ch[0] = PasswordChar; out->addString("PasswordChar", ch.c_str()); out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); IGUIEditBox::serializeAttributes(out,options); } //! Reads attributes of the element void CGUIEditBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUIEditBox::deserializeAttributes(in,options); setDrawBorder( in->getAttributeAsBool("Border") ); setDrawBackground( in->getAttributeAsBool("Background") ); setOverrideColor(in->getAttributeAsColor("OverrideColor")); enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled")); setMax(in->getAttributeAsInt("MaxChars")); setWordWrap(in->getAttributeAsBool("WordWrap")); setMultiLine(in->getAttributeAsBool("MultiLine")); setAutoScroll(in->getAttributeAsBool("AutoScroll")); core::stringw ch = in->getAttributeAsStringW("PasswordChar"); if (!ch.size()) setPasswordBox(in->getAttributeAsBool("PasswordBox")); else setPasswordBox(in->getAttributeAsBool("PasswordBox"), ch[0]); setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames), (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames)); // setOverrideFont(in->getAttributeAsFont("OverrideFont")); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIContextMenu.h0000644000000000000000000001207712574354552020236 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_CONTEXT_MENU_H_INCLUDED__ #define __C_GUI_CONTEXT_MENU_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIContextMenu.h" #include "irrString.h" #include "irrArray.h" #include "IGUIFont.h" namespace irr { namespace gui { //! GUI Context menu interface. class CGUIContextMenu : public IGUIContextMenu { public: //! constructor CGUIContextMenu(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool getFocus = true, bool allowFocus = true); //! destructor virtual ~CGUIContextMenu(); //! set behavior when menus are closed virtual void setCloseHandling(ECONTEXT_MENU_CLOSE onClose); //! get current behavior when the menue will be closed virtual ECONTEXT_MENU_CLOSE getCloseHandling() const; //! Returns amount of menu items virtual u32 getItemCount() const; //! Adds a menu item. virtual u32 addItem(const wchar_t* text, s32 commandid, bool enabled, bool hasSubMenu, bool checked, bool autoChecking); //! Insert a menu item at specified position. virtual u32 insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled, bool hasSubMenu, bool checked, bool autoChecking); //! Find a item which has the given CommandId starting from given index virtual s32 findItemWithCommandId(s32 commandId, u32 idxStartSearch) const; //! Adds a separator item to the menu virtual void addSeparator(); //! Returns text of the menu item. virtual const wchar_t* getItemText(u32 idx) const; //! Sets text of the menu item. virtual void setItemText(u32 idx, const wchar_t* text); //! Returns if a menu item is enabled virtual bool isItemEnabled(u32 idx) const; //! Sets if the menu item should be enabled. virtual void setItemEnabled(u32 idx, bool enabled); //! Returns if a menu item is checked virtual bool isItemChecked(u32 idx) const; //! Sets if the menu item should be checked. virtual void setItemChecked(u32 idx, bool enabled); //! Removes a menu item virtual void removeItem(u32 idx); //! Removes all menu items virtual void removeAllItems(); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! draws the element and its children virtual void draw(); //! Returns the selected item in the menu virtual s32 getSelectedItem() const; //! Returns a pointer to the submenu of an item. //! \return Pointer to the submenu of an item. virtual IGUIContextMenu* getSubMenu(u32 idx) const; //! Sets the visible state of this element. virtual void setVisible(bool visible); //! should the element change the checked status on clicking virtual void setItemAutoChecking(u32 idx, bool autoChecking); //! does the element change the checked status on clicking virtual bool getItemAutoChecking(u32 idx) const; //! Returns command id of a menu item virtual s32 getItemCommandId(u32 idx) const; //! Sets the command id of a menu item virtual void setItemCommandId(u32 idx, s32 id); //! Adds a sub menu from an element that already exists. virtual void setSubMenu(u32 index, CGUIContextMenu* menu); //! When an eventparent is set it receives events instead of the usual parent element virtual void setEventParent(IGUIElement *parent); //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); protected: void closeAllSubMenus(); bool hasOpenSubMenu() const; struct SItem { core::stringw Text; bool IsSeparator; bool Enabled; bool Checked; bool AutoChecking; core::dimension2d Dim; s32 PosY; CGUIContextMenu* SubMenu; s32 CommandId; }; virtual void recalculateSize(); //! returns true, if an element was highlighted virtual bool highlight(const core::position2d& p, bool canOpenSubMenu); //! sends a click Returns: //! 0 if click went outside of the element, //! 1 if a valid button was clicked, //! 2 if a nonclickable element was clicked virtual u32 sendClick(const core::position2d& p); //! returns the item highlight-area virtual core::rect getHRect(const SItem& i, const core::rect& absolute) const; //! Gets drawing rect of Item virtual core::rect getRect(const SItem& i, const core::rect& absolute) const; core::array Items; core::position2d Pos; IGUIElement* EventParent; IGUIFont *LastFont; ECONTEXT_MENU_CLOSE CloseHandling; s32 HighLighted; u32 ChangeTime; bool AllowFocus; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_CONTEXT_MENU_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUIContextMenu.cpp0000644000000000000000000004737012574354552020575 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIContextMenu.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIFont.h" #include "IGUISpriteBank.h" #include "os.h" namespace irr { namespace gui { //! constructor CGUIContextMenu::CGUIContextMenu(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool getFocus, bool allowFocus) : IGUIContextMenu(environment, parent, id, rectangle), EventParent(0), LastFont(0), CloseHandling(ECMC_REMOVE), HighLighted(-1), ChangeTime(0), AllowFocus(allowFocus) { #ifdef _DEBUG setDebugName("CGUIContextMenu"); #endif Pos = rectangle.UpperLeftCorner; recalculateSize(); if (getFocus) Environment->setFocus(this); setNotClipped(true); } //! destructor CGUIContextMenu::~CGUIContextMenu() { for (u32 i=0; idrop(); if (LastFont) LastFont->drop(); } //! set behavior when menus are closed void CGUIContextMenu::setCloseHandling(ECONTEXT_MENU_CLOSE onClose) { CloseHandling = onClose; } //! get current behavior when the menue will be closed ECONTEXT_MENU_CLOSE CGUIContextMenu::getCloseHandling() const { return CloseHandling; } //! Returns amount of menu items u32 CGUIContextMenu::getItemCount() const { return Items.size(); } //! Adds a menu item. u32 CGUIContextMenu::addItem(const wchar_t* text, s32 commandId, bool enabled, bool hasSubMenu, bool checked, bool autoChecking) { return insertItem(Items.size(), text, commandId, enabled, hasSubMenu, checked, autoChecking); } //! Insert a menu item at specified position. u32 CGUIContextMenu::insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled, bool hasSubMenu, bool checked, bool autoChecking) { SItem s; s.Enabled = enabled; s.Checked = checked; s.AutoChecking = autoChecking; s.Text = text; s.IsSeparator = (text == 0); s.SubMenu = 0; s.CommandId = commandId; if (hasSubMenu) { s.SubMenu = new CGUIContextMenu(Environment, this, commandId, core::rect(0,0,100,100), false, false); s.SubMenu->setVisible(false); } u32 result = idx; if ( idx < Items.size() ) { Items.insert(s, idx); } else { Items.push_back(s); result = Items.size() - 1; } recalculateSize(); return result; } s32 CGUIContextMenu::findItemWithCommandId(s32 commandId, u32 idxStartSearch) const { for ( u32 i=idxStartSearch; i= Items.size()) return; if (menu) menu->grab(); if (Items[index].SubMenu) Items[index].SubMenu->drop(); Items[index].SubMenu = menu; menu->setVisible(false); if (Items[index].SubMenu) { menu->AllowFocus = false; if ( Environment->getFocus() == menu ) { Environment->setFocus( this ); } } recalculateSize(); } //! Adds a separator item to the menu void CGUIContextMenu::addSeparator() { addItem(0, -1, true, false, false, false); } //! Returns text of the menu item. const wchar_t* CGUIContextMenu::getItemText(u32 idx) const { if (idx >= Items.size()) return 0; return Items[idx].Text.c_str(); } //! Sets text of the menu item. void CGUIContextMenu::setItemText(u32 idx, const wchar_t* text) { if (idx >= Items.size()) return; Items[idx].Text = text; recalculateSize(); } //! should the element change the checked status on clicking void CGUIContextMenu::setItemAutoChecking(u32 idx, bool autoChecking) { if ( idx >= Items.size()) return; Items[idx].AutoChecking = autoChecking; } //! does the element change the checked status on clicking bool CGUIContextMenu::getItemAutoChecking(u32 idx) const { if (idx >= Items.size()) return false; return Items[idx].AutoChecking; } //! Returns if a menu item is enabled bool CGUIContextMenu::isItemEnabled(u32 idx) const { if (idx >= Items.size()) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Items[idx].Enabled; } //! Returns if a menu item is checked bool CGUIContextMenu::isItemChecked(u32 idx) const { if (idx >= Items.size()) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Items[idx].Checked; } //! Sets if the menu item should be enabled. void CGUIContextMenu::setItemEnabled(u32 idx, bool enabled) { if (idx >= Items.size()) return; Items[idx].Enabled = enabled; } //! Sets if the menu item should be checked. void CGUIContextMenu::setItemChecked(u32 idx, bool checked ) { if (idx >= Items.size()) return; Items[idx].Checked = checked; } //! Removes a menu item void CGUIContextMenu::removeItem(u32 idx) { if (idx >= Items.size()) return; if (Items[idx].SubMenu) { Items[idx].SubMenu->drop(); Items[idx].SubMenu = 0; } Items.erase(idx); recalculateSize(); } //! Removes all menu items void CGUIContextMenu::removeAllItems() { for (u32 i=0; idrop(); Items.clear(); recalculateSize(); } //! called if an event happened. bool CGUIContextMenu::OnEvent(const SEvent& event) { if (isEnabled()) { switch(event.EventType) { case EET_GUI_EVENT: switch(event.GUIEvent.EventType) { case EGET_ELEMENT_FOCUS_LOST: if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element) && AllowFocus) { // set event parent of submenus IGUIElement * p = EventParent ? EventParent : Parent; setEventParent(p); SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_ELEMENT_CLOSED; if ( !p->OnEvent(event) ) { if ( CloseHandling & ECMC_HIDE ) { setVisible(false); } if ( CloseHandling & ECMC_REMOVE ) { remove(); } } return false; } break; case EGET_ELEMENT_FOCUSED: if (event.GUIEvent.Caller == this && !AllowFocus) { return true; } break; default: break; } break; case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) { case EMIE_LMOUSE_LEFT_UP: { // menu might be removed if it loses focus in sendClick, so grab a reference grab(); const u32 t = sendClick(core::position2d(event.MouseInput.X, event.MouseInput.Y)); if ((t==0 || t==1) && Environment->hasFocus(this)) Environment->removeFocus(this); drop(); } return true; case EMIE_LMOUSE_PRESSED_DOWN: return true; case EMIE_MOUSE_MOVED: if (Environment->hasFocus(this)) highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), true); return true; default: break; } break; default: break; } } return IGUIElement::OnEvent(event); } //! Sets the visible state of this element. void CGUIContextMenu::setVisible(bool visible) { HighLighted = -1; ChangeTime = os::Timer::getTime(); for (u32 j=0; jsetVisible(false); IGUIElement::setVisible(visible); } //! sends a click Returns: //! 0 if click went outside of the element, //! 1 if a valid button was clicked, //! 2 if a nonclickable element was clicked u32 CGUIContextMenu::sendClick(const core::position2d& p) { u32 t = 0; // get number of open submenu s32 openmenu = -1; s32 j; for (j=0; j<(s32)Items.size(); ++j) if (Items[j].SubMenu && Items[j].SubMenu->isVisible()) { openmenu = j; break; } // delegate click operation to submenu if (openmenu != -1) { t = Items[j].SubMenu->sendClick(p); if (t != 0) return t; // clicked something } // check click on myself if (isPointInside(p) && (u32)HighLighted < Items.size()) { if (!Items[HighLighted].Enabled || Items[HighLighted].IsSeparator || Items[HighLighted].SubMenu) return 2; if ( Items[HighLighted].AutoChecking ) { Items[HighLighted].Checked = Items[HighLighted].Checked ? false : true; } SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_MENU_ITEM_SELECTED; if (EventParent) EventParent->OnEvent(event); else if (Parent) Parent->OnEvent(event); return 1; } return 0; } //! returns true, if an element was highligted bool CGUIContextMenu::highlight(const core::position2d& p, bool canOpenSubMenu) { if (!isEnabled()) { return false; } // get number of open submenu s32 openmenu = -1; s32 i; for (i=0; i<(s32)Items.size(); ++i) if (Items[i].Enabled && Items[i].SubMenu && Items[i].SubMenu->isVisible()) { openmenu = i; break; } // delegate highlight operation to submenu if (openmenu != -1) { if (Items[openmenu].Enabled && Items[openmenu].SubMenu->highlight(p, canOpenSubMenu)) { HighLighted = openmenu; ChangeTime = os::Timer::getTime(); return true; } } // highlight myself for (i=0; i<(s32)Items.size(); ++i) { if (Items[i].Enabled && getHRect(Items[i], AbsoluteRect).isPointInside(p)) { HighLighted = i; ChangeTime = os::Timer::getTime(); // make submenus visible/invisible for (s32 j=0; j<(s32)Items.size(); ++j) if (Items[j].SubMenu) { if ( j == i && canOpenSubMenu && Items[j].Enabled ) Items[j].SubMenu->setVisible(true); else if ( j != i ) Items[j].SubMenu->setVisible(false); } return true; } } HighLighted = openmenu; return false; } //! returns the item highlight-area core::rect CGUIContextMenu::getHRect(const SItem& i, const core::rect& absolute) const { core::rect r = absolute; r.UpperLeftCorner.Y += i.PosY; r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height; return r; } //! Gets drawing rect of Item core::rect CGUIContextMenu::getRect(const SItem& i, const core::rect& absolute) const { core::rect r = absolute; r.UpperLeftCorner.Y += i.PosY; r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height; r.UpperLeftCorner.X += 20; return r; } //! draws the element and its children void CGUIContextMenu::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); if (!skin) return; IGUIFont* font = skin->getFont(EGDF_MENU); if (font != LastFont) { if (LastFont) LastFont->drop(); LastFont = font; if (LastFont) LastFont->grab(); recalculateSize(); } IGUISpriteBank* sprites = skin->getSpriteBank(); core::rect rect = AbsoluteRect; core::rect* clip = 0; // draw frame skin->draw3DMenuPane(this, AbsoluteRect, clip); // loop through all menu items rect = AbsoluteRect; s32 y = AbsoluteRect.UpperLeftCorner.Y; for (s32 i=0; i<(s32)Items.size(); ++i) { if (Items[i].IsSeparator) { // draw separator rect = AbsoluteRect; rect.UpperLeftCorner.Y += Items[i].PosY + 3; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1; rect.UpperLeftCorner.X += 5; rect.LowerRightCorner.X -= 5; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), rect, clip); rect.LowerRightCorner.Y += 1; rect.UpperLeftCorner.Y += 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), rect, clip); y += 10; } else { rect = getRect(Items[i], AbsoluteRect); // draw highlighted if (i == HighLighted && Items[i].Enabled) { core::rect r = AbsoluteRect; r.LowerRightCorner.Y = rect.LowerRightCorner.Y; r.UpperLeftCorner.Y = rect.UpperLeftCorner.Y; r.LowerRightCorner.X -= 5; r.UpperLeftCorner.X += 5; skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), r, clip); } // draw text EGUI_DEFAULT_COLOR c = EGDC_BUTTON_TEXT; if (i == HighLighted) c = EGDC_HIGH_LIGHT_TEXT; if (!Items[i].Enabled) c = EGDC_GRAY_TEXT; if (font) font->draw(Items[i].Text.c_str(), rect, skin->getColor(c), false, true, clip); // draw submenu symbol if (Items[i].SubMenu && sprites) { core::rect r = rect; r.UpperLeftCorner.X = r.LowerRightCorner.X - 15; sprites->draw2DSprite(skin->getIcon(EGDI_CURSOR_RIGHT), r.getCenter(), clip, skin->getColor(c), (i == HighLighted) ? ChangeTime : 0, (i == HighLighted) ? os::Timer::getTime() : 0, (i == HighLighted), true); } // draw checked symbol if (Items[i].Checked && sprites) { core::rect r = rect; r.LowerRightCorner.X = r.UpperLeftCorner.X - 15; r.UpperLeftCorner.X = r.LowerRightCorner.X + 15; sprites->draw2DSprite(skin->getIcon(EGDI_CHECK_BOX_CHECKED), r.getCenter(), clip, skin->getColor(c), (i == HighLighted) ? ChangeTime : 0, (i == HighLighted) ? os::Timer::getTime() : 0, (i == HighLighted), true); } } } IGUIElement::draw(); } void CGUIContextMenu::recalculateSize() { IGUIFont* font = Environment->getSkin()->getFont(EGDF_MENU); if (!font) return; core::rect rect; rect.UpperLeftCorner = RelativeRect.UpperLeftCorner; u32 width = 100; u32 height = 3; u32 i; for (i=0; igetDimension(Items[i].Text.c_str()); Items[i].Dim.Width += 40; if (Items[i].Dim.Width > width) width = Items[i].Dim.Width; } Items[i].PosY = height; height += Items[i].Dim.Height; } height += 5; if (height < 10) height = 10; rect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + width; rect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + height; setRelativePosition(rect); // recalculate submenus for (i=0; igetAbsolutePosition().getWidth(); const s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight(); core::rect subRect(width-5, Items[i].PosY, width+w-5, Items[i].PosY+h); // if it would be drawn beyond the right border, then add it to the left side gui::IGUIElement * root = Environment->getRootGUIElement(); if ( root ) { core::rect rectRoot( root->getAbsolutePosition() ); if ( getAbsolutePosition().UpperLeftCorner.X+subRect.LowerRightCorner.X > rectRoot.LowerRightCorner.X ) { subRect.UpperLeftCorner.X = -w; subRect.LowerRightCorner.X = 0; } } Items[i].SubMenu->setRelativePosition(subRect); } } } //! Returns the selected item in the menu s32 CGUIContextMenu::getSelectedItem() const { return HighLighted; } //! \return Returns a pointer to the submenu of an item. IGUIContextMenu* CGUIContextMenu::getSubMenu(u32 idx) const { if (idx >= Items.size()) return 0; return Items[idx].SubMenu; } //! Returns command id of a menu item s32 CGUIContextMenu::getItemCommandId(u32 idx) const { if (idx >= Items.size()) return -1; return Items[idx].CommandId; } //! Sets the command id of a menu item void CGUIContextMenu::setItemCommandId(u32 idx, s32 id) { if (idx >= Items.size()) return; Items[idx].CommandId = id; } //! Writes attributes of the element. void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUIElement::serializeAttributes(out,options); out->addPosition2d("Position", Pos); if (Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) { const IGUIContextMenu* const ptr = (const IGUIContextMenu*)Parent; // find the position of this item in its parent's list u32 i; // VC6 needs the cast for this for (i=0; (igetItemCount()) && (ptr->getSubMenu(i) != (const IGUIContextMenu*)this); ++i) ; // do nothing out->addInt("ParentItem", i); } out->addInt("CloseHandling", (s32)CloseHandling); // write out the item list out->addInt("ItemCount", Items.size()); core::stringc tmp; for (u32 i=0; i < Items.size(); ++i) { tmp = "IsSeparator"; tmp += i; out->addBool(tmp.c_str(), Items[i].IsSeparator); if (!Items[i].IsSeparator) { tmp = "Text"; tmp += i; out->addString(tmp.c_str(), Items[i].Text.c_str()); tmp = "CommandID"; tmp += i; out->addInt(tmp.c_str(), Items[i].CommandId); tmp = "Enabled"; tmp += i; out->addBool(tmp.c_str(), Items[i].Enabled); tmp = "Checked"; tmp += i; out->addBool(tmp.c_str(), Items[i].Checked); tmp = "AutoChecking"; tmp += i; out->addBool(tmp.c_str(), Items[i].AutoChecking); } } } //! Reads attributes of the element void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUIElement::deserializeAttributes(in,options); Pos = in->getAttributeAsPosition2d("Position"); // link to this item's parent if (Parent && ( Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) ) ((CGUIContextMenu*)Parent)->setSubMenu(in->getAttributeAsInt("ParentItem"),this); CloseHandling = (ECONTEXT_MENU_CLOSE)in->getAttributeAsInt("CloseHandling"); removeAllItems(); // read the item list const s32 count = in->getAttributeAsInt("ItemCount"); for (s32 i=0; iexistsAttribute(tmp.c_str()) && in->getAttributeAsBool(tmp.c_str()) ) addSeparator(); else { tmp = "Text"; tmp += i; if ( in->existsAttribute(tmp.c_str()) ) txt = in->getAttributeAsStringW(tmp.c_str()); tmp = "CommandID"; tmp += i; if ( in->existsAttribute(tmp.c_str()) ) commandid = in->getAttributeAsInt(tmp.c_str()); tmp = "Enabled"; tmp += i; if ( in->existsAttribute(tmp.c_str()) ) enabled = in->getAttributeAsBool(tmp.c_str()); tmp = "Checked"; tmp += i; if ( in->existsAttribute(tmp.c_str()) ) checked = in->getAttributeAsBool(tmp.c_str()); tmp = "AutoChecking"; tmp += i; if ( in->existsAttribute(tmp.c_str()) ) autochecking = in->getAttributeAsBool(tmp.c_str()); addItem(core::stringw(txt.c_str()).c_str(), commandid, enabled, false, checked, autochecking); } } recalculateSize(); } // because sometimes the element has no parent at click time void CGUIContextMenu::setEventParent(IGUIElement *parent) { EventParent = parent; for (u32 i=0; isetEventParent(parent); } bool CGUIContextMenu::hasOpenSubMenu() const { for (u32 i=0; iisVisible()) return true; return false; } void CGUIContextMenu::closeAllSubMenus() { for (u32 i=0; isetVisible(false); //HighLighted = -1; } } // end namespace } // end namespace #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIComboBox.h0000644000000000000000000000615512574354552017475 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_COMBO_BOX_H_INCLUDED__ #define __C_GUI_COMBO_BOX_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIComboBox.h" #include "IGUIStaticText.h" #include "irrString.h" #include "irrArray.h" namespace irr { namespace gui { class IGUIButton; class IGUIListBox; //! Single line edit box for editing simple text. class CGUIComboBox : public IGUIComboBox { public: //! constructor CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle); //! Returns amount of items in box virtual u32 getItemCount() const; //! returns string of an item. the idx may be a value from 0 to itemCount-1 virtual const wchar_t* getItem(u32 idx) const; //! Returns item data of an item. the idx may be a value from 0 to itemCount-1 virtual u32 getItemData(u32 idx) const; //! Returns index based on item data virtual s32 getIndexForItemData( u32 data ) const; //! adds an item and returns the index of it virtual u32 addItem(const wchar_t* text, u32 data); //! Removes an item from the combo box. virtual void removeItem(u32 id); //! deletes all items in the combo box virtual void clear(); //! returns the text of the currently selected item virtual const wchar_t* getText() const; //! returns id of selected item. returns -1 if no item is selected. virtual s32 getSelected() const; //! sets the selected item. Set this to -1 if no item should be selected virtual void setSelected(s32 idx); //! sets the text alignment of the text part virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical); //! Set the maximal number of rows for the selection listbox virtual void setMaxSelectionRows(u32 max); //! Get the maximimal number of rows for the selection listbox virtual u32 getMaxSelectionRows() const; //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! draws the element and its children virtual void draw(); //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: void openCloseMenu(); void sendSelectionChangedEvent(); IGUIButton* ListButton; IGUIStaticText* SelectedText; IGUIListBox* ListBox; IGUIElement *LastFocus; struct SComboData { SComboData ( const wchar_t * text, u32 data ) : Name (text), Data ( data ) {} core::stringw Name; u32 Data; }; core::array< SComboData > Items; s32 Selected; EGUI_ALIGNMENT HAlign, VAlign; u32 MaxSelectionRows; bool HasFocus; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_COMBO_BOX_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUIComboBox.cpp0000644000000000000000000003071512574354552020027 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIComboBox.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IGUIFont.h" #include "IGUIButton.h" #include "CGUIListBox.h" #include "os.h" namespace irr { namespace gui { //! constructor CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIComboBox(environment, parent, id, rectangle), ListButton(0), SelectedText(0), ListBox(0), LastFocus(0), Selected(-1), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), MaxSelectionRows(5), HasFocus(false) { #ifdef _DEBUG setDebugName("CGUIComboBox"); #endif IGUISkin* skin = Environment->getSkin(); s32 width = 15; if (skin) width = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); core::rect r; r.UpperLeftCorner.X = rectangle.getWidth() - width - 2; r.LowerRightCorner.X = rectangle.getWidth() - 2; r.UpperLeftCorner.Y = 2; r.LowerRightCorner.Y = rectangle.getHeight() - 2; ListButton = Environment->addButton(r, this, -1, L""); if (skin && skin->getSpriteBank()) { ListButton->setSpriteBank(skin->getSpriteBank()); ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL)); ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL)); } ListButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); ListButton->setSubElement(true); ListButton->setTabStop(false); r.UpperLeftCorner.X = 2; r.UpperLeftCorner.Y = 2; r.LowerRightCorner.X = RelativeRect.getWidth() - (ListButton->getAbsolutePosition().getWidth() + 2); r.LowerRightCorner.Y = RelativeRect.getHeight() - 2; SelectedText = Environment->addStaticText(L"", r, false, false, this, -1, false); SelectedText->setSubElement(true); SelectedText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); SelectedText->setTextAlignment(EGUIA_UPPERLEFT, EGUIA_CENTER); if (skin) SelectedText->setOverrideColor(skin->getColor(EGDC_BUTTON_TEXT)); SelectedText->enableOverrideColor(true); // this element can be tabbed to setTabStop(true); setTabOrder(-1); } void CGUIComboBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) { HAlign = horizontal; VAlign = vertical; SelectedText->setTextAlignment(horizontal, vertical); } //! Set the maximal number of rows for the selection listbox void CGUIComboBox::setMaxSelectionRows(u32 max) { MaxSelectionRows = max; // force recalculation of open listbox if (ListBox) { openCloseMenu(); openCloseMenu(); } } //! Get the maximimal number of rows for the selection listbox u32 CGUIComboBox::getMaxSelectionRows() const { return MaxSelectionRows; } //! Returns amount of items in box u32 CGUIComboBox::getItemCount() const { return Items.size(); } //! returns string of an item. the idx may be a value from 0 to itemCount-1 const wchar_t* CGUIComboBox::getItem(u32 idx) const { if (idx >= Items.size()) return 0; return Items[idx].Name.c_str(); } //! returns string of an item. the idx may be a value from 0 to itemCount-1 u32 CGUIComboBox::getItemData(u32 idx) const { if (idx >= Items.size()) return 0; return Items[idx].Data; } //! Returns index based on item data s32 CGUIComboBox::getIndexForItemData(u32 data ) const { for ( u32 i = 0; i < Items.size (); ++i ) { if ( Items[i].Data == data ) return i; } return -1; } //! Removes an item from the combo box. void CGUIComboBox::removeItem(u32 idx) { if (idx >= Items.size()) return; if (Selected == (s32)idx) setSelected(-1); Items.erase(idx); } //! Returns caption of this element. const wchar_t* CGUIComboBox::getText() const { return getItem(Selected); } //! adds an item and returns the index of it u32 CGUIComboBox::addItem(const wchar_t* text, u32 data) { Items.push_back( SComboData ( text, data ) ); if (Selected == -1) setSelected(0); return Items.size() - 1; } //! deletes all items in the combo box void CGUIComboBox::clear() { Items.clear(); setSelected(-1); } //! returns id of selected item. returns -1 if no item is selected. s32 CGUIComboBox::getSelected() const { return Selected; } //! sets the selected item. Set this to -1 if no item should be selected void CGUIComboBox::setSelected(s32 idx) { if (idx < -1 || idx >= (s32)Items.size()) return; Selected = idx; if (Selected == -1) SelectedText->setText(L""); else SelectedText->setText(Items[Selected].Name.c_str()); } //! called if an event happened. bool CGUIComboBox::OnEvent(const SEvent& event) { if (isEnabled()) { switch(event.EventType) { case EET_KEY_INPUT_EVENT: if (ListBox && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE) { // hide list box openCloseMenu(); return true; } else if (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE) { if (!event.KeyInput.PressedDown) { openCloseMenu(); } ListButton->setPressed(ListBox == 0); return true; } else if (event.KeyInput.PressedDown) { s32 oldSelected = Selected; bool absorb = true; switch (event.KeyInput.Key) { case KEY_DOWN: setSelected(Selected+1); break; case KEY_UP: setSelected(Selected-1); break; case KEY_HOME: case KEY_PRIOR: setSelected(0); break; case KEY_END: case KEY_NEXT: setSelected((s32)Items.size()-1); break; default: absorb = false; } if (Selected <0) setSelected(0); if (Selected >= (s32)Items.size()) setSelected((s32)Items.size() -1); if (Selected != oldSelected) { sendSelectionChangedEvent(); return true; } if (absorb) return true; } break; case EET_GUI_EVENT: switch(event.GUIEvent.EventType) { case EGET_ELEMENT_FOCUS_LOST: if (ListBox && (Environment->hasFocus(ListBox) || ListBox->isMyChild(event.GUIEvent.Caller) ) && event.GUIEvent.Element != this && !isMyChild(event.GUIEvent.Element) && !ListBox->isMyChild(event.GUIEvent.Element)) { openCloseMenu(); } break; case EGET_BUTTON_CLICKED: if (event.GUIEvent.Caller == ListButton) { openCloseMenu(); return true; } break; case EGET_LISTBOX_SELECTED_AGAIN: case EGET_LISTBOX_CHANGED: if (event.GUIEvent.Caller == ListBox) { setSelected(ListBox->getSelected()); if (Selected <0 || Selected >= (s32)Items.size()) setSelected(-1); openCloseMenu(); sendSelectionChangedEvent(); } return true; default: break; } break; case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: { core::position2d p(event.MouseInput.X, event.MouseInput.Y); // send to list box if (ListBox && ListBox->isPointInside(p) && ListBox->OnEvent(event)) return true; return true; } case EMIE_LMOUSE_LEFT_UP: { core::position2d p(event.MouseInput.X, event.MouseInput.Y); // send to list box if (!(ListBox && ListBox->getAbsolutePosition().isPointInside(p) && ListBox->OnEvent(event))) { openCloseMenu(); } return true; } case EMIE_MOUSE_WHEEL: { s32 oldSelected = Selected; setSelected( Selected + ((event.MouseInput.Wheel < 0) ? 1 : -1)); if (Selected <0) setSelected(0); if (Selected >= (s32)Items.size()) setSelected((s32)Items.size() -1); if (Selected != oldSelected) { sendSelectionChangedEvent(); return true; } } default: break; } break; default: break; } } return IGUIElement::OnEvent(event); } void CGUIComboBox::sendSelectionChangedEvent() { if (Parent) { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_COMBO_BOX_CHANGED; Parent->OnEvent(event); } } //! draws the element and its children void CGUIComboBox::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); IGUIElement *currentFocus = Environment->getFocus(); if (currentFocus != LastFocus) { HasFocus = currentFocus == this || isMyChild(currentFocus); LastFocus = currentFocus; } // set colors each time as skin-colors can be changed SelectedText->setBackgroundColor(skin->getColor(EGDC_HIGH_LIGHT)); if(isEnabled()) { SelectedText->setDrawBackground(HasFocus); SelectedText->setOverrideColor(skin->getColor(HasFocus ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT)); } else { SelectedText->setDrawBackground(false); SelectedText->setOverrideColor(skin->getColor(EGDC_GRAY_TEXT)); } ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL)); ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL)); core::rect frameRect(AbsoluteRect); // draw the border skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT), true, true, frameRect, &AbsoluteClippingRect); // draw children IGUIElement::draw(); } void CGUIComboBox::openCloseMenu() { if (ListBox) { // close list box Environment->setFocus(this); ListBox->remove(); ListBox = 0; } else { if (Parent) Parent->bringToFront(this); IGUISkin* skin = Environment->getSkin(); u32 h = Items.size(); if (h > getMaxSelectionRows()) h = getMaxSelectionRows(); if (h == 0) h = 1; IGUIFont* font = skin->getFont(); if (font) h *= (font->getDimension(L"A").Height + 4); // open list box core::rect r(0, AbsoluteRect.getHeight(), AbsoluteRect.getWidth(), AbsoluteRect.getHeight() + h); ListBox = new CGUIListBox(Environment, this, -1, r, false, true, true); ListBox->setSubElement(true); ListBox->setNotClipped(true); ListBox->drop(); // ensure that list box is always completely visible if (ListBox->getAbsolutePosition().LowerRightCorner.Y > Environment->getRootGUIElement()->getAbsolutePosition().getHeight()) ListBox->setRelativePosition( core::rect(0, -ListBox->getAbsolutePosition().getHeight(), AbsoluteRect.getWidth(), 0) ); for (s32 i=0; i<(s32)Items.size(); ++i) ListBox->addItem(Items[i].Name.c_str()); ListBox->setSelected(Selected); // set focus Environment->setFocus(ListBox); } } //! Writes attributes of the element. void CGUIComboBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUIComboBox::serializeAttributes(out,options); out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); out->addInt("MaxSelectionRows", (s32)MaxSelectionRows ); out->addInt ("Selected", Selected ); out->addInt ("ItemCount", Items.size()); for (u32 i=0; i < Items.size(); ++i) { core::stringc s = "Item"; s += i; s += "Text"; out->addString(s.c_str(), Items[i].Name.c_str()); } } //! Reads attributes of the element void CGUIComboBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUIComboBox::deserializeAttributes(in,options); setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames), (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames)); setMaxSelectionRows( (u32)(in->getAttributeAsInt("MaxSelectionRows")) ); // clear the list clear(); // get item count u32 c = in->getAttributeAsInt("ItemCount"); // add items for (u32 i=0; i < c; ++i) { core::stringc s = "Item"; s += i; s += "Text"; addItem(in->getAttributeAsStringW(s.c_str()).c_str(), 0); } setSelected(in->getAttributeAsInt("Selected")); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIColorSelectDialog.h0000644000000000000000000000335012574354552021315 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__ #define __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIColorSelectDialog.h" #include "IGUIButton.h" #include "IGUISpinBox.h" #include "IGUIImage.h" #include "irrArray.h" namespace irr { namespace gui { class CGUIColorSelectDialog : public IGUIColorSelectDialog { public: //! constructor CGUIColorSelectDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id); //! destructor virtual ~CGUIColorSelectDialog(); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! draws the element and its children virtual void draw(); virtual video::SColor getColor(); virtual video::SColorHSL getColorHSL(); private: //! sends the event that the file has been selected. void sendSelectedEvent(); //! sends the event that the file choose process has been canceld void sendCancelEvent(); core::position2d DragStart; bool Dragging; IGUIButton* CloseButton; IGUIButton* OKButton; IGUIButton* CancelButton; core::array Battery; struct SColorCircle { IGUIImage * Control; video::ITexture * Texture; }; SColorCircle ColorRing; void buildColorRing( const core::dimension2d & dim, s32 supersample, const video::SColor& borderColor ); }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUIColorSelectDialog.cpp0000644000000000000000000003277412574354552021664 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIColorSelectDialog.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIButton.h" #include "IGUIStaticText.h" #include "IGUIFont.h" #include "IGUISpriteBank.h" #include "IFileList.h" #include "os.h" #include "fast_atof.h" namespace irr { namespace gui { const s32 CSD_WIDTH = 350; const s32 CSD_HEIGHT = 300; namespace { struct subElementPredefines { const wchar_t *pre; const wchar_t *init; const wchar_t *post; int x, y; int range_down ,range_up; }; static const subElementPredefines Template [] = { { L"A:", L"0", 0,50,165, 0, 255 }, { L"R:", L"0", 0,20,205, 0, 255 }, { L"G:", L"0", 0,20,230, 0, 255 }, { L"B:", L"0", 0,20,255, 0, 255 }, { L"H:", L"0", L"°",80,205, 0, 360 }, { L"S:", L"0", L"%",80,230, 0, 100 }, { L"L:", L"0", L"%",80,255, 0, 100 }, }; } //! constructor CGUIColorSelectDialog::CGUIColorSelectDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id) : IGUIColorSelectDialog(environment, parent, id, core::rect((parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2, (parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2, (parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2+CSD_WIDTH, (parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2+CSD_HEIGHT)), Dragging(false) { #ifdef _DEBUG IGUIElement::setDebugName("CGUIColorSelectDialog"); #endif Text = title; IGUISkin* skin = Environment->getSkin(); const s32 buttonw = environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH); const s32 posx = RelativeRect.getWidth() - buttonw - 4; CloseButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close"); if (skin && skin->getSpriteBank()) { CloseButton->setSpriteBank(skin->getSpriteBank()); CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL)); CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL)); } CloseButton->setSubElement(true); CloseButton->setTabStop(false); CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); CloseButton->grab(); OKButton = Environment->addButton( core::rect(RelativeRect.getWidth()-80, 30, RelativeRect.getWidth()-10, 50), this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK"); OKButton->setSubElement(true); OKButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); OKButton->grab(); CancelButton = Environment->addButton( core::rect(RelativeRect.getWidth()-80, 55, RelativeRect.getWidth()-10, 75), this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel"); CancelButton->setSubElement(true); CancelButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); CancelButton->grab(); video::IVideoDriver* driver = Environment->getVideoDriver(); ColorRing.Texture = driver->getTexture ( "#colorring" ); if ( 0 == ColorRing.Texture ) { buildColorRing(core::dimension2d(128, 128), 1, Environment->getSkin()->getColor(EGDC_3D_SHADOW)); } core::rect r(20,20, 0,0); ColorRing.Control = Environment->addImage(ColorRing.Texture, r.UpperLeftCorner, true, this); ColorRing.Control->setSubElement(true); ColorRing.Control->grab(); for ( u32 i = 0; i != sizeof (Template) / sizeof ( subElementPredefines ); ++i ) { if ( Template[i].pre ) { r.UpperLeftCorner.X = Template[i].x; r.UpperLeftCorner.Y = Template[i].y; r.LowerRightCorner.X = r.UpperLeftCorner.X + 15; r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20; IGUIElement *t = Environment->addStaticText(Template[i].pre, r, false, false, this); t->setSubElement(true); } if ( Template[i].post ) { r.UpperLeftCorner.X = Template[i].x + 56; r.UpperLeftCorner.Y = Template[i].y; r.LowerRightCorner.X = r.UpperLeftCorner.X + 15; r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20; IGUIElement *t = Environment->addStaticText( Template[i].post, r, false, false, this); t->setSubElement(true); } r.UpperLeftCorner.X = Template[i].x + 15; r.UpperLeftCorner.Y = Template[i].y-2; r.LowerRightCorner.X = r.UpperLeftCorner.X + 40; r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20; gui::IGUISpinBox* spin = Environment->addSpinBox( Template[i].init, r, true, this); spin->setSubElement(true); spin->setDecimalPlaces(0); spin->setRange((f32)Template[i].range_down, (f32)Template[i].range_up); spin->grab(); Battery.push_back(spin); } bringToFront(CancelButton); bringToFront(OKButton); } //! destructor CGUIColorSelectDialog::~CGUIColorSelectDialog() { if (CloseButton) CloseButton->drop(); if (OKButton) OKButton->drop(); if (CancelButton) CancelButton->drop(); for (u32 i = 0; i != Battery.size(); ++i) Battery[i]->drop(); if (ColorRing.Control) ColorRing.Control->drop(); } //! renders a antialiased, colored ring void CGUIColorSelectDialog::buildColorRing( const core::dimension2d & dim, s32 supersample, const video::SColor& borderColor ) { const core::dimension2d d(dim.Width * supersample, dim.Height * supersample); video::IVideoDriver* driver = Environment->getVideoDriver(); video::IImage *RawTexture = driver->createImage(video::ECF_A8R8G8B8, d); RawTexture->fill ( 0x00808080 ); const s32 radiusOut = ( d.Width / 2 ) - 4; const s32 fullR2 = radiusOut * radiusOut; video::SColorf rgb(0,0,0); video::SColorHSL hsl; hsl.Luminance = 50; hsl.Saturation = 100; core::position2d p; for ( p.Y = -radiusOut; p.Y <= radiusOut; p.Y += 1 ) { s32 y2 = p.Y * p.Y; for (p.X = -radiusOut; p.X <= radiusOut; p.X += 1) { s32 r2 = y2 + ( p.X * p.X ); // test point in circle s32 testa = r2 - fullR2; if ( testa < 0 ) { // dotproduct u ( x,y ) * v ( 1, 0 ) = cosinus(a) const f32 r = sqrtf((f32) r2); // normalize, dotproduct = xnorm const f32 xn = r == 0.f ? 0.f : -p.X * core::reciprocal(r); hsl.Hue = acosf(xn)*core::RADTODEG; if ( p.Y > 0 ) hsl.Hue = 360 - hsl.Hue; hsl.Hue -= 90; const f32 rTest = r / radiusOut; #if 0 if (rTest < 0.33f) { // luminance from 0 to 50 hsl.Luminance = 50*(rTest/0.33); hsl.Saturation = 0.f; hsl.toRGB(rgb); } else if ( rTest < 0.66f ) { // saturation from 0 to 100 hsl.Saturation = 100*(( rTest - 0.33f ) / 0.33f); hsl.Luminance = 50; hsl.toRGB(rgb); } else { // luminance from 50 to 100 hsl.Luminance = 100*(0.5f + ( ( rTest - 0.66f ) / .66f )); hsl.Saturation = 100; hsl.toRGB(rgb); } // borders should be slightly transparent if ( rTest >= 0.95f ) rgb.a = (1.f-rTest)*20; else rgb.a=1.f; #else if ( rTest > 0.5f ) { hsl.Saturation = 100; hsl.Luminance = 50; hsl.toRGB(rgb); } // borders should be slightly transparent if ( rTest < 0.5f ) rgb.a = 0; else if ( rTest >= 0.95f ) rgb.a = (1.f-rTest)*20; else if ( rTest <= 0.55f ) rgb.a = (rTest-0.5f)*20; else rgb.a=1.f; #endif RawTexture->setPixel(4+p.X+radiusOut, 4+p.Y+radiusOut, rgb.toSColor()); } } } RawTexture->unlock (); if ( supersample > 1 ) { video::IImage * filter = driver->createImage(video::ECF_A8R8G8B8, dim ); RawTexture->copyToScalingBoxFilter(filter); RawTexture->drop(); RawTexture = filter; } bool generateMipLevels = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); driver->setTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS, false); ColorRing.Texture = driver->addTexture ( "#colorring", RawTexture); RawTexture->drop(); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, generateMipLevels); } //! called if an event happened. bool CGUIColorSelectDialog::OnEvent(const SEvent& event) { if (isEnabled()) { switch(event.EventType) { case EET_GUI_EVENT: switch(event.GUIEvent.EventType) { case EGET_SPINBOX_CHANGED: { for ( u32 i = 0; i!= Battery.size (); ++i ) { if ( event.GUIEvent.Caller == Battery[i] ) { if (i<4) { video::SColor rgb((u32)Battery[0]->getValue(), (u32)Battery[1]->getValue(), (u32)Battery[2]->getValue(), (u32)Battery[3]->getValue()); video::SColorHSL hsl; video::SColorf rgb2(rgb); hsl.fromRGB(rgb2); Battery[4]->setValue(hsl.Hue); Battery[5]->setValue(hsl.Saturation); Battery[6]->setValue(hsl.Luminance); } else { video::SColorHSL hsl(Battery[4]->getValue(), Battery[5]->getValue(), Battery[6]->getValue()); video::SColorf rgb2; hsl.toRGB(rgb2); video::SColor rgb = rgb2.toSColor(); Battery[1]->setValue((f32)rgb.getRed()); Battery[2]->setValue((f32)rgb.getGreen()); Battery[3]->setValue((f32)rgb.getBlue()); } } } return true; } case EGET_ELEMENT_FOCUS_LOST: Dragging = false; break; case EGET_BUTTON_CLICKED: if (event.GUIEvent.Caller == CloseButton || event.GUIEvent.Caller == CancelButton) { sendCancelEvent(); remove(); return true; } else if (event.GUIEvent.Caller == OKButton) { sendSelectedEvent(); remove(); return true; } break; case EGET_LISTBOX_CHANGED: case EGET_LISTBOX_SELECTED_AGAIN: default: break; } break; case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; Dragging = true; Environment->setFocus(this); return true; case EMIE_LMOUSE_LEFT_UP: Dragging = false; Environment->removeFocus(this); return true; case EMIE_MOUSE_MOVED: if (Dragging) { // gui window should not be dragged outside its parent if (Parent) if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 || event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 || event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 || event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1) return true; move(core::position2d(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y)); DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; return true; } default: break; } default: break; } } return IGUIElement::OnEvent(event); } //! draws the element and its children void CGUIColorSelectDialog::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); core::rect rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER), AbsoluteRect, &AbsoluteClippingRect); if (Text.size()) { rect.UpperLeftCorner.X += 2; rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5; IGUIFont* font = skin->getFont(EGDF_WINDOW); if (font) font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true, &AbsoluteClippingRect); } IGUIElement::draw(); // draw color selector after the window elements core::vector2di pos(ColorRing.Control->getAbsolutePosition().UpperLeftCorner); pos.X += ColorRing.Texture->getOriginalSize().Width/2; pos.Y += ColorRing.Texture->getOriginalSize().Height/2; #if 0 const f32 h = Battery[4]->getValue(); const f32 s = Battery[5]->getValue(); const f32 l = Battery[6]->getValue(); const f32 factor = 58.f*(((s==0)&&(l<50))?(l*0.33f/50):( (s<100)?((.33f+(s*0.33f/100))):((0.66f+(l-50)*0.33f/50)))); #else const f32 factor = 44; #endif pos.X += core::round32(sinf(Battery[4]->getValue()*core::DEGTORAD)*factor); pos.Y -= core::round32(cosf(Battery[4]->getValue()*core::DEGTORAD)*factor); Environment->getVideoDriver()->draw2DPolygon(pos, 4, 0xffffffff, 4); } video::SColor CGUIColorSelectDialog::getColor() { return video::SColor((u32)Battery[0]->getValue(), (u32)Battery[1]->getValue(), (u32)Battery[2]->getValue(), (u32)Battery[3]->getValue()); } video::SColorHSL CGUIColorSelectDialog::getColorHSL() { return video::SColorHSL(Battery[4]->getValue(), Battery[5]->getValue(), Battery[6]->getValue()); } //! sends the event that the file has been selected. void CGUIColorSelectDialog::sendSelectedEvent() { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_FILE_SELECTED; Parent->OnEvent(event); } //! sends the event that the file choose process has been canceld void CGUIColorSelectDialog::sendCancelEvent() { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED; Parent->OnEvent(event); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUICheckBox.h0000644000000000000000000000253012574354552017444 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_CHECKBOX_H_INCLUDED__ #define __C_GUI_CHECKBOX_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUICheckBox.h" namespace irr { namespace gui { class CGUICheckBox : public IGUICheckBox { public: //! constructor CGUICheckBox(bool checked, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle); //! set if box is checked virtual void setChecked(bool checked); //! returns if box is checked virtual bool isChecked() const; //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! draws the element and its children virtual void draw(); //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: u32 checkTime; bool Pressed; bool Checked; }; } // end namespace gui } // end namespace irr #endif // __C_GUI_CHECKBOX_H_INCLUDED__ #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUICheckBox.cpp0000644000000000000000000001162612574354552020005 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUICheckBox.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIFont.h" #include "os.h" namespace irr { namespace gui { //! constructor CGUICheckBox::CGUICheckBox(bool checked, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUICheckBox(environment, parent, id, rectangle), checkTime(0), Pressed(false), Checked(checked) { #ifdef _DEBUG setDebugName("CGUICheckBox"); #endif // this element can be tabbed into setTabStop(true); setTabOrder(-1); } //! called if an event happened. bool CGUICheckBox::OnEvent(const SEvent& event) { if (isEnabled()) { switch(event.EventType) { case EET_KEY_INPUT_EVENT: if (event.KeyInput.PressedDown && (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) { Pressed = true; return true; } else if (Pressed && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE) { Pressed = false; return true; } else if (!event.KeyInput.PressedDown && Pressed && (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) { Pressed = false; if (Parent) { SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; newEvent.GUIEvent.Element = 0; Checked = !Checked; newEvent.GUIEvent.EventType = EGET_CHECKBOX_CHANGED; Parent->OnEvent(newEvent); } return true; } break; case EET_GUI_EVENT: if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) { if (event.GUIEvent.Caller == this) Pressed = false; } break; case EET_MOUSE_INPUT_EVENT: if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { Pressed = true; checkTime = os::Timer::getTime(); Environment->setFocus(this); return true; } else if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) { bool wasPressed = Pressed; Environment->removeFocus(this); Pressed = false; if (wasPressed && Parent) { if ( !AbsoluteClippingRect.isPointInside( core::position2d(event.MouseInput.X, event.MouseInput.Y) ) ) { Pressed = false; return true; } SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; newEvent.GUIEvent.Element = 0; Checked = !Checked; newEvent.GUIEvent.EventType = EGET_CHECKBOX_CHANGED; Parent->OnEvent(newEvent); } return true; } break; default: break; } } return IGUIElement::OnEvent(event); } //! draws the element and its children void CGUICheckBox::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); if (skin) { const s32 height = skin->getSize(EGDS_CHECK_BOX_WIDTH); core::rect checkRect(AbsoluteRect.UpperLeftCorner.X, ((AbsoluteRect.getHeight() - height) / 2) + AbsoluteRect.UpperLeftCorner.Y, 0, 0); checkRect.LowerRightCorner.X = checkRect.UpperLeftCorner.X + height; checkRect.LowerRightCorner.Y = checkRect.UpperLeftCorner.Y + height; EGUI_DEFAULT_COLOR col = EGDC_GRAY_EDITABLE; if ( isEnabled() ) col = Pressed ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE; skin->draw3DSunkenPane(this, skin->getColor(col), false, true, checkRect, &AbsoluteClippingRect); if (Checked) { skin->drawIcon(this, EGDI_CHECK_BOX_CHECKED, checkRect.getCenter(), checkTime, os::Timer::getTime(), false, &AbsoluteClippingRect); } if (Text.size()) { checkRect = AbsoluteRect; checkRect.UpperLeftCorner.X += height + 5; IGUIFont* font = skin->getFont(); if (font) { font->draw(Text.c_str(), checkRect, skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), false, true, &AbsoluteClippingRect); } } } IGUIElement::draw(); } //! set if box is checked void CGUICheckBox::setChecked(bool checked) { Checked = checked; } //! returns if box is checked bool CGUICheckBox::isChecked() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Checked; } //! Writes attributes of the element. void CGUICheckBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUICheckBox::serializeAttributes(out,options); out->addBool("Checked", Checked); } //! Reads attributes of the element void CGUICheckBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { Checked = in->getAttributeAsBool ("Checked"); IGUICheckBox::deserializeAttributes(in,options); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGUIButton.h0000644000000000000000000001073512574354552017237 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GUI_BUTTON_H_INCLUDED__ #define __C_GUI_BUTTON_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUIButton.h" #include "IGUISpriteBank.h" #include "SColor.h" namespace irr { namespace gui { class CGUIButton : public IGUIButton { public: //! constructor CGUIButton(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool noclip=false); //! destructor virtual ~CGUIButton(); //! called if an event happened. virtual bool OnEvent(const SEvent& event); //! draws the element and its children virtual void draw(); //! sets another skin independent font. if this is set to zero, the button uses the font of the skin. virtual void setOverrideFont(IGUIFont* font=0); //! Gets the override font (if any) virtual IGUIFont* getOverrideFont() const; //! Get the font which is used right now for drawing virtual IGUIFont* getActiveFont() const; //! Sets an image which should be displayed on the button when it is in normal state. virtual void setImage(video::ITexture* image=0); //! Sets an image which should be displayed on the button when it is in normal state. virtual void setImage(video::ITexture* image, const core::rect& pos); //! Sets an image which should be displayed on the button when it is in pressed state. virtual void setPressedImage(video::ITexture* image=0); //! Sets an image which should be displayed on the button when it is in pressed state. virtual void setPressedImage(video::ITexture* image, const core::rect& pos); //! Sets the sprite bank used by the button virtual void setSpriteBank(IGUISpriteBank* bank=0); //! Sets the animated sprite for a specific button state /** \param index: Number of the sprite within the sprite bank, use -1 for no sprite \param state: State of the button to set the sprite for \param index: The sprite number from the current sprite bank \param color: The color of the sprite */ virtual void setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color=video::SColor(255,255,255,255), bool loop=false); //! Sets if the button should behave like a push button. Which means it //! can be in two states: Normal or Pressed. With a click on the button, //! the user can change the state of the button. virtual void setIsPushButton(bool isPushButton=true); //! Checks whether the button is a push button virtual bool isPushButton() const; //! Sets the pressed state of the button if this is a pushbutton virtual void setPressed(bool pressed=true); //! Returns if the button is currently pressed virtual bool isPressed() const; //! Sets if the button should use the skin to draw its border virtual void setDrawBorder(bool border=true); //! Checks if the button face and border are being drawn virtual bool isDrawingBorder() const; //! Sets if the alpha channel should be used for drawing images on the button (default is false) virtual void setUseAlphaChannel(bool useAlphaChannel=true); //! Checks if the alpha channel should be used for drawing images on the button virtual bool isAlphaChannelUsed() const; //! Sets if the button should scale the button images to fit virtual void setScaleImage(bool scaleImage=true); //! Checks whether the button scales the used images virtual bool isScalingImage() const; //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: struct ButtonSprite { s32 Index; video::SColor Color; bool Loop; }; ButtonSprite ButtonSprites[EGBS_COUNT]; IGUISpriteBank* SpriteBank; IGUIFont* OverrideFont; video::ITexture* Image; video::ITexture* PressedImage; core::rect ImageRect; core::rect PressedImageRect; u32 ClickTime, HoverTime, FocusTime; bool IsPushButton; bool Pressed; bool UseAlphaChannel; bool DrawBorder; bool ScaleImage; }; } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif // __C_GUI_BUTTON_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CGUIButton.cpp0000644000000000000000000003173312574354552017573 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIButton.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIFont.h" #include "os.h" namespace irr { namespace gui { //! constructor CGUIButton::CGUIButton(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool noclip) : IGUIButton(environment, parent, id, rectangle), SpriteBank(0), OverrideFont(0), Image(0), PressedImage(0), ClickTime(0), HoverTime(0), FocusTime(0), IsPushButton(false), Pressed(false), UseAlphaChannel(false), DrawBorder(true), ScaleImage(false) { #ifdef _DEBUG setDebugName("CGUIButton"); #endif setNotClipped(noclip); // Initialize the sprites. for (u32 i=0; idrop(); if (Image) Image->drop(); if (PressedImage) PressedImage->drop(); if (SpriteBank) SpriteBank->drop(); } //! Sets if the images should be scaled to fit the button void CGUIButton::setScaleImage(bool scaleImage) { ScaleImage = scaleImage; } //! Returns whether the button scale the used images bool CGUIButton::isScalingImage() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ScaleImage; } //! Sets if the button should use the skin to draw its border void CGUIButton::setDrawBorder(bool border) { DrawBorder = border; } void CGUIButton::setSpriteBank(IGUISpriteBank* sprites) { if (sprites) sprites->grab(); if (SpriteBank) SpriteBank->drop(); SpriteBank = sprites; } void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop) { if (SpriteBank) { ButtonSprites[(u32)state].Index = index; ButtonSprites[(u32)state].Color = color; ButtonSprites[(u32)state].Loop = loop; } else { ButtonSprites[(u32)state].Index = -1; } } //! called if an event happened. bool CGUIButton::OnEvent(const SEvent& event) { if (!isEnabled()) return IGUIElement::OnEvent(event); switch(event.EventType) { case EET_KEY_INPUT_EVENT: if (event.KeyInput.PressedDown && (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) { if (!IsPushButton) setPressed(true); else setPressed(!Pressed); return true; } if (Pressed && !IsPushButton && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE) { setPressed(false); return true; } else if (!event.KeyInput.PressedDown && Pressed && (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)) { if (!IsPushButton) setPressed(false); if (Parent) { SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; newEvent.GUIEvent.Element = 0; newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED; Parent->OnEvent(newEvent); } return true; } break; case EET_GUI_EVENT: if (event.GUIEvent.Caller == this) { if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) { if (!IsPushButton) setPressed(false); FocusTime = os::Timer::getTime(); } else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED) { FocusTime = os::Timer::getTime(); } else if (event.GUIEvent.EventType == EGET_ELEMENT_HOVERED || event.GUIEvent.EventType == EGET_ELEMENT_LEFT) { HoverTime = os::Timer::getTime(); } } break; case EET_MOUSE_INPUT_EVENT: if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { if (Environment->hasFocus(this) && !AbsoluteClippingRect.isPointInside(core::position2d(event.MouseInput.X, event.MouseInput.Y))) { Environment->removeFocus(this); return false; } if (!IsPushButton) setPressed(true); Environment->setFocus(this); return true; } else if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) { bool wasPressed = Pressed; if ( !AbsoluteClippingRect.isPointInside( core::position2d(event.MouseInput.X, event.MouseInput.Y ) ) ) { if (!IsPushButton) setPressed(false); return true; } if (!IsPushButton) setPressed(false); else { setPressed(!Pressed); } if ((!IsPushButton && wasPressed && Parent) || (IsPushButton && wasPressed != Pressed)) { SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; newEvent.GUIEvent.Element = 0; newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED; Parent->OnEvent(newEvent); } return true; } break; default: break; } return Parent ? Parent->OnEvent(event) : false; } //! draws the element and its children void CGUIButton::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); video::IVideoDriver* driver = Environment->getVideoDriver(); // todo: move sprite up and text down if the pressed state has a sprite const core::position2di spritePos = AbsoluteRect.getCenter(); if (!Pressed) { if (DrawBorder) skin->draw3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect); if (Image) { core::position2d pos = spritePos; pos.X -= ImageRect.getWidth() / 2; pos.Y -= ImageRect.getHeight() / 2; driver->draw2DImage(Image, ScaleImage? AbsoluteRect : core::recti(pos, ImageRect.getSize()), ImageRect, &AbsoluteClippingRect, 0, UseAlphaChannel); } } else { if (DrawBorder) skin->draw3DButtonPanePressed(this, AbsoluteRect, &AbsoluteClippingRect); if (PressedImage) { core::position2d pos = spritePos; pos.X -= PressedImageRect.getWidth() / 2; pos.Y -= PressedImageRect.getHeight() / 2; if (Image == PressedImage && PressedImageRect == ImageRect) { pos.X += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X); pos.Y += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y); } driver->draw2DImage(PressedImage, ScaleImage? AbsoluteRect : core::recti(pos, PressedImageRect.getSize()), PressedImageRect, &AbsoluteClippingRect, 0, UseAlphaChannel); } } if (SpriteBank) { // pressed / unpressed animation u32 state = Pressed ? (u32)EGBS_BUTTON_DOWN : (u32)EGBS_BUTTON_UP; if (ButtonSprites[state].Index != -1) { SpriteBank->draw2DSprite(ButtonSprites[state].Index, spritePos, &AbsoluteClippingRect, ButtonSprites[state].Color, ClickTime, os::Timer::getTime(), ButtonSprites[state].Loop, true); } // focused / unfocused animation state = Environment->hasFocus(this) ? (u32)EGBS_BUTTON_FOCUSED : (u32)EGBS_BUTTON_NOT_FOCUSED; if (ButtonSprites[state].Index != -1) { SpriteBank->draw2DSprite(ButtonSprites[state].Index, spritePos, &AbsoluteClippingRect, ButtonSprites[state].Color, FocusTime, os::Timer::getTime(), ButtonSprites[state].Loop, true); } // mouse over / off animation if (isEnabled()) { state = Environment->getHovered() == this ? (u32)EGBS_BUTTON_MOUSE_OVER : (u32)EGBS_BUTTON_MOUSE_OFF; if (ButtonSprites[state].Index != -1) { SpriteBank->draw2DSprite(ButtonSprites[state].Index, spritePos, &AbsoluteClippingRect, ButtonSprites[state].Color, HoverTime, os::Timer::getTime(), ButtonSprites[state].Loop, true); } } } if (Text.size()) { IGUIFont* font = getActiveFont(); core::rect rect = AbsoluteRect; if (Pressed) { rect.UpperLeftCorner.X += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_X); rect.UpperLeftCorner.Y += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y); } if (font) font->draw(Text.c_str(), rect, skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), true, true, &AbsoluteClippingRect); } IGUIElement::draw(); } //! sets another skin independent font. if this is set to zero, the button uses the font of the skin. void CGUIButton::setOverrideFont(IGUIFont* font) { if (OverrideFont == font) return; if (OverrideFont) OverrideFont->drop(); OverrideFont = font; if (OverrideFont) OverrideFont->grab(); } //! Gets the override font (if any) IGUIFont * CGUIButton::getOverrideFont() const { return OverrideFont; } //! Get the font which is used right now for drawing IGUIFont* CGUIButton::getActiveFont() const { if ( OverrideFont ) return OverrideFont; IGUISkin* skin = Environment->getSkin(); if (skin) return skin->getFont(EGDF_BUTTON); return 0; } //! Sets an image which should be displayed on the button when it is in normal state. void CGUIButton::setImage(video::ITexture* image) { if (image) image->grab(); if (Image) Image->drop(); Image = image; if (image) ImageRect = core::rect(core::position2d(0,0), image->getOriginalSize()); if (!PressedImage) setPressedImage(Image); } //! Sets the image which should be displayed on the button when it is in its normal state. void CGUIButton::setImage(video::ITexture* image, const core::rect& pos) { setImage(image); ImageRect = pos; } //! Sets an image which should be displayed on the button when it is in pressed state. void CGUIButton::setPressedImage(video::ITexture* image) { if (image) image->grab(); if (PressedImage) PressedImage->drop(); PressedImage = image; if (image) PressedImageRect = core::rect(core::position2d(0,0), image->getOriginalSize()); } //! Sets the image which should be displayed on the button when it is in its pressed state. void CGUIButton::setPressedImage(video::ITexture* image, const core::rect& pos) { setPressedImage(image); PressedImageRect = pos; } //! Sets if the button should behave like a push button. Which means it //! can be in two states: Normal or Pressed. With a click on the button, //! the user can change the state of the button. void CGUIButton::setIsPushButton(bool isPushButton) { IsPushButton = isPushButton; } //! Returns if the button is currently pressed bool CGUIButton::isPressed() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Pressed; } //! Sets the pressed state of the button if this is a pushbutton void CGUIButton::setPressed(bool pressed) { if (Pressed != pressed) { ClickTime = os::Timer::getTime(); Pressed = pressed; } } //! Returns whether the button is a push button bool CGUIButton::isPushButton() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return IsPushButton; } //! Sets if the alpha channel should be used for drawing images on the button (default is false) void CGUIButton::setUseAlphaChannel(bool useAlphaChannel) { UseAlphaChannel = useAlphaChannel; } //! Returns if the alpha channel should be used for drawing images on the button bool CGUIButton::isAlphaChannelUsed() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return UseAlphaChannel; } bool CGUIButton::isDrawingBorder() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return DrawBorder; } //! Writes attributes of the element. void CGUIButton::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { IGUIButton::serializeAttributes(out,options); out->addBool ("PushButton", IsPushButton ); if (IsPushButton) out->addBool("Pressed", Pressed); out->addTexture ("Image", Image); out->addRect ("ImageRect", ImageRect); out->addTexture ("PressedImage", PressedImage); out->addRect ("PressedImageRect", PressedImageRect); out->addBool ("UseAlphaChannel", isAlphaChannelUsed()); out->addBool ("Border", isDrawingBorder()); out->addBool ("ScaleImage", isScalingImage()); // out->addString ("OverrideFont", OverrideFont); } //! Reads attributes of the element void CGUIButton::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { IGUIButton::deserializeAttributes(in,options); IsPushButton = in->getAttributeAsBool("PushButton"); Pressed = IsPushButton ? in->getAttributeAsBool("Pressed") : false; core::rect rec = in->getAttributeAsRect("ImageRect"); if (rec.isValid()) setImage( in->getAttributeAsTexture("Image"), rec); else setImage( in->getAttributeAsTexture("Image") ); rec = in->getAttributeAsRect("PressedImageRect"); if (rec.isValid()) setPressedImage( in->getAttributeAsTexture("PressedImage"), rec); else setPressedImage( in->getAttributeAsTexture("PressedImage") ); setDrawBorder(in->getAttributeAsBool("Border")); setUseAlphaChannel(in->getAttributeAsBool("UseAlphaChannel")); setScaleImage(in->getAttributeAsBool("ScaleImage")); // setOverrideFont(in->getAttributeAsString("OverrideFont")); updateAbsolutePosition(); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ irrlicht-1.8.3/source/Irrlicht/CGeometryCreator.h0000644000000000000000000000420112574354552020521 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_GEOMETRY_CREATOR_H_INCLUDED__ #define __C_GEOMETRY_CREATOR_H_INCLUDED__ #include "IGeometryCreator.h" #include "SMeshBuffer.h" namespace irr { namespace scene { //! class for creating geometry on the fly class CGeometryCreator : public IGeometryCreator { void addToBuffer(const video::S3DVertex& v, SMeshBuffer* Buffer) const; public: IMesh* createCubeMesh(const core::vector3df& size) const; IMesh* createHillPlaneMesh( const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material, f32 hillHeight, const core::dimension2d& countHills, const core::dimension2d& textureRepeatCount) const; IMesh* createTerrainMesh(video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize, f32 maxHeight, video::IVideoDriver* driver, const core::dimension2d& defaultVertexBlockSize, bool debugBorders=false) const; IMesh* createArrowMesh(const u32 tesselationCylinder, const u32 tesselationCone, const f32 height, const f32 cylinderHeight, const f32 width0, const f32 width1, const video::SColor vtxColor0, const video::SColor vtxColor1) const; IMesh* createSphereMesh(f32 radius, u32 polyCountX, u32 polyCountY) const; IMesh* createCylinderMesh(f32 radius, f32 length, u32 tesselation, const video::SColor& color=0xffffffff, bool closeTop=true, f32 oblique=0.f) const; IMesh* createConeMesh(f32 radius, f32 length, u32 tesselation, const video::SColor& colorTop=0xffffffff, const video::SColor& colorBottom=0xffffffff, f32 oblique=0.f) const; IMesh* createVolumeLightMesh( const u32 subdivideU=32, const u32 subdivideV=32, const video::SColor footColor=0xffffffff, const video::SColor tailColor=0xffffffff, const f32 lpDistance = 8.f, const core::vector3df& lightDim = core::vector3df(1.f,1.2f,1.f)) const; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CGeometryCreator.cpp0000644000000000000000000006535512574354552021075 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGeometryCreator.h" #include "SAnimatedMesh.h" #include "SMeshBuffer.h" #include "SMesh.h" #include "IMesh.h" #include "IVideoDriver.h" #include "os.h" namespace irr { namespace scene { IMesh* CGeometryCreator::createCubeMesh(const core::vector3df& size) const { SMeshBuffer* buffer = new SMeshBuffer(); // Create indices const u16 u[36] = { 0,2,1, 0,3,2, 1,5,4, 1,2,5, 4,6,7, 4,5,6, 7,3,0, 7,6,3, 9,5,2, 9,8,5, 0,11,10, 0,10,7}; buffer->Indices.set_used(36); for (u32 i=0; i<36; ++i) buffer->Indices[i] = u[i]; // Create vertices video::SColor clr(255,255,255,255); buffer->Vertices.reallocate(12); buffer->Vertices.push_back(video::S3DVertex(0,0,0, -1,-1,-1, clr, 0, 1)); buffer->Vertices.push_back(video::S3DVertex(1,0,0, 1,-1,-1, clr, 1, 1)); buffer->Vertices.push_back(video::S3DVertex(1,1,0, 1, 1,-1, clr, 1, 0)); buffer->Vertices.push_back(video::S3DVertex(0,1,0, -1, 1,-1, clr, 0, 0)); buffer->Vertices.push_back(video::S3DVertex(1,0,1, 1,-1, 1, clr, 0, 1)); buffer->Vertices.push_back(video::S3DVertex(1,1,1, 1, 1, 1, clr, 0, 0)); buffer->Vertices.push_back(video::S3DVertex(0,1,1, -1, 1, 1, clr, 1, 0)); buffer->Vertices.push_back(video::S3DVertex(0,0,1, -1,-1, 1, clr, 1, 1)); buffer->Vertices.push_back(video::S3DVertex(0,1,1, -1, 1, 1, clr, 0, 1)); buffer->Vertices.push_back(video::S3DVertex(0,1,0, -1, 1,-1, clr, 1, 1)); buffer->Vertices.push_back(video::S3DVertex(1,0,1, 1,-1, 1, clr, 1, 0)); buffer->Vertices.push_back(video::S3DVertex(1,0,0, 1,-1,-1, clr, 0, 0)); // Recalculate bounding box buffer->BoundingBox.reset(0,0,0); for (u32 i=0; i<12; ++i) { buffer->Vertices[i].Pos -= core::vector3df(0.5f, 0.5f, 0.5f); buffer->Vertices[i].Pos *= size; buffer->BoundingBox.addInternalPoint(buffer->Vertices[i].Pos); } SMesh* mesh = new SMesh; mesh->addMeshBuffer(buffer); buffer->drop(); mesh->recalculateBoundingBox(); return mesh; } // creates a hill plane IMesh* CGeometryCreator::createHillPlaneMesh( const core::dimension2d& tileSize, const core::dimension2d& tc, video::SMaterial* material, f32 hillHeight, const core::dimension2d& ch, const core::dimension2d& textureRepeatCount) const { core::dimension2d tileCount = tc; core::dimension2d countHills = ch; if (countHills.Width < 0.01f) countHills.Width = 1.f; if (countHills.Height < 0.01f) countHills.Height = 1.f; // center const core::position2d center((tileSize.Width * tileCount.Width) * 0.5f, (tileSize.Height * tileCount.Height) * 0.5f); // texture coord step const core::dimension2d tx( textureRepeatCount.Width / tileCount.Width, textureRepeatCount.Height / tileCount.Height); // add one more point in each direction for proper tile count ++tileCount.Height; ++tileCount.Width; SMeshBuffer* buffer = new SMeshBuffer(); video::S3DVertex vtx; vtx.Color.set(255,255,255,255); // create vertices from left-front to right-back u32 x; f32 sx=0.f, tsx=0.f; for (x=0; xVertices.push_back(vtx); sy += tileSize.Height; tsy += tx.Height; } sx += tileSize.Width; tsx += tx.Width; } // create indices for (x=0; xIndices.push_back(current); buffer->Indices.push_back(current + 1); buffer->Indices.push_back(current + tileCount.Height); buffer->Indices.push_back(current + 1); buffer->Indices.push_back(current + 1 + tileCount.Height); buffer->Indices.push_back(current + tileCount.Height); } } // recalculate normals for (u32 i=0; iIndices.size(); i+=3) { const core::vector3df normal = core::plane3d( buffer->Vertices[buffer->Indices[i+0]].Pos, buffer->Vertices[buffer->Indices[i+1]].Pos, buffer->Vertices[buffer->Indices[i+2]].Pos).Normal; buffer->Vertices[buffer->Indices[i+0]].Normal = normal; buffer->Vertices[buffer->Indices[i+1]].Normal = normal; buffer->Vertices[buffer->Indices[i+2]].Normal = normal; } if (material) buffer->Material = *material; buffer->recalculateBoundingBox(); buffer->setHardwareMappingHint(EHM_STATIC); SMesh* mesh = new SMesh(); mesh->addMeshBuffer(buffer); mesh->recalculateBoundingBox(); buffer->drop(); return mesh; } IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize, f32 maxHeight, video::IVideoDriver* driver, const core::dimension2d& maxVtxBlockSize, bool debugBorders) const { if (!texture || !heightmap) return 0; // debug border const s32 borderSkip = debugBorders ? 0 : 1; video::S3DVertex vtx; vtx.Color.set(255,255,255,255); SMesh* mesh = new SMesh(); const u32 tm = os::Timer::getRealTime()/1000; const core::dimension2d hMapSize= heightmap->getDimension(); const core::dimension2d tMapSize= texture->getDimension(); const core::position2d thRel(static_cast(tMapSize.Width) / hMapSize.Width, static_cast(tMapSize.Height) / hMapSize.Height); maxHeight /= 255.0f; // height step per color value core::position2d processed(0,0); while (processed.Y blockSize = maxVtxBlockSize; if (processed.X + blockSize.Width > hMapSize.Width) blockSize.Width = hMapSize.Width - processed.X; if (processed.Y + blockSize.Height > hMapSize.Height) blockSize.Height = hMapSize.Height - processed.Y; SMeshBuffer* buffer = new SMeshBuffer(); buffer->setHardwareMappingHint(scene::EHM_STATIC); buffer->Vertices.reallocate(blockSize.getArea()); // add vertices of vertex block u32 y; core::vector2df pos(0.f, processed.Y*stretchSize.Height); const core::vector2df bs(1.f/blockSize.Width, 1.f/blockSize.Height); core::vector2df tc(0.f, 0.5f*bs.Y); for (y=0; ygetPixel(x+processed.X, y+processed.Y).getAverage() * maxHeight; vtx.Pos.set(pos.X, height, pos.Y); vtx.TCoords.set(tc); buffer->Vertices.push_back(vtx); pos.X += stretchSize.Width; tc.X += bs.X; } pos.Y += stretchSize.Height; tc.Y += bs.Y; } buffer->Indices.reallocate((blockSize.Height-1)*(blockSize.Width-1)*6); // add indices of vertex block s32 c1 = 0; for (y=0; yIndices.push_back(c); buffer->Indices.push_back(c + blockSize.Width); buffer->Indices.push_back(c + 1); buffer->Indices.push_back(c + 1); buffer->Indices.push_back(c + blockSize.Width); buffer->Indices.push_back(c + 1 + blockSize.Width); } c1 += blockSize.Width; } // recalculate normals for (u32 i=0; iIndices.size(); i+=3) { const core::vector3df normal = core::plane3d( buffer->Vertices[buffer->Indices[i+0]].Pos, buffer->Vertices[buffer->Indices[i+1]].Pos, buffer->Vertices[buffer->Indices[i+2]].Pos).Normal; buffer->Vertices[buffer->Indices[i+0]].Normal = normal; buffer->Vertices[buffer->Indices[i+1]].Normal = normal; buffer->Vertices[buffer->Indices[i+2]].Normal = normal; } if (buffer->Vertices.size()) { c8 textureName[64]; // create texture for this block video::IImage* img = driver->createImage(texture->getColorFormat(), core::dimension2d(core::floor32(blockSize.Width*thRel.X), core::floor32(blockSize.Height*thRel.Y))); texture->copyTo(img, core::position2di(0,0), core::recti( core::position2d(core::floor32(processed.X*thRel.X), core::floor32(processed.Y*thRel.Y)), core::dimension2d(core::floor32(blockSize.Width*thRel.X), core::floor32(blockSize.Height*thRel.Y))), 0); sprintf(textureName, "terrain%u_%u", tm, mesh->getMeshBufferCount()); buffer->Material.setTexture(0, driver->addTexture(textureName, img)); if (buffer->Material.getTexture(0)) { c8 tmp[255]; sprintf(tmp, "Generated terrain texture (%dx%d): %s", buffer->Material.getTexture(0)->getSize().Width, buffer->Material.getTexture(0)->getSize().Height, textureName); os::Printer::log(tmp); } else os::Printer::log("Could not create terrain texture.", textureName, ELL_ERROR); img->drop(); } buffer->recalculateBoundingBox(); mesh->addMeshBuffer(buffer); buffer->drop(); // keep on processing processed.X += maxVtxBlockSize.Width - borderSkip; } // keep on processing processed.X = 0; processed.Y += maxVtxBlockSize.Height - borderSkip; } mesh->recalculateBoundingBox(); return mesh; } /* a cylinder, a cone and a cross point up on (0,1.f, 0.f ) */ IMesh* CGeometryCreator::createArrowMesh(const u32 tesselationCylinder, const u32 tesselationCone, const f32 height, const f32 cylinderHeight, const f32 width0, const f32 width1, const video::SColor vtxColor0, const video::SColor vtxColor1) const { SMesh* mesh = (SMesh*)createCylinderMesh(width0, cylinderHeight, tesselationCylinder, vtxColor0, false); IMesh* mesh2 = createConeMesh(width1, height-cylinderHeight, tesselationCone, vtxColor1, vtxColor0); for (u32 i=0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* buffer = mesh2->getMeshBuffer(i); for (u32 j=0; jgetVertexCount(); ++j) buffer->getPosition(j).Y += cylinderHeight; buffer->setDirty(EBT_VERTEX); buffer->recalculateBoundingBox(); mesh->addMeshBuffer(buffer); } mesh2->drop(); mesh->setHardwareMappingHint(EHM_STATIC); mesh->recalculateBoundingBox(); return mesh; } /* A sphere with proper normals and texture coords */ IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCountY) const { // thanks to Alfaz93 who made his code available for Irrlicht on which // this one is based! // we are creating the sphere mesh here. if (polyCountX < 2) polyCountX = 2; if (polyCountY < 2) polyCountY = 2; while (polyCountX * polyCountY > 32767) // prevent u16 overflow { polyCountX /= 2; polyCountY /= 2; } const u32 polyCountXPitch = polyCountX+1; // get to same vertex on next level SMeshBuffer* buffer = new SMeshBuffer(); buffer->Indices.reallocate((polyCountX * polyCountY) * 6); const video::SColor clr(255, 255,255,255); u32 level = 0; for (u32 p1 = 0; p1 < polyCountY-1; ++p1) { //main quads, top to bottom for (u32 p2 = 0; p2 < polyCountX - 1; ++p2) { const u32 curr = level + p2; buffer->Indices.push_back(curr + polyCountXPitch); buffer->Indices.push_back(curr); buffer->Indices.push_back(curr + 1); buffer->Indices.push_back(curr + polyCountXPitch); buffer->Indices.push_back(curr+1); buffer->Indices.push_back(curr + 1 + polyCountXPitch); } // the connectors from front to end buffer->Indices.push_back(level + polyCountX - 1 + polyCountXPitch); buffer->Indices.push_back(level + polyCountX - 1); buffer->Indices.push_back(level + polyCountX); buffer->Indices.push_back(level + polyCountX - 1 + polyCountXPitch); buffer->Indices.push_back(level + polyCountX); buffer->Indices.push_back(level + polyCountX + polyCountXPitch); level += polyCountXPitch; } const u32 polyCountSq = polyCountXPitch * polyCountY; // top point const u32 polyCountSq1 = polyCountSq + 1; // bottom point const u32 polyCountSqM1 = (polyCountY - 1) * polyCountXPitch; // last row's first vertex for (u32 p2 = 0; p2 < polyCountX - 1; ++p2) { // create triangles which are at the top of the sphere buffer->Indices.push_back(polyCountSq); buffer->Indices.push_back(p2 + 1); buffer->Indices.push_back(p2); // create triangles which are at the bottom of the sphere buffer->Indices.push_back(polyCountSqM1 + p2); buffer->Indices.push_back(polyCountSqM1 + p2 + 1); buffer->Indices.push_back(polyCountSq1); } // create final triangle which is at the top of the sphere buffer->Indices.push_back(polyCountSq); buffer->Indices.push_back(polyCountX); buffer->Indices.push_back(polyCountX-1); // create final triangle which is at the bottom of the sphere buffer->Indices.push_back(polyCountSqM1 + polyCountX - 1); buffer->Indices.push_back(polyCountSqM1); buffer->Indices.push_back(polyCountSq1); // calculate the angle which separates all points in a circle const f64 AngleX = 2 * core::PI / polyCountX; const f64 AngleY = core::PI / polyCountY; u32 i=0; f64 axz; // we don't start at 0. f64 ay = 0;//AngleY / 2; buffer->Vertices.set_used((polyCountXPitch * polyCountY) + 2); for (u32 y = 0; y < polyCountY; ++y) { ay += AngleY; const f64 sinay = sin(ay); axz = 0; // calculate the necessary vertices without the doubled one for (u32 xz = 0;xz < polyCountX; ++xz) { // calculate points position const core::vector3df pos(static_cast(radius * cos(axz) * sinay), static_cast(radius * cos(ay)), static_cast(radius * sin(axz) * sinay)); // for spheres the normal is the position core::vector3df normal(pos); normal.normalize(); // calculate texture coordinates via sphere mapping // tu is the same on each level, so only calculate once f32 tu = 0.5f; if (y==0) { if (normal.Y != -1.0f && normal.Y != 1.0f) tu = static_cast(acos(core::clamp(normal.X/sinay, -1.0, 1.0)) * 0.5 *core::RECIPROCAL_PI64); if (normal.Z < 0.0f) tu=1-tu; } else tu = buffer->Vertices[i-polyCountXPitch].TCoords.X; buffer->Vertices[i] = video::S3DVertex(pos.X, pos.Y, pos.Z, normal.X, normal.Y, normal.Z, clr, tu, static_cast(ay*core::RECIPROCAL_PI64)); ++i; axz += AngleX; } // This is the doubled vertex on the initial position buffer->Vertices[i] = video::S3DVertex(buffer->Vertices[i-polyCountX]); buffer->Vertices[i].TCoords.X=1.0f; ++i; } // the vertex at the top of the sphere buffer->Vertices[i] = video::S3DVertex(0.0f,radius,0.0f, 0.0f,1.0f,0.0f, clr, 0.5f, 0.0f); // the vertex at the bottom of the sphere ++i; buffer->Vertices[i] = video::S3DVertex(0.0f,-radius,0.0f, 0.0f,-1.0f,0.0f, clr, 0.5f, 1.0f); // recalculate bounding box buffer->BoundingBox.reset(buffer->Vertices[i].Pos); buffer->BoundingBox.addInternalPoint(buffer->Vertices[i-1].Pos); buffer->BoundingBox.addInternalPoint(radius,0.0f,0.0f); buffer->BoundingBox.addInternalPoint(-radius,0.0f,0.0f); buffer->BoundingBox.addInternalPoint(0.0f,0.0f,radius); buffer->BoundingBox.addInternalPoint(0.0f,0.0f,-radius); SMesh* mesh = new SMesh(); mesh->addMeshBuffer(buffer); buffer->drop(); mesh->setHardwareMappingHint(EHM_STATIC); mesh->recalculateBoundingBox(); return mesh; } /* A cylinder with proper normals and texture coords */ IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, u32 tesselation, const video::SColor& color, bool closeTop, f32 oblique) const { SMeshBuffer* buffer = new SMeshBuffer(); const f32 recTesselation = core::reciprocal((f32)tesselation); const f32 recTesselationHalf = recTesselation * 0.5f; const f32 angleStep = (core::PI * 2.f ) * recTesselation; const f32 angleStepHalf = angleStep*0.5f; u32 i; video::S3DVertex v; v.Color = color; buffer->Vertices.reallocate(tesselation*4+4+(closeTop?2:1)); buffer->Indices.reallocate((tesselation*2+1)*(closeTop?12:9)); f32 tcx = 0.f; for ( i = 0; i <= tesselation; ++i ) { const f32 angle = angleStep * i; v.Pos.X = radius * cosf(angle); v.Pos.Y = 0.f; v.Pos.Z = radius * sinf(angle); v.Normal = v.Pos; v.Normal.normalize(); v.TCoords.X=tcx; v.TCoords.Y=0.f; buffer->Vertices.push_back(v); v.Pos.X += oblique; v.Pos.Y = length; v.Normal = v.Pos; v.Normal.normalize(); v.TCoords.Y=1.f; buffer->Vertices.push_back(v); v.Pos.X = radius * cosf(angle + angleStepHalf); v.Pos.Y = 0.f; v.Pos.Z = radius * sinf(angle + angleStepHalf); v.Normal = v.Pos; v.Normal.normalize(); v.TCoords.X=tcx+recTesselationHalf; v.TCoords.Y=0.f; buffer->Vertices.push_back(v); v.Pos.X += oblique; v.Pos.Y = length; v.Normal = v.Pos; v.Normal.normalize(); v.TCoords.Y=1.f; buffer->Vertices.push_back(v); tcx += recTesselation; } // indices for the main hull part const u32 nonWrappedSize = tesselation* 4; for (i=0; i != nonWrappedSize; i += 2) { buffer->Indices.push_back(i + 2); buffer->Indices.push_back(i + 0); buffer->Indices.push_back(i + 1); buffer->Indices.push_back(i + 2); buffer->Indices.push_back(i + 1); buffer->Indices.push_back(i + 3); } // two closing quads between end and start buffer->Indices.push_back(0); buffer->Indices.push_back(i + 0); buffer->Indices.push_back(i + 1); buffer->Indices.push_back(0); buffer->Indices.push_back(i + 1); buffer->Indices.push_back(1); // close down v.Pos.X = 0.f; v.Pos.Y = 0.f; v.Pos.Z = 0.f; v.Normal.X = 0.f; v.Normal.Y = -1.f; v.Normal.Z = 0.f; v.TCoords.X = 1.f; v.TCoords.Y = 1.f; buffer->Vertices.push_back(v); u32 index = buffer->Vertices.size() - 1; for ( i = 0; i != nonWrappedSize; i += 2 ) { buffer->Indices.push_back(index); buffer->Indices.push_back(i + 0); buffer->Indices.push_back(i + 2); } buffer->Indices.push_back(index); buffer->Indices.push_back(i + 0); buffer->Indices.push_back(0); if (closeTop) { // close top v.Pos.X = oblique; v.Pos.Y = length; v.Pos.Z = 0.f; v.Normal.X = 0.f; v.Normal.Y = 1.f; v.Normal.Z = 0.f; v.TCoords.X = 0.f; v.TCoords.Y = 0.f; buffer->Vertices.push_back(v); index = buffer->Vertices.size() - 1; for ( i = 0; i != nonWrappedSize; i += 2 ) { buffer->Indices.push_back(i + 1); buffer->Indices.push_back(index); buffer->Indices.push_back(i + 3); } buffer->Indices.push_back(i + 1); buffer->Indices.push_back(index); buffer->Indices.push_back(1); } buffer->recalculateBoundingBox(); SMesh* mesh = new SMesh(); mesh->addMeshBuffer(buffer); mesh->setHardwareMappingHint(EHM_STATIC); mesh->recalculateBoundingBox(); buffer->drop(); return mesh; } /* A cone with proper normals and texture coords */ IMesh* CGeometryCreator::createConeMesh(f32 radius, f32 length, u32 tesselation, const video::SColor& colorTop, const video::SColor& colorBottom, f32 oblique) const { SMeshBuffer* buffer = new SMeshBuffer(); const f32 angleStep = (core::PI * 2.f ) / tesselation; const f32 angleStepHalf = angleStep*0.5f; video::S3DVertex v; u32 i; v.Color = colorTop; for ( i = 0; i != tesselation; ++i ) { f32 angle = angleStep * f32(i); v.Pos.X = radius * cosf(angle); v.Pos.Y = 0.f; v.Pos.Z = radius * sinf(angle); v.Normal = v.Pos; v.Normal.normalize(); buffer->Vertices.push_back(v); angle += angleStepHalf; v.Pos.X = radius * cosf(angle); v.Pos.Y = 0.f; v.Pos.Z = radius * sinf(angle); v.Normal = v.Pos; v.Normal.normalize(); buffer->Vertices.push_back(v); } const u32 nonWrappedSize = buffer->Vertices.size() - 1; // close top v.Pos.X = oblique; v.Pos.Y = length; v.Pos.Z = 0.f; v.Normal.X = 0.f; v.Normal.Y = 1.f; v.Normal.Z = 0.f; buffer->Vertices.push_back(v); u32 index = buffer->Vertices.size() - 1; for ( i = 0; i != nonWrappedSize; i += 1 ) { buffer->Indices.push_back(i + 0); buffer->Indices.push_back(index); buffer->Indices.push_back(i + 1); } buffer->Indices.push_back(i + 0); buffer->Indices.push_back(index); buffer->Indices.push_back(0); // close down v.Color = colorBottom; v.Pos.X = 0.f; v.Pos.Y = 0.f; v.Pos.Z = 0.f; v.Normal.X = 0.f; v.Normal.Y = -1.f; v.Normal.Z = 0.f; buffer->Vertices.push_back(v); index = buffer->Vertices.size() - 1; for ( i = 0; i != nonWrappedSize; i += 1 ) { buffer->Indices.push_back(index); buffer->Indices.push_back(i + 0); buffer->Indices.push_back(i + 1); } buffer->Indices.push_back(index); buffer->Indices.push_back(i + 0); buffer->Indices.push_back(0); buffer->recalculateBoundingBox(); SMesh* mesh = new SMesh(); mesh->addMeshBuffer(buffer); buffer->drop(); mesh->setHardwareMappingHint(EHM_STATIC); mesh->recalculateBoundingBox(); return mesh; } void CGeometryCreator::addToBuffer(const video::S3DVertex& v, SMeshBuffer* Buffer) const { const s32 tnidx = Buffer->Vertices.linear_reverse_search(v); const bool alreadyIn = (tnidx != -1); u16 nidx = (u16)tnidx; if (!alreadyIn) { nidx = (u16)Buffer->Vertices.size(); Buffer->Indices.push_back(nidx); Buffer->Vertices.push_back(v); } else Buffer->Indices.push_back(nidx); } IMesh* CGeometryCreator::createVolumeLightMesh( const u32 subdivideU, const u32 subdivideV, const video::SColor footColor, const video::SColor tailColor, const f32 lpDistance, const core::vector3df& lightDim) const { SMeshBuffer* Buffer = new SMeshBuffer(); Buffer->setHardwareMappingHint(EHM_STATIC); const core::vector3df lightPoint(0, -(lpDistance*lightDim.Y), 0); const f32 ax = lightDim.X * 0.5f; // X Axis const f32 az = lightDim.Z * 0.5f; // Z Axis Buffer->Vertices.clear(); Buffer->Vertices.reallocate(6+12*(subdivideU+subdivideV)); Buffer->Indices.clear(); Buffer->Indices.reallocate(6+12*(subdivideU+subdivideV)); //draw the bottom foot.. the glowing region addToBuffer(video::S3DVertex(-ax, 0, az, 0,0,0, footColor, 0, 1),Buffer); addToBuffer(video::S3DVertex( ax, 0, az, 0,0,0, footColor, 1, 1),Buffer); addToBuffer(video::S3DVertex( ax, 0,-az, 0,0,0, footColor, 1, 0),Buffer); addToBuffer(video::S3DVertex( ax, 0,-az, 0,0,0, footColor, 1, 0),Buffer); addToBuffer(video::S3DVertex(-ax, 0,-az, 0,0,0, footColor, 0, 0),Buffer); addToBuffer(video::S3DVertex(-ax, 0, az, 0,0,0, footColor, 0, 1),Buffer); f32 tu = 0.f; const f32 tuStep = 1.f/subdivideU; f32 bx = -ax; const f32 bxStep = lightDim.X * tuStep; // Slices in X/U space for (u32 i = 0; i <= subdivideU; ++i) { // These are the two endpoints for a slice at the foot core::vector3df end1(bx, 0.0f, -az); core::vector3df end2(bx, 0.0f, az); end1 -= lightPoint; // get a vector from point to lightsource end1.normalize(); // normalize vector end1 *= lightDim.Y; // multiply it out by shootlength end1.X += bx; // Add the original point location to the vector end1.Z -= az; // Do it again for the other point. end2 -= lightPoint; end2.normalize(); end2 *= lightDim.Y; end2.X += bx; end2.Z += az; addToBuffer(video::S3DVertex(bx , 0, az, 0,0,0, footColor, tu, 1),Buffer); addToBuffer(video::S3DVertex(bx , 0, -az, 0,0,0, footColor, tu, 0),Buffer); addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, tailColor, tu, 1),Buffer); addToBuffer(video::S3DVertex(bx , 0, -az, 0,0,0, footColor, tu, 0),Buffer); addToBuffer(video::S3DVertex(end1.X , end1.Y, end1.Z, 0,0,0, tailColor, tu, 0),Buffer); addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, tailColor, tu, 1),Buffer); //back side addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, tailColor, tu, 1),Buffer); addToBuffer(video::S3DVertex(-bx , 0, -az, 0,0,0, footColor, tu, 1),Buffer); addToBuffer(video::S3DVertex(-bx , 0, az, 0,0,0, footColor, tu, 0),Buffer); addToBuffer(video::S3DVertex(-bx , 0, az, 0,0,0, footColor, tu, 0),Buffer); addToBuffer(video::S3DVertex(-end1.X , end1.Y, -end1.Z, 0,0,0, tailColor, tu, 0),Buffer); addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, tailColor, tu, 1),Buffer); tu += tuStep; bx += bxStep; } f32 tv = 0.f; const f32 tvStep = 1.f/subdivideV; f32 bz = -az; const f32 bzStep = lightDim.Z * tvStep; // Slices in Z/V space for(u32 i = 0; i <= subdivideV; ++i) { // These are the two endpoints for a slice at the foot core::vector3df end1(-ax, 0.0f, bz); core::vector3df end2(ax, 0.0f, bz); end1 -= lightPoint; // get a vector from point to lightsource end1.normalize(); // normalize vector end1 *= lightDim.Y; // multiply it out by shootlength end1.X -= ax; // Add the original point location to the vector end1.Z += bz; // Do it again for the other point. end2 -= lightPoint; end2.normalize(); end2 *= lightDim.Y; end2.X += ax; end2.Z += bz; addToBuffer(video::S3DVertex(-ax , 0, bz, 0,0,0, footColor, 0, tv),Buffer); addToBuffer(video::S3DVertex(ax , 0, bz, 0,0,0, footColor, 1, tv),Buffer); addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, tailColor, 1, tv),Buffer); addToBuffer(video::S3DVertex(end2.X , end2.Y, end2.Z, 0,0,0, tailColor, 1, tv),Buffer); addToBuffer(video::S3DVertex(end1.X , end1.Y, end1.Z, 0,0,0, tailColor, 0, tv),Buffer); addToBuffer(video::S3DVertex(-ax , 0, bz, 0,0,0, footColor, 0, tv),Buffer); //back side addToBuffer(video::S3DVertex(ax , 0, -bz, 0,0,0, footColor, 0, tv),Buffer); addToBuffer(video::S3DVertex(-ax , 0, -bz, 0,0,0, footColor, 1, tv),Buffer); addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, tailColor, 1, tv),Buffer); addToBuffer(video::S3DVertex(-end2.X , end2.Y, -end2.Z, 0,0,0, tailColor, 1, tv),Buffer); addToBuffer(video::S3DVertex(-end1.X , end1.Y, -end1.Z, 0,0,0, tailColor, 0, tv),Buffer); addToBuffer(video::S3DVertex(ax , 0, -bz, 0,0,0, footColor, 0, tv),Buffer); tv += tvStep; bz += bzStep; } Buffer->recalculateBoundingBox(); Buffer->Material.MaterialType = video::EMT_ONETEXTURE_BLEND; Buffer->Material.MaterialTypeParam = pack_textureBlendFunc( video::EBF_SRC_COLOR, video::EBF_SRC_ALPHA, video::EMFN_MODULATE_1X ); Buffer->Material.Lighting = false; Buffer->Material.ZWriteEnable = false; Buffer->setDirty(EBT_VERTEX_AND_INDEX); Buffer->recalculateBoundingBox(); SMesh* mesh = new SMesh(); mesh->addMeshBuffer(Buffer); Buffer->drop(); mesh->recalculateBoundingBox(); return mesh; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CFPSCounter.h0000644000000000000000000000170412574354552017403 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_FPSCOUNTER_H_INCLUDED__ #define __C_FPSCOUNTER_H_INCLUDED__ #include "irrTypes.h" namespace irr { namespace video { class CFPSCounter { public: CFPSCounter(); //! returns current fps s32 getFPS() const; //! returns primitive count u32 getPrimitive() const; //! returns average primitive count of last period u32 getPrimitiveAverage() const; //! returns accumulated primitive count since start u32 getPrimitiveTotal() const; //! to be called every frame void registerFrame(u32 now, u32 primitive); private: s32 FPS; u32 Primitive; u32 StartTime; u32 FramesCounted; u32 PrimitivesCounted; u32 PrimitiveAverage; u32 PrimitiveTotal; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CFPSCounter.cpp0000644000000000000000000000277612574354552017750 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CFPSCounter.h" #include "irrMath.h" namespace irr { namespace video { CFPSCounter::CFPSCounter() : FPS(60), Primitive(0), StartTime(0), FramesCounted(0), PrimitivesCounted(0), PrimitiveAverage(0), PrimitiveTotal(0) { } //! returns current fps s32 CFPSCounter::getFPS() const { return FPS; } //! returns current primitive count u32 CFPSCounter::getPrimitive() const { return Primitive; } //! returns average primitive count of last period u32 CFPSCounter::getPrimitiveAverage() const { return PrimitiveAverage; } //! returns accumulated primitive count since start u32 CFPSCounter::getPrimitiveTotal() const { return PrimitiveTotal; } //! to be called every frame void CFPSCounter::registerFrame(u32 now, u32 primitivesDrawn) { ++FramesCounted; PrimitiveTotal += primitivesDrawn; PrimitivesCounted += primitivesDrawn; Primitive = primitivesDrawn; const u32 milliseconds = now - StartTime; if (milliseconds >= 1500 ) { const f32 invMilli = core::reciprocal ( (f32) milliseconds ); FPS = core::ceil32 ( ( 1000 * FramesCounted ) * invMilli ); PrimitiveAverage = core::ceil32 ( ( 1000 * PrimitivesCounted ) * invMilli ); FramesCounted = 0; PrimitivesCounted = 0; StartTime = now; } } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CFileSystem.h0000644000000000000000000001404212574354552017476 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_FILE_SYSTEM_H_INCLUDED__ #define __C_FILE_SYSTEM_H_INCLUDED__ #include "IFileSystem.h" #include "irrArray.h" namespace irr { namespace io { class CZipReader; class CPakReader; class CMountPointReader; /*! FileSystem which uses normal files and one zipfile */ class CFileSystem : public IFileSystem { public: //! constructor CFileSystem(); //! destructor virtual ~CFileSystem(); //! opens a file for read access virtual IReadFile* createAndOpenFile(const io::path& filename); //! Creates an IReadFile interface for accessing memory like a file. virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped = false); //! Creates an IReadFile interface for accessing files inside files virtual IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize); //! Creates an IWriteFile interface for accessing memory like a file. virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped=false); //! Opens a file for write access. virtual IWriteFile* createAndWriteFile(const io::path& filename, bool append=false); //! Adds an archive to the file system. virtual bool addFileArchive(const io::path& filename, bool ignoreCase = true, bool ignorePaths = true, E_FILE_ARCHIVE_TYPE archiveType = EFAT_UNKNOWN, const core::stringc& password="", IFileArchive** retArchive = 0); //! Adds an archive to the file system. virtual bool addFileArchive(IReadFile* file, bool ignoreCase=true, bool ignorePaths=true, E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN, const core::stringc& password="", IFileArchive** retArchive = 0); //! Adds an archive to the file system. virtual bool addFileArchive(IFileArchive* archive); //! move the hirarchy of the filesystem. moves sourceIndex relative up or down virtual bool moveFileArchive(u32 sourceIndex, s32 relative); //! Adds an external archive loader to the engine. virtual void addArchiveLoader(IArchiveLoader* loader); //! Returns the total number of archive loaders added. virtual u32 getArchiveLoaderCount() const; //! Gets the archive loader by index. virtual IArchiveLoader* getArchiveLoader(u32 index) const; //! gets the file archive count virtual u32 getFileArchiveCount() const; //! gets an archive virtual IFileArchive* getFileArchive(u32 index); //! removes an archive from the file system. virtual bool removeFileArchive(u32 index); //! removes an archive from the file system. virtual bool removeFileArchive(const io::path& filename); //! Removes an archive from the file system. virtual bool removeFileArchive(const IFileArchive* archive); //! Returns the string of the current working directory virtual const io::path& getWorkingDirectory(); //! Changes the current Working Directory to the string given. //! The string is operating system dependent. Under Windows it will look //! like this: "drive:\directory\sudirectory\" virtual bool changeWorkingDirectoryTo(const io::path& newDirectory); //! Converts a relative path to an absolute (unique) path, resolving symbolic links virtual io::path getAbsolutePath(const io::path& filename) const; //! Returns the directory a file is located in. /** \param filename: The file to get the directory from */ virtual io::path getFileDir(const io::path& filename) const; //! Returns the base part of a filename, i.e. the name without the directory //! part. If no directory is prefixed, the full name is returned. /** \param filename: The file to get the basename from */ virtual io::path getFileBasename(const io::path& filename, bool keepExtension=true) const; //! flatten a path and file name for example: "/you/me/../." becomes "/you" virtual io::path& flattenFilename( io::path& directory, const io::path& root = "/" ) const; //! Get the relative filename, relative to the given directory virtual path getRelativeFilename(const path& filename, const path& directory) const; virtual EFileSystemType setFileListSystem(EFileSystemType listType); //! Creates a list of files and directories in the current working directory //! and returns it. virtual IFileList* createFileList(); //! Creates an empty filelist virtual IFileList* createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths); //! determines if a file exists and would be able to be opened. virtual bool existFile(const io::path& filename) const; //! Creates a XML Reader from a file. virtual IXMLReader* createXMLReader(const io::path& filename); //! Creates a XML Reader from a file. virtual IXMLReader* createXMLReader(IReadFile* file); //! Creates a XML Reader from a file. virtual IXMLReaderUTF8* createXMLReaderUTF8(const io::path& filename); //! Creates a XML Reader from a file. virtual IXMLReaderUTF8* createXMLReaderUTF8(IReadFile* file); //! Creates a XML Writer from a file. virtual IXMLWriter* createXMLWriter(const io::path& filename); //! Creates a XML Writer from a file. virtual IXMLWriter* createXMLWriter(IWriteFile* file); //! Creates a new empty collection of attributes, usable for serialization and more. virtual IAttributes* createEmptyAttributes(video::IVideoDriver* driver); private: // don't expose, needs refactoring bool changeArchivePassword(const path& filename, const core::stringc& password, IFileArchive** archive = 0); //! Currently used FileSystemType EFileSystemType FileSystemType; //! WorkingDirectory for Native and Virtual filesystems io::path WorkingDirectory [2]; //! currently attached ArchiveLoaders core::array ArchiveLoader; //! currently attached Archives core::array FileArchives; }; } // end namespace irr } // end namespace io #endif irrlicht-1.8.3/source/Irrlicht/CFileSystem.cpp0000644000000000000000000006260012574354552020034 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "CFileSystem.h" #include "IReadFile.h" #include "IWriteFile.h" #include "CZipReader.h" #include "CMountPointReader.h" #include "CPakReader.h" #include "CNPKReader.h" #include "CTarReader.h" #include "CWADReader.h" #include "CFileList.h" #include "CXMLReader.h" #include "CXMLWriter.h" #include "stdio.h" #include "os.h" #include "CAttributes.h" #include "CMemoryFile.h" #include "CLimitReadFile.h" #include "irrList.h" #if defined (_IRR_WINDOWS_API_) #if !defined ( _WIN32_WCE ) #include // for _chdir #include // for _access #include #endif #else #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) #include #include #include #include #include #include #include #include #endif #endif namespace irr { namespace io { //! constructor CFileSystem::CFileSystem() { #ifdef _DEBUG setDebugName("CFileSystem"); #endif setFileListSystem(FILESYSTEM_NATIVE); //! reset current working directory getWorkingDirectory(); #ifdef __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ ArchiveLoader.push_back(new CArchiveLoaderPAK(this)); #endif #ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ ArchiveLoader.push_back(new CArchiveLoaderNPK(this)); #endif #ifdef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ ArchiveLoader.push_back(new CArchiveLoaderTAR(this)); #endif #ifdef __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ ArchiveLoader.push_back(new CArchiveLoaderWAD(this)); #endif #ifdef __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ ArchiveLoader.push_back(new CArchiveLoaderMount(this)); #endif #ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ ArchiveLoader.push_back(new CArchiveLoaderZIP(this)); #endif } //! destructor CFileSystem::~CFileSystem() { u32 i; for ( i=0; i < FileArchives.size(); ++i) { FileArchives[i]->drop(); } for ( i=0; i < ArchiveLoader.size(); ++i) { ArchiveLoader[i]->drop(); } } //! opens a file for read access IReadFile* CFileSystem::createAndOpenFile(const io::path& filename) { IReadFile* file = 0; u32 i; for (i=0; i< FileArchives.size(); ++i) { file = FileArchives[i]->createAndOpenFile(filename); if (file) return file; } // Create the file using an absolute path so that it matches // the scheme used by CNullDriver::getTexture(). return createReadFile(getAbsolutePath(filename)); } //! Creates an IReadFile interface for treating memory like a file. IReadFile* CFileSystem::createMemoryReadFile(void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped) { if (!memory) return 0; else return new CMemoryFile(memory, len, fileName, deleteMemoryWhenDropped); } //! Creates an IReadFile interface for reading files inside files IReadFile* CFileSystem::createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize) { if (!alreadyOpenedFile) return 0; else return new CLimitReadFile(alreadyOpenedFile, pos, areaSize, fileName); } //! Creates an IReadFile interface for treating memory like a file. IWriteFile* CFileSystem::createMemoryWriteFile(void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped) { if (!memory) return 0; else return new CMemoryFile(memory, len, fileName, deleteMemoryWhenDropped); } //! Opens a file for write access. IWriteFile* CFileSystem::createAndWriteFile(const io::path& filename, bool append) { return createWriteFile(filename, append); } //! Adds an external archive loader to the engine. void CFileSystem::addArchiveLoader(IArchiveLoader* loader) { if (!loader) return; loader->grab(); ArchiveLoader.push_back(loader); } //! Returns the total number of archive loaders added. u32 CFileSystem::getArchiveLoaderCount() const { return ArchiveLoader.size(); } //! Gets the archive loader by index. IArchiveLoader* CFileSystem::getArchiveLoader(u32 index) const { if (index < ArchiveLoader.size()) return ArchiveLoader[index]; else return 0; } //! move the hirarchy of the filesystem. moves sourceIndex relative up or down bool CFileSystem::moveFileArchive(u32 sourceIndex, s32 relative) { bool r = false; const s32 dest = (s32) sourceIndex + relative; const s32 dir = relative < 0 ? -1 : 1; const s32 sourceEnd = ((s32) FileArchives.size() ) - 1; IFileArchive *t; for (s32 s = (s32) sourceIndex;s != dest; s += dir) { if (s < 0 || s > sourceEnd || s + dir < 0 || s + dir > sourceEnd) continue; t = FileArchives[s + dir]; FileArchives[s + dir] = FileArchives[s]; FileArchives[s] = t; r = true; } return r; } //! Adds an archive to the file system. bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase, bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType, const core::stringc& password, IFileArchive** retArchive) { IFileArchive* archive = 0; bool ret = false; // see if archive is already added if (changeArchivePassword(filename, password, retArchive)) return true; s32 i; // do we know what type it should be? if (archiveType == EFAT_UNKNOWN || archiveType == EFAT_FOLDER) { // try to load archive based on file name for (i = ArchiveLoader.size()-1; i >=0 ; --i) { if (ArchiveLoader[i]->isALoadableFileFormat(filename)) { archive = ArchiveLoader[i]->createArchive(filename, ignoreCase, ignorePaths); if (archive) break; } } // try to load archive based on content if (!archive) { io::IReadFile* file = createAndOpenFile(filename); if (file) { for (i = ArchiveLoader.size()-1; i >= 0; --i) { file->seek(0); if (ArchiveLoader[i]->isALoadableFileFormat(file)) { file->seek(0); archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths); if (archive) break; } } file->drop(); } } } else { // try to open archive based on archive loader type io::IReadFile* file = 0; for (i = ArchiveLoader.size()-1; i >= 0; --i) { if (ArchiveLoader[i]->isALoadableFileFormat(archiveType)) { // attempt to open file if (!file) file = createAndOpenFile(filename); // is the file open? if (file) { // attempt to open archive file->seek(0); if (ArchiveLoader[i]->isALoadableFileFormat(file)) { file->seek(0); archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths); if (archive) break; } } else { // couldn't open file break; } } } // if open, close the file if (file) file->drop(); } if (archive) { FileArchives.push_back(archive); if (password.size()) archive->Password=password; if (retArchive) *retArchive = archive; ret = true; } else { os::Printer::log("Could not create archive for", filename, ELL_ERROR); } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } // don't expose! bool CFileSystem::changeArchivePassword(const path& filename, const core::stringc& password, IFileArchive** archive) { for (s32 idx = 0; idx < (s32)FileArchives.size(); ++idx) { // TODO: This should go into a path normalization method // We need to check for directory names with trailing slash and without const path absPath = getAbsolutePath(filename); const path arcPath = FileArchives[idx]->getFileList()->getPath(); if ((absPath == arcPath) || ((absPath+_IRR_TEXT("/")) == arcPath)) { if (password.size()) FileArchives[idx]->Password=password; if (archive) *archive = FileArchives[idx]; return true; } } return false; } bool CFileSystem::addFileArchive(IReadFile* file, bool ignoreCase, bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType, const core::stringc& password, IFileArchive** retArchive) { if (!file || archiveType == EFAT_FOLDER) return false; if (file) { if (changeArchivePassword(file->getFileName(), password, retArchive)) return true; IFileArchive* archive = 0; s32 i; if (archiveType == EFAT_UNKNOWN) { // try to load archive based on file name for (i = ArchiveLoader.size()-1; i >=0 ; --i) { if (ArchiveLoader[i]->isALoadableFileFormat(file->getFileName())) { archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths); if (archive) break; } } // try to load archive based on content if (!archive) { for (i = ArchiveLoader.size()-1; i >= 0; --i) { file->seek(0); if (ArchiveLoader[i]->isALoadableFileFormat(file)) { file->seek(0); archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths); if (archive) break; } } } } else { // try to open archive based on archive loader type for (i = ArchiveLoader.size()-1; i >= 0; --i) { if (ArchiveLoader[i]->isALoadableFileFormat(archiveType)) { // attempt to open archive file->seek(0); if (ArchiveLoader[i]->isALoadableFileFormat(file)) { file->seek(0); archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths); if (archive) break; } } } } if (archive) { FileArchives.push_back(archive); if (password.size()) archive->Password=password; if (retArchive) *retArchive = archive; return true; } else { os::Printer::log("Could not create archive for", file->getFileName(), ELL_ERROR); } } return false; } //! Adds an archive to the file system. bool CFileSystem::addFileArchive(IFileArchive* archive) { for (u32 i=0; i < FileArchives.size(); ++i) { if (archive == FileArchives[i]) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } } FileArchives.push_back(archive); return true; } //! removes an archive from the file system. bool CFileSystem::removeFileArchive(u32 index) { bool ret = false; if (index < FileArchives.size()) { FileArchives[index]->drop(); FileArchives.erase(index); ret = true; } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! removes an archive from the file system. bool CFileSystem::removeFileArchive(const io::path& filename) { const path absPath = getAbsolutePath(filename); for (u32 i=0; i < FileArchives.size(); ++i) { if (absPath == FileArchives[i]->getFileList()->getPath()) return removeFileArchive(i); } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } //! Removes an archive from the file system. bool CFileSystem::removeFileArchive(const IFileArchive* archive) { for (u32 i=0; i < FileArchives.size(); ++i) { if (archive == FileArchives[i]) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return removeFileArchive(i); } } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } //! gets an archive u32 CFileSystem::getFileArchiveCount() const { return FileArchives.size(); } IFileArchive* CFileSystem::getFileArchive(u32 index) { return index < getFileArchiveCount() ? FileArchives[index] : 0; } //! Returns the string of the current working directory const io::path& CFileSystem::getWorkingDirectory() { EFileSystemType type = FileSystemType; if (type != FILESYSTEM_NATIVE) { type = FILESYSTEM_VIRTUAL; } else { #if defined(_IRR_WINDOWS_CE_PLATFORM_) // does not need this #elif defined(_IRR_WINDOWS_API_) fschar_t tmp[_MAX_PATH]; #if defined(_IRR_WCHAR_FILESYSTEM ) _wgetcwd(tmp, _MAX_PATH); WorkingDirectory[FILESYSTEM_NATIVE] = tmp; WorkingDirectory[FILESYSTEM_NATIVE].replace(L'\\', L'/'); #else _getcwd(tmp, _MAX_PATH); WorkingDirectory[FILESYSTEM_NATIVE] = tmp; WorkingDirectory[FILESYSTEM_NATIVE].replace('\\', '/'); #endif #endif #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) // getting the CWD is rather complex as we do not know the size // so try it until the call was successful // Note that neither the first nor the second parameter may be 0 according to POSIX #if defined(_IRR_WCHAR_FILESYSTEM ) u32 pathSize=256; wchar_t *tmpPath = new wchar_t[pathSize]; while ((pathSize < (1<<16)) && !(wgetcwd(tmpPath,pathSize))) { delete [] tmpPath; pathSize *= 2; tmpPath = new char[pathSize]; } if (tmpPath) { WorkingDirectory[FILESYSTEM_NATIVE] = tmpPath; delete [] tmpPath; } #else u32 pathSize=256; char *tmpPath = new char[pathSize]; while ((pathSize < (1<<16)) && !(getcwd(tmpPath,pathSize))) { delete [] tmpPath; pathSize *= 2; tmpPath = new char[pathSize]; } if (tmpPath) { WorkingDirectory[FILESYSTEM_NATIVE] = tmpPath; delete [] tmpPath; } #endif #endif WorkingDirectory[type].validate(); } return WorkingDirectory[type]; } //! Changes the current Working Directory to the given string. bool CFileSystem::changeWorkingDirectoryTo(const io::path& newDirectory) { bool success=false; if (FileSystemType != FILESYSTEM_NATIVE) { WorkingDirectory[FILESYSTEM_VIRTUAL] = newDirectory; // is this empty string constant really intended? flattenFilename(WorkingDirectory[FILESYSTEM_VIRTUAL], _IRR_TEXT("")); success = true; } else { WorkingDirectory[FILESYSTEM_NATIVE] = newDirectory; #if defined(_IRR_WINDOWS_CE_PLATFORM_) success = true; #elif defined(_MSC_VER) #if defined(_IRR_WCHAR_FILESYSTEM) success = (_wchdir(newDirectory.c_str()) == 0); #else success = (_chdir(newDirectory.c_str()) == 0); #endif #else #if defined(_IRR_WCHAR_FILESYSTEM) success = (_wchdir(newDirectory.c_str()) == 0); #else success = (chdir(newDirectory.c_str()) == 0); #endif #endif } return success; } io::path CFileSystem::getAbsolutePath(const io::path& filename) const { #if defined(_IRR_WINDOWS_CE_PLATFORM_) return filename; #elif defined(_IRR_WINDOWS_API_) fschar_t *p=0; fschar_t fpath[_MAX_PATH]; #if defined(_IRR_WCHAR_FILESYSTEM ) p = _wfullpath(fpath, filename.c_str(), _MAX_PATH); core::stringw tmp(p); tmp.replace(L'\\', L'/'); #else p = _fullpath(fpath, filename.c_str(), _MAX_PATH); core::stringc tmp(p); tmp.replace('\\', '/'); #endif return tmp; #elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) c8* p=0; c8 fpath[4096]; fpath[0]=0; p = realpath(filename.c_str(), fpath); if (!p) { // content in fpath is unclear at this point if (!fpath[0]) // seems like fpath wasn't altered, use our best guess { io::path tmp(filename); return flattenFilename(tmp); } else return io::path(fpath); } if (filename[filename.size()-1]=='/') return io::path(p)+_IRR_TEXT("/"); else return io::path(p); #else return io::path(filename); #endif } //! returns the directory part of a filename, i.e. all until the first //! slash or backslash, excluding it. If no directory path is prefixed, a '.' //! is returned. io::path CFileSystem::getFileDir(const io::path& filename) const { // find last forward or backslash s32 lastSlash = filename.findLast('/'); const s32 lastBackSlash = filename.findLast('\\'); lastSlash = lastSlash > lastBackSlash ? lastSlash : lastBackSlash; if ((u32)lastSlash < filename.size()) return filename.subString(0, lastSlash); else return _IRR_TEXT("."); } //! returns the base part of a filename, i.e. all except for the directory //! part. If no directory path is prefixed, the full name is returned. io::path CFileSystem::getFileBasename(const io::path& filename, bool keepExtension) const { // find last forward or backslash s32 lastSlash = filename.findLast('/'); const s32 lastBackSlash = filename.findLast('\\'); lastSlash = core::max_(lastSlash, lastBackSlash); // get number of chars after last dot s32 end = 0; if (!keepExtension) { // take care to search only after last slash to check only for // dots in the filename end = filename.findLast('.'); if (end == -1 || end < lastSlash) end=0; else end = filename.size()-end; } if ((u32)lastSlash < filename.size()) return filename.subString(lastSlash+1, filename.size()-lastSlash-1-end); else if (end != 0) return filename.subString(0, filename.size()-end); else return filename; } //! flatten a path and file name for example: "/you/me/../." becomes "/you" io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root) const { directory.replace('\\', '/'); if (directory.lastChar() != '/') directory.append('/'); io::path dir; io::path subdir; s32 lastpos = 0; s32 pos = 0; bool lastWasRealDir=false; while ((pos = directory.findNext('/', lastpos)) >= 0) { subdir = directory.subString(lastpos, pos - lastpos + 1); if (subdir == _IRR_TEXT("../")) { if (lastWasRealDir) { deletePathFromPath(dir, 2); lastWasRealDir=(dir.size()!=0); } else { dir.append(subdir); lastWasRealDir=false; } } else if (subdir == _IRR_TEXT("/")) { dir = root; } else if (subdir != _IRR_TEXT("./")) { dir.append(subdir); lastWasRealDir=true; } lastpos = pos + 1; } directory = dir; return directory; } //! Get the relative filename, relative to the given directory path CFileSystem::getRelativeFilename(const path& filename, const path& directory) const { if ( filename.empty() || directory.empty() ) return filename; io::path path1, file, ext; core::splitFilename(getAbsolutePath(filename), &path1, &file, &ext); io::path path2(getAbsolutePath(directory)); core::list list1, list2; path1.split(list1, _IRR_TEXT("/\\"), 2); path2.split(list2, _IRR_TEXT("/\\"), 2); u32 i=0; core::list::ConstIterator it1,it2; it1=list1.begin(); it2=list2.begin(); #if defined (_IRR_WINDOWS_API_) fschar_t partition1 = 0, partition2 = 0; io::path prefix1, prefix2; if ( it1 != list1.end() ) prefix1 = *it1; if ( it2 != list2.end() ) prefix2 = *it2; if ( prefix1.size() > 1 && prefix1[1] == _IRR_TEXT(':') ) partition1 = core::locale_lower(prefix1[0]); if ( prefix2.size() > 1 && prefix2[1] == _IRR_TEXT(':') ) partition2 = core::locale_lower(prefix2[0]); // must have the same prefix or we can't resolve it to a relative filename if ( partition1 != partition2 ) { return filename; } #endif for (; iaddItem(Path + c_file.name, 0, c_file.size, (_A_SUBDIR & c_file.attrib) != 0, 0); } while( _tfindnext( hFile, &c_file ) == 0 ); _findclose( hFile ); } #endif //TODO add drives //entry.Name = "E:\\"; //entry.isDirectory = true; //Files.push_back(entry); #endif // -------------------------------------------- //! Linux version #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) r = new CFileList(Path, false, false); r->addItem(Path + _IRR_TEXT(".."), 0, 0, true, 0); //! We use the POSIX compliant methods instead of scandir DIR* dirHandle=opendir(Path.c_str()); if (dirHandle) { struct dirent *dirEntry; while ((dirEntry=readdir(dirHandle))) { u32 size = 0; bool isDirectory = false; if((strcmp(dirEntry->d_name, ".")==0) || (strcmp(dirEntry->d_name, "..")==0)) { continue; } struct stat buf; if (stat(dirEntry->d_name, &buf)==0) { size = buf.st_size; isDirectory = S_ISDIR(buf.st_mode); } #if !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__CYGWIN__) // only available on some systems else { isDirectory = dirEntry->d_type == DT_DIR; } #endif r->addItem(Path + dirEntry->d_name, 0, size, isDirectory, 0); } closedir(dirHandle); } #endif } else { //! create file list for the virtual filesystem r = new CFileList(Path, false, false); //! add relative navigation SFileListEntry e2; SFileListEntry e3; //! PWD r->addItem(Path + _IRR_TEXT("."), 0, 0, true, 0); //! parent r->addItem(Path + _IRR_TEXT(".."), 0, 0, true, 0); //! merge archives for (u32 i=0; i < FileArchives.size(); ++i) { const IFileList *merge = FileArchives[i]->getFileList(); for (u32 j=0; j < merge->getFileCount(); ++j) { if (core::isInSameDirectory(Path, merge->getFullFileName(j)) == 0) { r->addItem(merge->getFullFileName(j), merge->getFileOffset(j), merge->getFileSize(j), merge->isDirectory(j), 0); } } } } if (r) r->sort(); return r; } //! Creates an empty filelist IFileList* CFileSystem::createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths) { return new CFileList(path, ignoreCase, ignorePaths); } //! determines if a file exists and would be able to be opened. bool CFileSystem::existFile(const io::path& filename) const { for (u32 i=0; i < FileArchives.size(); ++i) if (FileArchives[i]->getFileList()->findFile(filename)!=-1) return true; #if defined(_IRR_WINDOWS_CE_PLATFORM_) #if defined(_IRR_WCHAR_FILESYSTEM) HANDLE hFile = CreateFileW(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); #else HANDLE hFile = CreateFileW(core::stringw(filename).c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); #endif if (hFile == INVALID_HANDLE_VALUE) return false; else { CloseHandle(hFile); return true; } #else _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; #if defined(_MSC_VER) #if defined(_IRR_WCHAR_FILESYSTEM) return (_waccess(filename.c_str(), 0) != -1); #else return (_access(filename.c_str(), 0) != -1); #endif #elif defined(F_OK) #if defined(_IRR_WCHAR_FILESYSTEM) return (_waccess(filename.c_str(), F_OK) != -1); #else return (access(filename.c_str(), F_OK) != -1); #endif #else return (access(filename.c_str(), 0) != -1); #endif #endif } //! Creates a XML Reader from a file. IXMLReader* CFileSystem::createXMLReader(const io::path& filename) { IReadFile* file = createAndOpenFile(filename); if (!file) return 0; IXMLReader* reader = createXMLReader(file); file->drop(); return reader; } //! Creates a XML Reader from a file. IXMLReader* CFileSystem::createXMLReader(IReadFile* file) { if (!file) return 0; return createIXMLReader(file); } //! Creates a XML Reader from a file. IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(const io::path& filename) { IReadFile* file = createAndOpenFile(filename); if (!file) return 0; IXMLReaderUTF8* reader = createIXMLReaderUTF8(file); file->drop(); return reader; } //! Creates a XML Reader from a file. IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(IReadFile* file) { if (!file) return 0; return createIXMLReaderUTF8(file); } //! Creates a XML Writer from a file. IXMLWriter* CFileSystem::createXMLWriter(const io::path& filename) { IWriteFile* file = createAndWriteFile(filename); IXMLWriter* writer = 0; if (file) { writer = createXMLWriter(file); file->drop(); } return writer; } //! Creates a XML Writer from a file. IXMLWriter* CFileSystem::createXMLWriter(IWriteFile* file) { return new CXMLWriter(file); } //! creates a filesystem which is able to open files from the ordinary file system, //! and out of zipfiles, which are able to be added to the filesystem. IFileSystem* createFileSystem() { return new CFileSystem(); } //! Creates a new empty collection of attributes, usable for serialization and more. IAttributes* CFileSystem::createEmptyAttributes(video::IVideoDriver* driver) { return new CAttributes(driver); } } // end namespace irr } // end namespace io irrlicht-1.8.3/source/Irrlicht/CFileList.h0000644000000000000000000000756712574354552017143 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_FILE_LIST_H_INCLUDED__ #define __C_FILE_LIST_H_INCLUDED__ #include "IFileList.h" #include "irrString.h" #include "irrArray.h" namespace irr { namespace io { //! An entry in a list of files, can be a folder or a file. struct SFileListEntry { //! The name of the file /** If this is a file or folder in the virtual filesystem and the archive was created with the ignoreCase flag then the file name will be lower case. */ io::path Name; //! The name of the file including the path /** If this is a file or folder in the virtual filesystem and the archive was created with the ignoreDirs flag then it will be the same as Name. */ io::path FullName; //! The size of the file in bytes u32 Size; //! The ID of the file in an archive /** This is used to link the FileList entry to extra info held about this file in an archive, which can hold things like data offset and CRC. */ u32 ID; //! FileOffset inside an archive u32 Offset; //! True if this is a folder, false if not. bool IsDirectory; //! The == operator is provided so that CFileList can slowly search the list! bool operator ==(const struct SFileListEntry& other) const { if (IsDirectory != other.IsDirectory) return false; return FullName.equals_ignore_case(other.FullName); } //! The < operator is provided so that CFileList can sort and quickly search the list. bool operator <(const struct SFileListEntry& other) const { if (IsDirectory != other.IsDirectory) return IsDirectory; return FullName.lower_ignore_case(other.FullName); } }; //! Implementation of a file list class CFileList : public IFileList { public: // CFileList methods //! Constructor /** \param path The path of this file archive */ CFileList(const io::path& path, bool ignoreCase, bool ignorePaths); //! Destructor virtual ~CFileList(); //! Add as a file or folder to the list /** \param fullPath The file name including path, up to the root of the file list. \param isDirectory True if this is a directory rather than a file. \param offset The offset where the file is stored in an archive \param size The size of the file in bytes. \param id The ID of the file in the archive which owns it */ virtual u32 addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id=0); //! Sorts the file list. You should call this after adding any items to the file list virtual void sort(); //! Returns the amount of files in the filelist. virtual u32 getFileCount() const; //! Gets the name of a file in the list, based on an index. virtual const io::path& getFileName(u32 index) const; //! Gets the full name of a file in the list, path included, based on an index. virtual const io::path& getFullFileName(u32 index) const; //! Returns the ID of a file in the file list, based on an index. virtual u32 getID(u32 index) const; //! Returns true if the file is a directory virtual bool isDirectory(u32 index) const; //! Returns the size of a file virtual u32 getFileSize(u32 index) const; //! Returns the offest of a file virtual u32 getFileOffset(u32 index) const; //! Searches for a file or folder within the list, returns the index virtual s32 findFile(const io::path& filename, bool isFolder) const; //! Returns the base path of the file list virtual const io::path& getPath() const; protected: //! Ignore paths when adding or searching for files bool IgnorePaths; //! Ignore case when adding or searching for files bool IgnoreCase; //! Path to the file list io::path Path; //! List of files core::array Files; }; } // end namespace irr } // end namespace io #endif irrlicht-1.8.3/source/Irrlicht/CFileList.cpp0000644000000000000000000000664012574354552017465 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CFileList.h" #include "IrrCompileConfig.h" #include "irrArray.h" #include "coreutil.h" #include "os.h" namespace irr { namespace io { static const io::path emptyFileListEntry; CFileList::CFileList(const io::path& path, bool ignoreCase, bool ignorePaths) : IgnorePaths(ignorePaths), IgnoreCase(ignoreCase), Path(path) { #ifdef _DEBUG setDebugName("CFileList"); #endif Path.replace('\\', '/'); } CFileList::~CFileList() { Files.clear(); } u32 CFileList::getFileCount() const { return Files.size(); } void CFileList::sort() { Files.sort(); } const io::path& CFileList::getFileName(u32 index) const { if (index >= Files.size()) return emptyFileListEntry; return Files[index].Name; } //! Gets the full name of a file in the list, path included, based on an index. const io::path& CFileList::getFullFileName(u32 index) const { if (index >= Files.size()) return emptyFileListEntry; return Files[index].FullName; } //! adds a file or folder u32 CFileList::addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id) { SFileListEntry entry; entry.ID = id ? id : Files.size(); entry.Offset = offset; entry.Size = size; entry.Name = fullPath; entry.Name.replace('\\', '/'); entry.IsDirectory = isDirectory; // remove trailing slash if (entry.Name.lastChar() == '/') { entry.IsDirectory = true; entry.Name[entry.Name.size()-1] = 0; entry.Name.validate(); } if (IgnoreCase) entry.Name.make_lower(); entry.FullName = entry.Name; core::deletePathFromFilename(entry.Name); if (IgnorePaths) entry.FullName = entry.Name; //os::Printer::log(Path.c_str(), entry.FullName); Files.push_back(entry); return Files.size() - 1; } //! Returns the ID of a file in the file list, based on an index. u32 CFileList::getID(u32 index) const { return index < Files.size() ? Files[index].ID : 0; } bool CFileList::isDirectory(u32 index) const { bool ret = false; if (index < Files.size()) ret = Files[index].IsDirectory; _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! Returns the size of a file u32 CFileList::getFileSize(u32 index) const { return index < Files.size() ? Files[index].Size : 0; } //! Returns the size of a file u32 CFileList::getFileOffset(u32 index) const { return index < Files.size() ? Files[index].Offset : 0; } //! Searches for a file or folder within the list, returns the index s32 CFileList::findFile(const io::path& filename, bool isDirectory = false) const { SFileListEntry entry; // we only need FullName to be set for the search entry.FullName = filename; entry.IsDirectory = isDirectory; // exchange entry.FullName.replace('\\', '/'); // remove trailing slash if (entry.FullName.lastChar() == '/') { entry.IsDirectory = true; entry.FullName[entry.FullName.size()-1] = 0; entry.FullName.validate(); } if (IgnoreCase) entry.FullName.make_lower(); if (IgnorePaths) core::deletePathFromFilename(entry.FullName); return Files.binary_search(entry); } //! Returns the base path of the file list const io::path& CFileList::getPath() const { return Path; } } // end namespace irr } // end namespace io irrlicht-1.8.3/source/Irrlicht/CEmptySceneNode.h0000644000000000000000000000216112574354552020273 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_EMPTY_SCENE_NODE_H_INCLUDED__ #define __C_EMPTY_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" namespace irr { namespace scene { class CEmptySceneNode : public ISceneNode { public: //! constructor CEmptySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! This method is called just before the rendering process of the whole scene. virtual void OnRegisterSceneNode(); //! does nothing. virtual void render(); //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_EMPTY; } //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); private: core::aabbox3d Box; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CEmptySceneNode.cpp0000644000000000000000000000256112574354552020632 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CEmptySceneNode.h" #include "ISceneManager.h" namespace irr { namespace scene { //! constructor CEmptySceneNode::CEmptySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id) : ISceneNode(parent, mgr, id) { #ifdef _DEBUG setDebugName("CEmptySceneNode"); #endif setAutomaticCulling(scene::EAC_OFF); } //! pre render event void CEmptySceneNode::OnRegisterSceneNode() { if (IsVisible) SceneManager->registerNodeForRendering(this); ISceneNode::OnRegisterSceneNode(); } //! render void CEmptySceneNode::render() { // do nothing } //! returns the axis aligned bounding box of this node const core::aabbox3d& CEmptySceneNode::getBoundingBox() const { return Box; } //! Creates a clone of this scene node and its children. ISceneNode* CEmptySceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CEmptySceneNode* nb = new CEmptySceneNode(newParent, newManager, ID); nb->cloneMembers(this, newManager); nb->Box = Box; if ( newParent ) nb->drop(); return nb; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CDummyTransformationSceneNode.h0000644000000000000000000000370712574354552023226 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_DUMMY_TRANSFORMATION_SCENE_NODE_H_INCLUDED__ #define __C_DUMMY_TRANSFORMATION_SCENE_NODE_H_INCLUDED__ #include "IDummyTransformationSceneNode.h" namespace irr { namespace scene { class CDummyTransformationSceneNode : public IDummyTransformationSceneNode { public: //! constructor CDummyTransformationSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! Returns a reference to the current relative transformation matrix. //! This is the matrix, this scene node uses instead of scale, translation //! and rotation. virtual core::matrix4& getRelativeTransformationMatrix(); //! Returns the relative transformation of the scene node. virtual core::matrix4 getRelativeTransformation() const; //! does nothing. virtual void render() {} //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_DUMMY_TRANSFORMATION; } //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); private: // TODO: We can add least add some warnings to find troubles faster until we have // fixed bug id 2318691. virtual const core::vector3df& getScale() const; virtual void setScale(const core::vector3df& scale); virtual const core::vector3df& getRotation() const; virtual void setRotation(const core::vector3df& rotation); virtual const core::vector3df& getPosition() const; virtual void setPosition(const core::vector3df& newpos); core::matrix4 RelativeTransformationMatrix; core::aabbox3d Box; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CDummyTransformationSceneNode.cpp0000644000000000000000000000624012574354552023554 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CDummyTransformationSceneNode.h" #include "os.h" namespace irr { namespace scene { //! constructor CDummyTransformationSceneNode::CDummyTransformationSceneNode( ISceneNode* parent, ISceneManager* mgr, s32 id) : IDummyTransformationSceneNode(parent, mgr, id) { #ifdef _DEBUG setDebugName("CDummyTransformationSceneNode"); #endif setAutomaticCulling(scene::EAC_OFF); } //! returns the axis aligned bounding box of this node const core::aabbox3d& CDummyTransformationSceneNode::getBoundingBox() const { return Box; } //! Returns a reference to the current relative transformation matrix. //! This is the matrix, this scene node uses instead of scale, translation //! and rotation. core::matrix4& CDummyTransformationSceneNode::getRelativeTransformationMatrix() { return RelativeTransformationMatrix; } //! Returns the relative transformation of the scene node. core::matrix4 CDummyTransformationSceneNode::getRelativeTransformation() const { return RelativeTransformationMatrix; } //! Creates a clone of this scene node and its children. ISceneNode* CDummyTransformationSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CDummyTransformationSceneNode* nb = new CDummyTransformationSceneNode(newParent, newManager, ID); nb->cloneMembers(this, newManager); nb->RelativeTransformationMatrix = RelativeTransformationMatrix; nb->Box = Box; if ( newParent ) nb->drop(); return nb; } const core::vector3df& CDummyTransformationSceneNode::getScale() const { os::Printer::log("CDummyTransformationSceneNode::getScale() does not contain the relative transformation.", ELL_DEBUG); return RelativeScale; } void CDummyTransformationSceneNode::setScale(const core::vector3df& scale) { os::Printer::log("CDummyTransformationSceneNode::setScale() does not affect the relative transformation.", ELL_DEBUG); RelativeScale = scale; } const core::vector3df& CDummyTransformationSceneNode::getRotation() const { os::Printer::log("CDummyTransformationSceneNode::getRotation() does not contain the relative transformation.", ELL_DEBUG); return RelativeRotation; } void CDummyTransformationSceneNode::setRotation(const core::vector3df& rotation) { os::Printer::log("CDummyTransformationSceneNode::setRotation() does not affect the relative transformation.", ELL_DEBUG); RelativeRotation = rotation; } const core::vector3df& CDummyTransformationSceneNode::getPosition() const { os::Printer::log("CDummyTransformationSceneNode::getPosition() does not contain the relative transformation.", ELL_DEBUG); return RelativeTranslation; } void CDummyTransformationSceneNode::setPosition(const core::vector3df& newpos) { os::Printer::log("CDummyTransformationSceneNode::setPosition() does not affect the relative transformation.", ELL_DEBUG); RelativeTranslation = newpos; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CDMFLoader.h0000644000000000000000000000640112574354552017147 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // This file was originally written by Salvatore Russo. // I (Nikolaus Gebhardt) did some minor modifications changes to it and integrated // it into Irrlicht: // - removed STL dependency // - removed log file and replaced it with irrlicht logging // - adapted code formatting a bit to Irrlicht style // - removed memory leaks // Thanks a lot to Salvatore for his work on this and that he gave me // his permission to add it into Irrlicht. /* CDMFLoader by Salvatore Russo Version 1.3 This loader is used to load DMF files in Irrlicht. Look at the documentation for a sample application. Parts of this code are from Murphy McCauley COCTLoader just like GetFaceNormal() or indexes creation routines and a routine to add faces. So please refer to COCTLoader.h to know more about rights granted. You can use this software as you wish but you must not remove these notes about license nor credits to others for parts of this code. */ #ifndef __C_DMF_LOADER_H_INCLUDED__ #define __C_DMF_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "IReadFile.h" #include "IFileSystem.h" #include "SMesh.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "SAnimatedMesh.h" namespace irr { namespace scene { /** A class to load DeleD mesh files.*/ class CDMFLoader : public IMeshLoader { public: /** constructor*/ CDMFLoader(ISceneManager* smgr, io::IFileSystem* filesys); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") virtual bool isALoadableFileExtension(const io::path& filename) const; /** creates/loads an animated mesh from the file. \return Pointer to the created mesh. Returns 0 if loading failed. If you no longer need the mesh, you should call IAnimatedMesh::drop(). See IReferenceCounted::drop() for more information.*/ virtual IAnimatedMesh* createMesh(io::IReadFile* file); /** loads dynamic lights present in this scene. Note that loaded lights from DeleD must have the suffix \b dynamic_ and must be \b pointlight. Irrlicht correctly loads specular color, diffuse color , position and distance of object affected by light. \return number of lights loaded or 0 if loading failed.*/ int loadLights(const c8 * filename, ISceneManager* smgr, ISceneNode* parent = 0, s32 base_id = 1000); /** loads water plains present in this scene. Note that loaded water plains from DeleD must have the suffix \b water_ and must be \b rectangle (with just 1 rectangular face). Irrlicht correctly loads position and rotation of water plain as well as texture layers. \return number of water plains loaded or 0 if loading failed.*/ int loadWaterPlains(const c8 *filename, ISceneManager* smgr, ISceneNode * parent = 0, s32 base_id = 2000, bool mode = true); private: void findFile(bool use_mat_dirs, const core::stringc& path, const core::stringc& matPath, core::stringc& filename); ISceneManager* SceneMgr; io::IFileSystem* FileSystem; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CDMFLoader.cpp0000644000000000000000000003204512574354552017505 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // This file was originally written by Salvatore Russo. // I (Nikolaus Gebhardt) did some minor modifications and changes to it and // integrated it into Irrlicht. // Thanks a lot to Salvatore for his work on this and that he gave me // his permission to add it into Irrlicht using the zlib license. /* CDMFLoader by Salvatore Russo (September 2005) See the header file for additional information including use and distribution rights. */ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DMF_LOADER_ #ifdef _DEBUG #define _IRR_DMF_DEBUG_ #include "os.h" #endif #include "CDMFLoader.h" #include "ISceneManager.h" #include "IAttributes.h" #include "SAnimatedMesh.h" #include "SSkinMeshBuffer.h" #include "irrString.h" #include "irrMath.h" #include "dmfsupport.h" namespace irr { namespace scene { /** Constructor*/ CDMFLoader::CDMFLoader(ISceneManager* smgr, io::IFileSystem* filesys) : SceneMgr(smgr), FileSystem(filesys) { #ifdef _DEBUG IReferenceCounted::setDebugName("CDMFLoader"); #endif } void CDMFLoader::findFile(bool use_mat_dirs, const core::stringc& path, const core::stringc& matPath, core::stringc& filename) { // path + texpath + full name if (use_mat_dirs && FileSystem->existFile(path+matPath+filename)) filename = path+matPath+filename; // path + full name else if (FileSystem->existFile(path+filename)) filename = path+filename; // path + texpath + base name else if (use_mat_dirs && FileSystem->existFile(path+matPath+FileSystem->getFileBasename(filename))) filename = path+matPath+FileSystem->getFileBasename(filename); // path + base name else if (FileSystem->existFile(path+FileSystem->getFileBasename(filename))) filename = path+FileSystem->getFileBasename(filename); // texpath + full name else if (use_mat_dirs && FileSystem->existFile(matPath+filename)) filename = matPath+filename; // texpath + base name else if (use_mat_dirs && FileSystem->existFile(matPath+FileSystem->getFileBasename(filename))) filename = matPath+FileSystem->getFileBasename(filename); // base name else if (FileSystem->existFile(FileSystem->getFileBasename(filename))) filename = FileSystem->getFileBasename(filename); } /**Creates/loads an animated mesh from the file. \return Pointer to the created mesh. Returns 0 if loading failed. If you no longer need the mesh, you should call IAnimatedMesh::drop(). See IReferenceCounted::drop() for more information.*/ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) { if (!file) return 0; video::IVideoDriver* driver = SceneMgr->getVideoDriver(); //Load stringlist StringList dmfRawFile; LoadFromFile(file, dmfRawFile); if (dmfRawFile.size()==0) return 0; SMesh * mesh = new SMesh(); u32 i; dmfHeader header; //load header core::array materiali; if (GetDMFHeader(dmfRawFile, header)) { //let's set ambient light SceneMgr->setAmbientLight(header.dmfAmbient); //let's create the correct number of materials, vertices and faces dmfVert *verts=new dmfVert[header.numVertices]; dmfFace *faces=new dmfFace[header.numFaces]; //let's get the materials #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Loading materials", core::stringc(header.numMaterials).c_str()); #endif GetDMFMaterials(dmfRawFile, materiali, header.numMaterials); //let's get vertices and faces #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Loading geometry"); #endif GetDMFVerticesFaces(dmfRawFile, verts, faces); //create a meshbuffer for each material, then we'll remove empty ones #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Creating meshbuffers."); #endif for (i=0; iMaterial.MaterialType = video::EMT_LIGHTMAP_LIGHTING; buffer->Material.Wireframe = false; buffer->Material.Lighting = true; mesh->addMeshBuffer(buffer); buffer->drop(); } // Build the mesh buffers #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Adding geometry to mesh."); #endif for (i = 0; i < header.numFaces; i++) { #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Polygon with #vertices", core::stringc(faces[i].numVerts).c_str()); #endif if (faces[i].numVerts < 3) continue; const core::vector3df normal = core::triangle3df(verts[faces[i].firstVert].pos, verts[faces[i].firstVert+1].pos, verts[faces[i].firstVert+2].pos).getNormal().normalize(); SSkinMeshBuffer* meshBuffer = (SSkinMeshBuffer*)mesh->getMeshBuffer( faces[i].materialID); const bool use2TCoords = meshBuffer->Vertices_2TCoords.size() || materiali[faces[i].materialID].lightmapName.size(); if (use2TCoords && meshBuffer->Vertices_Standard.size()) meshBuffer->convertTo2TCoords(); const u32 base = meshBuffer->Vertices_2TCoords.size()?meshBuffer->Vertices_2TCoords.size():meshBuffer->Vertices_Standard.size(); // Add this face's verts if (use2TCoords) { // make sure we have the proper type set meshBuffer->VertexType=video::EVT_2TCOORDS; for (u32 v = 0; v < faces[i].numVerts; v++) { const dmfVert& vv = verts[faces[i].firstVert + v]; video::S3DVertex2TCoords vert(vv.pos, normal, video::SColor(255,255,255,255), vv.tc, vv.lc); if (materiali[faces[i].materialID].textureBlend==4 && SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES)) { vert.TCoords.set(vv.tc.X,-vv.tc.Y); } meshBuffer->Vertices_2TCoords.push_back(vert); } } else { for (u32 v = 0; v < faces[i].numVerts; v++) { const dmfVert& vv = verts[faces[i].firstVert + v]; video::S3DVertex vert(vv.pos, normal, video::SColor(255,255,255,255), vv.tc); if (materiali[faces[i].materialID].textureBlend==4 && SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES)) { vert.TCoords.set(vv.tc.X,-vv.tc.Y); } meshBuffer->Vertices_Standard.push_back(vert); } } // Now add the indices // This weird loop turns convex polygons into triangle strips. // I do it this way instead of a simple fan because it usually // looks a lot better in wireframe, for example. u32 h = faces[i].numVerts - 1, l = 0, c; // High, Low, Center for (u32 v = 0; v < faces[i].numVerts - 2; v++) { if (v & 1) // odd c = h - 1; else // even c = l + 1; meshBuffer->Indices.push_back(base + h); meshBuffer->Indices.push_back(base + l); meshBuffer->Indices.push_back(base + c); if (v & 1) // odd h--; else // even l++; } } delete [] verts; delete [] faces; } // delete all buffers without geometry in it. #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Cleaning meshbuffers."); #endif i = 0; while(i < mesh->MeshBuffers.size()) { if (mesh->MeshBuffers[i]->getVertexCount() == 0 || mesh->MeshBuffers[i]->getIndexCount() == 0) { // Meshbuffer is empty -- drop it mesh->MeshBuffers[i]->drop(); mesh->MeshBuffers.erase(i); materiali.erase(i); } else { i++; } } { //load textures and lightmaps in materials. //don't worry if you receive a could not load texture, cause if you don't need //a particular material in your scene it will be loaded and then destroyed. #ifdef _IRR_DMF_DEBUG_ os::Printer::log("Loading textures."); #endif const bool use_mat_dirs=!SceneMgr->getParameters()->getAttributeAsBool(DMF_IGNORE_MATERIALS_DIRS); core::stringc path; if ( SceneMgr->getParameters()->existsAttribute(DMF_TEXTURE_PATH) ) path = SceneMgr->getParameters()->getAttributeAsString(DMF_TEXTURE_PATH); else path = FileSystem->getFileDir(file->getFileName()); path += ('/'); for (i=0; igetMeshBufferCount(); i++) { //texture and lightmap video::ITexture *tex = 0; video::ITexture *lig = 0; //current buffer to apply material video::SMaterial& mat = mesh->getMeshBuffer(i)->getMaterial(); //Primary texture is normal if (materiali[i].textureFlag==0) { if (materiali[i].textureBlend==4) driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true); findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].textureName); tex = driver->getTexture(materiali[i].textureName); } //Primary texture is just a color else if(materiali[i].textureFlag==1) { video::SColor color(axtoi(materiali[i].textureName.c_str())); //just for compatibility with older Irrlicht versions //to support transparent materials if (color.getAlpha()!=255 && materiali[i].textureBlend==4) driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true); video::IImage *immagine= driver->createImage(video::ECF_A8R8G8B8, core::dimension2d(8,8)); immagine->fill(color); tex = driver->addTexture("", immagine); immagine->drop(); //to support transparent materials if (color.getAlpha()!=255 && materiali[i].textureBlend==4) { mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; mat.MaterialTypeParam =(((f32) (color.getAlpha()-1))/255.0f); } } //Lightmap is present if (materiali[i].lightmapFlag == 0) { findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].lightmapName); lig = driver->getTexture(materiali[i].lightmapName); } else //no lightmap { mat.MaterialType = video::EMT_SOLID; const f32 mult = 100.0f - header.dmfShadow; mat.AmbientColor=header.dmfAmbient.getInterpolated(video::SColor(255,0,0,0),mult/100.f); } if (materiali[i].textureBlend==4) { mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; mat.MaterialTypeParam = SceneMgr->getParameters()->getAttributeAsFloat(DMF_ALPHA_CHANNEL_REF); } //if texture is present mirror vertically owing to DeleD representation if (tex && header.dmfVersion<1.1) { const core::dimension2d texsize = tex->getSize(); void* pp = tex->lock(); if (pp) { const video::ECOLOR_FORMAT format = tex->getColorFormat(); if (format == video::ECF_A1R5G5B5) { s16* p = (s16*)pp; s16 tmp=0; for (u32 x=0; xunlock(); tex->regenerateMipMapLevels(); } //if lightmap is present mirror vertically owing to DeleD rapresentation if (lig && header.dmfVersion<1.1) { const core::dimension2d ligsize=lig->getSize(); void* pp = lig->lock(); if (pp) { video::ECOLOR_FORMAT format = lig->getColorFormat(); if (format == video::ECF_A1R5G5B5) { s16* p = (s16*)pp; s16 tmp=0; for (u32 x=0; xunlock(); lig->regenerateMipMapLevels(); } mat.setTexture(0, tex); mat.setTexture(1, lig); } } // create bounding box for (i = 0; i < mesh->MeshBuffers.size(); ++i) { mesh->MeshBuffers[i]->recalculateBoundingBox(); } mesh->recalculateBoundingBox(); // Set up an animated mesh to hold the mesh SAnimatedMesh* AMesh = new SAnimatedMesh(); AMesh->Type = EAMT_UNKNOWN; AMesh->addMesh(mesh); AMesh->recalculateBoundingBox(); mesh->drop(); return AMesh; } /** \brief Tell us if this file is able to be loaded by this class based on the file extension (e.g. ".bsp") \return true if file is loadable.*/ bool CDMFLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "dmf" ); } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_DMF_LOADER_ irrlicht-1.8.3/source/Irrlicht/CDepthBuffer.h0000644000000000000000000000363112574354552017612 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_Z_BUFFER_H_INCLUDED__ #define __C_Z_BUFFER_H_INCLUDED__ #include "IDepthBuffer.h" namespace irr { namespace video { class CDepthBuffer : public IDepthBuffer { public: //! constructor CDepthBuffer(const core::dimension2d& size); //! destructor virtual ~CDepthBuffer(); //! clears the zbuffer virtual void clear(); //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size); //! returns the size of the zbuffer virtual const core::dimension2d& getSize() const; //! locks the zbuffer virtual void* lock() { return (void*) Buffer; } //! unlocks the zbuffer virtual void unlock() {} //! returns pitch of depthbuffer (in bytes) virtual u32 getPitch() const { return Pitch; } private: u8* Buffer; core::dimension2d Size; u32 TotalSize; u32 Pitch; }; class CStencilBuffer : public IStencilBuffer { public: //! constructor CStencilBuffer(const core::dimension2d& size); //! destructor virtual ~CStencilBuffer(); //! clears the zbuffer virtual void clear(); //! sets the new size of the zbuffer virtual void setSize(const core::dimension2d& size); //! returns the size of the zbuffer virtual const core::dimension2d& getSize() const; //! locks the zbuffer virtual void* lock() { return (void*) Buffer; } //! unlocks the zbuffer virtual void unlock() {} //! returns pitch of depthbuffer (in bytes) virtual u32 getPitch() const { return Pitch; } private: u8* Buffer; core::dimension2d Size; u32 TotalSize; u32 Pitch; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CDepthBuffer.cpp0000644000000000000000000000560512574354552020150 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "SoftwareDriver2_compile_config.h" #include "CDepthBuffer.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! constructor CDepthBuffer::CDepthBuffer(const core::dimension2d& size) : Buffer(0), Size(0,0) { #ifdef _DEBUG setDebugName("CDepthBuffer"); #endif setSize(size); } //! destructor CDepthBuffer::~CDepthBuffer() { if (Buffer) delete [] Buffer; } //! clears the zbuffer void CDepthBuffer::clear() { #ifdef SOFTWARE_DRIVER_2_USE_WBUFFER f32 zMax = 0.f; #else f32 zMax = 1.f; #endif u32 zMaxValue; zMaxValue = IR(zMax); memset32 ( Buffer, zMaxValue, TotalSize ); } //! sets the new size of the zbuffer void CDepthBuffer::setSize(const core::dimension2d& size) { if (size == Size) return; Size = size; if (Buffer) delete [] Buffer; Pitch = size.Width * sizeof ( fp24 ); TotalSize = Pitch * size.Height; Buffer = new u8[TotalSize]; clear (); } //! returns the size of the zbuffer const core::dimension2d& CDepthBuffer::getSize() const { return Size; } // ----------------------------------------------------------------- //! constructor CStencilBuffer::CStencilBuffer(const core::dimension2d& size) : Buffer(0), Size(0,0) { #ifdef _DEBUG setDebugName("CDepthBuffer"); #endif setSize(size); } //! destructor CStencilBuffer::~CStencilBuffer() { if (Buffer) delete [] Buffer; } //! clears the zbuffer void CStencilBuffer::clear() { memset32 ( Buffer, 0, TotalSize ); } //! sets the new size of the zbuffer void CStencilBuffer::setSize(const core::dimension2d& size) { if (size == Size) return; Size = size; if (Buffer) delete [] Buffer; Pitch = size.Width * sizeof ( u32 ); TotalSize = Pitch * size.Height; Buffer = new u8[TotalSize]; clear (); } //! returns the size of the zbuffer const core::dimension2d& CStencilBuffer::getSize() const { return Size; } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { //! creates a ZBuffer IDepthBuffer* createDepthBuffer(const core::dimension2d& size) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CDepthBuffer(size); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } //! creates a ZBuffer IStencilBuffer* createStencilBuffer(const core::dimension2d& size) { #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return new CStencilBuffer(size); #else return 0; #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CDefaultSceneNodeFactory.h0000644000000000000000000000534412574354552022117 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_DEFAULT_SCENE_NODE_FACTORY_H_INCLUDED__ #define __C_DEFAULT_SCENE_NODE_FACTORY_H_INCLUDED__ #include "ISceneNodeFactory.h" #include "irrArray.h" #include "irrString.h" namespace irr { namespace scene { class ISceneNode; class ISceneManager; //! Interface making it possible to dynamicly create scene nodes and animators class CDefaultSceneNodeFactory : public ISceneNodeFactory { public: CDefaultSceneNodeFactory(ISceneManager* mgr); //! adds a scene node to the scene graph based on its type id /** \param type: Type of the scene node to add. \param parent: Parent scene node of the new node, can be null to add the scene node to the root. \return Returns pointer to the new scene node or null if not successful. */ virtual ISceneNode* addSceneNode(ESCENE_NODE_TYPE type, ISceneNode* parent=0); //! adds a scene node to the scene graph based on its type name /** \param typeName: Type name of the scene node to add. \param parent: Parent scene node of the new node, can be null to add the scene node to the root. \return Returns pointer to the new scene node or null if not successful. */ virtual ISceneNode* addSceneNode(const c8* typeName, ISceneNode* parent=0); //! returns amount of scene node types this factory is able to create virtual u32 getCreatableSceneNodeTypeCount() const; //! returns type name of a createable scene node type by index /** \param idx: Index of scene node type in this factory. Must be a value between 0 and uetCreatableSceneNodeTypeCount() */ virtual const c8* getCreateableSceneNodeTypeName(u32 idx) const; //! returns type of a createable scene node type /** \param idx: Index of scene node type in this factory. Must be a value between 0 and getCreatableSceneNodeTypeCount() */ virtual ESCENE_NODE_TYPE getCreateableSceneNodeType(u32 idx) const; //! returns type name of a createable scene node type /** \param idx: Type of scene node. \return: Returns name of scene node type if this factory can create the type, otherwise 0. */ virtual const c8* getCreateableSceneNodeTypeName(ESCENE_NODE_TYPE type) const; private: ESCENE_NODE_TYPE getTypeFromName(const c8* name) const; struct SSceneNodeTypePair { SSceneNodeTypePair(ESCENE_NODE_TYPE type, const c8* name) : Type(type), TypeName(name) {} ESCENE_NODE_TYPE Type; core::stringc TypeName; }; core::array SupportedSceneNodeTypes; ISceneManager* Manager; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CDefaultSceneNodeFactory.cpp0000644000000000000000000001473012574354552022451 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CDefaultSceneNodeFactory.h" #include "ISceneManager.h" #include "ITextSceneNode.h" #include "ITerrainSceneNode.h" #include "IDummyTransformationSceneNode.h" #include "ICameraSceneNode.h" #include "IBillboardSceneNode.h" #include "IAnimatedMeshSceneNode.h" #include "IParticleSystemSceneNode.h" #include "ILightSceneNode.h" #include "IMeshSceneNode.h" namespace irr { namespace scene { CDefaultSceneNodeFactory::CDefaultSceneNodeFactory(ISceneManager* mgr) : Manager(mgr) { #ifdef _DEBUG setDebugName("CDefaultSceneNodeFactory"); #endif // don't grab the scene manager here to prevent cyclic references SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CUBE, "cube")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SPHERE, "sphere")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_TEXT, "text")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_WATER_SURFACE, "waterSurface")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_TERRAIN, "terrain")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_BOX, "skyBox")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_DOME, "skyDome")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SHADOW_VOLUME, "shadowVolume")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCTREE, "octree")); // Legacy support SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCTREE, "octTree")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_MESH, "mesh")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_LIGHT, "light")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_EMPTY, "empty")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_DUMMY_TRANSFORMATION, "dummyTransformation")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA, "camera")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_BILLBOARD, "billBoard")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_ANIMATED_MESH, "animatedMesh")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_PARTICLE_SYSTEM, "particleSystem")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_VOLUME_LIGHT, "volumeLight")); // SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_MD3_SCENE_NODE, "md3")); // legacy, for version <= 1.4.x irr files SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA_MAYA, "cameraMaya")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA_FPS, "cameraFPS")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_Q3SHADER_SCENE_NODE, "quake3Shader")); } //! adds a scene node to the scene graph based on its type id ISceneNode* CDefaultSceneNodeFactory::addSceneNode(ESCENE_NODE_TYPE type, ISceneNode* parent) { switch(type) { case ESNT_CUBE: return Manager->addCubeSceneNode(10, parent); case ESNT_SPHERE: return Manager->addSphereSceneNode(5, 16, parent); case ESNT_TEXT: return Manager->addTextSceneNode(0, L"example"); case ESNT_WATER_SURFACE: return Manager->addWaterSurfaceSceneNode(0, 2.0f, 300.0f, 10.0f, parent); case ESNT_TERRAIN: return Manager->addTerrainSceneNode("", parent, -1, core::vector3df(0.0f,0.0f,0.0f), core::vector3df(0.0f,0.0f,0.0f), core::vector3df(1.0f,1.0f,1.0f), video::SColor(255,255,255,255), 4, ETPS_17, 0, true); case ESNT_SKY_BOX: return Manager->addSkyBoxSceneNode(0,0,0,0,0,0, parent); case ESNT_SKY_DOME: return Manager->addSkyDomeSceneNode(0, 16, 8, 0.9f, 2.0f, 1000.0f, parent); case ESNT_SHADOW_VOLUME: return 0; case ESNT_OCTREE: return Manager->addOctreeSceneNode((IMesh*)0, parent, -1, 128, true); case ESNT_MESH: return Manager->addMeshSceneNode(0, parent, -1, core::vector3df(), core::vector3df(), core::vector3df(1,1,1), true); case ESNT_LIGHT: return Manager->addLightSceneNode(parent); case ESNT_EMPTY: return Manager->addEmptySceneNode(parent); case ESNT_DUMMY_TRANSFORMATION: return Manager->addDummyTransformationSceneNode(parent); case ESNT_CAMERA: return Manager->addCameraSceneNode(parent); case ESNT_CAMERA_MAYA: return Manager->addCameraSceneNodeMaya(parent); case ESNT_CAMERA_FPS: return Manager->addCameraSceneNodeFPS(parent); case ESNT_BILLBOARD: return Manager->addBillboardSceneNode(parent); case ESNT_ANIMATED_MESH: return Manager->addAnimatedMeshSceneNode(0, parent, -1, core::vector3df(), core::vector3df(), core::vector3df(1,1,1), true); case ESNT_PARTICLE_SYSTEM: return Manager->addParticleSystemSceneNode(true, parent); case ESNT_VOLUME_LIGHT: return (ISceneNode*)Manager->addVolumeLightSceneNode(parent); default: break; } return 0; } //! adds a scene node to the scene graph based on its type name ISceneNode* CDefaultSceneNodeFactory::addSceneNode(const c8* typeName, ISceneNode* parent) { return addSceneNode( getTypeFromName(typeName), parent ); } //! returns amount of scene node types this factory is able to create u32 CDefaultSceneNodeFactory::getCreatableSceneNodeTypeCount() const { return SupportedSceneNodeTypes.size(); } //! returns type of a createable scene node type ESCENE_NODE_TYPE CDefaultSceneNodeFactory::getCreateableSceneNodeType(u32 idx) const { if (idxgrab(); } CDefaultSceneNodeAnimatorFactory::~CDefaultSceneNodeAnimatorFactory() { if (CursorControl) CursorControl->drop(); } //! creates a scene node animator based on its type id ISceneNodeAnimator* CDefaultSceneNodeAnimatorFactory::createSceneNodeAnimator(ESCENE_NODE_ANIMATOR_TYPE type, ISceneNode* target) { scene::ISceneNodeAnimator* anim = 0; switch(type) { case ESNAT_FLY_CIRCLE: anim = Manager->createFlyCircleAnimator(core::vector3df(0,0,0), 10); break; case ESNAT_FLY_STRAIGHT: anim = Manager->createFlyStraightAnimator(core::vector3df(0,0,0), core::vector3df(100,100,100), 10000, true ); break; case ESNAT_FOLLOW_SPLINE: { core::array points; points.push_back(core::vector3df(0,0,0)); points.push_back(core::vector3df(10,5,10)); anim = Manager->createFollowSplineAnimator(0, points); } break; case ESNAT_ROTATION: anim = Manager->createRotationAnimator(core::vector3df(0.3f,0,0)); break; case ESNAT_TEXTURE: { core::array textures; anim = Manager->createTextureAnimator(textures, 250); } break; case ESNAT_DELETION: anim = Manager->createDeleteAnimator(5000); break; case ESNAT_COLLISION_RESPONSE: anim = Manager->createCollisionResponseAnimator(0, target); break; case ESNAT_CAMERA_FPS: anim = new CSceneNodeAnimatorCameraFPS(CursorControl); break; case ESNAT_CAMERA_MAYA: anim = new CSceneNodeAnimatorCameraMaya(CursorControl); break; default: break; } if (anim && target) target->addAnimator(anim); return anim; } //! creates a scene node animator based on its type name ISceneNodeAnimator* CDefaultSceneNodeAnimatorFactory::createSceneNodeAnimator(const c8* typeName, ISceneNode* target) { return createSceneNodeAnimator( getTypeFromName(typeName), target ); } //! returns amount of scene node animator types this factory is able to create u32 CDefaultSceneNodeAnimatorFactory::getCreatableSceneNodeAnimatorTypeCount() const { return ESNAT_COUNT; } //! returns type of a createable scene node animator type ESCENE_NODE_ANIMATOR_TYPE CDefaultSceneNodeAnimatorFactory::getCreateableSceneNodeAnimatorType(u32 idx) const { if (idxaddButton(core::rect(0,0,100,100),parent); case EGUIET_CHECK_BOX: return Environment->addCheckBox(false, core::rect(0,0,100,100), parent); case EGUIET_COLOR_SELECT_DIALOG: return Environment->addColorSelectDialog(0,true,parent); case EGUIET_COMBO_BOX: return Environment->addComboBox(core::rect(0,0,100,100),parent); case EGUIET_CONTEXT_MENU: return Environment->addContextMenu(core::rect(0,0,100,100),parent); case EGUIET_MENU: return Environment->addMenu(parent); case EGUIET_EDIT_BOX: return Environment->addEditBox(0,core::rect(0,0,100,100),true, parent); case EGUIET_FILE_OPEN_DIALOG: return Environment->addFileOpenDialog(0,true,parent); case EGUIET_IMAGE: return Environment->addImage(0,core::position2di(0,0), true, parent); case EGUIET_IN_OUT_FADER: return Environment->addInOutFader(0,parent); case EGUIET_LIST_BOX: return Environment->addListBox(core::rect(0,0,100,100),parent); case EGUIET_MESH_VIEWER: return Environment->addMeshViewer(core::rect(0,0,100,100),parent); case EGUIET_MODAL_SCREEN: return Environment->addModalScreen(parent); case EGUIET_MESSAGE_BOX: return Environment->addMessageBox(0,0,false,0,parent); case EGUIET_SCROLL_BAR: return Environment->addScrollBar(false,core::rect(0,0,100,100),parent); case EGUIET_STATIC_TEXT: return Environment->addStaticText(0,core::rect(0,0,100,100),false,true,parent); case EGUIET_TAB: return Environment->addTab(core::rect(0,0,100,100),parent); case EGUIET_TAB_CONTROL: return Environment->addTabControl(core::rect(0,0,100,100),parent); case EGUIET_TABLE: return Environment->addTable(core::rect(0,0,100,100), parent); case EGUIET_TOOL_BAR: return Environment->addToolBar(parent); case EGUIET_WINDOW: return Environment->addWindow(core::rect(0,0,100,100),false,0,parent); case EGUIET_SPIN_BOX: return Environment->addSpinBox(L"0.0", core::rect(0,0,100,100), true, parent); case EGUIET_TREE_VIEW: return Environment->addTreeView(core::rect(0,0,100,100),parent); default: return 0; } } //! adds an element to the environment based on its type name IGUIElement* CDefaultGUIElementFactory::addGUIElement(const c8* typeName, IGUIElement* parent) { return addGUIElement( getTypeFromName(typeName), parent ); } //! Returns the amount of element types this factory is able to create. s32 CDefaultGUIElementFactory::getCreatableGUIElementTypeCount() const { return EGUIET_COUNT; } //! Returns the type of a createable element type. EGUI_ELEMENT_TYPE CDefaultGUIElementFactory::getCreateableGUIElementType(s32 idx) const { if (idx>=0 && idx=0 && idx=0 && type namespace irr { namespace video { class CD3D9Driver; // forward declaration for RTT depth buffer handling struct SDepthSurface; /*! interface for a Video Driver dependent Texture. */ class CD3D9Texture : public ITexture { public: //! constructor CD3D9Texture(IImage* image, CD3D9Driver* driver, u32 flags, const io::path& name, void* mipmapData=0); //! rendertarget constructor CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! destructor virtual ~CD3D9Texture(); //! lock function virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0); //! unlock function virtual void unlock(); //! Returns original size of the texture. virtual const core::dimension2d& getOriginalSize() const; //! Returns (=size) of the texture. virtual const core::dimension2d& getSize() const; //! returns driver type of texture (=the driver, who created the texture) virtual E_DRIVER_TYPE getDriverType() const; //! returns color format of texture virtual ECOLOR_FORMAT getColorFormat() const; //! returns pitch of texture (in bytes) virtual u32 getPitch() const; //! returns the DIRECT3D9 Texture IDirect3DBaseTexture9* getDX9Texture() const; //! returns if texture has mipmap levels bool hasMipMaps() const; //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture virtual void regenerateMipMapLevels(void* mipmapData=0); //! returns if it is a render target virtual bool isRenderTarget() const; //! Returns pointer to the render target surface IDirect3DSurface9* getRenderTargetSurface(); private: friend class CD3D9Driver; void createRenderTarget(const ECOLOR_FORMAT format = ECF_UNKNOWN); //! creates the hardware texture bool createTexture(u32 flags, IImage * image); //! copies the image to the texture bool copyTexture(IImage * image); //! Helper function for mipmap generation. bool createMipMaps(u32 level=1); //! Helper function for mipmap generation. void copy16BitMipMap(char* src, char* tgt, s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const; //! Helper function for mipmap generation. void copy32BitMipMap(char* src, char* tgt, s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const; //! set Pitch based on the d3d format void setPitch(D3DFORMAT d3dformat); IDirect3DDevice9* Device; IDirect3DTexture9* Texture; IDirect3DSurface9* RTTSurface; CD3D9Driver* Driver; SDepthSurface* DepthSurface; core::dimension2d TextureSize; core::dimension2d ImageSize; s32 Pitch; u32 MipLevelLocked; ECOLOR_FORMAT ColorFormat; bool HasMipMaps; bool HardwareMipMaps; bool IsRenderTarget; }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ #endif // __C_DIRECTX9_TEXTURE_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CD3D9Texture.cpp0000644000000000000000000004156612574354552020004 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE #include "CD3D9Texture.h" #include "CD3D9Driver.h" #include "os.h" #include #ifndef _IRR_COMPILE_WITH_DIRECT3D_8_ // The D3DXFilterTexture function seems to get linked wrong when // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. // So mipmapgeneration is replaced with my own bad generation in d3d 8 when // compiling with both D3D 8 and 9. // #define _IRR_USE_D3DXFilterTexture_ #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ #ifdef _IRR_USE_D3DXFilterTexture_ #pragma comment(lib, "d3dx9.lib") #endif namespace irr { namespace video { //! rendertarget constructor CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0), TextureSize(size), ImageSize(size), Pitch(0), ColorFormat(ECF_UNKNOWN), HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(true) { #ifdef _DEBUG setDebugName("CD3D9Texture"); #endif Device=driver->getExposedVideoData().D3D9.D3DDev9; if (Device) Device->AddRef(); createRenderTarget(format); } //! constructor CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver, u32 flags, const io::path& name, void* mipmapData) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0), TextureSize(0,0), ImageSize(0,0), Pitch(0), ColorFormat(ECF_UNKNOWN), HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false) { #ifdef _DEBUG setDebugName("CD3D9Texture"); #endif HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); Device=driver->getExposedVideoData().D3D9.D3DDev9; if (Device) Device->AddRef(); if (image) { if (createTexture(flags, image)) { if (copyTexture(image)) { regenerateMipMapLevels(mipmapData); } } else os::Printer::log("Could not create DIRECT3D9 Texture.", ELL_WARNING); } } //! destructor CD3D9Texture::~CD3D9Texture() { if (Texture) Texture->Release(); if (RTTSurface) RTTSurface->Release(); // if this texture was the last one using the depth buffer // we can release the surface. We only use the value of the pointer // hence it is safe to use the dropped pointer... if (DepthSurface) { if (DepthSurface->drop()) Driver->removeDepthSurface(DepthSurface); } if (Device) Device->Release(); } void CD3D9Texture::createRenderTarget(const ECOLOR_FORMAT format) { // are texture size restrictions there ? if(!Driver->queryFeature(EVDF_TEXTURE_NPOT)) { if (TextureSize != ImageSize) os::Printer::log("RenderTarget size has to be a power of two", ELL_INFORMATION); } TextureSize = TextureSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth); D3DFORMAT d3dformat = Driver->getD3DColorFormat(); if(ColorFormat == ECF_UNKNOWN) { // get irrlicht format from backbuffer // (This will get overwritten by the custom format if it is provided, else kept.) ColorFormat = Driver->getColorFormat(); setPitch(d3dformat); // Use color format if provided. if(format != ECF_UNKNOWN) { ColorFormat = format; d3dformat = Driver->getD3DFormatFromColorFormat(format); setPitch(d3dformat); // This will likely set pitch to 0 for now. } } else { d3dformat = Driver->getD3DFormatFromColorFormat(ColorFormat); } // create texture HRESULT hr; hr = Device->CreateTexture( TextureSize.Width, TextureSize.Height, 1, // mip map level count, we don't want mipmaps here D3DUSAGE_RENDERTARGET, d3dformat, D3DPOOL_DEFAULT, &Texture, NULL); if (FAILED(hr)) { if (D3DERR_INVALIDCALL == hr) os::Printer::log("Could not create render target texture", "Invalid Call"); else if (D3DERR_OUTOFVIDEOMEMORY == hr) os::Printer::log("Could not create render target texture", "Out of Video Memory"); else if (E_OUTOFMEMORY == hr) os::Printer::log("Could not create render target texture", "Out of Memory"); else os::Printer::log("Could not create render target texture"); } } bool CD3D9Texture::createMipMaps(u32 level) { if (level==0) return true; if (HardwareMipMaps && Texture) { // generate mipmaps in hardware Texture->GenerateMipSubLevels(); return true; } // manual mipmap generation IDirect3DSurface9* upperSurface = 0; IDirect3DSurface9* lowerSurface = 0; // get upper level HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface); if (FAILED(hr) || !upperSurface) { os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING); return false; } // get lower level hr = Texture->GetSurfaceLevel(level, &lowerSurface); if (FAILED(hr) || !lowerSurface) { os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING); upperSurface->Release(); return false; } D3DSURFACE_DESC upperDesc, lowerDesc; upperSurface->GetDesc(&upperDesc); lowerSurface->GetDesc(&lowerDesc); D3DLOCKED_RECT upperlr; D3DLOCKED_RECT lowerlr; // lock upper surface if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0))) { upperSurface->Release(); lowerSurface->Release(); os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING); return false; } // lock lower surface if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0))) { upperSurface->UnlockRect(); upperSurface->Release(); lowerSurface->Release(); os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING); return false; } if (upperDesc.Format != lowerDesc.Format) { os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING); } else { if ((upperDesc.Format == D3DFMT_A1R5G5B5) || (upperDesc.Format == D3DFMT_R5G6B5)) copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits, lowerDesc.Width, lowerDesc.Height, upperlr.Pitch, lowerlr.Pitch); else if (upperDesc.Format == D3DFMT_A8R8G8B8) copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits, lowerDesc.Width, lowerDesc.Height, upperlr.Pitch, lowerlr.Pitch); else os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING); } bool result=true; // unlock if (FAILED(upperSurface->UnlockRect())) result=false; if (FAILED(lowerSurface->UnlockRect())) result=false; // release upperSurface->Release(); lowerSurface->Release(); if (!result || (upperDesc.Width <= 3 && upperDesc.Height <= 3)) return result; // stop generating levels // generate next level return createMipMaps(level+1); } //! creates the hardware texture bool CD3D9Texture::createTexture(u32 flags, IImage * image) { ImageSize = image->getDimension(); core::dimension2d optSize = ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth); D3DFORMAT format = D3DFMT_A1R5G5B5; switch(getTextureFormatFromFlags(flags)) { case ETCF_ALWAYS_16_BIT: format = D3DFMT_A1R5G5B5; break; case ETCF_ALWAYS_32_BIT: format = D3DFMT_A8R8G8B8; break; case ETCF_OPTIMIZED_FOR_QUALITY: { switch(image->getColorFormat()) { case ECF_R8G8B8: case ECF_A8R8G8B8: format = D3DFMT_A8R8G8B8; break; case ECF_A1R5G5B5: case ECF_R5G6B5: format = D3DFMT_A1R5G5B5; break; } } break; case ETCF_OPTIMIZED_FOR_SPEED: format = D3DFMT_A1R5G5B5; break; default: break; } if (Driver->getTextureCreationFlag(video::ETCF_NO_ALPHA_CHANNEL)) { if (format == D3DFMT_A8R8G8B8) format = D3DFMT_R8G8B8; else if (format == D3DFMT_A1R5G5B5) format = D3DFMT_R5G6B5; } const bool mipmaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); DWORD usage = 0; // This enables hardware mip map generation. if (mipmaps && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) { LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9; D3DDISPLAYMODE d3ddm; intf->GetAdapterDisplayMode(Driver->Params.DisplayAdapter, &d3ddm); if (D3D_OK==intf->CheckDeviceFormat(Driver->Params.DisplayAdapter,D3DDEVTYPE_HAL,d3ddm.Format,D3DUSAGE_AUTOGENMIPMAP,D3DRTYPE_TEXTURE,format)) { usage = D3DUSAGE_AUTOGENMIPMAP; HardwareMipMaps = true; } } HRESULT hr = Device->CreateTexture(optSize.Width, optSize.Height, mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all) usage, // usage format, D3DPOOL_MANAGED , &Texture, NULL); if (FAILED(hr)) { // try brute force 16 bit HardwareMipMaps = false; if (format == D3DFMT_A8R8G8B8) format = D3DFMT_A1R5G5B5; else if (format == D3DFMT_R8G8B8) format = D3DFMT_R5G6B5; else return false; hr = Device->CreateTexture(optSize.Width, optSize.Height, mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all) 0, format, D3DPOOL_MANAGED, &Texture, NULL); } ColorFormat = Driver->getColorFormatFromD3DFormat(format); setPitch(format); return (SUCCEEDED(hr)); } //! copies the image to the texture bool CD3D9Texture::copyTexture(IImage * image) { if (Texture && image) { D3DSURFACE_DESC desc; Texture->GetLevelDesc(0, &desc); TextureSize.Width = desc.Width; TextureSize.Height = desc.Height; D3DLOCKED_RECT rect; HRESULT hr = Texture->LockRect(0, &rect, 0, 0); if (FAILED(hr)) { os::Printer::log("Texture data not copied", "Could not LockRect D3D9 Texture.", ELL_ERROR); return false; } Pitch = rect.Pitch; image->copyToScaling(rect.pBits, TextureSize.Width, TextureSize.Height, ColorFormat, Pitch); hr = Texture->UnlockRect(0); if (FAILED(hr)) { os::Printer::log("Texture data not copied", "Could not UnlockRect D3D9 Texture.", ELL_ERROR); return false; } } return true; } //! lock function void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) { if (!Texture) return 0; MipLevelLocked=mipmapLevel; HRESULT hr; D3DLOCKED_RECT rect; if(!IsRenderTarget) { hr = Texture->LockRect(mipmapLevel, &rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); return 0; } } else { if (!RTTSurface) { // Make RTT surface large enough for all miplevels (including 0) D3DSURFACE_DESC desc; Texture->GetLevelDesc(0, &desc); hr = Device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &RTTSurface, 0); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D9 Texture", "Offscreen surface creation failed.", ELL_ERROR); return 0; } } IDirect3DSurface9 *surface = 0; hr = Texture->GetSurfaceLevel(mipmapLevel, &surface); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D9 Texture", "Could not get surface.", ELL_ERROR); return 0; } hr = Device->GetRenderTargetData(surface, RTTSurface); surface->Release(); if(FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR); return 0; } hr = RTTSurface->LockRect(&rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0); if(FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR); return 0; } } return rect.pBits; } //! unlock function void CD3D9Texture::unlock() { if (!Texture) return; if (!IsRenderTarget) Texture->UnlockRect(MipLevelLocked); else if (RTTSurface) RTTSurface->UnlockRect(); } //! Returns original size of the texture. const core::dimension2d& CD3D9Texture::getOriginalSize() const { return ImageSize; } //! Returns (=size) of the texture. const core::dimension2d& CD3D9Texture::getSize() const { return TextureSize; } //! returns driver type of texture (=the driver, who created the texture) E_DRIVER_TYPE CD3D9Texture::getDriverType() const { return EDT_DIRECT3D9; } //! returns color format of texture ECOLOR_FORMAT CD3D9Texture::getColorFormat() const { return ColorFormat; } //! returns pitch of texture (in bytes) u32 CD3D9Texture::getPitch() const { return Pitch; } //! returns the DIRECT3D9 Texture IDirect3DBaseTexture9* CD3D9Texture::getDX9Texture() const { return Texture; } //! returns if texture has mipmap levels bool CD3D9Texture::hasMipMaps() const { return HasMipMaps; } void CD3D9Texture::copy16BitMipMap(char* src, char* tgt, s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const { for (s32 y=0; y1) size.Width /=2; if (size.Height>1) size.Height /=2; ++level; IDirect3DSurface9* mipSurface = 0; HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface); if (FAILED(hr) || !mipSurface) { os::Printer::log("Could not get mipmap level", ELL_WARNING); return; } D3DSURFACE_DESC mipDesc; mipSurface->GetDesc(&mipDesc); D3DLOCKED_RECT miplr; // lock mipmap surface if (FAILED(mipSurface->LockRect(&miplr, NULL, 0))) { mipSurface->Release(); os::Printer::log("Could not lock texture", ELL_WARNING); return; } memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width); mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width; // unlock mipSurface->UnlockRect(); // release mipSurface->Release(); } while (size.Width != 1 || size.Height != 1); } else if (HasMipMaps) { // create mip maps. #ifdef _IRR_USE_D3DXFilterTexture_ // The D3DXFilterTexture function seems to get linked wrong when // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. // So mipmapgeneration is replaced with my own bad generation HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT, D3DX_DEFAULT); if (FAILED(hr)) #endif createMipMaps(); } } //! returns if it is a render target bool CD3D9Texture::isRenderTarget() const { return IsRenderTarget; } //! Returns pointer to the render target surface IDirect3DSurface9* CD3D9Texture::getRenderTargetSurface() { if (!IsRenderTarget) return 0; IDirect3DSurface9 *pRTTSurface = 0; if (Texture) Texture->GetSurfaceLevel(0, &pRTTSurface); if (pRTTSurface) pRTTSurface->Release(); return pRTTSurface; } void CD3D9Texture::setPitch(D3DFORMAT d3dformat) { switch(d3dformat) { case D3DFMT_X1R5G5B5: case D3DFMT_A1R5G5B5: Pitch = TextureSize.Width * 2; break; case D3DFMT_A8B8G8R8: case D3DFMT_A8R8G8B8: case D3DFMT_X8R8G8B8: Pitch = TextureSize.Width * 4; break; case D3DFMT_R5G6B5: Pitch = TextureSize.Width * 2; break; case D3DFMT_R8G8B8: Pitch = TextureSize.Width * 3; break; default: Pitch = 0; }; } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ irrlicht-1.8.3/source/Irrlicht/CD3D9ShaderMaterialRenderer.h0000644000000000000000000000646112574354552022360 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_D3D9_SHADER_MATERIAL_RENDERER_H_INCLUDED__ #define __C_D3D9_SHADER_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_WINDOWS_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #include "irrMath.h" // needed by borland for sqrtf define #endif #include #include "IMaterialRenderer.h" namespace irr { namespace video { class IVideoDriver; class IShaderConstantSetCallBack; class IMaterialRenderer; //! Class for using vertex and pixel shaders with D3D9 class CD3D9ShaderMaterialRenderer : public IMaterialRenderer { public: //! Public constructor CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData); //! Destructor ~CD3D9ShaderMaterialRenderer(); virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services); virtual void OnUnsetMaterial(); virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); //! Returns if the material is transparent. virtual bool isTransparent() const; protected: //! constructor only for use by derived classes who want to //! create a fall back material for example. CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData=0); void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram); bool createPixelShader(const c8* pxsh); bool createVertexShader(const char* vtxsh); HRESULT stubD3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs); HRESULT stubD3DXAssembleShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs); HRESULT stubD3DXCompileShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable); HRESULT stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable); IDirect3DDevice9* pID3DDevice; video::IVideoDriver* Driver; IShaderConstantSetCallBack* CallBack; IMaterialRenderer* BaseMaterial; IDirect3DVertexShader9* VertexShader; IDirect3DVertexShader9* OldVertexShader; IDirect3DPixelShader9* PixelShader; s32 UserData; }; } // end namespace video } // end namespace irr #endif #endif #endif irrlicht-1.8.3/source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp0000644000000000000000000003575712574354552022725 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #include "CD3D9ShaderMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" #include "IMaterialRendererServices.h" #include "IVideoDriver.h" #include "os.h" #include "irrString.h" #ifndef _IRR_D3D_NO_SHADER_DEBUGGING #include #endif namespace irr { namespace video { //! Public constructor CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData) { #ifdef _DEBUG setDebugName("CD3D9ShaderMaterialRenderer"); #endif if (BaseMaterial) BaseMaterial->grab(); if (CallBack) CallBack->grab(); init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram); } //! constructor only for use by derived classes who want to //! create a fall back material for example. CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData) { #ifdef _DEBUG setDebugName("CD3D9ShaderMaterialRenderer"); #endif if (BaseMaterial) BaseMaterial->grab(); if (CallBack) CallBack->grab(); } void CD3D9ShaderMaterialRenderer::init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram) { outMaterialTypeNr = -1; // create vertex shader if (!createVertexShader(vertexShaderProgram)) return; // create pixel shader if (!createPixelShader(pixelShaderProgram)) return; // register myself as new material outMaterialTypeNr = Driver->addMaterialRenderer(this); } //! Destructor CD3D9ShaderMaterialRenderer::~CD3D9ShaderMaterialRenderer() { if (CallBack) CallBack->drop(); if (VertexShader) VertexShader->Release(); if (PixelShader) PixelShader->Release(); if (BaseMaterial) BaseMaterial->drop(); } bool CD3D9ShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { // call callback to set shader constants if (CallBack && (VertexShader || PixelShader)) CallBack->OnSetConstants(service, UserData); return true; } void CD3D9ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services) { if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (VertexShader) { // save old vertex shader pID3DDevice->GetVertexShader(&OldVertexShader); // set new vertex shader if (FAILED(pID3DDevice->SetVertexShader(VertexShader))) os::Printer::log("Could not set vertex shader.", ELL_WARNING); } // set new pixel shader if (PixelShader) { if (FAILED(pID3DDevice->SetPixelShader(PixelShader))) os::Printer::log("Could not set pixel shader.", ELL_WARNING); } if (BaseMaterial) BaseMaterial->OnSetMaterial(material, material, true, services); } //let callback know used material if (CallBack) CallBack->OnSetMaterial(material); services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } void CD3D9ShaderMaterialRenderer::OnUnsetMaterial() { if (VertexShader) pID3DDevice->SetVertexShader(OldVertexShader); if (PixelShader) pID3DDevice->SetPixelShader(0); if (BaseMaterial) BaseMaterial->OnUnsetMaterial(); } //! Returns if the material is transparent. The scene managment needs to know this //! for being able to sort the materials by opaque and transparent. bool CD3D9ShaderMaterialRenderer::isTransparent() const { return BaseMaterial ? BaseMaterial->isTransparent() : false; } bool CD3D9ShaderMaterialRenderer::createPixelShader(const c8* pxsh) { if (!pxsh) return true; // compile shader LPD3DXBUFFER code = 0; LPD3DXBUFFER errors = 0; #ifdef _IRR_D3D_NO_SHADER_DEBUGGING // compile shader without debug info stubD3DXAssembleShader(pxsh, (UINT)strlen(pxsh), 0, 0, 0, &code, &errors); #else // compile shader and emitt some debug informations to // make it possible to debug the shader in visual studio static int irr_dbg_file_nr = 0; ++irr_dbg_file_nr; char tmp[32]; sprintf(tmp, "irr_d3d9_dbg_shader_%d.psh", irr_dbg_file_nr); FILE* f = fopen(tmp, "wb"); fwrite(pxsh, strlen(pxsh), 1, f); fflush(f); fclose(f); stubD3DXAssembleShaderFromFile(tmp, 0, 0, D3DXSHADER_DEBUG, &code, &errors); #endif if (errors) { // print out compilation errors. os::Printer::log("Pixel shader compilation failed:", ELL_ERROR); os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR); if (code) code->Release(); errors->Release(); return false; } if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)code->GetBufferPointer(), &PixelShader))) { os::Printer::log("Could not create pixel shader.", ELL_ERROR); code->Release(); return false; } code->Release(); return true; } bool CD3D9ShaderMaterialRenderer::createVertexShader(const char* vtxsh) { if (!vtxsh) return true; // compile shader LPD3DXBUFFER code = 0; LPD3DXBUFFER errors = 0; #ifdef _IRR_D3D_NO_SHADER_DEBUGGING // compile shader without debug info stubD3DXAssembleShader(vtxsh, (UINT)strlen(vtxsh), 0, 0, 0, &code, &errors); #else // compile shader and emitt some debug informations to // make it possible to debug the shader in visual studio static int irr_dbg_file_nr = 0; ++irr_dbg_file_nr; char tmp[32]; sprintf(tmp, "irr_d3d9_dbg_shader_%d.vsh", irr_dbg_file_nr); FILE* f = fopen(tmp, "wb"); fwrite(vtxsh, strlen(vtxsh), 1, f); fflush(f); fclose(f); stubD3DXAssembleShaderFromFile(tmp, 0, 0, D3DXSHADER_DEBUG, &code, &errors); #endif if (errors) { // print out compilation errors. os::Printer::log("Vertex shader compilation failed:", ELL_ERROR); os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR); if (code) code->Release(); errors->Release(); return false; } if (!code || FAILED(pID3DDevice->CreateVertexShader((DWORD*)code->GetBufferPointer(), &VertexShader))) { os::Printer::log("Could not create vertex shader.", ELL_ERROR); if (code) code->Release(); return false; } code->Release(); return true; } HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs) { // Because Irrlicht needs to be able to start up even without installed d3d dlls, it // needs to load external d3d dlls manually. examples for the dlls are: // SDK dll name D3DX_SDK_VERSION // Summer 2004: no dll 22 // February 2005: d3dx9_24.dll 24 // April 2005: d3dx9_25.dll 25 // June 2005: d3dx9_26.dll 26 // August 2005: d3dx9_27.dll 27 // October 2005, // December 2005: d3dx9_28.dll 28 #if ( D3DX_SDK_VERSION < 24 ) // directly link functions, old d3d sdks didn't try to load external dlls // when linking to the d3dx9.lib #ifdef _MSC_VER #pragma comment (lib, "d3dx9.lib") #endif // invoke static linked function return D3DXAssembleShader(pSrcData, SrcDataLen, pDefines, pInclude, Flags, ppShader, ppErrorMsgs); #else { // try to load shader functions from the dll and print error if failed. // D3DXAssembleShader signature typedef HRESULT (WINAPI *AssembleShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs); static bool LoadFailed = false; static AssembleShaderFunction pFn = 0; if (!pFn && !LoadFailed) { // try to load dll io::path strDllName = "d3dx9_"; strDllName += (int)D3DX_SDK_VERSION; strDllName += ".dll"; HMODULE hMod = LoadLibrary(strDllName.c_str()); if (hMod) pFn = (AssembleShaderFunction)GetProcAddress(hMod, "D3DXAssembleShader"); if (!pFn) { LoadFailed = true; os::Printer::log("Could not load shader function D3DXAssembleShader from dll, shaders disabled", strDllName.c_str(), ELL_ERROR); } } if (pFn) { // call already loaded function return (*pFn)(pSrcData, SrcDataLen, pDefines, pInclude, Flags, ppShader, ppErrorMsgs); } } #endif // D3DX_SDK_VERSION < 24 return 0; } HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs) { // wondering what I'm doing here? // see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader() #if ( D3DX_SDK_VERSION < 24 ) // directly link functions, old d3d sdks didn't try to load external dlls // when linking to the d3dx9.lib #ifdef _MSC_VER #pragma comment (lib, "d3dx9.lib") #endif // invoke static linked function return D3DXAssembleShaderFromFileA(pSrcFile, pDefines, pInclude, Flags, ppShader, ppErrorMsgs); #else { // try to load shader functions from the dll and print error if failed. // D3DXAssembleShaderFromFileA signature typedef HRESULT (WINAPI *AssembleShaderFromFileFunction)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs); static bool LoadFailed = false; static AssembleShaderFromFileFunction pFn = 0; if (!pFn && !LoadFailed) { // try to load dll io::path strDllName = "d3dx9_"; strDllName += (int)D3DX_SDK_VERSION; strDllName += ".dll"; HMODULE hMod = LoadLibrary(strDllName.c_str()); if (hMod) pFn = (AssembleShaderFromFileFunction)GetProcAddress(hMod, "D3DXAssembleShaderFromFileA"); if (!pFn) { LoadFailed = true; os::Printer::log("Could not load shader function D3DXAssembleShaderFromFileA from dll, shaders disabled", strDllName.c_str(), ELL_ERROR); } } if (pFn) { // call already loaded function return (*pFn)(pSrcFile, pDefines, pInclude, Flags, ppShader, ppErrorMsgs); } } #endif // D3DX_SDK_VERSION < 24 return 0; } HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable) { // wondering what I'm doing here? // see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader() #if ( D3DX_SDK_VERSION < 24 ) // directly link functions, old d3d sdks didn't try to load external dlls // when linking to the d3dx9.lib #ifdef _MSC_VER #pragma comment (lib, "d3dx9.lib") #endif // invoke static linked function return D3DXCompileShader(pSrcData, SrcDataLen, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable); #else { // try to load shader functions from the dll and print error if failed. // D3DXCompileShader typedef HRESULT (WINAPI *D3DXCompileShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable); static bool LoadFailed = false; static D3DXCompileShaderFunction pFn = 0; if (!pFn && !LoadFailed) { // try to load dll io::path strDllName = "d3dx9_"; strDllName += (int)D3DX_SDK_VERSION; strDllName += ".dll"; HMODULE hMod = LoadLibrary(strDllName.c_str()); if (hMod) pFn = (D3DXCompileShaderFunction)GetProcAddress(hMod, "D3DXCompileShader"); if (!pFn) { LoadFailed = true; os::Printer::log("Could not load shader function D3DXCompileShader from dll, shaders disabled", strDllName.c_str(), ELL_ERROR); } } if (pFn) { // call already loaded function return (*pFn)(pSrcData, SrcDataLen, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable); } } #endif // D3DX_SDK_VERSION < 24 return 0; } HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable) { // wondering what I'm doing here? // see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader() #if ( D3DX_SDK_VERSION < 24 ) // directly link functions, old d3d sdks didn't try to load external dlls // when linking to the d3dx9.lib #ifdef _MSC_VER #pragma comment (lib, "d3dx9.lib") #endif // invoke static linked function return D3DXCompileShaderFromFileA(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable); #else { // try to load shader functions from the dll and print error if failed. // D3DXCompileShaderFromFileA typedef HRESULT (WINAPI *D3DXCompileShaderFromFileFunction)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable); static bool LoadFailed = false; static D3DXCompileShaderFromFileFunction pFn = 0; if (!pFn && !LoadFailed) { // try to load dll io::path strDllName = "d3dx9_"; strDllName += (int)D3DX_SDK_VERSION; strDllName += ".dll"; HMODULE hMod = LoadLibrary(strDllName.c_str()); if (hMod) pFn = (D3DXCompileShaderFromFileFunction)GetProcAddress(hMod, "D3DXCompileShaderFromFileA"); if (!pFn) { LoadFailed = true; os::Printer::log("Could not load shader function D3DXCompileShaderFromFileA from dll, shaders disabled", strDllName.c_str(), ELL_ERROR); } } if (pFn) { // call already loaded function return (*pFn)(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable); } } #endif // D3DX_SDK_VERSION < 24 return 0; } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ irrlicht-1.8.3/source/Irrlicht/CD3D9ParallaxMapRenderer.h0000644000000000000000000000333612574354552021673 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_D3D9_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__ #define __C_D3D9_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_WINDOWS_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #include "irrMath.h" // needed by borland for sqrtf define #endif #include #include "CD3D9ShaderMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" namespace irr { namespace video { //! Renderer for normal maps using parallax mapping class CD3D9ParallaxMapRenderer : public CD3D9ShaderMaterialRenderer, IShaderConstantSetCallBack { public: CD3D9ParallaxMapRenderer( IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial); ~CD3D9ParallaxMapRenderer(); //! Called by the engine when the vertex and/or pixel shader constants for an //! material renderer should be set. virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData); virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); //! Returns the render capability of the material. virtual s32 getRenderCapability() const; virtual void OnSetMaterial(const SMaterial& material) { } virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services); private: f32 CurrentScale; }; } // end namespace video } // end namespace irr #endif #endif #endif irrlicht-1.8.3/source/Irrlicht/CD3D9ParallaxMapRenderer.cpp0000644000000000000000000003536112574354552022231 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #include "CD3D9ParallaxMapRenderer.h" #include "IMaterialRendererServices.h" #include "IVideoDriver.h" #include "os.h" #include "SLight.h" //#define SHADER_EXTERNAL_DEBUG #ifdef SHADER_EXTERNAL_DEBUG #include "CReadFile.h" #endif namespace irr { namespace video { // 1.1/1.4 Shaders with two lights and vertex based attenuation // Irrlicht Engine D3D9 render path normal map vertex shader const char D3D9_PARALLAX_MAP_VSH[] = ";Irrlicht Engine 0.10 D3D9 render path parallax mapping vertex shader\n"\ "; c0-3: Transposed world matrix \n"\ "; c4: Eye position \n"\ "; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\ "; c12: Light01 position \n"\ "; c13: x,y,z: Light01 color; .w: 1/LightRadius² \n"\ "; c14: Light02 position \n"\ "; c15: x,y,z: Light02 color; .w: 1/LightRadius² \n"\ "vs.1.1\n"\ "dcl_position v0 ; position \n"\ "dcl_normal v1 ; normal \n"\ "dcl_color v2 ; color \n"\ "dcl_texcoord0 v3 ; texture coord \n"\ "dcl_texcoord1 v4 ; tangent \n"\ "dcl_texcoord2 v5 ; binormal \n"\ "\n"\ "def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\ "def c96, -1, 1, 1, 1 ; somewhere I've got a bug. flipping the vectors with this fixes it. \n"\ "\n"\ "m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\ "\n"\ "m3x3 r5, v4, c0 ; transform tangent U\n"\ "m3x3 r7, v1, c0 ; transform normal W\n"\ "m3x3 r6, v5, c0 ; transform binormal V\n"\ "\n"\ "m4x4 r4, v0, c0 ; vertex into world position\n"\ "add r2, c12, -r4 ; vtxpos - light1 pos\n"\ "add r3, c14, -r4 ; vtxpos - light2 pos\n"\ "add r1, -c4, r4 ; eye - vtxpos \n"\ "\n"\ "dp3 r8.x, r5, r2 ; transform the light1 vector with U, V, W\n"\ "dp3 r8.y, r6, r2 \n"\ "dp3 r8.z, r7, r2 \n"\ "dp3 r9.x, r5, r3 ; transform the light2 vector with U, V, W\n"\ "dp3 r9.y, r6, r3 \n"\ "dp3 r9.z, r7, r3 \n"\ "dp3 r10.x, r5, r1 ; transform the eye vector with U, V, W\n"\ "dp3 r10.y, r6, r1 \n"\ "dp3 r10.z, r7, r1 \n"\ "\n"\ "dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\ "rsq r8.w, r8.w \n"\ "mul r8, r8, r8.w \n"\ ";mul r8, r8, c96 \n"\ "dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\ "rsq r9.w, r9.w \n"\ "mul r9, r9, r9.w \n"\ ";mul r9, r9, c96 \n"\ "dp3 r10.w, r10, r10 ; normalize eye vector (r10)\n"\ "rsq r10.w, r10.w \n"\ "mul r10, r10, r10.w \n"\ "mul r10, r10, c96 \n"\ "\n"\ "\n"\ "mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\ "mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\ "mad oT4.xyz, r10.xyz, c95, c95 ; move eye vector from -1..1 into 0..1 \n"\ "\n"\ " ; calculate attenuation of light 1 \n"\ "dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x² + r2.y² + r2.z² \n"\ "mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\ "rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\ "mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\ "\n"\ " ; calculate attenuation of light 2 \n"\ "dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x² + r3.y² + r3.z² \n"\ "mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\ "rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\ "mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\ "\n"\ "mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\ "mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\ "mov oD0.a, v2.a ; move out original alpha value \n"\ "\n"; // Irrlicht Engine D3D9 render path normal map pixel shader version 1.4 const char D3D9_PARALLAX_MAP_PSH[] = ";Irrlicht Engine 0.10 D3D9 render path parallax mapping pixel shader \n"\ ";Input: \n"\ ";t0: color map texture coord \n"\ ";t1: normal map texture coords \n"\ ";t2: light 1 vector in tangent space \n"\ ";t4: eye vector in tangent space \n"\ ";v0: light 1 color \n"\ ";t3: light 2 vector in tangent space \n"\ ";v1: light 2 color \n"\ ";v0.a: vertex alpha value \n"\ " \n"\ "ps.1.4 \n"\ " \n"\ ";def c6, 0.02f, 0.02f, 0.02f, 0.0f ; scale factor, now set in callback \n"\ "def c5, 0.5f, 0.5f, 0.5f, 0.0f ; for specular division \n"\ " \n"\ "texld r1, t1 ; sample (normal.x, normal.y, normal.z, height) \n"\ "texcrd r4.xyz, t4 ; fetch eye vector \n"\ "texcrd r0.xyz, t0 ; color map \n"\ " \n"\ "; original parallax mapping: \n"\ ";mul r3, r1_bx2.wwww, c6; ; r3 = (height, height, height) * scale \n"\ ";mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\ " \n"\ "; modified parallax mapping to reduce swimming effect: \n"\ "mul r3, r1_bx2.wwww, r1_bx2.zzzz ; (nh,nh,nh,nh) = (h,h,h,h) * (n.z,n.z,n.z,n.z,) \n"\ "mul r3, r3, c6; ; r3 = (nh, nh, nh) * scale \n"\ "mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\ " \n"\ "phase \n"\ " \n"\ "texld r0, r2 ; load diffuse texture with new tex coord \n"\ "texld r1, r2 ; sample normal map \n"\ "texcrd r2.xyz, t2 ; fetch light vector 1 \n"\ "texcrd r3.xyz, t3 ; fetch light vector 2 \n"\ " \n"\ "dp3_sat r5, r1_bx2, r2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1) \n"\ "mul r5, r5, v0 ; luminance1 * light color 1 \n"\ " \n"\ "dp3_sat r3, r1_bx2, r3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1) \n"\ "mad r3, r3, v1, r5 ; (luminance2 * light color 2) + luminance1 \n"\ " \n"\ "mul r0.xyz, r0, r3 ; total luminance * base color \n"\ "+mov r0.a, v0.a ; write original alpha value \n"\ "\n"; // Irrlicht Engine D3D9 render path normal map pixel shader version 2.0 const char D3D9_PARALLAX_MAP_PSH_20[] = ";Irrlicht Engine D3D9 render path parallax mapping pixel shader \n"\ ";Input: \n"\ " \n"\ ";t0: color map texture coord \n"\ ";t1: normal map texture coords \n"\ ";t2: light 1 vector in tangent space \n"\ ";t4: eye vector in tangent space \n"\ ";v0: light 1 color \n"\ ";t3: light 2 vector in tangent space \n"\ ";v1: light 2 color \n"\ ";v0.a: vertex alpha value \n"\ " \n"\ "ps.2.0 \n"\ " \n"\ "dcl_2d s0 ; Declare the s0 register to be the sampler for stage 0 \n"\ "dcl t0.xy ; Declare t0 to have 2D texture coordinates from stage 0 \n"\ "dcl t1.xy ; Declare t0 to have 2D texture coordinates from stage 0 \n"\ "dcl_2d s1 ; Declare the s1 register to be the sampler for stage 1 \n"\ " \n"\ "dcl t2.xyz ; \n"\ "dcl t3.xyz ; \n"\ "dcl t4.xyz ; \n"\ "dcl v0.xyzw; \n"\ "dcl v1.xyzw; \n"\ " \n"\ "def c0, -1.0f, -1.0f, -1.0f, -1.0f ; for _bx2 emulation \n"\ "def c1, 2.0f, 2.0f, 2.0f, 2.0f ; for _bx2 emulation \n"\ "mov r11, c1; \n"\ " \n"\ "texld r1, t1, s1 ; sample (normal.x, normal.y, normal.z, height) \n"\ "mov r4.xyz, t4 ; fetch eye vector \n"\ "mov r0.xy, t0 ; color map \n"\ " \n"\ "; original parallax mapping: \n"\ "; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\ "mad r1.xyz, r1, r11, c0; \n"\ " \n"\ "mul r3, r1.wwww, c6; ; r3 = (height, height, height) * scale \n"\ " \n"\ "; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\ "mad r4.xyz, r4, r11, c0; \n"\ " \n"\ "mad r2.xy, r3, r4, r0 ; newTexCoord = height * eye + oldTexCoord \n"\ " \n"\ "; modified parallax mapping to avoid swimming: \n"\ ";mul r3, r1_bx2.wwww, r1_bx2.zzzz ; r3 = (h,h,h,h) * (n.z, n.z, n.z, n.z,) \n"\ ";mul r3, r3, c6; ; r3 = (nh, nh, nh) * scale \n"\ ";mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\ " \n"\ "texld r0, r2, s0 ; load diffuse texture with new tex coord \n"\ "texld r1, r2, s1 ; sample normal map \n"\ "mov r2.xyz, t2 ; fetch light vector 1 \n"\ "mov r3.xyz, t3 ; fetch light vector 2 \n"\ " \n"\ "; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\ "mad r1.xyz, r1, r11, c0; \n"\ "mad r2.xyz, r2, r11, c0; \n"\ "mad r3.xyz, r3, r11, c0; \n"\ " \n"\ "dp3_sat r2, r1, r2 ; normal dot light 1 (_bx2 because moved into 0..1) \n"\ "mul r2, r2, v0 ; luminance1 * light color 1 \n"\ " \n"\ "dp3_sat r3, r1, r3 ; normal dot light 2 (_bx2 because moved into 0..1) \n"\ "mad r3, r3, v1, r2 ; (luminance2 * light color 2) + luminance1 \n"\ " \n"\ "mul r0.xyz, r0, r3 ; total luminance * base color \n"\ "mov r0.a, v0.a ; write original alpha value \n"\ "mov oC0, r0; \n"\ "\n"; CD3D9ParallaxMapRenderer::CD3D9ParallaxMapRenderer( IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial) : CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial), CurrentScale(0.0f) { #ifdef _DEBUG setDebugName("CD3D9ParallaxMapRenderer"); #endif // set this as callback. We could have done this in // the initialization list, but some compilers don't like it. CallBack = this; // basicly, this thing simply compiles these hardcoded shaders if the // hardware is able to do them, otherwise it maps to the base material if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) || !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1)) { // this hardware is not able to do shaders. Fall back to // base material. outMaterialTypeNr = driver->addMaterialRenderer(this); return; } // check if already compiled parallax map shaders are there. video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_PARALLAX_MAP_SOLID); if (renderer) { // use the already compiled shaders video::CD3D9ParallaxMapRenderer* nmr = (video::CD3D9ParallaxMapRenderer*)renderer; VertexShader = nmr->VertexShader; if (VertexShader) VertexShader->AddRef(); PixelShader = nmr->PixelShader; if (PixelShader) PixelShader->AddRef(); outMaterialTypeNr = driver->addMaterialRenderer(this); } else { #ifdef SHADER_EXTERNAL_DEBUG // quickly load shader from external file io::CReadFile* file = new io::CReadFile("parallax.psh"); s32 sz = file->getSize(); char* s = new char[sz+1]; file->read(s, sz); s[sz] = 0; init(outMaterialTypeNr, D3D9_PARALLAX_MAP_VSH, s); delete [] s; file->drop(); #else // compile shaders on our own init(outMaterialTypeNr, D3D9_PARALLAX_MAP_VSH, D3D9_PARALLAX_MAP_PSH); #endif // SHADER_EXTERNAL_DEBUG } // something failed, use base material if (-1==outMaterialTypeNr) driver->addMaterialRenderer(this); } CD3D9ParallaxMapRenderer::~CD3D9ParallaxMapRenderer() { if (CallBack == this) CallBack = 0; } bool CD3D9ParallaxMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { if (vtxtype != video::EVT_TANGENTS) { os::Printer::log("Error: Parallax map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR); return false; } return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype); } void CD3D9ParallaxMapRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services) { CD3D9ShaderMaterialRenderer::OnSetMaterial(material, lastMaterial, resetAllRenderstates, services); CurrentScale = material.MaterialTypeParam; } //! Returns the render capability of the material. s32 CD3D9ParallaxMapRenderer::getRenderCapability() const { if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) && Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1)) return 0; return 1; } //! Called by the engine when the vertex and/or pixel shader constants //! for an material renderer should be set. void CD3D9ParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData) { video::IVideoDriver* driver = services->getVideoDriver(); // set transposed world matrix services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4); // set eye position // The viewpoint is at (0., 0., 0.) in eye space. // Turning this into a vector [0 0 0 1] and multiply it by // the inverse of the view matrix, the resulting vector is the // object space location of the camera. f32 floats[4] = {0,0,0,1}; core::matrix4 minv = driver->getTransform(video::ETS_VIEW); minv.makeInverse(); minv.multiplyWith1x4Matrix(floats); services->setVertexShaderConstant(floats, 4, 1); // set transposed worldViewProj matrix core::matrix4 worldViewProj; worldViewProj = driver->getTransform(video::ETS_PROJECTION); worldViewProj *= driver->getTransform(video::ETS_VIEW); worldViewProj *= driver->getTransform(video::ETS_WORLD); services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4); // here we've got to fetch the fixed function lights from the // driver and set them as constants const u32 cnt = driver->getDynamicLightCount(); for (u32 i=0; i<2; ++i) { SLight light; if (igetDynamicLight(i); else { light.DiffuseColor.set(0,0,0); // make light dark light.Radius = 1.0f; } light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation services->setVertexShaderConstant(reinterpret_cast(&light.Position), 12+(i*2), 1); services->setVertexShaderConstant(reinterpret_cast(&light.DiffuseColor), 13+(i*2), 1); } // this is not really necessary in d3d9 (used a def instruction), but to be sure: f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f}; services->setVertexShaderConstant(c95, 95, 1); f32 c96[] = {-1, 1, 1, 1}; services->setVertexShaderConstant(c96, 96, 1); // set scale factor f32 factor = 0.02f; // default value if (CurrentScale != 0) factor = CurrentScale; f32 c6[] = {factor, factor, factor, 0}; services->setPixelShaderConstant(c6, 6, 1); } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ irrlicht-1.8.3/source/Irrlicht/CD3D9NormalMapRenderer.h0000644000000000000000000000266712574354552021365 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_D3D9_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__ #define __C_D3D9_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_WINDOWS_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #include "irrMath.h" // needed by borland for sqrtf define #endif #include #include "CD3D9ShaderMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" namespace irr { namespace video { //! Renderer for normal maps class CD3D9NormalMapRenderer : public CD3D9ShaderMaterialRenderer, IShaderConstantSetCallBack { public: CD3D9NormalMapRenderer( IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial); ~CD3D9NormalMapRenderer(); //! Called by the engine when the vertex and/or pixel shader constants for an //! material renderer should be set. virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData); virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); //! Returns the render capability of the material. virtual s32 getRenderCapability() const; private: }; } // end namespace video } // end namespace irr #endif #endif #endif irrlicht-1.8.3/source/Irrlicht/CD3D9NormalMapRenderer.cpp0000644000000000000000000002521212574354552021707 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #include "CD3D9NormalMapRenderer.h" #include "IVideoDriver.h" #include "IMaterialRendererServices.h" #include "os.h" #include "SLight.h" namespace irr { namespace video { // 1.1 Shaders with two lights and vertex based attenuation // Irrlicht Engine D3D9 render path normal map vertex shader const char D3D9_NORMAL_MAP_VSH[] = ";Irrlicht Engine 0.8 D3D9 render path normal map vertex shader\n"\ "; c0-3: Transposed world matrix \n"\ "; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\ "; c12: Light01 position \n"\ "; c13: x,y,z: Light01 color; .w: 1/LightRadius² \n"\ "; c14: Light02 position \n"\ "; c15: x,y,z: Light02 color; .w: 1/LightRadius² \n"\ "vs.1.1\n"\ "dcl_position v0 ; position \n"\ "dcl_normal v1 ; normal \n"\ "dcl_color v2 ; color \n"\ "dcl_texcoord0 v3 ; texture coord \n"\ "dcl_texcoord1 v4 ; tangent \n"\ "dcl_texcoord2 v5 ; binormal \n"\ "\n"\ "def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\ "\n"\ "m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\ "\n"\ "m3x3 r5, v4, c0 ; transform tangent U\n"\ "m3x3 r7, v1, c0 ; transform normal W\n"\ "m3x3 r6, v5, c0 ; transform binormal V\n"\ "\n"\ "m4x4 r4, v0, c0 ; vertex into world position\n"\ "add r2, c12, -r4 ; vtxpos - lightpos1\n"\ "add r3, c14, -r4 ; vtxpos - lightpos2\n"\ "\n"\ "dp3 r8.x, r5, r2 ; transform the light vector 1 with U, V, W\n"\ "dp3 r8.y, r6, r2 \n"\ "dp3 r8.z, r7, r2 \n"\ "dp3 r9.x, r5, r3 ; transform the light vector 2 with U, V, W\n"\ "dp3 r9.y, r6, r3 \n"\ "dp3 r9.z, r7, r3 \n"\ "\n"\ "dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\ "rsq r8.w, r8.w \n"\ "mul r8, r8, r8.w \n"\ "dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\ "rsq r9.w, r9.w \n"\ "mul r9, r9, r9.w \n"\ "\n"\ "mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\ "mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\ "\n"\ " ; calculate attenuation of light 1 \n"\ "dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x² + r2.y² + r2.z² \n"\ "mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\ "rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\ "mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\ "\n"\ " ; calculate attenuation of light 2 \n"\ "dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x² + r3.y² + r3.z² \n"\ "mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\ "rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\ "mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\ "\n"\ "mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\ "mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\ "mov oD0.a, v2.a ; move out original alpha value \n"\ "\n"; // Irrlicht Engine D3D9 render path normal map pixel shader const char D3D9_NORMAL_MAP_PSH_1_1[] = ";Irrlicht Engine 0.8 D3D9 render path normal map pixel shader\n"\ ";Input: \n"\ ";t0: color map texture coord \n"\ ";t1: normal map texture coords \n"\ ";t2: light 1 vector in tangent space \n"\ ";v0: light 1 color \n"\ ";t3: light 2 vector in tangent space \n"\ ";v1: light 2 color \n"\ ";v0.a: vertex alpha value \n"\ "ps.1.1 \n"\ "tex t0 ; sample color map \n"\ "tex t1 ; sample normal map\n"\ "texcoord t2 ; fetch light vector 1\n"\ "texcoord t3 ; fetch light vector 2\n"\ "\n"\ "dp3_sat r0, t1_bx2, t2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1)\n"\ "mul r0, r0, v0 ; luminance1 * light color 1 \n"\ "\n"\ "dp3_sat r1, t1_bx2, t3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1)\n"\ "mad r0, r1, v1, r0 ; (luminance2 * light color 2) + luminance 1 \n"\ "\n"\ "mul r0.xyz, t0, r0 ; total luminance * base color\n"\ "+mov r0.a, v0.a ; write interpolated vertex alpha value \n"\ "\n"\ ""; // Higher-quality normal map pixel shader (requires PS 2.0) // uses per-pixel normalization for improved accuracy const char D3D9_NORMAL_MAP_PSH_2_0[] = ";Irrlicht Engine 0.8 D3D9 render path normal map pixel shader\n"\ ";Input: \n"\ ";t0: color map texture coord \n"\ ";t1: normal map texture coords \n"\ ";t2: light 1 vector in tangent space \n"\ ";v0: light 1 color \n"\ ";t3: light 2 vector in tangent space \n"\ ";v1: light 2 color \n"\ ";v0.a: vertex alpha value \n"\ "ps_2_0 \n"\ "def c0, 0, 0, 0, 0\n"\ "def c1, 1.0, 1.0, 1.0, 1.0\n"\ "def c2, 2.0, 2.0, 2.0, 2.0\n"\ "def c3, -.5, -.5, -.5, -.5\n"\ "dcl t0\n"\ "dcl t1\n"\ "dcl t2\n"\ "dcl t3\n"\ "dcl v1\n"\ "dcl v0\n"\ "dcl_2d s0\n"\ "dcl_2d s1\n"\ "texld r0, t0, s0 ; sample color map into r0 \n"\ "texld r4, t0, s1 ; sample normal map into r4\n"\ "add r4, r4, c3 ; bias the normal vector\n"\ "add r5, t2, c3 ; bias the light 1 vector into r5\n"\ "add r6, t3, c3 ; bias the light 2 vector into r6\n"\ "nrm r1, r4 ; normalize the normal vector into r1\n"\ "nrm r2, r5 ; normalize the light1 vector into r2\n"\ "nrm r3, r6 ; normalize the light2 vector into r3\n"\ "dp3 r2, r2, r1 ; let r2 = normal DOT light 1 vector\n"\ "max r2, r2, c0 ; clamp result to positive numbers\n"\ "mul r2, r2, v0 ; let r2 = luminance1 * light color 1 \n"\ "dp3 r3, r3, r1 ; let r3 = normal DOT light 2 vector\n"\ "max r3, r3, c0 ; clamp result to positive numbers\n"\ "mad r2, r3, v1, r2 ; let r2 = (luminance2 * light color 2) + (luminance2 * light color 1) \n"\ "mul r2, r2, r0 ; let r2 = total luminance * base color\n"\ "mov r2.w, v0.w ; write interpolated vertex alpha value \n"\ "mov oC0, r2 ; copy r2 to the output register \n"\ "\n"\ ""; CD3D9NormalMapRenderer::CD3D9NormalMapRenderer( IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial) : CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial) { #ifdef _DEBUG setDebugName("CD3D9NormalMapRenderer"); #endif // set this as callback. We could have done this in // the initialization list, but some compilers don't like it. CallBack = this; // basically, this thing simply compiles the hardcoded shaders // if the hardware is able to do them, otherwise it maps to the // base material if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) || !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1)) { // this hardware is not able to do shaders. Fall back to // base material. outMaterialTypeNr = driver->addMaterialRenderer(this); return; } // check if already compiled normal map shaders are there. video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_NORMAL_MAP_SOLID); if (renderer) { // use the already compiled shaders video::CD3D9NormalMapRenderer* nmr = (video::CD3D9NormalMapRenderer*)renderer; VertexShader = nmr->VertexShader; if (VertexShader) VertexShader->AddRef(); PixelShader = nmr->PixelShader; if (PixelShader) PixelShader->AddRef(); outMaterialTypeNr = driver->addMaterialRenderer(this); } else { // compile shaders on our own if (driver->queryFeature(video::EVDF_PIXEL_SHADER_2_0)) { init(outMaterialTypeNr, D3D9_NORMAL_MAP_VSH, D3D9_NORMAL_MAP_PSH_2_0); } else { init(outMaterialTypeNr, D3D9_NORMAL_MAP_VSH, D3D9_NORMAL_MAP_PSH_1_1); } } // something failed, use base material if (-1==outMaterialTypeNr) driver->addMaterialRenderer(this); } CD3D9NormalMapRenderer::~CD3D9NormalMapRenderer() { if (CallBack == this) CallBack = 0; } bool CD3D9NormalMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { if (vtxtype != video::EVT_TANGENTS) { os::Printer::log("Error: Normal map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR); return false; } return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype); } //! Returns the render capability of the material. s32 CD3D9NormalMapRenderer::getRenderCapability() const { if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) && Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1)) return 0; return 1; } //! Called by the engine when the vertex and/or pixel shader constants //! for an material renderer should be set. void CD3D9NormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData) { video::IVideoDriver* driver = services->getVideoDriver(); // set transposed world matrix services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4); // set transposed worldViewProj matrix core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION)); worldViewProj *= driver->getTransform(video::ETS_VIEW); worldViewProj *= driver->getTransform(video::ETS_WORLD); services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4); // here we've got to fetch the fixed function lights from the // driver and set them as constants u32 cnt = driver->getDynamicLightCount(); for (u32 i=0; i<2; ++i) { SLight light; if (igetDynamicLight(i); else { light.DiffuseColor.set(0,0,0); // make light dark light.Radius = 1.0f; } light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation services->setVertexShaderConstant(reinterpret_cast(&light.Position), 12+(i*2), 1); services->setVertexShaderConstant(reinterpret_cast(&light.DiffuseColor), 13+(i*2), 1); } // this is not really necessary in d3d9 (used a def instruction), but to be sure: f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f}; services->setVertexShaderConstant(c95, 95, 1); } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ irrlicht-1.8.3/source/Irrlicht/CD3D9MaterialRenderer.h0000644000000000000000000005026312574354552021230 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_D3D9_MATERIAL_RENDERER_H_INCLUDED__ #define __C_D3D9_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_WINDOWS_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #include "irrMath.h" // needed by borland for sqrtf define #endif #include #include "IMaterialRenderer.h" namespace irr { namespace video { namespace { D3DMATRIX UnitMatrixD3D9; D3DMATRIX SphereMapMatrixD3D9; inline void setTextureColorStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1, DWORD op, DWORD arg2) { dev->SetTextureStageState(i, D3DTSS_COLOROP, op); dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1); dev->SetTextureStageState(i, D3DTSS_COLORARG2, arg2); } inline void setTextureColorStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1) { dev->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_SELECTARG1); dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1); } inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1, DWORD op, DWORD arg2) { dev->SetTextureStageState(i, D3DTSS_ALPHAOP, op); dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1); dev->SetTextureStageState(i, D3DTSS_ALPHAARG2, arg2); } inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1) { dev->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1); } } // anonymous namespace //! Base class for all internal D3D9 material renderers class CD3D9MaterialRenderer : public IMaterialRenderer { public: //! Constructor CD3D9MaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver) : pID3DDevice(d3ddev), Driver(driver) { } //! sets a variable in the shader. //! \param vertexShader: True if this should be set in the vertex shader, false if //! in the pixel shader. //! \param name: Name of the variable //! \param floats: Pointer to array of floats //! \param count: Amount of floats in array. virtual bool setVariable(bool vertexShader, const c8* name, const f32* floats, int count) { os::Printer::log("Invalid material to set variable in."); return false; } //! Bool interface for the above. virtual bool setVariable(bool vertexShader, const c8* name, const bool* bools, int count) { os::Printer::log("Invalid material to set variable in."); return false; } //! Int interface for the above. virtual bool setVariable(bool vertexShader, const c8* name, const s32* ints, int count) { os::Printer::log("Invalid material to set variable in."); return false; } protected: IDirect3DDevice9* pID3DDevice; video::IVideoDriver* Driver; }; //! Solid material renderer class CD3D9MaterialRenderer_SOLID : public CD3D9MaterialRenderer { public: CD3D9MaterialRenderer_SOLID(IDirect3DDevice9* p, video::IVideoDriver* d) : CD3D9MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); } pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } }; //! Generic Texture Blend class CD3D9MaterialRenderer_ONETEXTURE_BLEND : public CD3D9MaterialRenderer { public: CD3D9MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice9* p, video::IVideoDriver* d) : CD3D9MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || material.MaterialTypeParam != lastMaterial.MaterialTypeParam || resetAllRenderstates) { E_BLEND_FACTOR srcFact,dstFact; E_MODULATE_FUNC modulate; u32 alphaSource; unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam ); if (srcFact == EBF_SRC_COLOR && dstFact == EBF_ZERO) { pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } else { pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, getD3DBlend ( srcFact ) ); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, getD3DBlend ( dstFact ) ); } setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, getD3DModulate(modulate), D3DTA_DIFFUSE); if ( textureBlendFunc_hasAlpha ( srcFact ) || textureBlendFunc_hasAlpha ( dstFact ) ) { if (alphaSource==EAS_VERTEX_COLOR) { setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE); } else if (alphaSource==EAS_TEXTURE) { setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE); } else { setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); } } pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); } } //! Returns if the material is transparent. /** The scene management needs to know this for being able to sort the materials by opaque and transparent. The return value could be optimized, but we'd need to know the MaterialTypeParam for it. */ virtual bool isTransparent() const { return true; } private: u32 getD3DBlend ( E_BLEND_FACTOR factor ) const { u32 r = 0; switch ( factor ) { case EBF_ZERO: r = D3DBLEND_ZERO; break; case EBF_ONE: r = D3DBLEND_ONE; break; case EBF_DST_COLOR: r = D3DBLEND_DESTCOLOR; break; case EBF_ONE_MINUS_DST_COLOR: r = D3DBLEND_INVDESTCOLOR; break; case EBF_SRC_COLOR: r = D3DBLEND_SRCCOLOR; break; case EBF_ONE_MINUS_SRC_COLOR: r = D3DBLEND_INVSRCCOLOR; break; case EBF_SRC_ALPHA: r = D3DBLEND_SRCALPHA; break; case EBF_ONE_MINUS_SRC_ALPHA: r = D3DBLEND_INVSRCALPHA; break; case EBF_DST_ALPHA: r = D3DBLEND_DESTALPHA; break; case EBF_ONE_MINUS_DST_ALPHA: r = D3DBLEND_INVDESTALPHA; break; case EBF_SRC_ALPHA_SATURATE: r = D3DBLEND_SRCALPHASAT; break; } return r; } u32 getD3DModulate ( E_MODULATE_FUNC func ) const { u32 r = D3DTOP_MODULATE; switch ( func ) { case EMFN_MODULATE_1X: r = D3DTOP_MODULATE; break; case EMFN_MODULATE_2X: r = D3DTOP_MODULATE2X; break; case EMFN_MODULATE_4X: r = D3DTOP_MODULATE4X; break; } return r; } bool transparent; }; //! Solid 2 layer material renderer class CD3D9MaterialRenderer_SOLID_2_LAYER : public CD3D9MaterialRenderer { public: CD3D9MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d) : CD3D9MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } } }; //! Transparent add color material renderer class CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR : public CD3D9MaterialRenderer { public: CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice9* p, video::IVideoDriver* d) : CD3D9MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR); } } //! Returns if the material is transparent. The scene management needs to know this //! for being able to sort the materials by opaque and transparent. virtual bool isTransparent() const { return true; } }; //! Transparent vertex alpha material renderer class CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public CD3D9MaterialRenderer { public: CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice9* p, video::IVideoDriver* d) : CD3D9MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); } } //! Returns if the material is transparent. The scene managment needs to know this //! for being able to sort the materials by opaque and transparent. virtual bool isTransparent() const { return true; } }; //! Transparent alpha channel material renderer class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public CD3D9MaterialRenderer { public: CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice9* p, video::IVideoDriver* d) : CD3D9MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates || material.MaterialTypeParam != lastMaterial.MaterialTypeParam ) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT); setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); pID3DDevice->SetRenderState(D3DRS_ALPHAREF, core::floor32(material.MaterialTypeParam * 255.f)); pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); } } virtual void OnUnsetMaterial() { pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); } //! Returns if the material is transparent. The scene managment needs to know this //! for being able to sort the materials by opaque and transparent. virtual bool isTransparent() const { return true; } }; //! Transparent alpha channel material renderer class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public CD3D9MaterialRenderer { public: CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice9* p, video::IVideoDriver* d) : CD3D9MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT); setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); // 127 is required by EMT_TRANSPARENT_ALPHA_CHANNEL_REF pID3DDevice->SetRenderState(D3DRS_ALPHAREF, 127); pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); } } virtual void OnUnsetMaterial() { pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); } //! Returns if the material is transparent. The scene managment needs to know this //! for being able to sort the materials by opaque and transparent. virtual bool isTransparent() const { return false; // this material is not really transparent because it does no blending. } }; //! material renderer for all kinds of lightmaps class CD3D9MaterialRenderer_LIGHTMAP : public CD3D9MaterialRenderer { public: CD3D9MaterialRenderer_LIGHTMAP(IDirect3DDevice9* p, video::IVideoDriver* d) : CD3D9MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (material.MaterialType >= EMT_LIGHTMAP_LIGHTING) { // with lighting setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); } else { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE); } pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1); setTextureColorStage(pID3DDevice, 1, D3DTA_TEXTURE, (material.MaterialType == EMT_LIGHTMAP_ADD)? D3DTOP_ADD: (material.MaterialType == EMT_LIGHTMAP_M4 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M4)? D3DTOP_MODULATE4X: (material.MaterialType == EMT_LIGHTMAP_M2 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M2)? D3DTOP_MODULATE2X: D3DTOP_MODULATE, D3DTA_CURRENT); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } } }; //! material renderer for detail maps class CD3D9MaterialRenderer_DETAIL_MAP : public CD3D9MaterialRenderer { public: CD3D9MaterialRenderer_DETAIL_MAP(IDirect3DDevice9* p, video::IVideoDriver* d) : CD3D9MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); setTextureColorStage(pID3DDevice, 1, D3DTA_TEXTURE, D3DTOP_ADDSIGNED, D3DTA_CURRENT); pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } } }; //! sphere map material renderer class CD3D9MaterialRenderer_SPHERE_MAP : public CD3D9MaterialRenderer { public: CD3D9MaterialRenderer_SPHERE_MAP(IDirect3DDevice9* p, video::IVideoDriver* d) : CD3D9MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); pID3DDevice->SetTransform( D3DTS_TEXTURE0, &SphereMapMatrixD3D9 ); pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL ); } } virtual void OnUnsetMaterial() { pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0); pID3DDevice->SetTransform( D3DTS_TEXTURE0, &UnitMatrixD3D9 ); } }; //! reflection 2 layer material renderer class CD3D9MaterialRenderer_REFLECTION_2_LAYER : public CD3D9MaterialRenderer { public: CD3D9MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d) : CD3D9MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); setTextureColorStage(pID3DDevice, 1, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT); pID3DDevice->SetTransform( D3DTS_TEXTURE1, &SphereMapMatrixD3D9 ); pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } } virtual void OnUnsetMaterial() { pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1); pID3DDevice->SetTransform( D3DTS_TEXTURE1, &UnitMatrixD3D9 ); } }; //! reflection 2 layer material renderer class CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public CD3D9MaterialRenderer { public: CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d) : CD3D9MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE); setTextureColorStage(pID3DDevice, 1, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT); setTextureAlphaStage(pID3DDevice, 1, D3DTA_CURRENT); pID3DDevice->SetTransform(D3DTS_TEXTURE1, &SphereMapMatrixD3D9 ); pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); } } virtual void OnUnsetMaterial() { pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1); pID3DDevice->SetTransform(D3DTS_TEXTURE1, &UnitMatrixD3D9); } //! Returns if the material is transparent. The scene managment needs to know this //! for being able to sort the materials by opaque and transparent. virtual bool isTransparent() const { return true; } }; } // end namespace video } // end namespace irr #endif #endif #endif irrlicht-1.8.3/source/Irrlicht/CD3D9HLSLMaterialRenderer.h0000644000000000000000000000464512574354552021716 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_D3D9_HLSL_MATERIAL_RENDERER_H_INCLUDED__ #define __C_D3D9_HLSL_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_WINDOWS_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #include "CD3D9ShaderMaterialRenderer.h" #include "IGPUProgrammingServices.h" namespace irr { namespace video { class IVideoDriver; class IShaderConstantSetCallBack; class IMaterialRenderer; //! Class for using vertex and pixel shaders via HLSL with D3D9 class CD3D9HLSLMaterialRenderer : public CD3D9ShaderMaterialRenderer { public: //! Public constructor CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData); //! Destructor ~CD3D9HLSLMaterialRenderer(); //! sets a variable in the shader. //! \param vertexShader: True if this should be set in the vertex shader, false if //! in the pixel shader. //! \param name: Name of the variable //! \param floats: Pointer to array of floats //! \param count: Amount of floats in array. virtual bool setVariable(bool vertexShader, const c8* name, const f32* floats, int count); //! Bool interface for the above. virtual bool setVariable(bool vertexShader, const c8* name, const bool* bools, int count); //! Int interface for the above. virtual bool setVariable(bool vertexShader, const c8* name, const s32* ints, int count); bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); protected: bool createHLSLVertexShader(const char* vertexShaderProgram, const char* shaderEntryPointName, const char* shaderTargetName); bool createHLSLPixelShader(const char* pixelShaderProgram, const char* shaderEntryPointName, const char* shaderTargetName); void printHLSLVariables(LPD3DXCONSTANTTABLE table); LPD3DXCONSTANTTABLE VSConstantsTable; LPD3DXCONSTANTTABLE PSConstantsTable; }; } // end namespace video } // end namespace irr #endif #endif #endif irrlicht-1.8.3/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp0000644000000000000000000002420212574354552022240 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #include "CD3D9HLSLMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" #include "IVideoDriver.h" #include "os.h" #include "irrString.h" #ifndef _IRR_D3D_NO_SHADER_DEBUGGING #include #endif namespace irr { namespace video { //! Public constructor CD3D9HLSLMaterialRenderer::CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : CD3D9ShaderMaterialRenderer(d3ddev, driver, callback, baseMaterial, userData), VSConstantsTable(0), PSConstantsTable(0) { #ifdef _DEBUG setDebugName("CD3D9HLSLMaterialRenderer"); #endif outMaterialTypeNr = -1; // now create shaders if (vsCompileTarget < 0 || vsCompileTarget > EVST_COUNT) { os::Printer::log("Invalid HLSL vertex shader compilation target", ELL_ERROR); return; } if (!createHLSLVertexShader(vertexShaderProgram, vertexShaderEntryPointName, VERTEX_SHADER_TYPE_NAMES[vsCompileTarget])) return; if (!createHLSLPixelShader(pixelShaderProgram, pixelShaderEntryPointName, PIXEL_SHADER_TYPE_NAMES[psCompileTarget])) return; // register myself as new material outMaterialTypeNr = Driver->addMaterialRenderer(this); } //! Destructor CD3D9HLSLMaterialRenderer::~CD3D9HLSLMaterialRenderer() { if (VSConstantsTable) VSConstantsTable->Release(); if (PSConstantsTable) PSConstantsTable->Release(); } bool CD3D9HLSLMaterialRenderer::createHLSLVertexShader(const char* vertexShaderProgram, const char* shaderEntryPointName, const char* shaderTargetName) { if (!vertexShaderProgram) return true; LPD3DXBUFFER buffer = 0; LPD3DXBUFFER errors = 0; #ifdef _IRR_D3D_NO_SHADER_DEBUGGING // compile without debug info HRESULT h = stubD3DXCompileShader( vertexShaderProgram, strlen(vertexShaderProgram), 0, // macros 0, // no includes shaderEntryPointName, shaderTargetName, 0, // no flags &buffer, &errors, &VSConstantsTable); #else // compile shader and emitt some debug informations to // make it possible to debug the shader in visual studio static int irr_dbg_hlsl_file_nr = 0; ++irr_dbg_hlsl_file_nr; char tmp[32]; sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.vsh", irr_dbg_hlsl_file_nr); FILE* f = fopen(tmp, "wb"); fwrite(vertexShaderProgram, strlen(vertexShaderProgram), 1, f); fflush(f); fclose(f); HRESULT h = stubD3DXCompileShaderFromFile( tmp, 0, // macros 0, // no includes shaderEntryPointName, shaderTargetName, D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION, &buffer, &errors, &VSConstantsTable); #endif if (FAILED(h)) { os::Printer::log("HLSL vertex shader compilation failed:", ELL_ERROR); if (errors) { os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR); errors->Release(); if (buffer) buffer->Release(); } return false; } if (errors) errors->Release(); if (buffer) { if (FAILED(pID3DDevice->CreateVertexShader((DWORD*)buffer->GetBufferPointer(), &VertexShader))) { os::Printer::log("Could not create hlsl vertex shader.", ELL_ERROR); buffer->Release(); return false; } buffer->Release(); return true; } return false; } bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderProgram, const char* shaderEntryPointName, const char* shaderTargetName) { if (!pixelShaderProgram) return true; LPD3DXBUFFER buffer = 0; LPD3DXBUFFER errors = 0; DWORD flags = 0; #ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY if (Driver->queryFeature(video::EVDF_VERTEX_SHADER_2_0) || Driver->queryFeature(video::EVDF_VERTEX_SHADER_3_0)) // this one's for newer DX SDKs which don't support ps_1_x anymore // instead they'll silently compile 1_x as 2_x when using this flag flags |= D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY; #endif #if defined(_IRR_D3D_USE_LEGACY_HLSL_COMPILER) && defined(D3DXSHADER_USE_LEGACY_D3DX9_31_DLL) #ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY else #endif flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL; #endif #ifdef _IRR_D3D_NO_SHADER_DEBUGGING // compile without debug info HRESULT h = stubD3DXCompileShader( pixelShaderProgram, strlen(pixelShaderProgram), 0, // macros 0, // no includes shaderEntryPointName, shaderTargetName, flags, &buffer, &errors, &PSConstantsTable); #else // compile shader and emitt some debug informations to // make it possible to debug the shader in visual studio static int irr_dbg_hlsl_file_nr = 0; ++irr_dbg_hlsl_file_nr; char tmp[32]; sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.psh", irr_dbg_hlsl_file_nr); FILE* f = fopen(tmp, "wb"); fwrite(pixelShaderProgram, strlen(pixelShaderProgram), 1, f); fflush(f); fclose(f); HRESULT h = stubD3DXCompileShaderFromFile( tmp, 0, // macros 0, // no includes shaderEntryPointName, shaderTargetName, flags | D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION, &buffer, &errors, &PSConstantsTable); #endif if (FAILED(h)) { os::Printer::log("HLSL pixel shader compilation failed:", ELL_ERROR); if (errors) { os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR); errors->Release(); if (buffer) buffer->Release(); } return false; } if (errors) errors->Release(); if (buffer) { if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)buffer->GetBufferPointer(), &PixelShader))) { os::Printer::log("Could not create hlsl pixel shader.", ELL_ERROR); buffer->Release(); return false; } buffer->Release(); return true; } return false; } bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name, const f32* floats, int count) { LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable; if (!tbl) return false; // currently we only support top level parameters. // Should be enough for the beginning. (TODO) D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name); if (!hndl) { core::stringc s = "HLSL Variable to set not found: '"; s += name; s += "'. Available variables are:"; os::Printer::log(s.c_str(), ELL_WARNING); printHLSLVariables(tbl); return false; } D3DXCONSTANT_DESC Description; UINT ucount = 1; tbl->GetConstantDesc(hndl, &Description, &ucount); if(Description.RegisterSet != D3DXRS_SAMPLER) { HRESULT hr = tbl->SetFloatArray(pID3DDevice, hndl, floats, count); if (FAILED(hr)) { os::Printer::log("Error setting float array for HLSL variable", ELL_WARNING); return false; } } return true; } bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name, const bool* bools, int count) { LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable; if (!tbl) return false; // currently we only support top level parameters. // Should be enough for the beginning. (TODO) D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name); if (!hndl) { core::stringc s = "HLSL Variable to set not found: '"; s += name; s += "'. Available variables are:"; os::Printer::log(s.c_str(), ELL_WARNING); printHLSLVariables(tbl); return false; } D3DXCONSTANT_DESC Description; UINT ucount = 1; tbl->GetConstantDesc(hndl, &Description, &ucount); if(Description.RegisterSet != D3DXRS_SAMPLER) { HRESULT hr = tbl->SetBoolArray(pID3DDevice, hndl, (BOOL*)bools, count); if (FAILED(hr)) { os::Printer::log("Error setting bool array for HLSL variable", ELL_WARNING); return false; } } return true; } bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name, const s32* ints, int count) { LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable; if (!tbl) return false; // currently we only support top level parameters. // Should be enough for the beginning. (TODO) D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name); if (!hndl) { core::stringc s = "HLSL Variable to set not found: '"; s += name; s += "'. Available variables are:"; os::Printer::log(s.c_str(), ELL_WARNING); printHLSLVariables(tbl); return false; } D3DXCONSTANT_DESC Description; UINT ucount = 1; tbl->GetConstantDesc(hndl, &Description, &ucount); if(Description.RegisterSet != D3DXRS_SAMPLER) { HRESULT hr = tbl->SetIntArray(pID3DDevice, hndl, ints, count); if (FAILED(hr)) { os::Printer::log("Error setting int array for HLSL variable", ELL_WARNING); return false; } } return true; } bool CD3D9HLSLMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { if (VSConstantsTable) VSConstantsTable->SetDefaults(pID3DDevice); return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype); } void CD3D9HLSLMaterialRenderer::printHLSLVariables(LPD3DXCONSTANTTABLE table) { // currently we only support top level parameters. // Should be enough for the beginning. (TODO) // print out constant names D3DXCONSTANTTABLE_DESC tblDesc; HRESULT hr = table->GetDesc(&tblDesc); if (!FAILED(hr)) { for (int i=0; i<(int)tblDesc.Constants; ++i) { D3DXCONSTANT_DESC d; UINT n = 1; D3DXHANDLE cHndl = table->GetConstant(NULL, i); if (!FAILED(table->GetConstantDesc(cHndl, &d, &n))) { core::stringc s = " '"; s += d.Name; s += "' Registers:[begin:"; s += (int)d.RegisterIndex; s += ", count:"; s += (int)d.RegisterCount; s += "]"; os::Printer::log(s.c_str()); } } } } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ irrlicht-1.8.3/source/Irrlicht/CD3D9Driver.h0000644000000000000000000004255112574354552017237 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_VIDEO_DIRECTX_9_H_INCLUDED__ #define __C_VIDEO_DIRECTX_9_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #ifdef _IRR_WINDOWS_ #define WIN32_LEAN_AND_MEAN #include #endif #include "CNullDriver.h" #include "SIrrCreationParameters.h" #include "IMaterialRendererServices.h" #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #include "irrMath.h" // needed by borland for sqrtf define #endif #include #ifdef _IRR_COMPILE_WITH_CG_ #include "Cg/cg.h" #include "Cg/cgD3D9.h" #endif namespace irr { namespace video { struct SDepthSurface : public IReferenceCounted { SDepthSurface() : Surface(0) { #ifdef _DEBUG setDebugName("SDepthSurface"); #endif } virtual ~SDepthSurface() { if (Surface) Surface->Release(); } IDirect3DSurface9* Surface; core::dimension2du Size; }; class CD3D9Driver : public CNullDriver, IMaterialRendererServices { public: friend class CD3D9Texture; //! constructor CD3D9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io); //! destructor virtual ~CD3D9Driver(); //! applications must call this method before performing any rendering. returns false if failed. virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! applications must call this method after performing any rendering. returns false if failed. virtual bool endScene(); //! queries the features of the driver, returns true if feature is available virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const; //! sets transformation virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat); //! sets a material virtual void setMaterial(const SMaterial& material); //! sets a render target virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=video::SColor(0,0,0,0)); //! Sets multiple render targets virtual bool setRenderTarget(const core::array& texture, bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=video::SColor(0,0,0,0)); //! sets a viewport virtual void setViewPort(const core::rect& area); //! gets the area of the current viewport virtual const core::rect& getViewPort() const; struct SHWBufferLink_d3d9 : public SHWBufferLink { SHWBufferLink_d3d9(const scene::IMeshBuffer *_MeshBuffer): SHWBufferLink(_MeshBuffer), vertexBuffer(0), indexBuffer(0), vertexBufferSize(0), indexBufferSize(0) {} IDirect3DVertexBuffer9* vertexBuffer; IDirect3DIndexBuffer9* indexBuffer; u32 vertexBufferSize; u32 indexBufferSize; }; bool updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer); bool updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer); //! updates hardware buffer if needed virtual bool updateHardwareBuffer(SHWBufferLink *HWBuffer); //! Create hardware buffer from mesh virtual SHWBufferLink *createHardwareBuffer(const scene::IMeshBuffer* mb); //! Delete hardware buffer (only some drivers can) virtual void deleteHardwareBuffer(SHWBufferLink *HWBuffer); //! Draw hardware buffer virtual void drawHardwareBuffer(SHWBufferLink *HWBuffer); //! Create occlusion query. /** Use node for identification and mesh for occlusion test. */ virtual void addOcclusionQuery(scene::ISceneNode* node, const scene::IMesh* mesh=0); //! Remove occlusion query. virtual void removeOcclusionQuery(scene::ISceneNode* node); //! Run occlusion query. Draws mesh stored in query. /** If the mesh shall not be rendered visible, use overrideMaterial to disable the color and depth buffer. */ virtual void runOcclusionQuery(scene::ISceneNode* node, bool visible=false); //! Update occlusion query. Retrieves results from GPU. /** If the query shall not block, set the flag to false. Update might not occur in this case, though */ virtual void updateOcclusionQuery(scene::ISceneNode* node, bool block=true); //! Return query result. /** Return value is the number of visible pixels/fragments. The value is a safe approximation, i.e. can be larger then the actual value of pixels. */ virtual u32 getOcclusionQueryResult(scene::ISceneNode* node) const; //! draws a vertex primitive list virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); //! draws a vertex primitive list in 2d virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect = 0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false); //! Draws a part of the texture into the rectangle. virtual void draw2DImage(const video::ITexture* texture, const core::rect& destRect, const core::rect& sourceRect, const core::rect* clipRect = 0, const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false); //! Draws a set of 2d images, using a color and the alpha channel of the texture. virtual void draw2DImageBatch(const video::ITexture* texture, const core::array >& positions, const core::array >& sourceRects, const core::rect* clipRect=0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false); //!Draws an 2d rectangle with a gradient. virtual void draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip); //! Draws a 2d line. virtual void draw2DLine(const core::position2d& start, const core::position2d& end, SColor color=SColor(255,255,255,255)); //! Draws a pixel. virtual void drawPixel(u32 x, u32 y, const SColor & color); //! Draws a 3d line. virtual void draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color = SColor(255,255,255,255)); //! initialises the Direct3D API bool initDriver(HWND hwnd, bool pureSoftware); //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8 //! driver, it would return "Direct3D8.1". virtual const wchar_t* getName() const; //! deletes all dynamic lights there are virtual void deleteAllDynamicLights(); //! adds a dynamic light, returning an index to the light //! \param light: the light data to use to create the light //! \return An index to the light, or -1 if an error occurs virtual s32 addDynamicLight(const SLight& light); //! Turns a dynamic light on or off //! \param lightIndex: the index returned by addDynamicLight //! \param turnOn: true to turn the light on, false to turn it off virtual void turnLightOn(s32 lightIndex, bool turnOn); //! returns the maximal amount of dynamic lights the device can handle virtual u32 getMaximalDynamicLightAmount() const; //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. virtual void setAmbientLight(const SColorf& color); //! Draws a shadow volume into the stencil buffer. virtual void drawStencilShadowVolume(const core::array& triangles, bool zfail=true, u32 debugDataVisible=0); //! Fills the stencil shadow with color. virtual void drawStencilShadow(bool clearStencilBuffer=false, video::SColor leftUpEdge = video::SColor(0,0,0,0), video::SColor rightUpEdge = video::SColor(0,0,0,0), video::SColor leftDownEdge = video::SColor(0,0,0,0), video::SColor rightDownEdge = video::SColor(0,0,0,0)); //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. virtual u32 getMaximalPrimitiveCount() const; //! Enables or disables a texture creation flag. virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled); //! Sets the fog mode. virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog); //! Only used by the internal engine. Used to notify the driver that //! the window was resized. virtual void OnResize(const core::dimension2d& size); //! Can be called by an IMaterialRenderer to make its work easier. virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates); //! Returns type of video driver virtual E_DRIVER_TYPE getDriverType() const; //! Returns the transformation set by setTransform virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const; //! Sets a vertex shader constant. virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1); //! Sets a pixel shader constant. virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1); //! Sets a constant for the vertex shader based on a name. virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count); //! Bool interface for the above. virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count); //! Int interface for the above. virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count); //! Sets a constant for the pixel shader based on a name. virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count); //! Bool interface for the above. virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count); //! Int interface for the above. virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count); //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) virtual IVideoDriver* getVideoDriver(); //! Creates a render target texture. virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! Clears the ZBuffer. virtual void clearZBuffer(); //! Returns an image created from the last rendered frame. virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER); //! Set/unset a clipping plane. virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false); //! Enable/disable a clipping plane. virtual void enableClipPlane(u32 index, bool enable); //! Returns the graphics card vendor name. virtual core::stringc getVendorInfo() {return VendorName;} //! Enable the 2d override material virtual void enableMaterial2D(bool enable=true); //! Check if the driver was recently reset. virtual bool checkDriverReset() {return DriverWasReset;} // removes the depth struct from the DepthSurface array void removeDepthSurface(SDepthSurface* depth); //! Get the current color format of the color buffer /** \return Color format of the color buffer. */ virtual ECOLOR_FORMAT getColorFormat() const; //! Returns the maximum texture size supported. virtual core::dimension2du getMaxTextureSize() const; //! Get the current color format of the color buffer /** \return Color format of the color buffer as D3D color value. */ D3DFORMAT getD3DColorFormat() const; //! Get D3D color format from Irrlicht color format. D3DFORMAT getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const; //! Get Irrlicht color format from D3D color format. ECOLOR_FORMAT getColorFormatFromD3DFormat(D3DFORMAT format) const; //! Get Cg context #ifdef _IRR_COMPILE_WITH_CG_ const CGcontext& getCgContext(); #endif private: //! enumeration for rendering modes such as 2d and 3d for minizing the switching of renderStates. enum E_RENDER_MODE { ERM_NONE = 0, // no render state has been set yet. ERM_2D, // 2d drawing rendermode ERM_3D, // 3d rendering mode ERM_STENCIL_FILL, // stencil fill mode ERM_SHADOW_VOLUME_ZFAIL, // stencil volume draw mode ERM_SHADOW_VOLUME_ZPASS // stencil volume draw mode }; //! sets right vertex shader void setVertexShader(video::E_VERTEX_TYPE newType); //! sets the needed renderstates bool setRenderStates3DMode(); //! sets the needed renderstates void setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel); //! sets the needed renderstates void setRenderStatesStencilFillMode(bool alpha); //! sets the needed renderstates void setRenderStatesStencilShadowMode(bool zfail, u32 debugDataVisible); //! sets the current Texture bool setActiveTexture(u32 stage, const video::ITexture* texture); //! resets the device bool reset(); //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); //! returns the current size of the screen or rendertarget virtual const core::dimension2d& getCurrentRenderTargetSize() const; //! Check if a proper depth buffer for the RTT is available, otherwise create it. void checkDepthBuffer(ITexture* tex); //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. s32 addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData); //! Adds a new material renderer to the VideoDriver, based on a high level shading //! language. virtual s32 addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, const c8* geometryShaderProgram, const c8* geometryShaderEntryPointName = "main", E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0, E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT); void createMaterialRenderers(); void draw2D3DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType, bool is3D); D3DTEXTUREADDRESS getTextureWrapMode(const u8 clamp); inline D3DCOLORVALUE colorToD3D(const SColor& col) { const f32 f = 1.0f / 255.0f; D3DCOLORVALUE v; v.r = col.getRed() * f; v.g = col.getGreen() * f; v.b = col.getBlue() * f; v.a = col.getAlpha() * f; return v; } E_RENDER_MODE CurrentRenderMode; D3DPRESENT_PARAMETERS present; SMaterial Material, LastMaterial; bool ResetRenderStates; // bool to make all renderstates be reseted if set. bool Transformation3DChanged; const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES]; bool LastTextureMipMapsAvailable[MATERIAL_MAX_TEXTURES]; core::matrix4 Matrices[ETS_COUNT]; // matrizes of the 3d mode we need to restore when we switch back from the 2d mode. HINSTANCE D3DLibrary; IDirect3D9* pID3D; IDirect3DDevice9* pID3DDevice; IDirect3DSurface9* PrevRenderTarget; core::dimension2d CurrentRendertargetSize; HWND WindowId; core::rect* SceneSourceRect; D3DCAPS9 Caps; SIrrlichtCreationParameters Params; E_VERTEX_TYPE LastVertexType; SColorf AmbientLight; core::stringc VendorName; u16 VendorID; core::array DepthBuffers; u32 MaxTextureUnits; u32 MaxUserClipPlanes; u32 MaxMRTs; u32 NumSetMRTs; f32 MaxLightDistance; s32 LastSetLight; enum E_CACHE_2D_ATTRIBUTES { EC2D_ALPHA = 0x1, EC2D_TEXTURE = 0x2, EC2D_ALPHA_CHANNEL = 0x4 }; ECOLOR_FORMAT ColorFormat; D3DFORMAT D3DColorFormat; bool DeviceLost; bool DriverWasReset; bool OcclusionQuerySupport; bool AlphaToCoverageSupport; #ifdef _IRR_COMPILE_WITH_CG_ CGcontext CgContext; #endif }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ #endif // __C_VIDEO_DIRECTX_9_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CD3D9Driver.cpp0000644000000000000000000033375312574354552017601 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE #include "CD3D9Driver.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ #include "os.h" #include "S3DVertex.h" #include "CD3D9Texture.h" #include "CD3D9MaterialRenderer.h" #include "CD3D9ShaderMaterialRenderer.h" #include "CD3D9NormalMapRenderer.h" #include "CD3D9ParallaxMapRenderer.h" #include "CD3D9HLSLMaterialRenderer.h" #include "CD3D9CgMaterialRenderer.h" #include "SIrrCreationParameters.h" namespace irr { namespace video { namespace { inline DWORD F2DW( FLOAT f ) { return *((DWORD*)&f); } } //! constructor CD3D9Driver::CD3D9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io) : CNullDriver(io, params.WindowSize), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(false), D3DLibrary(0), pID3D(0), pID3DDevice(0), PrevRenderTarget(0), WindowId(0), SceneSourceRect(0), LastVertexType((video::E_VERTEX_TYPE)-1), VendorID(0), MaxTextureUnits(0), MaxUserClipPlanes(0), MaxMRTs(1), NumSetMRTs(1), MaxLightDistance(0.f), LastSetLight(-1), ColorFormat(ECF_A8R8G8B8), DeviceLost(false), DriverWasReset(true), OcclusionQuerySupport(false), AlphaToCoverageSupport(false), Params(params) { #ifdef _DEBUG setDebugName("CD3D9Driver"); #endif printVersion(); for (u32 i=0; idrop(); } DepthBuffers.clear(); // drop d3d9 if (pID3DDevice) pID3DDevice->Release(); if (pID3D) pID3D->Release(); #ifdef _IRR_COMPILE_WITH_CG_ cgD3D9SetDevice(0); if(CgContext) { cgDestroyContext(CgContext); } #endif } void CD3D9Driver::createMaterialRenderers() { // create D3D9 material renderers addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SOLID(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SOLID_2_LAYER(pID3DDevice, this)); // add the same renderer for all lightmap types CD3D9MaterialRenderer_LIGHTMAP* lmr = new CD3D9MaterialRenderer_LIGHTMAP(pID3DDevice, this); addMaterialRenderer(lmr); // for EMT_LIGHTMAP: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_ADD: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M2: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M4: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M2: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M4: lmr->drop(); // add remaining fixed function pipeline material renderers addAndDropMaterialRenderer(new CD3D9MaterialRenderer_DETAIL_MAP(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SPHERE_MAP(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D9MaterialRenderer_REFLECTION_2_LAYER(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(pID3DDevice, this)); // add normal map renderers s32 tmp = 0; video::IMaterialRenderer* renderer = 0; renderer = new CD3D9NormalMapRenderer(pID3DDevice, this, tmp, MaterialRenderers[EMT_SOLID].Renderer); renderer->drop(); renderer = new CD3D9NormalMapRenderer(pID3DDevice, this, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer); renderer->drop(); renderer = new CD3D9NormalMapRenderer(pID3DDevice, this, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); renderer->drop(); // add parallax map renderers renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp, MaterialRenderers[EMT_SOLID].Renderer); renderer->drop(); renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer); renderer->drop(); renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); renderer->drop(); // add basic 1 texture blending addAndDropMaterialRenderer(new CD3D9MaterialRenderer_ONETEXTURE_BLEND(pID3DDevice, this)); } //! initialises the Direct3D API bool CD3D9Driver::initDriver(HWND hwnd, bool pureSoftware) { if (!pID3D) { D3DLibrary = LoadLibrary( __TEXT("d3d9.dll") ); if (!D3DLibrary) { os::Printer::log("Error, could not load d3d9.dll.", ELL_ERROR); return false; } typedef IDirect3D9 * (__stdcall *D3DCREATETYPE)(UINT); D3DCREATETYPE d3dCreate = (D3DCREATETYPE) GetProcAddress(D3DLibrary, "Direct3DCreate9"); if (!d3dCreate) { os::Printer::log("Error, could not get proc adress of Direct3DCreate9.", ELL_ERROR); return false; } //just like pID3D = Direct3DCreate9(D3D_SDK_VERSION); pID3D = (*d3dCreate)(D3D_SDK_VERSION); if (!pID3D) { os::Printer::log("Error initializing D3D.", ELL_ERROR); return false; } } // print device information D3DADAPTER_IDENTIFIER9 dai; if (!FAILED(pID3D->GetAdapterIdentifier(Params.DisplayAdapter, 0, &dai))) { char tmp[512]; s32 Product = HIWORD(dai.DriverVersion.HighPart); s32 Version = LOWORD(dai.DriverVersion.HighPart); s32 SubVersion = HIWORD(dai.DriverVersion.LowPart); s32 Build = LOWORD(dai.DriverVersion.LowPart); sprintf(tmp, "%s %s %d.%d.%d.%d", dai.Description, dai.Driver, Product, Version, SubVersion, Build); os::Printer::log(tmp, ELL_INFORMATION); // Assign vendor name based on vendor id. VendorID= static_cast(dai.VendorId); switch(dai.VendorId) { case 0x1002 : VendorName = "ATI Technologies Inc."; break; case 0x10DE : VendorName = "NVIDIA Corporation"; break; case 0x102B : VendorName = "Matrox Electronic Systems Ltd."; break; case 0x121A : VendorName = "3dfx Interactive Inc"; break; case 0x5333 : VendorName = "S3 Graphics Co., Ltd."; break; case 0x8086 : VendorName = "Intel Corporation"; break; default: VendorName = "Unknown VendorId: ";VendorName += (u32)dai.VendorId; break; } } D3DDISPLAYMODE d3ddm; if (FAILED(pID3D->GetAdapterDisplayMode(Params.DisplayAdapter, &d3ddm))) { os::Printer::log("Error: Could not get Adapter Display mode.", ELL_ERROR); return false; } ZeroMemory(&present, sizeof(present)); present.BackBufferCount = 1; present.EnableAutoDepthStencil = TRUE; if (Params.Vsync) present.PresentationInterval = D3DPRESENT_INTERVAL_ONE; else present.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; if (Params.Fullscreen) { present.BackBufferWidth = Params.WindowSize.Width; present.BackBufferHeight = Params.WindowSize.Height; // request 32bit mode if user specified 32 bit, added by Thomas Stuefe if (Params.Bits == 32) present.BackBufferFormat = D3DFMT_X8R8G8B8; else present.BackBufferFormat = D3DFMT_R5G6B5; present.SwapEffect = D3DSWAPEFFECT_FLIP; present.Windowed = FALSE; present.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; } else { present.BackBufferFormat = d3ddm.Format; present.SwapEffect = D3DSWAPEFFECT_DISCARD; present.Windowed = TRUE; } UINT adapter = Params.DisplayAdapter; D3DDEVTYPE devtype = D3DDEVTYPE_HAL; #ifndef _IRR_D3D_NO_SHADER_DEBUGGING devtype = D3DDEVTYPE_REF; #elif defined(_IRR_USE_NVIDIA_PERFHUD_) for (UINT adapter_i = 0; adapter_i < pID3D->GetAdapterCount(); ++adapter_i) { D3DADAPTER_IDENTIFIER9 identifier; pID3D->GetAdapterIdentifier(adapter_i,0,&identifier); if (strstr(identifier.Description,"PerfHUD") != 0) { adapter = adapter_i; devtype = D3DDEVTYPE_REF; break; } } #endif // enable anti alias if possible and desired if (Params.AntiAlias > 0) { if (Params.AntiAlias > 32) Params.AntiAlias = 32; DWORD qualityLevels = 0; while(Params.AntiAlias > 0) { if(SUCCEEDED(pID3D->CheckDeviceMultiSampleType(adapter, devtype, present.BackBufferFormat, !Params.Fullscreen, (D3DMULTISAMPLE_TYPE)Params.AntiAlias, &qualityLevels))) { present.MultiSampleType = (D3DMULTISAMPLE_TYPE)Params.AntiAlias; present.MultiSampleQuality = qualityLevels-1; present.SwapEffect = D3DSWAPEFFECT_DISCARD; break; } --Params.AntiAlias; } if (Params.AntiAlias==0) { os::Printer::log("Anti aliasing disabled because hardware/driver lacks necessary caps.", ELL_WARNING); } } // check stencil buffer compatibility if (Params.Stencilbuffer) { present.AutoDepthStencilFormat = D3DFMT_D24S8; if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { present.AutoDepthStencilFormat = D3DFMT_D24X4S4; if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { present.AutoDepthStencilFormat = D3DFMT_D15S1; if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { os::Printer::log("Device does not support stencilbuffer, disabling stencil buffer.", ELL_WARNING); Params.Stencilbuffer = false; } } } else if(FAILED(pID3D->CheckDepthStencilMatch(adapter, devtype, present.BackBufferFormat, present.BackBufferFormat, present.AutoDepthStencilFormat))) { os::Printer::log("Depth-stencil format is not compatible with display format, disabling stencil buffer.", ELL_WARNING); Params.Stencilbuffer = false; } } // do not use else here to cope with flag change in previous block if (!Params.Stencilbuffer) { present.AutoDepthStencilFormat = D3DFMT_D32; if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { present.AutoDepthStencilFormat = D3DFMT_D24X8; if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { present.AutoDepthStencilFormat = D3DFMT_D16; if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { os::Printer::log("Device does not support required depth buffer.", ELL_WARNING); return false; } } } } // create device DWORD fpuPrecision = Params.HighPrecisionFPU ? D3DCREATE_FPU_PRESERVE : 0; DWORD multithreaded = Params.DriverMultithreaded ? D3DCREATE_MULTITHREADED : 0; if (pureSoftware) { if (FAILED(pID3D->CreateDevice(Params.DisplayAdapter, D3DDEVTYPE_REF, hwnd, fpuPrecision | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &pID3DDevice))) os::Printer::log("Was not able to create Direct3D9 software device.", ELL_ERROR); } else { HRESULT hr = pID3D->CreateDevice(adapter, devtype, hwnd, fpuPrecision | multithreaded | D3DCREATE_HARDWARE_VERTEXPROCESSING, &present, &pID3DDevice); if(FAILED(hr)) hr = pID3D->CreateDevice(adapter, devtype, hwnd, fpuPrecision | multithreaded | D3DCREATE_MIXED_VERTEXPROCESSING , &present, &pID3DDevice); if(FAILED(hr)) hr = pID3D->CreateDevice(adapter, devtype, hwnd, fpuPrecision | multithreaded | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &pID3DDevice); if (FAILED(hr)) os::Printer::log("Was not able to create Direct3D9 device.", ELL_ERROR); } if (!pID3DDevice) { os::Printer::log("Was not able to create DIRECT3D9 device.", ELL_ERROR); return false; } // get caps pID3DDevice->GetDeviceCaps(&Caps); os::Printer::log("Currently available Video Memory (kB)", core::stringc(pID3DDevice->GetAvailableTextureMem()/1024).c_str()); // disable stencilbuffer if necessary if (Params.Stencilbuffer && (!(Caps.StencilCaps & D3DSTENCILCAPS_DECRSAT) || !(Caps.StencilCaps & D3DSTENCILCAPS_INCRSAT) || !(Caps.StencilCaps & D3DSTENCILCAPS_KEEP))) { os::Printer::log("Device not able to use stencil buffer, disabling stencil buffer.", ELL_WARNING); Params.Stencilbuffer = false; } // set default vertex shader setVertexShader(EVT_STANDARD); // set fog mode setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); // set exposed data ExposedData.D3D9.D3D9 = pID3D; ExposedData.D3D9.D3DDev9 = pID3DDevice; ExposedData.D3D9.HWnd = hwnd; ResetRenderStates = true; // create materials createMaterialRenderers(); MaxTextureUnits = core::min_((u32)Caps.MaxSimultaneousTextures, MATERIAL_MAX_TEXTURES); MaxUserClipPlanes = (u32)Caps.MaxUserClipPlanes; MaxMRTs = (s32)Caps.NumSimultaneousRTs; OcclusionQuerySupport=(pID3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL) == S_OK); if (VendorID==0x10DE)//NVidia AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')) == S_OK); else if (VendorID==0x1002)//ATI AlphaToCoverageSupport = true; // TODO: Check unknown #if 0 AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE, (D3DFORMAT)MAKEFOURCC('A','2','M','1')) == S_OK); #endif DriverAttributes->setAttribute("MaxTextures", (s32)MaxTextureUnits); DriverAttributes->setAttribute("MaxSupportedTextures", (s32)Caps.MaxSimultaneousTextures); DriverAttributes->setAttribute("MaxLights", (s32)Caps.MaxActiveLights); DriverAttributes->setAttribute("MaxAnisotropy", (s32)Caps.MaxAnisotropy); DriverAttributes->setAttribute("MaxUserClipPlanes", (s32)Caps.MaxUserClipPlanes); DriverAttributes->setAttribute("MaxMultipleRenderTargets", (s32)Caps.NumSimultaneousRTs); DriverAttributes->setAttribute("MaxIndices", (s32)Caps.MaxVertexIndex); DriverAttributes->setAttribute("MaxTextureSize", (s32)core::min_(Caps.MaxTextureHeight,Caps.MaxTextureWidth)); DriverAttributes->setAttribute("MaxTextureLODBias", 16); DriverAttributes->setAttribute("Version", 901); DriverAttributes->setAttribute("ShaderLanguageVersion", (s32)(((0x00ff00 & Caps.VertexShaderVersion)>>8)*100 + (Caps.VertexShaderVersion&0xff))); DriverAttributes->setAttribute("AntiAlias", Params.AntiAlias); // set the renderstates setRenderStates3DMode(); // store the screen's depth buffer DepthBuffers.push_back(new SDepthSurface()); if (SUCCEEDED(pID3DDevice->GetDepthStencilSurface(&(DepthBuffers[0]->Surface)))) { D3DSURFACE_DESC desc; DepthBuffers[0]->Surface->GetDesc(&desc); DepthBuffers[0]->Size.set(desc.Width, desc.Height); } else { os::Printer::log("Was not able to get main depth buffer.", ELL_ERROR); return false; } D3DColorFormat = D3DFMT_A8R8G8B8; IDirect3DSurface9* bb=0; if (SUCCEEDED(pID3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &bb))) { D3DSURFACE_DESC desc; bb->GetDesc(&desc); D3DColorFormat = desc.Format; if (D3DColorFormat == D3DFMT_X8R8G8B8) D3DColorFormat = D3DFMT_A8R8G8B8; bb->Release(); } ColorFormat = getColorFormatFromD3DFormat(D3DColorFormat); #ifdef _IRR_COMPILE_WITH_CG_ CgContext = cgCreateContext(); cgD3D9SetDevice(pID3DDevice); #endif // so far so good. return true; } //! applications must call this method before performing any rendering. returns false if failed. bool CD3D9Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, const SExposedVideoData& videoData, core::rect* sourceRect) { CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); WindowId = (HWND)videoData.D3D9.HWnd; SceneSourceRect = sourceRect; if (!pID3DDevice) return false; HRESULT hr; if (DeviceLost) { if (FAILED(hr = pID3DDevice->TestCooperativeLevel())) { if (hr == D3DERR_DEVICELOST) { Sleep(100); hr = pID3DDevice->TestCooperativeLevel(); if (hr == D3DERR_DEVICELOST) return false; } if ((hr == D3DERR_DEVICENOTRESET) && !reset()) return false; } } DWORD flags = 0; if (backBuffer) flags |= D3DCLEAR_TARGET; if (zBuffer) flags |= D3DCLEAR_ZBUFFER; if (Params.Stencilbuffer) flags |= D3DCLEAR_STENCIL; if (flags) { hr = pID3DDevice->Clear( 0, NULL, flags, color.color, 1.0, 0); if (FAILED(hr)) os::Printer::log("DIRECT3D9 clear failed.", ELL_WARNING); } hr = pID3DDevice->BeginScene(); if (FAILED(hr)) { os::Printer::log("DIRECT3D9 begin scene failed.", ELL_WARNING); return false; } return true; } //! applications must call this method after performing any rendering. returns false if failed. bool CD3D9Driver::endScene() { CNullDriver::endScene(); DriverWasReset=false; HRESULT hr = pID3DDevice->EndScene(); if (FAILED(hr)) { os::Printer::log("DIRECT3D9 end scene failed.", ELL_WARNING); return false; } RECT* srcRct = 0; RECT sourceRectData; if ( SceneSourceRect ) { srcRct = &sourceRectData; sourceRectData.left = SceneSourceRect->UpperLeftCorner.X; sourceRectData.top = SceneSourceRect->UpperLeftCorner.Y; sourceRectData.right = SceneSourceRect->LowerRightCorner.X; sourceRectData.bottom = SceneSourceRect->LowerRightCorner.Y; } IDirect3DSwapChain9* swChain; hr = pID3DDevice->GetSwapChain(0, &swChain); DWORD flags = (Params.HandleSRGB && (Caps.Caps3&D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION))?D3DPRESENT_LINEAR_CONTENT:0; hr = swChain->Present(srcRct, NULL, WindowId, NULL, flags); swChain->Release(); if (SUCCEEDED(hr)) return true; if (hr == D3DERR_DEVICELOST) { DeviceLost = true; os::Printer::log("Present failed", "DIRECT3D9 device lost.", ELL_WARNING); } #ifdef D3DERR_DEVICEREMOVED else if (hr == D3DERR_DEVICEREMOVED) { os::Printer::log("Present failed", "Device removed.", ELL_WARNING); } #endif else if (hr == D3DERR_INVALIDCALL) { os::Printer::log("Present failed", "Invalid Call", ELL_WARNING); } else os::Printer::log("DIRECT3D9 present failed.", ELL_WARNING); return false; } //! queries the features of the driver, returns true if feature is available bool CD3D9Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const { if (!FeatureEnabled[feature]) return false; switch (feature) { case EVDF_MULTITEXTURE: case EVDF_BILINEAR_FILTER: return true; case EVDF_RENDER_TO_TARGET: return Caps.NumSimultaneousRTs > 0; case EVDF_HARDWARE_TL: return (Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0; case EVDF_MIP_MAP: return (Caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP) != 0; case EVDF_MIP_MAP_AUTO_UPDATE: // always return false because a lot of drivers claim they do // this but actually don't do this at all. return false; //(Caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0; case EVDF_STENCIL_BUFFER: return Params.Stencilbuffer && Caps.StencilCaps; case EVDF_VERTEX_SHADER_1_1: return Caps.VertexShaderVersion >= D3DVS_VERSION(1,1); case EVDF_VERTEX_SHADER_2_0: return Caps.VertexShaderVersion >= D3DVS_VERSION(2,0); case EVDF_VERTEX_SHADER_3_0: return Caps.VertexShaderVersion >= D3DVS_VERSION(3,0); case EVDF_PIXEL_SHADER_1_1: return Caps.PixelShaderVersion >= D3DPS_VERSION(1,1); case EVDF_PIXEL_SHADER_1_2: return Caps.PixelShaderVersion >= D3DPS_VERSION(1,2); case EVDF_PIXEL_SHADER_1_3: return Caps.PixelShaderVersion >= D3DPS_VERSION(1,3); case EVDF_PIXEL_SHADER_1_4: return Caps.PixelShaderVersion >= D3DPS_VERSION(1,4); case EVDF_PIXEL_SHADER_2_0: return Caps.PixelShaderVersion >= D3DPS_VERSION(2,0); case EVDF_PIXEL_SHADER_3_0: return Caps.PixelShaderVersion >= D3DPS_VERSION(3,0); case EVDF_HLSL: return Caps.VertexShaderVersion >= D3DVS_VERSION(1,1); case EVDF_TEXTURE_NSQUARE: return (Caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) == 0; case EVDF_TEXTURE_NPOT: return (Caps.TextureCaps & D3DPTEXTURECAPS_POW2) == 0; case EVDF_COLOR_MASK: return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) != 0; case EVDF_MULTIPLE_RENDER_TARGETS: return Caps.NumSimultaneousRTs > 1; case EVDF_MRT_COLOR_MASK: return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_INDEPENDENTWRITEMASKS) != 0; case EVDF_MRT_BLEND: return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING) != 0; case EVDF_OCCLUSION_QUERY: return OcclusionQuerySupport; case EVDF_POLYGON_OFFSET: return (Caps.RasterCaps & (D3DPRASTERCAPS_DEPTHBIAS|D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS)) != 0; case EVDF_BLEND_OPERATIONS: case EVDF_TEXTURE_MATRIX: #ifdef _IRR_COMPILE_WITH_CG_ // available iff. define is present case EVDF_CG: #endif return true; default: return false; }; } //! sets transformation void CD3D9Driver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) { Transformation3DChanged = true; switch(state) { case ETS_VIEW: pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)mat.pointer())); break; case ETS_WORLD: pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)mat.pointer())); break; case ETS_PROJECTION: pID3DDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)((void*)mat.pointer())); break; case ETS_COUNT: return; default: if (state-ETS_TEXTURE_0 < MATERIAL_MAX_TEXTURES) { if (mat.isIdentity()) pID3DDevice->SetTextureStageState( state - ETS_TEXTURE_0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); else { pID3DDevice->SetTextureStageState( state - ETS_TEXTURE_0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); pID3DDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+ ( state - ETS_TEXTURE_0 )), (D3DMATRIX*)((void*)mat.pointer())); } } break; } Matrices[state] = mat; } //! sets the current Texture bool CD3D9Driver::setActiveTexture(u32 stage, const video::ITexture* texture) { if (CurrentTexture[stage] == texture) return true; if (texture && texture->getDriverType() != EDT_DIRECT3D9) { os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); return false; } CurrentTexture[stage] = texture; if (!texture) { pID3DDevice->SetTexture(stage, 0); pID3DDevice->SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); } else { pID3DDevice->SetTexture(stage, ((const CD3D9Texture*)texture)->getDX9Texture()); } return true; } //! sets a material void CD3D9Driver::setMaterial(const SMaterial& material) { Material = material; OverrideMaterial.apply(Material); for (u32 i=0; igetDriverType() != EDT_DIRECT3D9) { os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); return false; } // check for valid render target if (texture && !texture->isRenderTarget()) { os::Printer::log("Fatal Error: Tried to set a non render target texture as render target.", ELL_ERROR); return false; } CD3D9Texture* tex = static_cast(texture); // check if we should set the previous RT back bool ret = true; for(u32 i = 1; i < NumSetMRTs; i++) { // First texture handled elsewhere pID3DDevice->SetRenderTarget(i, NULL); } if (tex == 0) { if (PrevRenderTarget) { if (FAILED(pID3DDevice->SetRenderTarget(0, PrevRenderTarget))) { os::Printer::log("Error: Could not set back to previous render target.", ELL_ERROR); ret = false; } if (FAILED(pID3DDevice->SetDepthStencilSurface(DepthBuffers[0]->Surface))) { os::Printer::log("Error: Could not set main depth buffer.", ELL_ERROR); } CurrentRendertargetSize = core::dimension2d(0,0); PrevRenderTarget->Release(); PrevRenderTarget = 0; } } else { // we want to set a new target. so do this. // store previous target if (!PrevRenderTarget) { if (FAILED(pID3DDevice->GetRenderTarget(0, &PrevRenderTarget))) { os::Printer::log("Could not get previous render target.", ELL_ERROR); return false; } } // set new render target if (FAILED(pID3DDevice->SetRenderTarget(0, tex->getRenderTargetSurface()))) { os::Printer::log("Error: Could not set render target.", ELL_ERROR); return false; } CurrentRendertargetSize = tex->getSize(); if (FAILED(pID3DDevice->SetDepthStencilSurface(tex->DepthSurface->Surface))) { os::Printer::log("Error: Could not set new depth buffer.", ELL_ERROR); } } Transformation3DChanged=true; if (clearBackBuffer || clearZBuffer) { DWORD flags = 0; if (clearBackBuffer) flags |= D3DCLEAR_TARGET; if (clearZBuffer) flags |= D3DCLEAR_ZBUFFER; pID3DDevice->Clear(0, NULL, flags, color.color, 1.0f, 0); } return ret; } //! Sets multiple render targets bool CD3D9Driver::setRenderTarget(const core::array& targets, bool clearBackBuffer, bool clearZBuffer, SColor color) { if (targets.size()==0) return setRenderTarget(0, clearBackBuffer, clearZBuffer, color); u32 maxMultipleRTTs = core::min_(MaxMRTs, targets.size()); for (u32 i = 0; i < maxMultipleRTTs; ++i) { if (targets[i].TargetType != ERT_RENDER_TEXTURE || !targets[i].RenderTexture) { maxMultipleRTTs = i; os::Printer::log("Missing texture for MRT.", ELL_WARNING); break; } // check for right driver type if (targets[i].RenderTexture->getDriverType() != EDT_DIRECT3D9) { maxMultipleRTTs = i; os::Printer::log("Tried to set a texture not owned by this driver.", ELL_WARNING); break; } // check for valid render target if (!targets[i].RenderTexture->isRenderTarget()) { maxMultipleRTTs = i; os::Printer::log("Tried to set a non render target texture as render target.", ELL_WARNING); break; } // check for valid size if (targets[0].RenderTexture->getSize() != targets[i].RenderTexture->getSize()) { maxMultipleRTTs = i; os::Printer::log("Render target texture has wrong size.", ELL_WARNING); break; } } if (maxMultipleRTTs==0) { os::Printer::log("Fatal Error: No valid MRT found.", ELL_ERROR); return false; } CD3D9Texture* tex = static_cast(targets[0].RenderTexture); // check if we should set the previous RT back bool ret = true; // we want to set a new target. so do this. // store previous target if (!PrevRenderTarget) { if (FAILED(pID3DDevice->GetRenderTarget(0, &PrevRenderTarget))) { os::Printer::log("Could not get previous render target.", ELL_ERROR); return false; } } // set new render target // In d3d9 we have at most 4 MRTs, so the following is enough D3DRENDERSTATETYPE colorWrite[4]={D3DRS_COLORWRITEENABLE, D3DRS_COLORWRITEENABLE1, D3DRS_COLORWRITEENABLE2, D3DRS_COLORWRITEENABLE3}; for (u32 i = 0; i < maxMultipleRTTs; ++i) { if (FAILED(pID3DDevice->SetRenderTarget(i, static_cast(targets[i].RenderTexture)->getRenderTargetSurface()))) { os::Printer::log("Error: Could not set render target.", ELL_ERROR); return false; } if (i<4 && (i==0 || queryFeature(EVDF_MRT_COLOR_MASK))) { const DWORD flag = ((targets[i].ColorMask & ECP_RED)?D3DCOLORWRITEENABLE_RED:0) | ((targets[i].ColorMask & ECP_GREEN)?D3DCOLORWRITEENABLE_GREEN:0) | ((targets[i].ColorMask & ECP_BLUE)?D3DCOLORWRITEENABLE_BLUE:0) | ((targets[i].ColorMask & ECP_ALPHA)?D3DCOLORWRITEENABLE_ALPHA:0); pID3DDevice->SetRenderState(colorWrite[i], flag); } } for(u32 i = maxMultipleRTTs; i < NumSetMRTs; i++) { pID3DDevice->SetRenderTarget(i, NULL); } NumSetMRTs=maxMultipleRTTs; CurrentRendertargetSize = tex->getSize(); if (FAILED(pID3DDevice->SetDepthStencilSurface(tex->DepthSurface->Surface))) { os::Printer::log("Error: Could not set new depth buffer.", ELL_ERROR); } if (clearBackBuffer || clearZBuffer) { DWORD flags = 0; if (clearBackBuffer) flags |= D3DCLEAR_TARGET; if (clearZBuffer) flags |= D3DCLEAR_ZBUFFER; pID3DDevice->Clear(0, NULL, flags, color.color, 1.0f, 0); } return ret; } //! sets a viewport void CD3D9Driver::setViewPort(const core::rect& area) { core::rect vp = area; core::rect rendert(0,0, getCurrentRenderTargetSize().Width, getCurrentRenderTargetSize().Height); vp.clipAgainst(rendert); if (vp.getHeight()>0 && vp.getWidth()>0) { D3DVIEWPORT9 viewPort; viewPort.X = vp.UpperLeftCorner.X; viewPort.Y = vp.UpperLeftCorner.Y; viewPort.Width = vp.getWidth(); viewPort.Height = vp.getHeight(); viewPort.MinZ = 0.0f; viewPort.MaxZ = 1.0f; HRESULT hr = pID3DDevice->SetViewport(&viewPort); if (FAILED(hr)) os::Printer::log("Failed setting the viewport.", ELL_WARNING); else ViewPort = vp; } } //! gets the area of the current viewport const core::rect& CD3D9Driver::getViewPort() const { return ViewPort; } bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *hwBuffer) { if (!hwBuffer) return false; const scene::IMeshBuffer* mb = hwBuffer->MeshBuffer; const void* vertices=mb->getVertices(); const u32 vertexCount=mb->getVertexCount(); const E_VERTEX_TYPE vType=mb->getVertexType(); const u32 vertexSize = getVertexPitchFromType(vType); const u32 bufSize = vertexSize * vertexCount; if (!hwBuffer->vertexBuffer || (bufSize > hwBuffer->vertexBufferSize)) { if (hwBuffer->vertexBuffer) { hwBuffer->vertexBuffer->Release(); hwBuffer->vertexBuffer=0; } DWORD FVF; // Get the vertex sizes and cvf switch (vType) { case EVT_STANDARD: FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1; break; case EVT_2TCOORDS: FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2; break; case EVT_TANGENTS: FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX3; break; default: return false; } DWORD flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY if (hwBuffer->Mapped_Vertex != scene::EHM_STATIC) flags |= D3DUSAGE_DYNAMIC; if (FAILED(pID3DDevice->CreateVertexBuffer(bufSize, flags, FVF, D3DPOOL_DEFAULT, &hwBuffer->vertexBuffer, NULL))) return false; hwBuffer->vertexBufferSize = bufSize; flags = 0; // SIO2: Reset flags before Lock if (hwBuffer->Mapped_Vertex != scene::EHM_STATIC) flags = D3DLOCK_DISCARD; void* lockedBuffer = 0; hwBuffer->vertexBuffer->Lock(0, bufSize, (void**)&lockedBuffer, flags); memcpy(lockedBuffer, vertices, bufSize); hwBuffer->vertexBuffer->Unlock(); } else { void* lockedBuffer = 0; hwBuffer->vertexBuffer->Lock(0, bufSize, (void**)&lockedBuffer, D3DLOCK_DISCARD); memcpy(lockedBuffer, vertices, bufSize); hwBuffer->vertexBuffer->Unlock(); } return true; } bool CD3D9Driver::updateIndexHardwareBuffer(SHWBufferLink_d3d9 *hwBuffer) { if (!hwBuffer) return false; const scene::IMeshBuffer* mb = hwBuffer->MeshBuffer; const u16* indices=mb->getIndices(); const u32 indexCount=mb->getIndexCount(); u32 indexSize = 2; D3DFORMAT indexType=D3DFMT_UNKNOWN; switch (mb->getIndexType()) { case EIT_16BIT: { indexType=D3DFMT_INDEX16; indexSize = 2; break; } case EIT_32BIT: { indexType=D3DFMT_INDEX32; indexSize = 4; break; } } const u32 bufSize = indexSize * indexCount; if (!hwBuffer->indexBuffer || (bufSize > hwBuffer->indexBufferSize)) { if (hwBuffer->indexBuffer) { hwBuffer->indexBuffer->Release(); hwBuffer->indexBuffer=0; } DWORD flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY if (hwBuffer->Mapped_Index != scene::EHM_STATIC) flags |= D3DUSAGE_DYNAMIC; // SIO2: Add DYNAMIC flag for dynamic buffer data if (FAILED(pID3DDevice->CreateIndexBuffer(bufSize, flags, indexType, D3DPOOL_DEFAULT, &hwBuffer->indexBuffer, NULL))) return false; flags = 0; // SIO2: Reset flags before Lock if (hwBuffer->Mapped_Index != scene::EHM_STATIC) flags = D3DLOCK_DISCARD; void* lockedBuffer = 0; if (FAILED(hwBuffer->indexBuffer->Lock( 0, 0, (void**)&lockedBuffer, flags))) return false; memcpy(lockedBuffer, indices, bufSize); hwBuffer->indexBuffer->Unlock(); hwBuffer->indexBufferSize = bufSize; } else { void* lockedBuffer = 0; if( SUCCEEDED(hwBuffer->indexBuffer->Lock( 0, 0, (void**)&lockedBuffer, D3DLOCK_DISCARD))) { memcpy(lockedBuffer, indices, bufSize); hwBuffer->indexBuffer->Unlock(); } } return true; } //! updates hardware buffer if needed bool CD3D9Driver::updateHardwareBuffer(SHWBufferLink *hwBuffer) { if (!hwBuffer) return false; if (hwBuffer->Mapped_Vertex!=scene::EHM_NEVER) { if (hwBuffer->ChangedID_Vertex != hwBuffer->MeshBuffer->getChangedID_Vertex() || !((SHWBufferLink_d3d9*)hwBuffer)->vertexBuffer) { hwBuffer->ChangedID_Vertex = hwBuffer->MeshBuffer->getChangedID_Vertex(); if (!updateVertexHardwareBuffer((SHWBufferLink_d3d9*)hwBuffer)) return false; } } if (hwBuffer->Mapped_Index!=scene::EHM_NEVER) { if (hwBuffer->ChangedID_Index != hwBuffer->MeshBuffer->getChangedID_Index() || !((SHWBufferLink_d3d9*)hwBuffer)->indexBuffer) { hwBuffer->ChangedID_Index = hwBuffer->MeshBuffer->getChangedID_Index(); if (!updateIndexHardwareBuffer((SHWBufferLink_d3d9*)hwBuffer)) return false; } } return true; } //! Create hardware buffer from meshbuffer CD3D9Driver::SHWBufferLink *CD3D9Driver::createHardwareBuffer(const scene::IMeshBuffer* mb) { // Looks like d3d does not support only partial buffering, so refuse // in any case of NEVER if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER || mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER)) return 0; SHWBufferLink_d3d9 *hwBuffer=new SHWBufferLink_d3d9(mb); //add to map HWBufferMap.insert(hwBuffer->MeshBuffer, hwBuffer); hwBuffer->ChangedID_Vertex=hwBuffer->MeshBuffer->getChangedID_Vertex(); hwBuffer->ChangedID_Index=hwBuffer->MeshBuffer->getChangedID_Index(); hwBuffer->Mapped_Vertex=mb->getHardwareMappingHint_Vertex(); hwBuffer->Mapped_Index=mb->getHardwareMappingHint_Index(); hwBuffer->LastUsed=0; hwBuffer->vertexBuffer=0; hwBuffer->indexBuffer=0; hwBuffer->vertexBufferSize=0; hwBuffer->indexBufferSize=0; if (!updateHardwareBuffer(hwBuffer)) { deleteHardwareBuffer(hwBuffer); return 0; } return hwBuffer; } void CD3D9Driver::deleteHardwareBuffer(SHWBufferLink *_HWBuffer) { if (!_HWBuffer) return; SHWBufferLink_d3d9 *HWBuffer=(SHWBufferLink_d3d9*)_HWBuffer; if (HWBuffer->indexBuffer) { HWBuffer->indexBuffer->Release(); HWBuffer->indexBuffer = 0; } if (HWBuffer->vertexBuffer) { HWBuffer->vertexBuffer->Release(); HWBuffer->vertexBuffer = 0; } CNullDriver::deleteHardwareBuffer(_HWBuffer); } //! Draw hardware buffer void CD3D9Driver::drawHardwareBuffer(SHWBufferLink *_HWBuffer) { if (!_HWBuffer) return; SHWBufferLink_d3d9 *HWBuffer=(SHWBufferLink_d3d9*)_HWBuffer; updateHardwareBuffer(HWBuffer); //check if update is needed HWBuffer->LastUsed=0;//reset count const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; const E_VERTEX_TYPE vType = mb->getVertexType(); const u32 stride = getVertexPitchFromType(vType); const void* vPtr = mb->getVertices(); const void* iPtr = mb->getIndices(); if (HWBuffer->vertexBuffer) { pID3DDevice->SetStreamSource(0, HWBuffer->vertexBuffer, 0, stride); vPtr=0; } if (HWBuffer->indexBuffer) { pID3DDevice->SetIndices(HWBuffer->indexBuffer); iPtr=0; } drawVertexPrimitiveList(vPtr, mb->getVertexCount(), iPtr, mb->getIndexCount()/3, mb->getVertexType(), scene::EPT_TRIANGLES, mb->getIndexType()); if (HWBuffer->vertexBuffer) pID3DDevice->SetStreamSource(0, 0, 0, 0); if (HWBuffer->indexBuffer) pID3DDevice->SetIndices(0); } //! Create occlusion query. /** Use node for identification and mesh for occlusion test. */ void CD3D9Driver::addOcclusionQuery(scene::ISceneNode* node, const scene::IMesh* mesh) { if (!queryFeature(EVDF_OCCLUSION_QUERY)) return; CNullDriver::addOcclusionQuery(node, mesh); const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if ((index != -1) && (OcclusionQueries[index].PID == 0)) pID3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, reinterpret_cast(&OcclusionQueries[index].PID)); } //! Remove occlusion query. void CD3D9Driver::removeOcclusionQuery(scene::ISceneNode* node) { const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if (index != -1) { if (OcclusionQueries[index].PID != 0) reinterpret_cast(OcclusionQueries[index].PID)->Release(); CNullDriver::removeOcclusionQuery(node); } } //! Run occlusion query. Draws mesh stored in query. /** If the mesh shall not be rendered visible, use overrideMaterial to disable the color and depth buffer. */ void CD3D9Driver::runOcclusionQuery(scene::ISceneNode* node, bool visible) { if (!node) return; const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if (index != -1) { if (OcclusionQueries[index].PID) reinterpret_cast(OcclusionQueries[index].PID)->Issue(D3DISSUE_BEGIN); CNullDriver::runOcclusionQuery(node,visible); if (OcclusionQueries[index].PID) reinterpret_cast(OcclusionQueries[index].PID)->Issue(D3DISSUE_END); } } //! Update occlusion query. Retrieves results from GPU. /** If the query shall not block, set the flag to false. Update might not occur in this case, though */ void CD3D9Driver::updateOcclusionQuery(scene::ISceneNode* node, bool block) { const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if (index != -1) { // not yet started if (OcclusionQueries[index].Run==u32(~0)) return; bool available = block?true:false; int tmp=0; if (!block) available=(reinterpret_cast(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), 0)==S_OK); else { do { HRESULT hr = reinterpret_cast(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), D3DGETDATA_FLUSH); available = (hr == S_OK); if (hr!=S_FALSE) break; } while (!available); } if (available) OcclusionQueries[index].Result = tmp; } } //! Return query result. /** Return value is the number of visible pixels/fragments. The value is a safe approximation, i.e. can be larger than the actual value of pixels. */ u32 CD3D9Driver::getOcclusionQueryResult(scene::ISceneNode* node) const { const s32 index = OcclusionQueries.linear_search(SOccQuery(node)); if (index != -1) return OcclusionQueries[index].Result; else return ~0; } //! draws a vertex primitive list void CD3D9Driver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { if (!checkPrimitiveCount(primitiveCount)) return; CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType,iType); if (!vertexCount || !primitiveCount) return; draw2D3DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType, true); } //! draws a vertex primitive list void CD3D9Driver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { if (!checkPrimitiveCount(primitiveCount)) return; CNullDriver::draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType,iType); if (!vertexCount || !primitiveCount) return; draw2D3DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType, false); } void CD3D9Driver::draw2D3DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType, bool is3D) { setVertexShader(vType); const u32 stride = getVertexPitchFromType(vType); D3DFORMAT indexType=D3DFMT_UNKNOWN; switch (iType) { case (EIT_16BIT): { indexType=D3DFMT_INDEX16; break; } case (EIT_32BIT): { indexType=D3DFMT_INDEX32; break; } } if (is3D) { if (!setRenderStates3DMode()) return; } else { if (Material.MaterialType==EMT_ONETEXTURE_BLEND) { E_BLEND_FACTOR srcFact; E_BLEND_FACTOR dstFact; E_MODULATE_FUNC modulo; u32 alphaSource; unpack_textureBlendFunc ( srcFact, dstFact, modulo, alphaSource, Material.MaterialTypeParam); setRenderStates2DMode(alphaSource&video::EAS_VERTEX_COLOR, (Material.getTexture(0) != 0), (alphaSource&video::EAS_TEXTURE) != 0); } else setRenderStates2DMode(Material.MaterialType==EMT_TRANSPARENT_VERTEX_ALPHA, (Material.getTexture(0) != 0), Material.MaterialType==EMT_TRANSPARENT_ALPHA_CHANNEL); } switch (pType) { case scene::EPT_POINT_SPRITES: case scene::EPT_POINTS: { f32 tmp=Material.Thickness/getScreenSize().Height; if (pType==scene::EPT_POINT_SPRITES) pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_POINTSIZE, F2DW(tmp)); tmp=1.0f; pID3DDevice->SetRenderState(D3DRS_POINTSCALE_A, F2DW(tmp)); pID3DDevice->SetRenderState(D3DRS_POINTSCALE_B, F2DW(tmp)); pID3DDevice->SetRenderState(D3DRS_POINTSIZE_MIN, F2DW(tmp)); tmp=0.0f; pID3DDevice->SetRenderState(D3DRS_POINTSCALE_C, F2DW(tmp)); if (!vertices) { pID3DDevice->DrawIndexedPrimitive(D3DPT_POINTLIST, 0, 0, vertexCount, 0, primitiveCount); } else { pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_POINTLIST, 0, vertexCount, primitiveCount, indexList, indexType, vertices, stride); } pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE); if (pType==scene::EPT_POINT_SPRITES) pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE); } break; case scene::EPT_LINE_STRIP: if(!vertices) pID3DDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, 0, 0, vertexCount, 0, primitiveCount); else pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount, primitiveCount, indexList, indexType, vertices, stride); break; case scene::EPT_LINE_LOOP: if(!vertices) { // TODO: Implement proper hardware support for this primitive type. // (No looping occurs currently because this would require a way to // draw the hardware buffer with a custom set of indices. We may even // need to create a new mini index buffer specifically for this // primitive type.) pID3DDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertexCount, 0, primitiveCount); } else { pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount, primitiveCount - 1, indexList, indexType, vertices, stride); u16 tmpIndices[] = {primitiveCount - 1, 0}; pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount, 1, tmpIndices, indexType, vertices, stride); } break; case scene::EPT_LINES: if(!vertices) pID3DDevice->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, vertexCount, 0, primitiveCount); else pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount, primitiveCount, indexList, indexType, vertices, stride); break; case scene::EPT_TRIANGLE_STRIP: if(!vertices) pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, vertexCount, 0, primitiveCount); else pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLESTRIP, 0, vertexCount, primitiveCount, indexList, indexType, vertices, stride); break; case scene::EPT_TRIANGLE_FAN: if(!vertices) pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0, 0, vertexCount, 0, primitiveCount); else pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLEFAN, 0, vertexCount, primitiveCount, indexList, indexType, vertices, stride); break; case scene::EPT_TRIANGLES: if(!vertices) { pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, vertexCount, 0, primitiveCount); } else { pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vertexCount, primitiveCount, indexList, indexType, vertices, stride); } break; } } void CD3D9Driver::draw2DImage(const video::ITexture* texture, const core::rect& destRect, const core::rect& sourceRect, const core::rect* clipRect, const video::SColor* const colors, bool useAlphaChannelOfTexture) { if(!texture) return; const core::dimension2d& ss = texture->getOriginalSize(); core::rect tcoords; tcoords.UpperLeftCorner.X = (f32)sourceRect.UpperLeftCorner.X / (f32)ss.Width; tcoords.UpperLeftCorner.Y = (f32)sourceRect.UpperLeftCorner.Y / (f32)ss.Height; tcoords.LowerRightCorner.X = (f32)sourceRect.LowerRightCorner.X / (f32)ss.Width; tcoords.LowerRightCorner.Y = (f32)sourceRect.LowerRightCorner.Y / (f32)ss.Height; const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); const video::SColor temp[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; const video::SColor* const useColor = colors ? colors : temp; S3DVertex vtx[4]; // clock wise vtx[0] = S3DVertex((f32)destRect.UpperLeftCorner.X, (f32)destRect.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[0], tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); vtx[1] = S3DVertex((f32)destRect.LowerRightCorner.X, (f32)destRect.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[3], tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); vtx[2] = S3DVertex((f32)destRect.LowerRightCorner.X, (f32)destRect.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[2], tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); vtx[3] = S3DVertex((f32)destRect.UpperLeftCorner.X, (f32)destRect.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[1], tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); s16 indices[6] = {0,1,2,0,2,3}; setActiveTexture(0, const_cast(texture)); setRenderStates2DMode(useColor[0].getAlpha()<255 || useColor[1].getAlpha()<255 || useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255, true, useAlphaChannelOfTexture); setVertexShader(EVT_STANDARD); if (clipRect) { pID3DDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); RECT scissor; scissor.left = clipRect->UpperLeftCorner.X; scissor.top = clipRect->UpperLeftCorner.Y; scissor.right = clipRect->LowerRightCorner.X; scissor.bottom = clipRect->LowerRightCorner.Y; pID3DDevice->SetScissorRect(&scissor); } pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], D3DFMT_INDEX16,&vtx[0], sizeof(S3DVertex)); if (clipRect) pID3DDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); } void CD3D9Driver::draw2DImageBatch(const video::ITexture* texture, const core::array >& positions, const core::array >& sourceRects, const core::rect* clipRect, SColor color, bool useAlphaChannelOfTexture) { if (!texture) return; if (!setActiveTexture(0, const_cast(texture))) return; setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); const irr::u32 drawCount = core::min_(positions.size(), sourceRects.size()); core::array vtx(drawCount * 4); core::array indices(drawCount * 6); for(u32 i = 0;i < drawCount;i++) { core::position2d targetPos = positions[i]; core::position2d sourcePos = sourceRects[i].UpperLeftCorner; // This needs to be signed as it may go negative. core::dimension2d sourceSize(sourceRects[i].getSize()); if (clipRect) { if (targetPos.X < clipRect->UpperLeftCorner.X) { sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; if (sourceSize.Width <= 0) continue; sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; targetPos.X = clipRect->UpperLeftCorner.X; } if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; if (sourceSize.Width <= 0) continue; } if (targetPos.Y < clipRect->UpperLeftCorner.Y) { sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; if (sourceSize.Height <= 0) continue; sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; targetPos.Y = clipRect->UpperLeftCorner.Y; } if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; if (sourceSize.Height <= 0) continue; } } // clip these coordinates if (targetPos.X<0) { sourceSize.Width += targetPos.X; if (sourceSize.Width <= 0) continue; sourcePos.X -= targetPos.X; targetPos.X = 0; } const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; if (sourceSize.Width <= 0) continue; } if (targetPos.Y<0) { sourceSize.Height += targetPos.Y; if (sourceSize.Height <= 0) continue; sourcePos.Y -= targetPos.Y; targetPos.Y = 0; } if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; if (sourceSize.Height <= 0) continue; } // ok, we've clipped everything. // now draw it. core::rect tcoords; tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ; tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height; tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width); tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height); const core::rect poss(targetPos, sourceSize); vtx.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y)); vtx.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y)); vtx.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y)); vtx.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y)); const u32 curPos = vtx.size()-4; indices.push_back(0+curPos); indices.push_back(1+curPos); indices.push_back(2+curPos); indices.push_back(0+curPos); indices.push_back(2+curPos); indices.push_back(3+curPos); } if (vtx.size()) { setVertexShader(EVT_STANDARD); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vtx.size(), indices.size() / 3, indices.pointer(), D3DFMT_INDEX16,vtx.pointer(), sizeof(S3DVertex)); } } //! draws a 2d image, using a color and the alpha channel of the texture if //! desired. The image is drawn at pos and clipped against clipRect (if != 0). void CD3D9Driver::draw2DImage(const video::ITexture* texture, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect, SColor color, bool useAlphaChannelOfTexture) { if (!texture) return; if (!sourceRect.isValid()) return; if (!setActiveTexture(0, const_cast(texture))) return; core::position2d targetPos = pos; core::position2d sourcePos = sourceRect.UpperLeftCorner; // This needs to be signed as it may go negative. core::dimension2d sourceSize(sourceRect.getSize()); if (clipRect) { if (targetPos.X < clipRect->UpperLeftCorner.X) { sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; if (sourceSize.Width <= 0) return; sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; targetPos.X = clipRect->UpperLeftCorner.X; } if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; if (sourceSize.Width <= 0) return; } if (targetPos.Y < clipRect->UpperLeftCorner.Y) { sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; if (sourceSize.Height <= 0) return; sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; targetPos.Y = clipRect->UpperLeftCorner.Y; } if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; if (sourceSize.Height <= 0) return; } } // clip these coordinates if (targetPos.X<0) { sourceSize.Width += targetPos.X; if (sourceSize.Width <= 0) return; sourcePos.X -= targetPos.X; targetPos.X = 0; } const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; if (sourceSize.Width <= 0) return; } if (targetPos.Y<0) { sourceSize.Height += targetPos.Y; if (sourceSize.Height <= 0) return; sourcePos.Y -= targetPos.Y; targetPos.Y = 0; } if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; if (sourceSize.Height <= 0) return; } // ok, we've clipped everything. // now draw it. core::rect tcoords; tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ; tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height; tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width); tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height); const core::rect poss(targetPos, sourceSize); setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); S3DVertex vtx[4]; vtx[0] = S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); vtx[1] = S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); vtx[2] = S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); vtx[3] = S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); s16 indices[6] = {0,1,2,0,2,3}; setVertexShader(EVT_STANDARD); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], D3DFMT_INDEX16,&vtx[0], sizeof(S3DVertex)); } //!Draws a 2d rectangle with a gradient. void CD3D9Driver::draw2DRectangle(const core::rect& position, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip) { core::rect pos(position); if (clip) pos.clipAgainst(*clip); if (!pos.isValid()) return; S3DVertex vtx[4]; vtx[0] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorLeftUp, 0.0f, 0.0f); vtx[1] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorRightUp, 0.0f, 1.0f); vtx[2] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorRightDown, 1.0f, 0.0f); vtx[3] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorLeftDown, 1.0f, 1.0f); s16 indices[6] = {0,1,2,0,2,3}; setRenderStates2DMode( colorLeftUp.getAlpha() < 255 || colorRightUp.getAlpha() < 255 || colorLeftDown.getAlpha() < 255 || colorRightDown.getAlpha() < 255, false, false); setActiveTexture(0,0); setVertexShader(EVT_STANDARD); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex)); } //! Draws a 2d line. void CD3D9Driver::draw2DLine(const core::position2d& start, const core::position2d& end, SColor color) { if (start==end) drawPixel(start.X, start.Y, color); else { // thanks to Vash TheStampede who sent in his implementation S3DVertex vtx[2]; vtx[0] = S3DVertex((f32)start.X+0.375f, (f32)start.Y+0.375f, 0.0f, 0.0f, 0.0f, 0.0f, // normal color, 0.0f, 0.0f); // texture vtx[1] = S3DVertex((f32)end.X+0.375f, (f32)end.Y+0.375f, 0.0f, 0.0f, 0.0f, 0.0f, color, 0.0f, 0.0f); setRenderStates2DMode(color.getAlpha() < 255, false, false); setActiveTexture(0,0); setVertexShader(EVT_STANDARD); pID3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, &vtx[0], sizeof(S3DVertex) ); } } //! Draws a pixel void CD3D9Driver::drawPixel(u32 x, u32 y, const SColor & color) { const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); if(x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height) return; setRenderStates2DMode(color.getAlpha() < 255, false, false); setActiveTexture(0,0); setVertexShader(EVT_STANDARD); S3DVertex vertex((f32)x+0.375f, (f32)y+0.375f, 0.f, 0.f, 0.f, 0.f, color, 0.f, 0.f); pID3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, &vertex, sizeof(vertex)); } //! sets right vertex shader void CD3D9Driver::setVertexShader(E_VERTEX_TYPE newType) { if (newType != LastVertexType) { LastVertexType = newType; HRESULT hr = 0; switch(newType) { case EVT_STANDARD: hr = pID3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1); break; case EVT_2TCOORDS: hr = pID3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2); break; case EVT_TANGENTS: hr = pID3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE2(0) | // real texture coord D3DFVF_TEXCOORDSIZE3(1) | // misuse texture coord 2 for tangent D3DFVF_TEXCOORDSIZE3(2) // misuse texture coord 3 for binormal ); break; } if (FAILED(hr)) { os::Printer::log("Could not set vertex Shader.", ELL_ERROR); return; } } } //! sets the needed renderstates bool CD3D9Driver::setRenderStates3DMode() { if (!pID3DDevice) return false; if (CurrentRenderMode != ERM_3D) { // switch back the matrices pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)&Matrices[ETS_VIEW])); pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)&Matrices[ETS_WORLD])); pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)&Matrices[ETS_PROJECTION])); pID3DDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); pID3DDevice->SetRenderState(D3DRS_CLIPPING, TRUE); ResetRenderStates = true; } if (ResetRenderStates || LastMaterial != Material) { // unset old material if (CurrentRenderMode == ERM_3D && LastMaterial.MaterialType != Material.MaterialType && LastMaterial.MaterialType >= 0 && LastMaterial.MaterialType < (s32)MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); // set new material. if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) MaterialRenderers[Material.MaterialType].Renderer->OnSetMaterial( Material, LastMaterial, ResetRenderStates, this); } bool shaderOK = true; if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) shaderOK = MaterialRenderers[Material.MaterialType].Renderer->OnRender(this, LastVertexType); LastMaterial = Material; ResetRenderStates = false; CurrentRenderMode = ERM_3D; return shaderOK; } //! Map Irrlicht texture wrap mode to native values D3DTEXTUREADDRESS CD3D9Driver::getTextureWrapMode(const u8 clamp) { switch (clamp) { case ETC_REPEAT: if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP) return D3DTADDRESS_WRAP; case ETC_CLAMP: case ETC_CLAMP_TO_EDGE: if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_CLAMP) return D3DTADDRESS_CLAMP; case ETC_MIRROR: if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR) return D3DTADDRESS_MIRROR; case ETC_CLAMP_TO_BORDER: if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER) return D3DTADDRESS_BORDER; else return D3DTADDRESS_CLAMP; case ETC_MIRROR_CLAMP: case ETC_MIRROR_CLAMP_TO_EDGE: case ETC_MIRROR_CLAMP_TO_BORDER: if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRRORONCE) return D3DTADDRESS_MIRRORONCE; else return D3DTADDRESS_CLAMP; default: return D3DTADDRESS_WRAP; } } //! Can be called by an IMaterialRenderer to make its work easier. void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderstates) { // This needs only to be updated onresets if (Params.HandleSRGB && resetAllRenderstates) pID3DDevice->SetRenderState(D3DRS_SRGBWRITEENABLE, TRUE); if (resetAllRenderstates || lastmaterial.AmbientColor != material.AmbientColor || lastmaterial.DiffuseColor != material.DiffuseColor || lastmaterial.SpecularColor != material.SpecularColor || lastmaterial.EmissiveColor != material.EmissiveColor || lastmaterial.Shininess != material.Shininess) { D3DMATERIAL9 mat; mat.Diffuse = colorToD3D(material.DiffuseColor); mat.Ambient = colorToD3D(material.AmbientColor); mat.Specular = colorToD3D(material.SpecularColor); mat.Emissive = colorToD3D(material.EmissiveColor); mat.Power = material.Shininess; pID3DDevice->SetMaterial(&mat); } if (lastmaterial.ColorMaterial != material.ColorMaterial) { pID3DDevice->SetRenderState(D3DRS_COLORVERTEX, (material.ColorMaterial != ECM_NONE)); pID3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, ((material.ColorMaterial == ECM_DIFFUSE)|| (material.ColorMaterial == ECM_DIFFUSE_AND_AMBIENT))?D3DMCS_COLOR1:D3DMCS_MATERIAL); pID3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, ((material.ColorMaterial == ECM_AMBIENT)|| (material.ColorMaterial == ECM_DIFFUSE_AND_AMBIENT))?D3DMCS_COLOR1:D3DMCS_MATERIAL); pID3DDevice->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, (material.ColorMaterial == ECM_EMISSIVE)?D3DMCS_COLOR1:D3DMCS_MATERIAL); pID3DDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, (material.ColorMaterial == ECM_SPECULAR)?D3DMCS_COLOR1:D3DMCS_MATERIAL); } // fillmode if (resetAllRenderstates || lastmaterial.Wireframe != material.Wireframe || lastmaterial.PointCloud != material.PointCloud) { if (material.Wireframe) pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); else if (material.PointCloud) pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_POINT); else pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); } // shademode if (resetAllRenderstates || lastmaterial.GouraudShading != material.GouraudShading) { if (material.GouraudShading) pID3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); else pID3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); } // lighting if (resetAllRenderstates || lastmaterial.Lighting != material.Lighting) { if (material.Lighting) pID3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE); else pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); } // zbuffer if (resetAllRenderstates || lastmaterial.ZBuffer != material.ZBuffer) { switch (material.ZBuffer) { case ECFN_NEVER: pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE); break; case ECFN_LESSEQUAL: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); break; case ECFN_EQUAL: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL); break; case ECFN_LESS: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS); break; case ECFN_NOTEQUAL: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_NOTEQUAL); break; case ECFN_GREATEREQUAL: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATEREQUAL); break; case ECFN_GREATER: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATER); break; case ECFN_ALWAYS: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); break; } } // zwrite // if (resetAllRenderstates || (lastmaterial.ZWriteEnable != material.ZWriteEnable)) { if ( material.ZWriteEnable && (AllowZWriteOnTransparent || !material.isTransparent())) pID3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE); else pID3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE); } // back face culling if (resetAllRenderstates || (lastmaterial.FrontfaceCulling != material.FrontfaceCulling) || (lastmaterial.BackfaceCulling != material.BackfaceCulling)) { // if (material.FrontfaceCulling && material.BackfaceCulling) // pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW|D3DCULL_CCW); // else if (material.FrontfaceCulling) pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); else if (material.BackfaceCulling) pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); else pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); } // fog if (resetAllRenderstates || lastmaterial.FogEnable != material.FogEnable) { pID3DDevice->SetRenderState(D3DRS_FOGENABLE, material.FogEnable); } // specular highlights if (resetAllRenderstates || !core::equals(lastmaterial.Shininess,material.Shininess)) { const bool enable = (material.Shininess!=0.0f); pID3DDevice->SetRenderState(D3DRS_SPECULARENABLE, enable); pID3DDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL); } // normalization if (resetAllRenderstates || lastmaterial.NormalizeNormals != material.NormalizeNormals) { pID3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, material.NormalizeNormals); } // Color Mask if (queryFeature(EVDF_COLOR_MASK) && (resetAllRenderstates || lastmaterial.ColorMask != material.ColorMask)) { const DWORD flag = ((material.ColorMask & ECP_RED)?D3DCOLORWRITEENABLE_RED:0) | ((material.ColorMask & ECP_GREEN)?D3DCOLORWRITEENABLE_GREEN:0) | ((material.ColorMask & ECP_BLUE)?D3DCOLORWRITEENABLE_BLUE:0) | ((material.ColorMask & ECP_ALPHA)?D3DCOLORWRITEENABLE_ALPHA:0); pID3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, flag); } if (queryFeature(EVDF_BLEND_OPERATIONS) && (resetAllRenderstates|| lastmaterial.BlendOperation != material.BlendOperation)) { if (material.BlendOperation==EBO_NONE) pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); else { pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); switch (material.BlendOperation) { case EBO_SUBTRACT: pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT); break; case EBO_REVSUBTRACT: pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT); break; case EBO_MIN: case EBO_MIN_FACTOR: case EBO_MIN_ALPHA: pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MIN); break; case EBO_MAX: case EBO_MAX_FACTOR: case EBO_MAX_ALPHA: pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MAX); break; default: pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); break; } } } // Polygon offset if (queryFeature(EVDF_POLYGON_OFFSET) && (resetAllRenderstates || lastmaterial.PolygonOffsetDirection != material.PolygonOffsetDirection || lastmaterial.PolygonOffsetFactor != material.PolygonOffsetFactor)) { if (material.PolygonOffsetFactor) { if (material.PolygonOffsetDirection==EPO_BACK) { pID3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(1.f)); pID3DDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW((FLOAT)material.PolygonOffsetFactor)); } else { pID3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(-1.f)); pID3DDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW((FLOAT)-material.PolygonOffsetFactor)); } } else { pID3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); pID3DDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); } } // Anti Aliasing if (resetAllRenderstates || lastmaterial.AntiAliasing != material.AntiAliasing) { if (AlphaToCoverageSupport && (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE)) { if (VendorID==0x10DE)//NVidia pID3DDevice->SetRenderState(D3DRS_ADAPTIVETESS_Y, MAKEFOURCC('A','T','O','C')); // SSAA could give better results on NVidia cards else if (VendorID==0x1002)//ATI pID3DDevice->SetRenderState(D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','1')); } else if (AlphaToCoverageSupport && (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE)) { if (VendorID==0x10DE) pID3DDevice->SetRenderState(D3DRS_ADAPTIVETESS_Y, D3DFMT_UNKNOWN); else if (VendorID==0x1002) pID3DDevice->SetRenderState(D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','0')); } // enable antialiasing if (Params.AntiAlias) { if (material.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY)) pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); else if (lastmaterial.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY)) pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE); if (material.AntiAliasing & (EAAM_LINE_SMOOTH)) pID3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, TRUE); else if (lastmaterial.AntiAliasing & (EAAM_LINE_SMOOTH)) pID3DDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE); } } // thickness if (resetAllRenderstates || lastmaterial.Thickness != material.Thickness) { pID3DDevice->SetRenderState(D3DRS_POINTSIZE, F2DW(material.Thickness)); } // texture address mode for (u32 st=0; stSetSamplerState(st, D3DSAMP_SRGBTEXTURE, TRUE); if (resetAllRenderstates || lastmaterial.TextureLayer[st].LODBias != material.TextureLayer[st].LODBias) { const float tmp = material.TextureLayer[st].LODBias * 0.125f; pID3DDevice->SetSamplerState(st, D3DSAMP_MIPMAPLODBIAS, F2DW(tmp)); } if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapU != material.TextureLayer[st].TextureWrapU) pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSU, getTextureWrapMode(material.TextureLayer[st].TextureWrapU)); // If separate UV not supported reuse U for V if (!(Caps.TextureAddressCaps & D3DPTADDRESSCAPS_INDEPENDENTUV)) pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapU)); else if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapV != material.TextureLayer[st].TextureWrapV) pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapV)); // Bilinear, trilinear, and anisotropic filter if (resetAllRenderstates || lastmaterial.TextureLayer[st].BilinearFilter != material.TextureLayer[st].BilinearFilter || lastmaterial.TextureLayer[st].TrilinearFilter != material.TextureLayer[st].TrilinearFilter || lastmaterial.TextureLayer[st].AnisotropicFilter != material.TextureLayer[st].AnisotropicFilter || lastmaterial.UseMipMaps != material.UseMipMaps) { if (material.TextureLayer[st].BilinearFilter || material.TextureLayer[st].TrilinearFilter || material.TextureLayer[st].AnisotropicFilter) { D3DTEXTUREFILTERTYPE tftMag = ((Caps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) && material.TextureLayer[st].AnisotropicFilter) ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR; D3DTEXTUREFILTERTYPE tftMin = ((Caps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) && material.TextureLayer[st].AnisotropicFilter) ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR; D3DTEXTUREFILTERTYPE tftMip = material.UseMipMaps? (material.TextureLayer[st].TrilinearFilter ? D3DTEXF_LINEAR : D3DTEXF_POINT) : D3DTEXF_NONE; if (tftMag==D3DTEXF_ANISOTROPIC || tftMin == D3DTEXF_ANISOTROPIC) pID3DDevice->SetSamplerState(st, D3DSAMP_MAXANISOTROPY, core::min_((DWORD)material.TextureLayer[st].AnisotropicFilter, Caps.MaxAnisotropy)); pID3DDevice->SetSamplerState(st, D3DSAMP_MAGFILTER, tftMag); pID3DDevice->SetSamplerState(st, D3DSAMP_MINFILTER, tftMin); pID3DDevice->SetSamplerState(st, D3DSAMP_MIPFILTER, tftMip); } else { pID3DDevice->SetSamplerState(st, D3DSAMP_MINFILTER, D3DTEXF_POINT); pID3DDevice->SetSamplerState(st, D3DSAMP_MIPFILTER, D3DTEXF_NONE); pID3DDevice->SetSamplerState(st, D3DSAMP_MAGFILTER, D3DTEXF_POINT); } } } } //! sets the needed renderstates void CD3D9Driver::setRenderStatesStencilShadowMode(bool zfail, u32 debugDataVisible) { if ((CurrentRenderMode != ERM_SHADOW_VOLUME_ZFAIL && CurrentRenderMode != ERM_SHADOW_VOLUME_ZPASS) || Transformation3DChanged) { // unset last 3d material if (CurrentRenderMode == ERM_3D && static_cast(Material.MaterialType) < MaterialRenderers.size()) { MaterialRenderers[Material.MaterialType].Renderer->OnUnsetMaterial(); ResetRenderStates = true; } // switch back the matrices pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)&Matrices[ETS_VIEW])); pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)&Matrices[ETS_WORLD])); pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)&Matrices[ETS_PROJECTION])); Transformation3DChanged = false; setActiveTexture(0,0); setActiveTexture(1,0); setActiveTexture(2,0); setActiveTexture(3,0); pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetFVF(D3DFVF_XYZ); LastVertexType = (video::E_VERTEX_TYPE)(-1); pID3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); pID3DDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //pID3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); //pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); pID3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); pID3DDevice->SetRenderState(D3DRS_STENCILREF, 0x0); pID3DDevice->SetRenderState(D3DRS_STENCILMASK, 0xffffffff); pID3DDevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff); pID3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); pID3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ZERO ); pID3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE ); pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS); //if (!(debugDataVisible & (scene::EDS_SKELETON|scene::EDS_MESH_WIRE_OVERLAY))) // pID3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); if ((debugDataVisible & scene::EDS_MESH_WIRE_OVERLAY)) pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); } if (CurrentRenderMode != ERM_SHADOW_VOLUME_ZPASS && !zfail) { // USE THE ZPASS METHOD pID3DDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP); //pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR); // does not matter, will be set later } else if (CurrentRenderMode != ERM_SHADOW_VOLUME_ZFAIL && zfail) { // USE THE ZFAIL METHOD pID3DDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); //pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR); // does not matter, will be set later pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); } CurrentRenderMode = zfail ? ERM_SHADOW_VOLUME_ZFAIL : ERM_SHADOW_VOLUME_ZPASS; } //! sets the needed renderstates void CD3D9Driver::setRenderStatesStencilFillMode(bool alpha) { if (CurrentRenderMode != ERM_STENCIL_FILL || Transformation3DChanged) { core::matrix4 mat; pID3DDevice->SetTransform(D3DTS_VIEW, &UnitMatrixD3D9); pID3DDevice->SetTransform(D3DTS_WORLD, &UnitMatrixD3D9); pID3DDevice->SetTransform(D3DTS_PROJECTION, &UnitMatrixD3D9); pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE); pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); pID3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_STENCILREF, 0x1); pID3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL); //pID3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATEREQUAL); pID3DDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP); pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); pID3DDevice->SetRenderState(D3DRS_STENCILMASK, 0xffffffff); pID3DDevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff); pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); Transformation3DChanged = false; pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); if (alpha) { pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); } else { pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } } CurrentRenderMode = ERM_STENCIL_FILL; } //! Enable the 2d override material void CD3D9Driver::enableMaterial2D(bool enable) { if (!enable) CurrentRenderMode = ERM_NONE; CNullDriver::enableMaterial2D(enable); } //! sets the needed renderstates void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel) { if (!pID3DDevice) return; if (CurrentRenderMode != ERM_2D || Transformation3DChanged) { // unset last 3d material if (CurrentRenderMode == ERM_3D) { if (static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); } if (!OverrideMaterial2DEnabled) { setBasicRenderStates(InitMaterial2D, LastMaterial, true); LastMaterial=InitMaterial2D; // fix everything that is wrongly set by InitMaterial2D default pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); } core::matrix4 m; // this fixes some problems with pixel exact rendering, but also breaks nice texturing // moreover, it would have to be tested in each call, as the texture flag can change each time // if (!texture) // m.setTranslation(core::vector3df(0.5f,0.5f,0)); pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)m.pointer())); // adjust the view such that pixel center aligns with texels // Otherwise, subpixel artifacts will occur m.setTranslation(core::vector3df(-0.5f,-0.5f,0)); pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)m.pointer())); const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0, 1.0); m.setTranslation(core::vector3df(-1,1,0)); pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)m.pointer())); // 2d elements are clipped in software pID3DDevice->SetRenderState(D3DRS_CLIPPING, FALSE); Transformation3DChanged = false; } if (OverrideMaterial2DEnabled) { OverrideMaterial2D.Lighting=false; setBasicRenderStates(OverrideMaterial2D, LastMaterial, false); LastMaterial = OverrideMaterial2D; } // no alphaChannel without texture alphaChannel &= texture; if (alpha || alphaChannel) { pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); } else pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); if (texture) { setTransform(ETS_TEXTURE_0, core::IdentityMatrix); // Due to the transformation change, the previous line would call a reset each frame // but we can safely reset the variable as it was false before Transformation3DChanged=false; } if (alphaChannel) { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); if (alpha) { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); } else { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); } } else { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); if (alpha) { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); } else { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); } } CurrentRenderMode = ERM_2D; } //! deletes all dynamic lights there are void CD3D9Driver::deleteAllDynamicLights() { for (s32 i=0; iLightEnable(i, false); LastSetLight = -1; CNullDriver::deleteAllDynamicLights(); } //! adds a dynamic light s32 CD3D9Driver::addDynamicLight(const SLight& dl) { CNullDriver::addDynamicLight(dl); D3DLIGHT9 light; switch (dl.Type) { case ELT_POINT: light.Type = D3DLIGHT_POINT; break; case ELT_SPOT: light.Type = D3DLIGHT_SPOT; break; case ELT_DIRECTIONAL: light.Type = D3DLIGHT_DIRECTIONAL; break; } light.Position = *(D3DVECTOR*)((void*)(&dl.Position)); light.Direction = *(D3DVECTOR*)((void*)(&dl.Direction)); light.Range = core::min_(dl.Radius, MaxLightDistance); light.Falloff = dl.Falloff; light.Diffuse = *(D3DCOLORVALUE*)((void*)(&dl.DiffuseColor)); light.Specular = *(D3DCOLORVALUE*)((void*)(&dl.SpecularColor)); light.Ambient = *(D3DCOLORVALUE*)((void*)(&dl.AmbientColor)); light.Attenuation0 = dl.Attenuation.X; light.Attenuation1 = dl.Attenuation.Y; light.Attenuation2 = dl.Attenuation.Z; light.Theta = dl.InnerCone * 2.0f * core::DEGTORAD; light.Phi = dl.OuterCone * 2.0f * core::DEGTORAD; ++LastSetLight; if(D3D_OK == pID3DDevice->SetLight(LastSetLight, &light)) { // I don't care if this succeeds (void)pID3DDevice->LightEnable(LastSetLight, true); return LastSetLight; } return -1; } //! Turns a dynamic light on or off //! \param lightIndex: the index returned by addDynamicLight //! \param turnOn: true to turn the light on, false to turn it off void CD3D9Driver::turnLightOn(s32 lightIndex, bool turnOn) { if(lightIndex < 0 || lightIndex > LastSetLight) return; (void)pID3DDevice->LightEnable(lightIndex, turnOn); } //! returns the maximal amount of dynamic lights the device can handle u32 CD3D9Driver::getMaximalDynamicLightAmount() const { return Caps.MaxActiveLights; } //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. void CD3D9Driver::setAmbientLight(const SColorf& color) { if (!pID3DDevice) return; AmbientLight = color; D3DCOLOR col = color.toSColor().color; pID3DDevice->SetRenderState(D3DRS_AMBIENT, col); } //! \return Returns the name of the video driver. Example: In case of the DIRECT3D9 //! driver, it would return "Direct3D9.0". const wchar_t* CD3D9Driver::getName() const { return L"Direct3D 9.0"; } //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do //! this: First, draw all geometry. Then use this method, to draw the shadow //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. void CD3D9Driver::drawStencilShadowVolume(const core::array& triangles, bool zfail, u32 debugDataVisible) { if (!Params.Stencilbuffer) return; setRenderStatesStencilShadowMode(zfail, debugDataVisible); const u32 count = triangles.size(); if (!count) return; if (!zfail) { // ZPASS Method // Draw front-side of shadow volume in stencil only pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR); pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles.const_pointer(), sizeof(core::vector3df)); // Now reverse cull order so front sides of shadow volume are written. pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR); pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles.const_pointer(), sizeof(core::vector3df)); } else { // ZFAIL Method // Draw front-side of shadow volume in stencil only pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR); pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles.const_pointer(), sizeof(core::vector3df)); // Now reverse cull order so front sides of shadow volume are written. pID3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW); pID3DDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR); pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles.const_pointer(), sizeof(core::vector3df)); } } //! Fills the stencil shadow with color. After the shadow volume has been drawn //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this //! to draw the color of the shadow. void CD3D9Driver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge, video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge) { if (!Params.Stencilbuffer) return; S3DVertex vtx[4]; vtx[0] = S3DVertex(1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, leftUpEdge, 0.0f, 0.0f); vtx[1] = S3DVertex(1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, rightUpEdge, 0.0f, 1.0f); vtx[2] = S3DVertex(-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, leftDownEdge, 1.0f, 0.0f); vtx[3] = S3DVertex(-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, rightDownEdge, 1.0f, 1.0f); s16 indices[6] = {0,1,2,1,3,2}; setRenderStatesStencilFillMode( leftUpEdge.getAlpha() < 255 || rightUpEdge.getAlpha() < 255 || leftDownEdge.getAlpha() < 255 || rightDownEdge.getAlpha() < 255); setActiveTexture(0,0); setVertexShader(EVT_STANDARD); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex)); if (clearStencilBuffer) pID3DDevice->Clear( 0, NULL, D3DCLEAR_STENCIL,0, 1.0, 0); } //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. u32 CD3D9Driver::getMaximalPrimitiveCount() const { return Caps.MaxPrimitiveCount; } //! Sets the fog mode. void CD3D9Driver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog) { CNullDriver::setFog(color, fogType, start, end, density, pixelFog, rangeFog); if (!pID3DDevice) return; pID3DDevice->SetRenderState(D3DRS_FOGCOLOR, color.color); pID3DDevice->SetRenderState( pixelFog ? D3DRS_FOGTABLEMODE : D3DRS_FOGVERTEXMODE, (fogType==EFT_FOG_LINEAR)? D3DFOG_LINEAR : (fogType==EFT_FOG_EXP)?D3DFOG_EXP:D3DFOG_EXP2); if (fogType==EFT_FOG_LINEAR) { pID3DDevice->SetRenderState(D3DRS_FOGSTART, F2DW(start)); pID3DDevice->SetRenderState(D3DRS_FOGEND, F2DW(end)); } else pID3DDevice->SetRenderState(D3DRS_FOGDENSITY, F2DW(density)); if(!pixelFog) pID3DDevice->SetRenderState(D3DRS_RANGEFOGENABLE, rangeFog); } //! Draws a 3d line. void CD3D9Driver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color) { setVertexShader(EVT_STANDARD); setRenderStates3DMode(); video::S3DVertex v[2]; v[0].Color = color; v[1].Color = color; v[0].Pos = start; v[1].Pos = end; pID3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, v, sizeof(S3DVertex)); } //! resets the device bool CD3D9Driver::reset() { u32 i; os::Printer::log("Resetting D3D9 device.", ELL_INFORMATION); for (i=0; iisRenderTarget()) { IDirect3DBaseTexture9* tex = ((CD3D9Texture*)(Textures[i].Surface))->getDX9Texture(); if (tex) tex->Release(); } } for (i=0; iSurface) DepthBuffers[i]->Surface->Release(); } for (i=0; i(OcclusionQueries[i].PID)->Release(); OcclusionQueries[i].PID=0; } } // this does not require a restore in the reset method, it's updated // automatically in the next render cycle. removeAllHardwareBuffers(); DriverWasReset=true; HRESULT hr = pID3DDevice->Reset(&present); // restore RTTs for (i=0; iisRenderTarget()) ((CD3D9Texture*)(Textures[i].Surface))->createRenderTarget(); } // restore screen depthbuffer pID3DDevice->GetDepthStencilSurface(&(DepthBuffers[0]->Surface)); D3DSURFACE_DESC desc; // restore other depth buffers // depth format is taken from main depth buffer DepthBuffers[0]->Surface->GetDesc(&desc); // multisampling is taken from rendertarget D3DSURFACE_DESC desc2; for (i=1; iDepthSurface==DepthBuffers[i]) { ((CD3D9Texture*)(Textures[j].Surface))->Texture->GetLevelDesc(0,&desc2); break; } } pID3DDevice->CreateDepthStencilSurface(DepthBuffers[i]->Size.Width, DepthBuffers[i]->Size.Height, desc.Format, desc2.MultiSampleType, desc2.MultiSampleQuality, TRUE, &(DepthBuffers[i]->Surface), NULL); } for (i=0; iCreateQuery(D3DQUERYTYPE_OCCLUSION, reinterpret_cast(&OcclusionQueries[i].PID)); } if (FAILED(hr)) { if (hr == D3DERR_DEVICELOST) { DeviceLost = true; os::Printer::log("Resetting failed due to device lost.", ELL_WARNING); } #ifdef D3DERR_DEVICEREMOVED else if (hr == D3DERR_DEVICEREMOVED) { os::Printer::log("Resetting failed due to device removed.", ELL_WARNING); } #endif else if (hr == D3DERR_DRIVERINTERNALERROR) { os::Printer::log("Resetting failed due to internal error.", ELL_WARNING); } else if (hr == D3DERR_OUTOFVIDEOMEMORY) { os::Printer::log("Resetting failed due to out of memory.", ELL_WARNING); } else if (hr == D3DERR_DEVICENOTRESET) { os::Printer::log("Resetting failed due to not reset.", ELL_WARNING); } else if (hr == D3DERR_INVALIDCALL) { os::Printer::log("Resetting failed due to invalid call", "You need to release some more surfaces.", ELL_WARNING); } else { os::Printer::log("Resetting failed due to unknown reason.", core::stringc((int)hr).c_str(), ELL_WARNING); } return false; } DeviceLost = false; ResetRenderStates = true; LastVertexType = (E_VERTEX_TYPE)-1; for (u32 i=0; i& size) { if (!pID3DDevice) return; CNullDriver::OnResize(size); present.BackBufferWidth = size.Width; present.BackBufferHeight = size.Height; reset(); } //! Returns type of video driver E_DRIVER_TYPE CD3D9Driver::getDriverType() const { return EDT_DIRECT3D9; } //! Returns the transformation set by setTransform const core::matrix4& CD3D9Driver::getTransform(E_TRANSFORMATION_STATE state) const { return Matrices[state]; } //! Sets a vertex shader constant. void CD3D9Driver::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { if (data) pID3DDevice->SetVertexShaderConstantF(startRegister, data, constantAmount); } //! Sets a pixel shader constant. void CD3D9Driver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { if (data) pID3DDevice->SetPixelShaderConstantF(startRegister, data, constantAmount); } //! Sets a constant for the vertex shader based on a name. bool CD3D9Driver::setVertexShaderConstant(const c8* name, const f32* floats, int count) { if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) { CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; return r->setVariable(true, name, floats, count); } return false; } //! Bool interface for the above. bool CD3D9Driver::setVertexShaderConstant(const c8* name, const bool* bools, int count) { if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) { CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; return r->setVariable(true, name, bools, count); } return false; } //! Int interface for the above. bool CD3D9Driver::setVertexShaderConstant(const c8* name, const s32* ints, int count) { if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) { CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; return r->setVariable(true, name, ints, count); } return false; } //! Sets a constant for the pixel shader based on a name. bool CD3D9Driver::setPixelShaderConstant(const c8* name, const f32* floats, int count) { if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) { CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; return r->setVariable(false, name, floats, count); } return false; } //! Bool interface for the above. bool CD3D9Driver::setPixelShaderConstant(const c8* name, const bool* bools, int count) { if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) { CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; return r->setVariable(false, name, bools, count); } return false; } //! Int interface for the above. bool CD3D9Driver::setPixelShaderConstant(const c8* name, const s32* ints, int count) { if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) { CD3D9MaterialRenderer* r = (CD3D9MaterialRenderer*)MaterialRenderers[Material.MaterialType].Renderer; return r->setVariable(false, name, ints, count); } return false; } //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. s32 CD3D9Driver::addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) { s32 nr = -1; CD3D9ShaderMaterialRenderer* r = new CD3D9ShaderMaterialRenderer( pID3DDevice, this, nr, vertexShaderProgram, pixelShaderProgram, callback, getMaterialRenderer(baseMaterial), userData); r->drop(); return nr; } //! Adds a new material renderer to the VideoDriver, based on a high level shading //! language. s32 CD3D9Driver::addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, const c8* geometryShaderProgram, const c8* geometryShaderEntryPointName, E_GEOMETRY_SHADER_TYPE gsCompileTarget, scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 verticesOut, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData, E_GPU_SHADING_LANGUAGE shadingLang) { s32 nr = -1; #ifdef _IRR_COMPILE_WITH_CG_ if(shadingLang == EGSL_CG) { CD3D9CgMaterialRenderer* r = new CD3D9CgMaterialRenderer( this, nr, vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget, inType, outType, verticesOut, callback,getMaterialRenderer(baseMaterial), userData); r->drop(); } else #endif { CD3D9HLSLMaterialRenderer* r = new CD3D9HLSLMaterialRenderer( pID3DDevice, this, nr, vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, callback, getMaterialRenderer(baseMaterial), userData); r->drop(); } return nr; } //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) IVideoDriver* CD3D9Driver::getVideoDriver() { return this; } //! Creates a render target texture. ITexture* CD3D9Driver::addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format) { CD3D9Texture* tex = new CD3D9Texture(this, size, name, format); if (tex) { if (!tex->Texture) { tex->drop(); return 0; } checkDepthBuffer(tex); addTexture(tex); tex->drop(); } return tex; } //! Clears the ZBuffer. void CD3D9Driver::clearZBuffer() { HRESULT hr = pID3DDevice->Clear( 0, NULL, D3DCLEAR_ZBUFFER, 0, 1.0, 0); if (FAILED(hr)) os::Printer::log("CD3D9Driver clearZBuffer() failed.", ELL_WARNING); } //! Returns an image created from the last rendered frame. IImage* CD3D9Driver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target) { if (target != video::ERT_FRAME_BUFFER) return 0; // query the screen dimensions of the current adapter D3DDISPLAYMODE displayMode; pID3DDevice->GetDisplayMode(0, &displayMode); if (format==video::ECF_UNKNOWN) format=video::ECF_A8R8G8B8; // create the image surface to store the front buffer image [always A8R8G8B8] HRESULT hr; LPDIRECT3DSURFACE9 lpSurface; if (FAILED(hr = pID3DDevice->CreateOffscreenPlainSurface(displayMode.Width, displayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &lpSurface, 0))) return 0; // read the front buffer into the image surface if (FAILED(hr = pID3DDevice->GetFrontBufferData(0, lpSurface))) { lpSurface->Release(); return 0; } RECT clientRect; { POINT clientPoint; clientPoint.x = 0; clientPoint.y = 0; ClientToScreen((HWND)getExposedVideoData().D3D9.HWnd, &clientPoint); clientRect.left = clientPoint.x; clientRect.top = clientPoint.y; clientRect.right = clientRect.left + ScreenSize.Width; clientRect.bottom = clientRect.top + ScreenSize.Height; // window can be off-screen partly, we can't take screenshots from that clientRect.left = core::max_(clientRect.left, 0l); clientRect.top = core::max_(clientRect.top, 0l); clientRect.right = core::min_(clientRect.right, (long)displayMode.Width); clientRect.bottom = core::min_(clientRect.bottom, (long)displayMode.Height ); } // lock our area of the surface D3DLOCKED_RECT lockedRect; if (FAILED(lpSurface->LockRect(&lockedRect, &clientRect, D3DLOCK_READONLY))) { lpSurface->Release(); return 0; } irr::core::dimension2d shotSize; shotSize.Width = core::min_( ScreenSize.Width, (u32)(clientRect.right-clientRect.left) ); shotSize.Height = core::min_( ScreenSize.Height, (u32)(clientRect.bottom-clientRect.top) ); // this could throw, but we aren't going to worry about that case very much IImage* newImage = createImage(format, shotSize); if (newImage) { // d3d pads the image, so we need to copy the correct number of bytes u32* dP = (u32*)newImage->lock(); u8 * sP = (u8 *)lockedRect.pBits; // If the display mode format doesn't promise anything about the Alpha value // and it appears that it's not presenting 255, then we should manually // set each pixel alpha value to 255. if (D3DFMT_X8R8G8B8 == displayMode.Format && (0xFF000000 != (*dP & 0xFF000000))) { for (u32 y = 0; y < shotSize.Height; ++y) { for (u32 x = 0; x < shotSize.Width; ++x) { newImage->setPixel(x,y,*((u32*)sP) | 0xFF000000); sP += 4; } sP += lockedRect.Pitch - (4 * shotSize.Width); } } else { for (u32 y = 0; y < shotSize.Height; ++y) { convertColor(sP, video::ECF_A8R8G8B8, shotSize.Width, dP, format); sP += lockedRect.Pitch; dP += shotSize.Width; } } newImage->unlock(); } // we can unlock and release the surface lpSurface->UnlockRect(); // release the image surface lpSurface->Release(); // return status of save operation to caller return newImage; } //! returns color format ECOLOR_FORMAT CD3D9Driver::getColorFormat() const { return ColorFormat; } //! returns color format D3DFORMAT CD3D9Driver::getD3DColorFormat() const { return D3DColorFormat; } // returns the current size of the screen or rendertarget const core::dimension2d& CD3D9Driver::getCurrentRenderTargetSize() const { if ( CurrentRendertargetSize.Width == 0 ) return ScreenSize; else return CurrentRendertargetSize; } // Set/unset a clipping plane. bool CD3D9Driver::setClipPlane(u32 index, const core::plane3df& plane, bool enable) { if (index >= MaxUserClipPlanes) return false; HRESULT ok = pID3DDevice->SetClipPlane(index, (const float*)&(plane.Normal.X)); if (D3D_OK == ok) enableClipPlane(index, enable); return true; } // Enable/disable a clipping plane. void CD3D9Driver::enableClipPlane(u32 index, bool enable) { if (index >= MaxUserClipPlanes) return; DWORD renderstate; HRESULT ok = pID3DDevice->GetRenderState(D3DRS_CLIPPLANEENABLE, &renderstate); if (S_OK == ok) { if (enable) renderstate |= (1 << index); else renderstate &= ~(1 << index); ok = pID3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, renderstate); } } D3DFORMAT CD3D9Driver::getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const { switch(format) { case ECF_A1R5G5B5: return D3DFMT_A1R5G5B5; case ECF_R5G6B5: return D3DFMT_R5G6B5; case ECF_R8G8B8: return D3DFMT_R8G8B8; case ECF_A8R8G8B8: return D3DFMT_A8R8G8B8; // Floating Point formats. Thanks to Patryk "Nadro" Nadrowski. case ECF_R16F: return D3DFMT_R16F; case ECF_G16R16F: return D3DFMT_G16R16F; case ECF_A16B16G16R16F: return D3DFMT_A16B16G16R16F; case ECF_R32F: return D3DFMT_R32F; case ECF_G32R32F: return D3DFMT_G32R32F; case ECF_A32B32G32R32F: return D3DFMT_A32B32G32R32F; } return D3DFMT_UNKNOWN; } ECOLOR_FORMAT CD3D9Driver::getColorFormatFromD3DFormat(D3DFORMAT format) const { switch(format) { case D3DFMT_X1R5G5B5: case D3DFMT_A1R5G5B5: return ECF_A1R5G5B5; case D3DFMT_A8B8G8R8: case D3DFMT_A8R8G8B8: case D3DFMT_X8R8G8B8: return ECF_A8R8G8B8; case D3DFMT_R5G6B5: return ECF_R5G6B5; case D3DFMT_R8G8B8: return ECF_R8G8B8; // Floating Point formats. Thanks to Patryk "Nadro" Nadrowski. case D3DFMT_R16F: return ECF_R16F; case D3DFMT_G16R16F: return ECF_G16R16F; case D3DFMT_A16B16G16R16F: return ECF_A16B16G16R16F; case D3DFMT_R32F: return ECF_R32F; case D3DFMT_G32R32F: return ECF_G32R32F; case D3DFMT_A32B32G32R32F: return ECF_A32B32G32R32F; default: return (ECOLOR_FORMAT)0; }; } void CD3D9Driver::checkDepthBuffer(ITexture* tex) { if (!tex) return; const core::dimension2du optSize = tex->getSize().getOptimalSize( !queryFeature(EVDF_TEXTURE_NPOT), !queryFeature(EVDF_TEXTURE_NSQUARE), true); SDepthSurface* depth=0; core::dimension2du destSize(0x7fffffff, 0x7fffffff); for (u32 i=0; iSize.Width>=optSize.Width) && (DepthBuffers[i]->Size.Height>=optSize.Height)) { if ((DepthBuffers[i]->Size.WidthSize.HeightSize; } } } if (!depth) { D3DSURFACE_DESC desc; DepthBuffers[0]->Surface->GetDesc(&desc); // the multisampling needs to match the RTT D3DSURFACE_DESC desc2; ((CD3D9Texture*)tex)->Texture->GetLevelDesc(0,&desc2); DepthBuffers.push_back(new SDepthSurface()); HRESULT hr=pID3DDevice->CreateDepthStencilSurface(optSize.Width, optSize.Height, desc.Format, desc2.MultiSampleType, desc2.MultiSampleQuality, TRUE, &(DepthBuffers.getLast()->Surface), NULL); if (SUCCEEDED(hr)) { depth=DepthBuffers.getLast(); depth->Surface->GetDesc(&desc); depth->Size.set(desc.Width, desc.Height); } else { if (hr == D3DERR_OUTOFVIDEOMEMORY) os::Printer::log("Could not create DepthBuffer","out of video memory",ELL_ERROR); else if( hr == E_OUTOFMEMORY ) os::Printer::log("Could not create DepthBuffer","out of memory",ELL_ERROR); else { char buffer[128]; sprintf(buffer,"Could not create DepthBuffer of %ix%i",optSize.Width,optSize.Height); os::Printer::log(buffer,ELL_ERROR); } DepthBuffers.erase(DepthBuffers.size()-1); } } else depth->grab(); static_cast(tex)->DepthSurface=depth; } void CD3D9Driver::removeDepthSurface(SDepthSurface* depth) { for (u32 i=0; iinitDriver(window, pureSoftware)) { dx9->drop(); dx9 = 0; } return dx9; } #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CD3D9CgMaterialRenderer.h0000644000000000000000000000536012574354552021500 0ustar rootroot// Copyright (C) 2012-2012 Patryk Nadrowski // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_DIRECT3D_9_CG_MATERIAL_RENDERER_H_INCLUDED__ #define __C_DIRECT3D_9_CG_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #if defined(_IRR_COMPILE_WITH_DIRECT3D_9_) && defined(_IRR_COMPILE_WITH_CG_) #define WIN32_LEAN_AND_MEAN #include #include #include #include "CCgMaterialRenderer.h" #include "Cg/cgD3D9.h" #ifdef _MSC_VER #pragma comment(lib, "cgD3D9.lib") #endif namespace irr { namespace video { class CD3D9Driver; class IShaderConstantSetCallBack; class CD3D9CgUniformSampler2D : public CCgUniform { public: CD3D9CgUniformSampler2D(const CGparameter& parameter, bool global); void update(const void* data, const SMaterial& material) const; }; class CD3D9CgMaterialRenderer : public CCgMaterialRenderer { public: CD3D9CgMaterialRenderer(CD3D9Driver* driver, s32& materialType, const c8* vertexProgram = 0, const c8* vertexEntry = "main", E_VERTEX_SHADER_TYPE vertexProfile = video::EVST_VS_1_1, const c8* fragmentProgram = 0, const c8* fragmentEntry = "main", E_PIXEL_SHADER_TYPE fragmentProfile = video::EPST_PS_1_1, const c8* geometryProgram = 0, const c8* geometryEntry = "main", E_GEOMETRY_SHADER_TYPE geometryProfile = video::EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 vertices = 0, IShaderConstantSetCallBack* callback = 0, IMaterialRenderer* baseMaterial = 0, s32 userData = 0); virtual ~CD3D9CgMaterialRenderer(); virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services); virtual bool OnRender(IMaterialRendererServices* services, E_VERTEX_TYPE vtxtype); virtual void OnUnsetMaterial(); virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates); virtual IVideoDriver* getVideoDriver(); protected: void init(s32& materialType, const c8* vertexProgram = 0, const c8* vertexEntry = "main", E_VERTEX_SHADER_TYPE vertexProfile = video::EVST_VS_1_1, const c8* fragmentProgram = 0, const c8* fragmentEntry = "main", E_PIXEL_SHADER_TYPE fragmentProfile = video::EPST_PS_1_1, const c8* geometryProgram = 0, const c8* geometryEntry = "main", E_GEOMETRY_SHADER_TYPE geometryProfile = video::EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 vertices = 0); CD3D9Driver* Driver; }; } } #endif #endif irrlicht-1.8.3/source/Irrlicht/CD3D9CgMaterialRenderer.cpp0000644000000000000000000001446412574354552022040 0ustar rootroot// Copyright (C) 2012-2012 Patryk Nadrowski // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #if defined(_IRR_COMPILE_WITH_DIRECT3D_9_) && defined(_IRR_COMPILE_WITH_CG_) #include "CD3D9CgMaterialRenderer.h" #include "CD3D9Driver.h" #include "CD3D9Texture.h" namespace irr { namespace video { CD3D9CgUniformSampler2D::CD3D9CgUniformSampler2D(const CGparameter& parameter, bool global) : CCgUniform(parameter, global) { Type = CG_SAMPLER2D; } void CD3D9CgUniformSampler2D::update(const void* data, const SMaterial& material) const { s32* Data = (s32*)data; s32 LayerID = *Data; if (material.TextureLayer[LayerID].Texture) { IDirect3DBaseTexture9* Texture = reinterpret_cast(material.TextureLayer[LayerID].Texture)->getDX9Texture(); cgD3D9SetTextureParameter(Parameter, Texture); } } CD3D9CgMaterialRenderer::CD3D9CgMaterialRenderer(CD3D9Driver* driver, s32& materialType, const c8* vertexProgram, const c8* vertexEntry, E_VERTEX_SHADER_TYPE vertexProfile, const c8* fragmentProgram, const c8* fragmentEntry, E_PIXEL_SHADER_TYPE fragmentProfile, const c8* geometryProgram, const c8* geometryEntry, E_GEOMETRY_SHADER_TYPE geometryProfile, scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 vertices, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : Driver(driver), CCgMaterialRenderer(callback, baseMaterial, userData) { #ifdef _DEBUG setDebugName("CD3D9CgMaterialRenderer"); #endif init(materialType, vertexProgram, vertexEntry, vertexProfile, fragmentProgram, fragmentEntry, fragmentProfile, geometryProgram, geometryEntry, geometryProfile, inType, outType, vertices); } CD3D9CgMaterialRenderer::~CD3D9CgMaterialRenderer() { if (VertexProgram) { cgD3D9UnloadProgram(VertexProgram); cgDestroyProgram(VertexProgram); } if (FragmentProgram) { cgD3D9UnloadProgram(FragmentProgram); cgDestroyProgram(FragmentProgram); } /*if (GeometryProgram) { cgD3D9UnloadProgram(GeometryProgram); cgDestroyProgram(GeometryProgram); }*/ } void CD3D9CgMaterialRenderer::OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { Material = material; if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (VertexProgram) cgD3D9BindProgram(VertexProgram); if (FragmentProgram) cgD3D9BindProgram(FragmentProgram); /*if (GeometryProgram) cgD3D9BindProgram(GeometryProgram);*/ if (BaseMaterial) BaseMaterial->OnSetMaterial(material, material, true, this); } if (CallBack) CallBack->OnSetMaterial(material); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } bool CD3D9CgMaterialRenderer::OnRender(IMaterialRendererServices* services, E_VERTEX_TYPE vtxtype) { if (CallBack && (VertexProgram || FragmentProgram || GeometryProgram)) CallBack->OnSetConstants(this, UserData); return true; } void CD3D9CgMaterialRenderer::OnUnsetMaterial() { if (VertexProgram) cgD3D9UnbindProgram(VertexProgram); if (FragmentProgram) cgD3D9UnbindProgram(FragmentProgram); /*if (GeometryProgram) cgD3D9UnbindProgram(GeometryProgram);*/ if (BaseMaterial) BaseMaterial->OnUnsetMaterial(); Material = IdentityMaterial;; } void CD3D9CgMaterialRenderer::setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) { Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } IVideoDriver* CD3D9CgMaterialRenderer::getVideoDriver() { return Driver; } void CD3D9CgMaterialRenderer::init(s32& materialType, const c8* vertexProgram, const c8* vertexEntry, E_VERTEX_SHADER_TYPE vertexProfile, const c8* fragmentProgram, const c8* fragmentEntry, E_PIXEL_SHADER_TYPE fragmentProfile, const c8* geometryProgram, const c8* geometryEntry, E_GEOMETRY_SHADER_TYPE geometryProfile, scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 vertices) { bool Status = true; CGerror Error = CG_NO_ERROR; materialType = -1; // TODO: add profile selection if (vertexProgram) { VertexProfile = cgD3D9GetLatestVertexProfile(); if (VertexProfile) VertexProgram = cgCreateProgram(Driver->getCgContext(), CG_SOURCE, vertexProgram, VertexProfile, vertexEntry, 0); if (!VertexProgram) { Error = cgGetError(); os::Printer::log("Cg vertex program failed to compile:", ELL_ERROR); os::Printer::log(cgGetLastListing(Driver->getCgContext()), ELL_ERROR); Status = false; } else cgD3D9LoadProgram(VertexProgram, 0, 0); } if (fragmentProgram) { FragmentProfile = cgD3D9GetLatestPixelProfile(); if (FragmentProfile) FragmentProgram = cgCreateProgram(Driver->getCgContext(), CG_SOURCE, fragmentProgram, FragmentProfile, fragmentEntry, 0); if (!FragmentProgram) { Error = cgGetError(); os::Printer::log("Cg fragment program failed to compile:", ELL_ERROR); os::Printer::log(cgGetLastListing(Driver->getCgContext()), ELL_ERROR); Status = false; } else cgD3D9LoadProgram(FragmentProgram, 0, 0); } /*if (geometryProgram) { GeometryProfile = cgD3D9GetLatestGeometryProfile(); if (GeometryProfile) GeometryProgram = cgCreateProgram(Driver->getCgContext(), CG_SOURCE, geometryProgram, GeometryProfile, geometryEntry, 0); if (!GeometryProgram) { Error = cgGetError(); os::Printer::log("Cg geometry program failed to compile:", ELL_ERROR); os::Printer::log(cgGetLastListing(Driver->getCgContext()), ELL_ERROR); Status = false; } else cgD3D9LoadProgram(GeometryProgram, 0, 0); }*/ getUniformList(); // create D3D9 specifics sampler uniforms. for(unsigned int i = 0; i < UniformInfo.size(); ++i) { if (UniformInfo[i]->getType() == CG_SAMPLER2D) { bool IsGlobal = true; if (UniformInfo[i]->getSpace() == CG_PROGRAM) IsGlobal = false; CCgUniform* Uniform = new CD3D9CgUniformSampler2D(UniformInfo[i]->getParameter(), IsGlobal); delete UniformInfo[i]; UniformInfo[i] = Uniform; } } if (Status) materialType = Driver->addMaterialRenderer(this); } } } #endif irrlicht-1.8.3/source/Irrlicht/CD3D8Texture.h0000644000000000000000000000575312574354552017446 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_DIRECTX8_TEXTURE_H_INCLUDED__ #define __C_DIRECTX8_TEXTURE_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ #include "ITexture.h" #include "IImage.h" #include namespace irr { namespace video { class CD3D8Driver; /*! interface for a Video Driver dependent Texture. */ class CD3D8Texture : public ITexture { public: //! constructor CD3D8Texture(IImage* image, CD3D8Driver* driver, u32 flags, const io::path& name, void* mipmapData=0); //! rendertarget constructor CD3D8Texture(CD3D8Driver* driver, const core::dimension2d& size, const io::path& name); //! destructor virtual ~CD3D8Texture(); //! lock function virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0); //! unlock function virtual void unlock(); //! Returns original size of the texture. virtual const core::dimension2d& getOriginalSize() const; //! Returns (=size) of the texture. virtual const core::dimension2d& getSize() const; //! returns driver type of texture (=the driver, who created the texture) virtual E_DRIVER_TYPE getDriverType() const; //! returns color format of texture virtual ECOLOR_FORMAT getColorFormat() const; //! returns pitch of texture (in bytes) virtual u32 getPitch() const; //! returns the DIRECT3D8 Texture IDirect3DTexture8* getDX8Texture() const; //! returns if texture has mipmap levels bool hasMipMaps() const; //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture virtual void regenerateMipMapLevels(void* mipmapData=0); //! returns if it is a render target virtual bool isRenderTarget() const; //! Returns pointer to the render target surface IDirect3DSurface8* getRenderTargetSurface(); private: friend class CD3D8Driver; void createRenderTarget(); //! creates the hardware texture bool createTexture(u32 flags, IImage* Image); //! copies the image to the texture bool copyTexture(IImage* Image); //! convert color formats ECOLOR_FORMAT getColorFormatFromD3DFormat(D3DFORMAT format); bool createMipMaps(u32 level=1); void copy16BitMipMap(char* src, char* tgt, s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const; void copy32BitMipMap(char* src, char* tgt, s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const; IDirect3DDevice8* Device; IDirect3DTexture8* Texture; IDirect3DSurface8* RTTSurface; CD3D8Driver* Driver; core::dimension2d TextureSize; core::dimension2d ImageSize; s32 Pitch; u32 MipLevelLocked; ECOLOR_FORMAT ColorFormat; bool HasMipMaps; bool IsRenderTarget; }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ #endif // __C_DIRECTX8_TEXTURE_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CD3D8Texture.cpp0000644000000000000000000003645312574354552020002 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ #define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE #include "CD3D8Texture.h" #include "CD3D8Driver.h" #include "os.h" #ifndef _IRR_COMPILE_WITH_DIRECT3D_9_ // The D3DXFilterTexture function seems to get linked wrong when // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. // So mipmapgeneration is replaced with my own bad generation in d3d 8 when // compiling with both D3D 8 and 9. //#define _IRR_USE_D3DXFilterTexture_ #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ #include #ifdef _IRR_USE_D3DXFilterTexture_ #pragma comment (lib, "d3dx8.lib") #endif // _IRR_USE_D3DXFilterTexture_ namespace irr { namespace video { //! rendertarget constructor CD3D8Texture::CD3D8Texture(CD3D8Driver* driver, const core::dimension2d& size, const io::path& name) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), TextureSize(size), ImageSize(size), Pitch(0), HasMipMaps(false), IsRenderTarget(true) { #ifdef _DEBUG setDebugName("CD3D8Texture"); #endif Device=driver->getExposedVideoData().D3D8.D3DDev8; if (Device) Device->AddRef(); createRenderTarget(); } //! constructor CD3D8Texture::CD3D8Texture(IImage* image, CD3D8Driver* driver, u32 flags, const io::path& name, void* mipmapData) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), TextureSize(0,0), ImageSize(0,0), Pitch(0), HasMipMaps(false), IsRenderTarget(false) { #ifdef _DEBUG setDebugName("CD3D8Texture"); #endif HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); Device=driver->getExposedVideoData().D3D8.D3DDev8; if (Device) Device->AddRef(); if (image) { if (createTexture(flags, image)) { if (copyTexture(image)) { regenerateMipMapLevels(mipmapData); } } else os::Printer::log("Could not create DIRECT3D8 Texture.", ELL_WARNING); } } //! destructor CD3D8Texture::~CD3D8Texture() { if (Texture) Texture->Release(); if (RTTSurface) RTTSurface->Release(); if (Device) Device->Release(); } //! creates the hardware texture bool CD3D8Texture::createTexture(u32 flags, video::IImage* image) { ImageSize = image->getDimension(); core::dimension2d optSize = ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth); D3DFORMAT format = D3DFMT_A1R5G5B5; switch(getTextureFormatFromFlags(flags)) { case ETCF_ALWAYS_16_BIT: format = D3DFMT_A1R5G5B5; break; case ETCF_ALWAYS_32_BIT: format = D3DFMT_A8R8G8B8; break; case ETCF_OPTIMIZED_FOR_QUALITY: { switch(image->getColorFormat()) { case ECF_R8G8B8: case ECF_A8R8G8B8: format = D3DFMT_A8R8G8B8; break; case ECF_A1R5G5B5: case ECF_R5G6B5: format = D3DFMT_A1R5G5B5; break; } } break; case ETCF_OPTIMIZED_FOR_SPEED: format = D3DFMT_A1R5G5B5; break; } if (Driver->getTextureCreationFlag(video::ETCF_NO_ALPHA_CHANNEL)) { if (format == D3DFMT_A8R8G8B8) #ifdef _IRR_XBOX_PLATFORM_ format = D3DFMT_X8R8G8B8; #else format = D3DFMT_R8G8B8; #endif else if (format == D3DFMT_A1R5G5B5) format = D3DFMT_R5G6B5; } const bool mipmaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); HRESULT hr = Device->CreateTexture(optSize.Width, optSize.Height, mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all) 0, format, D3DPOOL_MANAGED, &Texture); if (FAILED(hr)) { // try brute force 16 bit if (format == D3DFMT_A8R8G8B8) format = D3DFMT_A1R5G5B5; #ifdef _IRR_XBOX_PLATFORM_ else if (format == D3DFMT_X8R8G8B8) format = D3DFMT_R5G6B5; #else else if (format == D3DFMT_R8G8B8) format = D3DFMT_R5G6B5; #endif else return false; hr = Device->CreateTexture(optSize.Width, optSize.Height, mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all) 0, format, D3DPOOL_MANAGED, &Texture); } ColorFormat = getColorFormatFromD3DFormat(format); return (SUCCEEDED(hr)); } //! copies the image to the texture bool CD3D8Texture::copyTexture(video::IImage* image) { if (Texture && image) { D3DSURFACE_DESC desc; Texture->GetLevelDesc(0, &desc); TextureSize.Width = desc.Width; TextureSize.Height = desc.Height; D3DLOCKED_RECT rect; HRESULT hr = Texture->LockRect(0, &rect, 0, 0); if (FAILED(hr)) { os::Printer::log("Could not lock D3D8 Texture.", ELL_ERROR); return false; } Pitch = rect.Pitch; image->copyToScaling(rect.pBits, TextureSize.Width, TextureSize.Height, ColorFormat, Pitch); hr = Texture->UnlockRect(0); if (FAILED(hr)) { os::Printer::log("Could not unlock D3D8 Texture.", ELL_ERROR); return false; } } return true; } //! lock function void* CD3D8Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) { if (!Texture) return 0; MipLevelLocked=mipmapLevel; HRESULT hr; D3DLOCKED_RECT rect; if(!IsRenderTarget) { hr = Texture->LockRect(mipmapLevel, &rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); return 0; } } else { if (!RTTSurface) { // Make RTT surface large enough for all miplevels (including 0) D3DSURFACE_DESC desc; Texture->GetLevelDesc(0, &desc); hr = Device->CreateImageSurface(desc.Width, desc.Height, desc.Format, &RTTSurface); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); return 0; } } IDirect3DSurface8 *surface = 0; hr = Texture->GetSurfaceLevel(mipmapLevel, &surface); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", "Could not get surface.", ELL_ERROR); return 0; } hr = Device->CopyRects(surface, 0, 0, RTTSurface, 0); surface->Release(); if(FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", "Data copy failed.", ELL_ERROR); return 0; } hr = RTTSurface->LockRect(&rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0); if(FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D8 Texture.", "LockRect failed.", ELL_ERROR); return 0; } } return rect.pBits; } //! unlock function void CD3D8Texture::unlock() { if (!Texture) return; if (!IsRenderTarget) Texture->UnlockRect(MipLevelLocked); else if (RTTSurface) RTTSurface->UnlockRect(); } //! Returns original size of the texture. const core::dimension2d& CD3D8Texture::getOriginalSize() const { return ImageSize; } //! Returns (=size) of the texture. const core::dimension2d& CD3D8Texture::getSize() const { return TextureSize; } //! returns driver type of texture (=the driver, who created the texture) E_DRIVER_TYPE CD3D8Texture::getDriverType() const { return EDT_DIRECT3D8; } //! returns color format of texture ECOLOR_FORMAT CD3D8Texture::getColorFormat() const { return ColorFormat; } //! returns pitch of texture (in bytes) u32 CD3D8Texture::getPitch() const { return Pitch; } //! returns the DIRECT3D8 Texture IDirect3DTexture8* CD3D8Texture::getDX8Texture() const { return Texture; } //! returns if texture has mipmap levels bool CD3D8Texture::hasMipMaps() const { return HasMipMaps; } // The D3DXFilterTexture function seems to get linked wrong when // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. // So mipmapgeneration is replaced with my own bad generation in d3d 8 when // compiling with both D3D 8 and 9. bool CD3D8Texture::createMipMaps(u32 level) { if (level==0) return true; IDirect3DSurface8* upperSurface = 0; IDirect3DSurface8* lowerSurface = 0; // get upper level HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface); if (FAILED(hr) || !upperSurface) { os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING); return false; } // get lower level hr = Texture->GetSurfaceLevel(level, &lowerSurface); if (FAILED(hr) || !lowerSurface) { os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING); upperSurface->Release(); return false; } D3DSURFACE_DESC upperDesc, lowerDesc; upperSurface->GetDesc(&upperDesc); lowerSurface->GetDesc(&lowerDesc); D3DLOCKED_RECT upperlr; D3DLOCKED_RECT lowerlr; // lock upper surface if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0))) { os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING); upperSurface->Release(); lowerSurface->Release(); return false; } // lock lower surface if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0))) { os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING); upperSurface->UnlockRect(); upperSurface->Release(); lowerSurface->Release(); return false; } if (upperDesc.Format != lowerDesc.Format) { os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING); } else { if (upperDesc.Format == D3DFMT_A1R5G5B5) copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits, lowerDesc.Width, lowerDesc.Height, upperlr.Pitch, lowerlr.Pitch); else if (upperDesc.Format == D3DFMT_A8R8G8B8) copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits, lowerDesc.Width, lowerDesc.Height, upperlr.Pitch, lowerlr.Pitch); else os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING); } bool result=true; // unlock if (FAILED(upperSurface->UnlockRect())) result=false; if (FAILED(lowerSurface->UnlockRect())) result=false; // release upperSurface->Release(); lowerSurface->Release(); if (!result || upperDesc.Width < 3 || upperDesc.Height < 3) return result; // stop generating levels // generate next level return createMipMaps(level+1); } ECOLOR_FORMAT CD3D8Texture::getColorFormatFromD3DFormat(D3DFORMAT format) { switch(format) { case D3DFMT_X1R5G5B5: case D3DFMT_A1R5G5B5: Pitch = TextureSize.Width * 2; return ECF_A1R5G5B5; break; case D3DFMT_A8R8G8B8: case D3DFMT_X8R8G8B8: Pitch = TextureSize.Width * 4; return ECF_A8R8G8B8; break; case D3DFMT_R5G6B5: Pitch = TextureSize.Width * 2; return ECF_R5G6B5; break; default: return (ECOLOR_FORMAT)0; }; } void CD3D8Texture::copy16BitMipMap(char* src, char* tgt, s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const { u16 c; for (int x=0; x>= 2; r >>= 2; g >>= 2; b >>= 2; c = ((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff); *(u32*)((void*)&tgt[(x*4)+(y*pitchtgt)]) = c.color; } } } void CD3D8Texture::createRenderTarget() { TextureSize = TextureSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth); // get backbuffer format to create the render target in the // same format IDirect3DSurface8* bb; D3DFORMAT d3DFormat = D3DFMT_A8R8G8B8; if (!FAILED(Device->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &bb))) { D3DSURFACE_DESC desc; bb->GetDesc(&desc); d3DFormat = desc.Format; if (d3DFormat == D3DFMT_X8R8G8B8) d3DFormat = D3DFMT_A8R8G8B8; bb->Release(); } else { os::Printer::log("Could not create RenderTarget texture: could not get BackBuffer.", ELL_WARNING); return; } // create texture HRESULT hr; hr = Device->CreateTexture( TextureSize.Width, TextureSize.Height, 1, // mip map level count, we don't want mipmaps here D3DUSAGE_RENDERTARGET, d3DFormat, D3DPOOL_DEFAULT, &Texture); // get irrlicht format from D3D format ColorFormat = getColorFormatFromD3DFormat(d3DFormat); if (FAILED(hr)) os::Printer::log("Could not create render target texture"); } //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture void CD3D8Texture::regenerateMipMapLevels(void* mipmapData) { if (mipmapData) { core::dimension2du size = TextureSize; u32 level=0; do { if (size.Width>1) size.Width /=2; if (size.Height>1) size.Height /=2; ++level; IDirect3DSurface8* mipSurface = 0; HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface); if (FAILED(hr) || !mipSurface) { os::Printer::log("Could not get mipmap level", ELL_WARNING); return; } D3DSURFACE_DESC mipDesc; mipSurface->GetDesc(&mipDesc); D3DLOCKED_RECT miplr; // lock mipmap surface if (FAILED(mipSurface->LockRect(&miplr, NULL, 0))) { mipSurface->Release(); os::Printer::log("Could not lock texture", ELL_WARNING); return; } memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width); mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width; // unlock mipSurface->UnlockRect(); // release mipSurface->Release(); } while (size.Width != 1 || size.Height != 1); } else if (HasMipMaps) { // create mip maps. #ifndef _IRR_USE_D3DXFilterTexture_ // The D3DXFilterTexture function seems to get linked wrong when // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. // So mipmapgeneration is replaced with my own bad generation in d3d 8 when // compiling with both D3D 8 and 9. HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT , D3DX_DEFAULT ); if (FAILED(hr)) #endif createMipMaps(); } } //! returns if it is a render target bool CD3D8Texture::isRenderTarget() const { return IsRenderTarget; } //! Returns pointer to the render target surface IDirect3DSurface8* CD3D8Texture::getRenderTargetSurface() { if (!IsRenderTarget) return 0; IDirect3DSurface8 *pRTTSurface = 0; if (Texture) Texture->GetSurfaceLevel(0, &pRTTSurface); if (pRTTSurface) pRTTSurface->Release(); return pRTTSurface; } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ irrlicht-1.8.3/source/Irrlicht/CD3D8ShaderMaterialRenderer.h0000644000000000000000000000444412574354552022356 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_D3D8_SHADER_MATERIAL_RENDERER_H_INCLUDED__ #define __C_D3D8_SHADER_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_WINDOWS_API_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ #include #include #include "IMaterialRenderer.h" #include "S3DVertex.h" namespace irr { namespace video { class IVideoDriver; class IShaderConstantSetCallBack; class IMaterialRenderer; //! Class for using vertex and pixel shaders with D3D8 class CD3D8ShaderMaterialRenderer : public IMaterialRenderer { public: //! Public constructor CD3D8ShaderMaterialRenderer(IDirect3DDevice8* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData); //! Destructor ~CD3D8ShaderMaterialRenderer(); virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services); virtual void OnUnsetMaterial(); virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); //! Returns if the material is transparent. virtual bool isTransparent() const; protected: //! constructor only for use by derived classes who want to //! create a fall back material for example. CD3D8ShaderMaterialRenderer(IDirect3DDevice8* d3ddev, video::IVideoDriver* driver, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData=0); void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, E_VERTEX_TYPE type); bool createPixelShader(const c8* pxsh); bool createVertexShader(const char* vtxsh, E_VERTEX_TYPE type); IDirect3DDevice8* pID3DDevice; video::IVideoDriver* Driver; IShaderConstantSetCallBack* CallBack; IMaterialRenderer* BaseMaterial; DWORD VertexShader; DWORD OldVertexShader; DWORD PixelShader; s32 UserData; }; } // end namespace video } // end namespace irr #endif #endif #endif irrlicht-1.8.3/source/Irrlicht/CD3D8ShaderMaterialRenderer.cpp0000644000000000000000000002044212574354552022705 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CD3D8ShaderMaterialRenderer.h" #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ #include #include #pragma comment (lib, "d3dx8.lib") #include "IShaderConstantSetCallBack.h" #include "IMaterialRendererServices.h" #include "IVideoDriver.h" #include "os.h" #ifndef _IRR_D3D_NO_SHADER_DEBUGGING #include #endif namespace irr { namespace video { //! Public constructor CD3D8ShaderMaterialRenderer::CD3D8ShaderMaterialRenderer(IDirect3DDevice8* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial), VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData) { #ifdef _DEBUG setDebugName("CD3D8ShaderMaterialRenderer"); #endif if (BaseMaterial) BaseMaterial->grab(); if (CallBack) CallBack->grab(); init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram, EVT_STANDARD); } //! constructor only for use by derived classes who want to //! create a fall back material for example. CD3D8ShaderMaterialRenderer::CD3D8ShaderMaterialRenderer(IDirect3DDevice8* d3ddev, video::IVideoDriver* driver, IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : pID3DDevice(d3ddev), Driver(driver), BaseMaterial(baseMaterial), CallBack(callback), VertexShader(0), PixelShader(0), UserData(userData) { if (BaseMaterial) BaseMaterial->grab(); if (CallBack) CallBack->grab(); } //! Destructor CD3D8ShaderMaterialRenderer::~CD3D8ShaderMaterialRenderer() { if (CallBack) CallBack->drop(); if (VertexShader) pID3DDevice->DeleteVertexShader(VertexShader); if (PixelShader) pID3DDevice->DeletePixelShader(PixelShader); if (BaseMaterial) BaseMaterial->drop (); } void CD3D8ShaderMaterialRenderer::init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, E_VERTEX_TYPE type) { outMaterialTypeNr = -1; // create vertex shader if (!createVertexShader(vertexShaderProgram, type)) return; // create pixel shader if (!createPixelShader(pixelShaderProgram)) return; // register myself as new material outMaterialTypeNr = Driver->addMaterialRenderer(this); } bool CD3D8ShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { // call callback to set shader constants if (CallBack && (VertexShader || PixelShader)) CallBack->OnSetConstants(service, UserData); return true; } void CD3D8ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services) { if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (VertexShader) { // We do not need to save and reset the old vertex shader, because // in D3D8, this is mixed up with the fvf, and this is set by the driver // every time. //pID3DDevice->GetVertexShader(&OldVertexShader); // set new vertex shader if (FAILED(pID3DDevice->SetVertexShader(VertexShader))) os::Printer::log("Could not set vertex shader.", ELL_ERROR); } // set new pixel shader if (PixelShader) { if (FAILED(pID3DDevice->SetPixelShader(PixelShader))) os::Printer::log("Could not set pixel shader.", ELL_ERROR); } if (BaseMaterial) BaseMaterial->OnSetMaterial(material, material, true, services); } //let callback know used material if (CallBack) CallBack->OnSetMaterial(material); services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); } void CD3D8ShaderMaterialRenderer::OnUnsetMaterial() { // We do not need to save and reset the old vertex shader, because // in D3D8, this is mixed up with the fvf, and this is set by the driver // every time. // if (VertexShader) // pID3DDevice->SetVertexShader(OldVertexShader); if (PixelShader) pID3DDevice->SetPixelShader(0); if (BaseMaterial) BaseMaterial->OnUnsetMaterial(); } //! Returns if the material is transparent. The scene managment needs to know this //! for being able to sort the materials by opaque and transparent. bool CD3D8ShaderMaterialRenderer::isTransparent() const { return BaseMaterial ? BaseMaterial->isTransparent() : false; } bool CD3D8ShaderMaterialRenderer::createPixelShader(const c8* pxsh) { if (!pxsh) return true; #if defined( _IRR_XBOX_PLATFORM_) return false; #else // compile shader LPD3DXBUFFER code = 0; LPD3DXBUFFER errors = 0; #ifdef _IRR_D3D_NO_SHADER_DEBUGGING // compile shader without debug info D3DXAssembleShader(pxsh, (UINT)strlen(pxsh), 0, 0, &code, &errors); #else // compile shader and emitt some debug informations to // make it possible to debug the shader in visual studio static int irr_dbg_file_nr = 0; ++irr_dbg_file_nr; char tmp[32]; sprintf(tmp, "irr_d3d8_dbg_shader_%d.psh", irr_dbg_file_nr); FILE* f = fopen(tmp, "wb"); fwrite(pxsh, strlen(pxsh), 1, f); fflush(f); fclose(f); D3DXAssembleShaderFromFile(tmp, D3DXASM_DEBUG, 0, &code, &errors); #endif if (errors) { // print out compilation errors. os::Printer::log("Pixel shader compilation failed:", ELL_ERROR); os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR); if (code) code->Release(); errors->Release(); return false; } if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)code->GetBufferPointer(), &PixelShader))) { os::Printer::log("Could not create pixel shader.", ELL_ERROR); code->Release(); return false; } code->Release(); return true; #endif } bool CD3D8ShaderMaterialRenderer::createVertexShader(const char* vtxsh, E_VERTEX_TYPE type) { if (!vtxsh) return true; // compile shader #if defined( _IRR_XBOX_PLATFORM_) return false; #else LPD3DXBUFFER code = 0; LPD3DXBUFFER errors = 0; #ifdef _IRR_D3D_NO_SHADER_DEBUGGING // compile shader without debug info D3DXAssembleShader(vtxsh, (UINT)strlen(vtxsh), 0, 0, &code, &errors); #else // compile shader and emitt some debug informations to // make it possible to debug the shader in visual studio static int irr_dbg_file_nr = 0; ++irr_dbg_file_nr; char tmp[32]; sprintf(tmp, "irr_d3d8_dbg_shader_%d.vsh", irr_dbg_file_nr); FILE* f = fopen(tmp, "wb"); fwrite(vtxsh, strlen(vtxsh), 1, f); fflush(f); fclose(f); D3DXAssembleShaderFromFile(tmp, D3DXASM_DEBUG, 0, &code, &errors); #endif if (errors) { // print out compilation errors. os::Printer::log("Vertex shader compilation failed:", ELL_ERROR); os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR); if (code) code->Release(); errors->Release(); return false; } DWORD* decl = 0; DWORD dwStdDecl[] = { D3DVSD_STREAM(0), D3DVSD_REG(0, D3DVSDT_FLOAT3), // position 0 D3DVSD_REG(1, D3DVSDT_FLOAT3), // normal 1 D3DVSD_REG(2, D3DVSDT_D3DCOLOR ),// color 2 D3DVSD_REG(3, D3DVSDT_FLOAT2 ), // tex1 3 D3DVSD_REG(4, D3DVSDT_FLOAT2 ), // tex2 4 D3DVSD_END() }; DWORD dwTngtDecl[] = { D3DVSD_STREAM(0), D3DVSD_REG(0 , D3DVSDT_FLOAT3), // position 0 D3DVSD_REG(1 , D3DVSDT_FLOAT3), // normal 1 D3DVSD_REG(2 , D3DVSDT_D3DCOLOR ),// color 2 D3DVSD_REG(3 , D3DVSDT_FLOAT2 ), // tex1 3 D3DVSD_REG(4, D3DVSDT_FLOAT3 ), // tangent 4 D3DVSD_REG(5, D3DVSDT_FLOAT3 ), // binormal 5 D3DVSD_END() }; if (type == EVT_TANGENTS) decl = dwTngtDecl; else decl = dwStdDecl; if (FAILED(pID3DDevice->CreateVertexShader(decl, (DWORD*)code->GetBufferPointer(), &VertexShader, 0))) { os::Printer::log("Could not create vertex shader.", ELL_ERROR); code->Release(); return false; } code->Release(); return true; #endif } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ irrlicht-1.8.3/source/Irrlicht/CD3D8ParallaxMapRenderer.h0000644000000000000000000000337012574354552021670 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_D3D8_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__ #define __C_D3D8_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_WINDOWS_API_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ #include #include "CD3D8ShaderMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" namespace irr { namespace video { //! Renderer for parallax maps class CD3D8ParallaxMapRenderer : public CD3D8ShaderMaterialRenderer, IShaderConstantSetCallBack { public: CD3D8ParallaxMapRenderer( IDirect3DDevice8* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial); ~CD3D8ParallaxMapRenderer(); //! Called by the engine when the vertex and/or pixel shader constants for an //! material renderer should be set. virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData); virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); virtual void OnSetMaterial(const SMaterial& material) { } virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services); //! Returns the render capability of the material. virtual s32 getRenderCapability() const; private: //! stores if this shader compiled the shaders and is //! allowed to delete them again. D3D8 lacks reference counting //! support for shaders. bool CompiledShaders; f32 CurrentScale; }; } // end namespace video } // end namespace irr #endif #endif #endif irrlicht-1.8.3/source/Irrlicht/CD3D8ParallaxMapRenderer.cpp0000644000000000000000000002651112574354552022225 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ #include "CD3D8ParallaxMapRenderer.h" #include "IMaterialRendererServices.h" #include "IVideoDriver.h" #include "os.h" #include "SLight.h" namespace irr { namespace video { // 1.1/1.4 Shaders with two lights and vertex based attenuation // Irrlicht Engine D3D8 render path normal map vertex shader const char D3D8_PARALLAX_MAP_VSH[] = ";Irrlicht Engine 0.10 D3D8 render path parallax mapping vertex shader\n"\ "; c0-3: Transposed world matrix \n"\ "; c4: Eye position \n"\ "; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\ "; c12: Light01 position \n"\ "; c13: x,y,z: Light01 color; .w: 1/LightRadius² \n"\ "; c14: Light02 position \n"\ "; c15: x,y,z: Light02 color; .w: 1/LightRadius² \n"\ "vs.1.1\n"\ "; v0 ; position \n"\ "; v1 ; normal \n"\ "; v2 ; color \n"\ "; v3 ; texture coord \n"\ "; v4 ; tangent \n"\ "; v5 ; binormal \n"\ "\n"\ "def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\ "def c96, -1, 1, 1, 1 ; somewhere I've got a bug. flipping the vectors with this fixes it. \n"\ "\n"\ "m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\ "\n"\ "m3x3 r5, v4, c0 ; transform tangent U\n"\ "m3x3 r7, v1, c0 ; transform normal W\n"\ "m3x3 r6, v5, c0 ; transform binormal V\n"\ "\n"\ "m4x4 r4, v0, c0 ; vertex into world position\n"\ "add r2, c12, -r4 ; vtxpos - light1 pos\n"\ "add r3, c14, -r4 ; vtxpos - light2 pos\n"\ "add r1, -c4, r4 ; eye - vtxpos \n"\ "\n"\ "dp3 r8.x, r5, r2 ; transform the light1 vector with U, V, W\n"\ "dp3 r8.y, r6, r2 \n"\ "dp3 r8.z, r7, r2 \n"\ "dp3 r9.x, r5, r3 ; transform the light2 vector with U, V, W\n"\ "dp3 r9.y, r6, r3 \n"\ "dp3 r9.z, r7, r3 \n"\ "dp3 r10.x, r5, r1 ; transform the eye vector with U, V, W\n"\ "dp3 r10.y, r6, r1 \n"\ "dp3 r10.z, r7, r1 \n"\ "\n"\ "dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\ "rsq r8.w, r8.w \n"\ "mul r8, r8, r8.w \n"\ ";mul r8, r8, c96 \n"\ "dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\ "rsq r9.w, r9.w \n"\ "mul r9, r9, r9.w \n"\ ";mul r9, r9, c96 \n"\ "dp3 r10.w, r10, r10 ; normalize eye vector (r10)\n"\ "rsq r10.w, r10.w \n"\ "mul r10, r10, r10.w \n"\ "mul r10, r10, c96 \n"\ "\n"\ "\n"\ "mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\ "mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\ "mad oT4.xyz, r10.xyz, c95, c95 ; move eye vector from -1..1 into 0..1 \n"\ "\n"\ " ; calculate attenuation of light 1 \n"\ "dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x² + r2.y² + r2.z² \n"\ "mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\ "rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\ "mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\ "\n"\ " ; calculate attenuation of light 2 \n"\ "dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x² + r3.y² + r3.z² \n"\ "mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\ "rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\ "mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\ "\n"\ "mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\ "mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\ "mov oD0.a, v2.a ; move out original alpha value \n"\ "\n"; // Irrlicht Engine D3D8 render path normal map pixel shader version 1.4 const char D3D8_PARALLAX_MAP_PSH[] = ";Irrlicht Engine 0.10 D3D8 render path parallax mapping pixel shader \n"\ ";Input: \n"\ ";t0: color map texture coord \n"\ ";t1: normal map texture coords \n"\ ";t2: light 1 vector in tangent space \n"\ ";t4: eye vector in tangent space \n"\ ";v0: light 1 color \n"\ ";t3: light 2 vector in tangent space \n"\ ";v1: light 2 color \n"\ ";v0.a: vertex alpha value \n"\ " \n"\ "ps.1.4 \n"\ " \n"\ ";def c6, 0.02f, 0.02f, 0.02f, 0.0f ; scale factor, now set in callback \n"\ " \n"\ "texld r1, t1 ; sample (normal.x, normal.y, normal.z, height) \n"\ "texcrd r4.xyz, t4 ; fetch eye vector \n"\ "texcrd r0.xyz, t0 ; color map \n"\ " \n"\ "; original parallax mapping: \n"\ ";mul r3, r1_bx2.wwww, c6; ; r3 = (height, height, height) * scale \n"\ ";mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\ " \n"\ "; modified parallax mapping to reduce swimming effect: \n"\ "mul r3, r1_bx2.wwww, r1_bx2.zzzz ; (nh,nh,nh,nh) = (h,h,h,h) * (n.z,n.z,n.z,n.z,) \n"\ "mul r3, r3, c6; ; r3 = (nh, nh, nh) * scale \n"\ "mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\ " \n"\ "phase \n"\ " \n"\ "texld r0, r2 ; load diffuse texture with new tex coord \n"\ "texld r1, r2 ; sample normal map \n"\ "texcrd r2.xyz, t2 ; fetch light vector 1 \n"\ "texcrd r3.xyz, t3 ; fetch light vector 2 \n"\ " \n"\ "dp3_sat r2, r1_bx2, r2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1) \n"\ "mul r2, r2, v0 ; luminance1 * light color 1 \n"\ " \n"\ "dp3_sat r3, r1_bx2, r3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1) \n"\ "mad r3, r3, v1, r2 ; (luminance2 * light color 2) + luminance1 \n"\ " \n"\ "mul r0.xyz, r0, r3 ; total luminance * base color \n"\ "+mov r0.a, v0.a ; write original alpha value \n"\ "\n"; CD3D8ParallaxMapRenderer::CD3D8ParallaxMapRenderer( IDirect3DDevice8* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial) : CD3D8ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial), CompiledShaders(true), CurrentScale(0.0f) { #ifdef _DEBUG setDebugName("CD3D8ParallaxMapRenderer"); #endif // set this as callback. We could have done this in // the initialization list, but some compilers don't like it. CallBack = this; // basicly, this thing simply compiles these hardcoded shaders if the // hardware is able to do them, otherwise it maps to the base material if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) || !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1)) { // this hardware is not able to do shaders. Fall back to // base material. outMaterialTypeNr = driver->addMaterialRenderer(this); return; } // check if already compiled parallax map shaders are there. video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_PARALLAX_MAP_SOLID); if (renderer) { // use the already compiled shaders video::CD3D8ParallaxMapRenderer* nmr = (video::CD3D8ParallaxMapRenderer*)renderer; CompiledShaders = false; VertexShader = nmr->VertexShader; PixelShader = nmr->PixelShader; outMaterialTypeNr = driver->addMaterialRenderer(this); } else { // compile shaders on our own init(outMaterialTypeNr, D3D8_PARALLAX_MAP_VSH, D3D8_PARALLAX_MAP_PSH, EVT_TANGENTS); } // something failed, use base material if (-1==outMaterialTypeNr) driver->addMaterialRenderer(this); } CD3D8ParallaxMapRenderer::~CD3D8ParallaxMapRenderer() { if (CallBack == this) CallBack = 0; if (!CompiledShaders) { // prevent this from deleting shaders we did not create VertexShader = 0; PixelShader = 0; } } bool CD3D8ParallaxMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { if (vtxtype != video::EVT_TANGENTS) { os::Printer::log("Error: Normal map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR); return false; } return CD3D8ShaderMaterialRenderer::OnRender(service, vtxtype); } void CD3D8ParallaxMapRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services) { CD3D8ShaderMaterialRenderer::OnSetMaterial(material, lastMaterial, resetAllRenderstates, services); CurrentScale = material.MaterialTypeParam; } //! Returns the render capability of the material. s32 CD3D8ParallaxMapRenderer::getRenderCapability() const { if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) && Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1)) return 0; return 1; } //! Called by the engine when the vertex and/or pixel shader constants //! for an material renderer should be set. void CD3D8ParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData) { video::IVideoDriver* driver = services->getVideoDriver(); // set transposed world matrix services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4); // set eye position // The viewpoint is at (0., 0., 0.) in eye space. // Turning this into a vector [0 0 0 1] and multiply it by // the inverse of the view matrix, the resulting vector is the // object space location of the camera. f32 floats[4] = {0,0,0,1}; core::matrix4 minv(driver->getTransform(video::ETS_VIEW)); minv.makeInverse(); minv.multiplyWith1x4Matrix(floats); services->setVertexShaderConstant(floats, 4, 1); // set transposed worldViewProj matrix core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION)); worldViewProj *= driver->getTransform(video::ETS_VIEW); worldViewProj *= driver->getTransform(video::ETS_WORLD); services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4); // here we've got to fetch the fixed function lights from the driver // and set them as constants const u32 cnt = driver->getDynamicLightCount(); for (u32 i=0; i<2; ++i) { SLight light; if (igetDynamicLight(i); else { light.DiffuseColor.set(0,0,0); // make light dark light.Radius = 1.0f; } light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation services->setVertexShaderConstant(reinterpret_cast(&light.Position), 12+(i*2), 1); services->setVertexShaderConstant(reinterpret_cast(&light.DiffuseColor), 13+(i*2), 1); } // this is not really necessary in d3d9 (used a def instruction), but to be sure: f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f}; services->setVertexShaderConstant(c95, 95, 1); f32 c96[] = {-1, 1, 1, 1}; services->setVertexShaderConstant(c96, 96, 1); // set scale factor f32 factor = 0.02f; // default value if (CurrentScale != 0) factor = CurrentScale; f32 c6[] = {factor, factor, factor, 0}; services->setPixelShaderConstant(c6, 6, 1); } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ irrlicht-1.8.3/source/Irrlicht/CD3D8NormalMapRenderer.h0000644000000000000000000000273712574354552021362 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_D3D8_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__ #define __C_D3D8_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_WINDOWS_API_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ #include #include "CD3D8ShaderMaterialRenderer.h" #include "IShaderConstantSetCallBack.h" namespace irr { namespace video { //! Renderer for normal maps class CD3D8NormalMapRenderer : public CD3D8ShaderMaterialRenderer, IShaderConstantSetCallBack { public: CD3D8NormalMapRenderer( IDirect3DDevice8* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial); ~CD3D8NormalMapRenderer(); //! Called by the engine when the vertex and/or pixel shader constants for an //! material renderer should be set. virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData); bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); //! Returns the render capability of the material. virtual s32 getRenderCapability() const; private: //! stores if this shader compiled the shaders and is //! allowed to delete them again. D3D8 lacks reference counting //! support for shaders. bool CompiledShaders; }; } // end namespace video } // end namespace irr #endif #endif #endif irrlicht-1.8.3/source/Irrlicht/CD3D8NormalMapRenderer.cpp0000644000000000000000000002064612574354552021714 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ #include "CD3D8NormalMapRenderer.h" #include "IMaterialRendererServices.h" #include "IVideoDriver.h" #include "os.h" #include "SLight.h" namespace irr { namespace video { // 1.1 Shaders with two lights and vertex based attenuation // Irrlicht Engine D3D8 render path normal map vertex shader const char D3D8_NORMAL_MAP_VSH[] = ";Irrlicht Engine 0.8 D3D8 render path normal map vertex shader\n"\ "; c0-3: Transposed world matrix \n"\ "; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\ "; c12: Light01 position \n"\ "; c13: x,y,z: Light01 color; .w: 1/LightRadius² \n"\ "; c14: Light02 position \n"\ "; c15: x,y,z: Light02 color; .w: 1/LightRadius² \n"\ "\n"\ "; v0 - position \n"\ "; v1 - normal \n"\ "; v2 - color \n"\ "; v3 - texture coord \n"\ "; v4 - tangent \n"\ "; v5 - binormal \n"\ "\n"\ "vs.1.1\n"\ "\n"\ "m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\ "\n"\ "m3x3 r5, v4, c0 ; transform tangent U\n"\ "m3x3 r7, v1, c0 ; transform normal W\n"\ "m3x3 r6, v5, c0 ; transform binormal V\n"\ "\n"\ "m4x4 r4, v0, c0 ; vertex into world position\n"\ "add r2, c12, -r4 ; vtxpos - lightpos1\n"\ "add r3, c14, -r4 ; vtxpos - lightpos2\n"\ "\n"\ "dp3 r8.x, r5, r2 ; transform the light vector 1 with U, V, W\n"\ "dp3 r8.y, r6, r2 \n"\ "dp3 r8.z, r7, r2 \n"\ "dp3 r9.x, r5, r3 ; transform the light vector 2 with U, V, W\n"\ "dp3 r9.y, r6, r3 \n"\ "dp3 r9.z, r7, r3 \n"\ "\n"\ "dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\ "rsq r8.w, r8.w \n"\ "mul r8, r8, r8.w \n"\ "dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\ "rsq r9.w, r9.w \n"\ "mul r9, r9, r9.w \n"\ "\n"\ "mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\ "mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\ "\n"\ " ; calculate attenuation of light 1 \n"\ "dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x² + r2.y² + r2.z² \n"\ "mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\ "rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\ "mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\ "\n"\ " ; calculate attenuation of light 2 \n"\ "dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x² + r3.y² + r3.z² \n"\ "mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\ "rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\ "mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\ "\n"\ "mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\ "mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\ "mov oD0.a, v2.a ; move out original alpha value \n"\ "\n"; // Irrlicht Engine D3D8 render path normal map pixel shader const char D3D8_NORMAL_MAP_PSH[] = ";Irrlicht Engine 0.8 D3D8 render path normal map pixel shader\n"\ ";Input: \n"\ ";t0: color map texture coord \n"\ ";t1: normal map texture coords \n"\ ";t2: light 1 vector in tangent space \n"\ ";v0: light 1 color \n"\ ";t3: light 2 vector in tangent space \n"\ ";v1: light 2 color \n"\ ";v0.a: vertex alpha value \n"\ "ps.1.1 \n"\ "tex t0 ; sample color map \n"\ "tex t1 ; sample normal map\n"\ "texcoord t2 ; fetch light vector 1\n"\ "texcoord t3 ; fetch light vector 2\n"\ "\n"\ "dp3_sat r0, t1_bx2, t2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1)\n"\ "mul r0, r0, v0 ; luminance1 * light color 1 \n"\ "\n"\ "dp3_sat r1, t1_bx2, t3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1)\n"\ "mad r0, r1, v1, r0 ; (luminance2 * light color 2) + luminance 1 \n"\ "\n"\ "mul r0, t0, r0 ; total luminance * base color\n"\ "mov r0.a, v0.a ; write interpolated vertex alpha value \n"\ "\n"\ ""; CD3D8NormalMapRenderer::CD3D8NormalMapRenderer( IDirect3DDevice8* d3ddev, video::IVideoDriver* driver, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial) : CD3D8ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial), CompiledShaders(true) { #ifdef _DEBUG setDebugName("CD3D8NormalMapRenderer"); #endif // set this as callback. We could have done this in // the initialization list, but some compilers don't like it. CallBack = this; // basicly, this thing simply compiles these hardcoded shaders if the // hardware is able to do them, otherwise it maps to the base material if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) || !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1)) { // this hardware is not able to do shaders. Fall back to // base material. outMaterialTypeNr = driver->addMaterialRenderer(this); return; } // check if already compiled normal map shaders are there. video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_NORMAL_MAP_SOLID); if (renderer) { // use the already compiled shaders video::CD3D8NormalMapRenderer* nmr = (video::CD3D8NormalMapRenderer*)renderer; CompiledShaders = false; VertexShader = nmr->VertexShader; PixelShader = nmr->PixelShader; outMaterialTypeNr = driver->addMaterialRenderer(this); } else { // compile shaders on our own init(outMaterialTypeNr, D3D8_NORMAL_MAP_VSH, D3D8_NORMAL_MAP_PSH, EVT_TANGENTS); } // something failed, use base material if (-1==outMaterialTypeNr) driver->addMaterialRenderer(this); } CD3D8NormalMapRenderer::~CD3D8NormalMapRenderer() { if (CallBack == this) CallBack = 0; if (!CompiledShaders) { // prevent this from deleting shaders we did not create VertexShader = 0; PixelShader = 0; } } bool CD3D8NormalMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { if (vtxtype != video::EVT_TANGENTS) { os::Printer::log("Error: Normal map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR); return false; } return CD3D8ShaderMaterialRenderer::OnRender(service, vtxtype); } //! Returns the render capability of the material. s32 CD3D8NormalMapRenderer::getRenderCapability() const { if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) && Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1)) return 0; return 1; } //! Called by the engine when the vertex and/or pixel shader constants for an //! material renderer should be set. void CD3D8NormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData) { video::IVideoDriver* driver = services->getVideoDriver(); // set transposed world matrix services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4); // set transposed worldViewProj matrix core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION)); worldViewProj *= driver->getTransform(video::ETS_VIEW); worldViewProj *= driver->getTransform(video::ETS_WORLD); services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4); // here we've got to fetch the fixed function lights from the // driver and set them as constants u32 cnt = driver->getDynamicLightCount(); for (u32 i=0; i<2; ++i) { SLight light; if (igetDynamicLight(i); else { light.DiffuseColor.set(0,0,0); // make light dark light.Radius = 1.0f; } light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation services->setVertexShaderConstant(reinterpret_cast(&light.Position), 12+(i*2), 1); services->setVertexShaderConstant(reinterpret_cast(&light.DiffuseColor), 13+(i*2), 1); } f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f}; services->setVertexShaderConstant(c95, 95, 1); } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ irrlicht-1.8.3/source/Irrlicht/CD3D8MaterialRenderer.h0000644000000000000000000004625712574354552021237 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_D3D8_MATERIAL_RENDERER_H_INCLUDED__ #define __C_D3D8_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_WINDOWS_API_ #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ #include #include "IMaterialRenderer.h" namespace irr { namespace video { namespace { D3DMATRIX UnitMatrixD3D8; D3DMATRIX SphereMapMatrixD3D8; inline void setTextureColorStage(IDirect3DDevice8* dev, DWORD i, DWORD arg1, DWORD op, DWORD arg2) { dev->SetTextureStageState(i, D3DTSS_COLOROP, op); dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1); dev->SetTextureStageState(i, D3DTSS_COLORARG2, arg2); } inline void setTextureColorStage(IDirect3DDevice8* dev, DWORD i, DWORD arg1) { dev->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_SELECTARG1); dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1); } inline void setTextureAlphaStage(IDirect3DDevice8* dev, DWORD i, DWORD arg1, DWORD op, DWORD arg2) { dev->SetTextureStageState(i, D3DTSS_ALPHAOP, op); dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1); dev->SetTextureStageState(i, D3DTSS_ALPHAARG2, arg2); } inline void setTextureAlphaStage(IDirect3DDevice8* dev, DWORD i, DWORD arg1) { dev->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1); } } // anonymous namespace //! Base class for all internal D3D8 material renderers class CD3D8MaterialRenderer : public IMaterialRenderer { public: //! Constructor CD3D8MaterialRenderer(IDirect3DDevice8* d3ddev, video::IVideoDriver* driver) : pID3DDevice(d3ddev), Driver(driver) { } protected: IDirect3DDevice8* pID3DDevice; video::IVideoDriver* Driver; }; //! Solid material renderer class CD3D8MaterialRenderer_SOLID : public CD3D8MaterialRenderer { public: CD3D8MaterialRenderer_SOLID(IDirect3DDevice8* p, video::IVideoDriver* d) : CD3D8MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); } pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } }; //! Generic Texture Blend class CD3D8MaterialRenderer_ONETEXTURE_BLEND : public CD3D8MaterialRenderer { public: CD3D8MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice8* p, video::IVideoDriver* d) : CD3D8MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || material.MaterialTypeParam != lastMaterial.MaterialTypeParam || resetAllRenderstates) { E_BLEND_FACTOR srcFact,dstFact; E_MODULATE_FUNC modulate; u32 alphaSource; unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam ); if (srcFact == EBF_SRC_COLOR && dstFact == EBF_ZERO) { pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } else { pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, getD3DBlend ( srcFact ) ); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, getD3DBlend ( dstFact ) ); } setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, getD3DModulate(modulate), D3DTA_DIFFUSE); if ( alphaSource && (textureBlendFunc_hasAlpha ( srcFact ) || textureBlendFunc_hasAlpha ( dstFact ) )) { if (alphaSource==EAS_VERTEX_COLOR) { setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE); } else if (alphaSource==EAS_TEXTURE) { setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE); } else { setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); } } pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); } } //! Returns if the material is transparent. /** The scene management needs to know this for being able to sort the materials by opaque and transparent. The return value could be optimized, but we'd need to know the MaterialTypeParam for it. */ virtual bool isTransparent() const { return true; } private: u32 getD3DBlend ( E_BLEND_FACTOR factor ) const { u32 r = 0; switch ( factor ) { case EBF_ZERO: r = D3DBLEND_ZERO; break; case EBF_ONE: r = D3DBLEND_ONE; break; case EBF_DST_COLOR: r = D3DBLEND_DESTCOLOR; break; case EBF_ONE_MINUS_DST_COLOR: r = D3DBLEND_INVDESTCOLOR; break; case EBF_SRC_COLOR: r = D3DBLEND_SRCCOLOR; break; case EBF_ONE_MINUS_SRC_COLOR: r = D3DBLEND_INVSRCCOLOR; break; case EBF_SRC_ALPHA: r = D3DBLEND_SRCALPHA; break; case EBF_ONE_MINUS_SRC_ALPHA: r = D3DBLEND_INVSRCALPHA; break; case EBF_DST_ALPHA: r = D3DBLEND_DESTALPHA; break; case EBF_ONE_MINUS_DST_ALPHA: r = D3DBLEND_INVDESTALPHA; break; case EBF_SRC_ALPHA_SATURATE: r = D3DBLEND_SRCALPHASAT; break; } return r; } u32 getD3DModulate ( E_MODULATE_FUNC func ) const { u32 r = D3DTOP_MODULATE; switch ( func ) { case EMFN_MODULATE_1X: r = D3DTOP_MODULATE; break; case EMFN_MODULATE_2X: r = D3DTOP_MODULATE2X; break; case EMFN_MODULATE_4X: r = D3DTOP_MODULATE4X; break; } return r; } }; //! Solid 2 layer material renderer class CD3D8MaterialRenderer_SOLID_2_LAYER : public CD3D8MaterialRenderer { public: CD3D8MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice8* p, video::IVideoDriver* d) : CD3D8MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } } }; //! Transparent add color material renderer class CD3D8MaterialRenderer_TRANSPARENT_ADD_COLOR : public CD3D8MaterialRenderer { public: CD3D8MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice8* p, video::IVideoDriver* d) : CD3D8MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR); } } //! Returns if the material is transparent. The scene management needs to know this //! for being able to sort the materials by opaque and transparent. virtual bool isTransparent() const { return true; } }; //! Transparent vertex alpha material renderer class CD3D8MaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public CD3D8MaterialRenderer { public: CD3D8MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice8* p, video::IVideoDriver* d) : CD3D8MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); } } //! Returns if the material is transparent. The scene managment needs to know this //! for being able to sort the materials by opaque and transparent. virtual bool isTransparent() const { return true; } }; //! Transparent alpha channel material renderer class CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public CD3D8MaterialRenderer { public: CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice8* p, video::IVideoDriver* d) : CD3D8MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates || material.MaterialTypeParam != lastMaterial.MaterialTypeParam ) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT); setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); pID3DDevice->SetRenderState(D3DRS_ALPHAREF, core::floor32(material.MaterialTypeParam * 255.f)); pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); } } virtual void OnUnsetMaterial() { pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); } //! Returns if the material is transparent. The scene managment needs to know this //! for being able to sort the materials by opaque and transparent. virtual bool isTransparent() const { return true; } }; //! Transparent alpha channel material renderer class CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public CD3D8MaterialRenderer { public: CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice8* p, video::IVideoDriver* d) : CD3D8MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT); setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); // 127 is required by EMT_TRANSPARENT_ALPHA_CHANNEL_REF pID3DDevice->SetRenderState(D3DRS_ALPHAREF, 127); pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); } } virtual void OnUnsetMaterial() { pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); } //! Returns if the material is transparent. The scene managment needs to know this //! for being able to sort the materials by opaque and transparent. virtual bool isTransparent() const { return false; // this material is not really transparent because it does no blending. } }; //! material renderer for all kinds of lightmaps class CD3D8MaterialRenderer_LIGHTMAP : public CD3D8MaterialRenderer { public: CD3D8MaterialRenderer_LIGHTMAP(IDirect3DDevice8* p, video::IVideoDriver* d) : CD3D8MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { if (material.MaterialType >= EMT_LIGHTMAP_LIGHTING) { // with lighting setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); } else { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE); } pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1); setTextureColorStage(pID3DDevice, 1, D3DTA_TEXTURE, (material.MaterialType == EMT_LIGHTMAP_ADD)? D3DTOP_ADD: (material.MaterialType == EMT_LIGHTMAP_M4 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M4)? D3DTOP_MODULATE4X: (material.MaterialType == EMT_LIGHTMAP_M2 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M2)? D3DTOP_MODULATE2X: D3DTOP_MODULATE, D3DTA_CURRENT); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } } }; //! material renderer for detail maps class CD3D8MaterialRenderer_DETAIL_MAP : public CD3D8MaterialRenderer { public: CD3D8MaterialRenderer_DETAIL_MAP(IDirect3DDevice8* p, video::IVideoDriver* d) : CD3D8MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); setTextureColorStage(pID3DDevice, 1, D3DTA_TEXTURE, D3DTOP_ADDSIGNED, D3DTA_CURRENT); pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } } }; //! sphere map material renderer class CD3D8MaterialRenderer_SPHERE_MAP : public CD3D8MaterialRenderer { public: CD3D8MaterialRenderer_SPHERE_MAP(IDirect3DDevice8* p, video::IVideoDriver* d) : CD3D8MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); pID3DDevice->SetTransform( D3DTS_TEXTURE0, &SphereMapMatrixD3D8 ); pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL ); } } virtual void OnUnsetMaterial() { pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0); pID3DDevice->SetTransform( D3DTS_TEXTURE0, &UnitMatrixD3D8 ); } }; //! reflection 2 layer material renderer class CD3D8MaterialRenderer_REFLECTION_2_LAYER : public CD3D8MaterialRenderer { public: CD3D8MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice8* p, video::IVideoDriver* d) : CD3D8MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); setTextureColorStage(pID3DDevice, 1, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT); pID3DDevice->SetTransform( D3DTS_TEXTURE1, &SphereMapMatrixD3D8 ); pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } } virtual void OnUnsetMaterial() { pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1); pID3DDevice->SetTransform( D3DTS_TEXTURE1, &UnitMatrixD3D8 ); } }; //! reflection 2 layer material renderer class CD3D8MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public CD3D8MaterialRenderer { public: CD3D8MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice8* p, video::IVideoDriver* d) : CD3D8MaterialRenderer(p, d) {} virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) { services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE); setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE); setTextureColorStage(pID3DDevice, 1, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT); setTextureAlphaStage(pID3DDevice, 1, D3DTA_CURRENT); pID3DDevice->SetTransform(D3DTS_TEXTURE1, &SphereMapMatrixD3D8 ); pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); } } virtual void OnUnsetMaterial() { pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1); pID3DDevice->SetTransform(D3DTS_TEXTURE1, &UnitMatrixD3D8); } //! Returns if the material is transparent. The scene managment needs to know this //! for being able to sort the materials by opaque and transparent. virtual bool isTransparent() const { return true; } }; } // end namespace video } // end namespace irr #endif #endif #endif irrlicht-1.8.3/source/Irrlicht/CD3D8Driver.h0000644000000000000000000003136312574354552017235 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_VIDEO_DIRECTX_8_H_INCLUDED__ #define __C_VIDEO_DIRECTX_8_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ #ifdef _IRR_WINDOWS_ #define WIN32_LEAN_AND_MEAN #include #endif #include "SIrrCreationParameters.h" // always included for static createDriver function #include "CNullDriver.h" #include "IMaterialRendererServices.h" #include namespace irr { namespace video { class CD3D8Driver : public CNullDriver, IMaterialRendererServices { friend class CD3D8Texture; public: //! constructor CD3D8Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io); //! destructor virtual ~CD3D8Driver(); //! applications must call this method before performing any rendering. returns false if failed. virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! applications must call this method after performing any rendering. returns false if failed. virtual bool endScene(); //! queries the features of the driver, returns true if feature is available virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const; //! sets transformation virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat); //! sets a material virtual void setMaterial(const SMaterial& material); //! sets a render target virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=video::SColor(0,0,0,0)); //! sets a viewport virtual void setViewPort(const core::rect& area); //! gets the area of the current viewport virtual const core::rect& getViewPort() const; //! draws a vertex primitive list virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); //! draws a vertex primitive list in 2d virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType); //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect = 0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false); //! Draws a part of the texture into the rectangle. virtual void draw2DImage(const video::ITexture* texture, const core::rect& destRect, const core::rect& sourceRect, const core::rect* clipRect = 0, const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false); //!Draws an 2d rectangle with a gradient. virtual void draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip = 0); //! Draws a 2d line. virtual void draw2DLine(const core::position2d& start, const core::position2d& end, SColor color=SColor(255,255,255,255)); //! Draws a pixel. virtual void drawPixel(u32 x, u32 y, const SColor & color); //! Draws a 3d line. virtual void draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color = SColor(255,255,255,255)); //! initialises the Direct3D API bool initDriver(HWND hwnd, bool pureSoftware); //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8 //! driver, it would return "Direct3D8.1". virtual const wchar_t* getName() const; //! deletes all dynamic lights there are virtual void deleteAllDynamicLights(); //! adds a dynamic light, returning an index to the light //! \param light: the light data to use to create the light //! \return An index to the light, or -1 if an error occurs virtual s32 addDynamicLight(const SLight& light); //! Turns a dynamic light on or off //! \param lightIndex: the index returned by addDynamicLight //! \param turnOn: true to turn the light on, false to turn it off virtual void turnLightOn(s32 lightIndex, bool turnOn); //! returns the maximal amount of dynamic lights the device can handle virtual u32 getMaximalDynamicLightAmount() const; //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. virtual void setAmbientLight(const SColorf& color); //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do //! this: Frist, draw all geometry. Then use this method, to draw the shadow //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. virtual void drawStencilShadowVolume(const core::array& triangles, bool zfail=true, u32 debugDataVisible=0); //! Fills the stencil shadow with color. After the shadow volume has been drawn //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this //! to draw the color of the shadow. virtual void drawStencilShadow(bool clearStencilBuffer=false, video::SColor leftUpEdge = video::SColor(0,0,0,0), video::SColor rightUpEdge = video::SColor(0,0,0,0), video::SColor leftDownEdge = video::SColor(0,0,0,0), video::SColor rightDownEdge = video::SColor(0,0,0,0)); //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. virtual u32 getMaximalPrimitiveCount() const; //! Enables or disables a texture creation flag. virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled); //! Sets the fog mode. virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog); //! Only used by the internal engine. Used to notify the driver that //! the window was resized. virtual void OnResize(const core::dimension2d& size); //! Returns type of video driver virtual E_DRIVER_TYPE getDriverType() const; //! Returns the transformation set by setTransform virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const; //! Can be called by an IMaterialRenderer to make its work easier. virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates); //! Sets a vertex shader constant. virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1); //! Sets a pixel shader constant. virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1); //! Sets a constant for the vertex shader based on a name. virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count); //! Bool interface for the above. virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count); //! Int interface for the above. virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count); //! Sets a constant for the pixel shader based on a name. virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count); //! Bool interface for the above. virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count); //! Int interface for the above. virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count); //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) virtual IVideoDriver* getVideoDriver(); //! Creates a render target texture. virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN); //! Clears the ZBuffer. virtual void clearZBuffer(); //! Returns an image created from the last rendered frame. virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER); //! Set/unset a clipping plane. //! There are at least 6 clipping planes available for the user to set at will. //! \param index: The plane index. Must be between 0 and MaxUserClipPlanes. //! \param plane: The plane itself. //! \param enable: If true, enable the clipping plane else disable it. virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false); //! Enable/disable a clipping plane. //! There are at least 6 clipping planes available for the user to set at will. //! \param index: The plane index. Must be between 0 and MaxUserClipPlanes. //! \param enable: If true, enable the clipping plane else disable it. virtual void enableClipPlane(u32 index, bool enable); //! Returns the maximum texture size supported. virtual core::dimension2du getMaxTextureSize() const; virtual bool checkDriverReset() {return DriverWasReset;} private: // enumeration for rendering modes such as 2d and 3d for minizing the switching of renderStates. enum E_RENDER_MODE { ERM_NONE = 0, // no render state has been set yet. ERM_2D, // 2d drawing rendermode ERM_3D, // 3d rendering mode ERM_STENCIL_FILL, // stencil fill mode ERM_SHADOW_VOLUME_ZFAIL, // stencil volume draw mode ERM_SHADOW_VOLUME_ZPASS // stencil volume draw mode }; //! sets right vertex shader void setVertexShader(video::E_VERTEX_TYPE newType); //! sets the needed renderstates bool setRenderStates3DMode(); //! sets the needed renderstates void setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel); //! sets the needed renderstates void setRenderStatesStencilFillMode(bool alpha); //! sets the needed renderstates void setRenderStatesStencilShadowMode(bool zfail, u32 debugDataVisible); //! sets the current Texture bool setActiveTexture(u32 stage, const video::ITexture* texture); //! resets the device bool reset(); //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); // returns the current size of the screen or rendertarget virtual const core::dimension2d& getCurrentRenderTargetSize() const; //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. s32 addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData); void createMaterialRenderers(); void draw2D3DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType, bool is3D); D3DTEXTUREADDRESS getTextureWrapMode(const u8 clamp); inline D3DCOLORVALUE colorToD3D(const SColor& col) { const f32 f = 1.0f / 255.0f; D3DCOLORVALUE v; v.r = col.getRed() * f; v.g = col.getGreen() * f; v.b = col.getBlue() * f; v.a = col.getAlpha() * f; return v; } E_RENDER_MODE CurrentRenderMode; D3DPRESENT_PARAMETERS present; SMaterial Material, LastMaterial; bool ResetRenderStates; // bool to make all renderstates be reseted if set. bool Transformation3DChanged; const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES]; core::matrix4 Matrices[ETS_COUNT]; // matrices of the 3d mode we need to restore when we switch back from the 2d mode. HINSTANCE D3DLibrary; IDirect3D8* pID3D; IDirect3DDevice8* pID3DDevice; IDirect3DSurface8* PrevRenderTarget; core::dimension2d CurrentRendertargetSize; HWND WindowId; core::rect* SceneSourceRect; D3DCAPS8 Caps; E_VERTEX_TYPE LastVertexType; D3DMATRIX UnitMatrix; u32 MaxTextureUnits; u32 MaxUserClipPlanes; f32 MaxLightDistance; s32 LastSetLight; bool DeviceLost; bool DriverWasReset; SColorf AmbientLight; SIrrlichtCreationParameters Params; }; } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ #endif // __C_VIDEO_DIRECTX_8_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CD3D8Driver.cpp0000644000000000000000000023057312574354552017574 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE #include "CD3D8Driver.h" #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ #include "os.h" #include "S3DVertex.h" #include "CD3D8Texture.h" #include "CD3D8MaterialRenderer.h" #include "CD3D8ShaderMaterialRenderer.h" #include "CD3D8NormalMapRenderer.h" #include "CD3D8ParallaxMapRenderer.h" #include "SIrrCreationParameters.h" namespace irr { namespace video { //! constructor CD3D8Driver::CD3D8Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io) : CNullDriver(io, params.WindowSize), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(false), D3DLibrary(0), pID3D(0), pID3DDevice(0), PrevRenderTarget(0), WindowId(0), SceneSourceRect(0), LastVertexType((video::E_VERTEX_TYPE)-1), MaxTextureUnits(0), MaxUserClipPlanes(0), MaxLightDistance(0), LastSetLight(-1), DeviceLost(false), DriverWasReset(true), Params(params) { #ifdef _DEBUG setDebugName("CD3D8Driver"); #endif printVersion(); for (u32 i=0; iRelease(); if (pID3D) pID3D->Release(); } void CD3D8Driver::createMaterialRenderers() { // create D3D8 material renderers addAndDropMaterialRenderer(new CD3D8MaterialRenderer_SOLID(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D8MaterialRenderer_SOLID_2_LAYER(pID3DDevice, this)); // add the same renderer for all lightmap types CD3D8MaterialRenderer_LIGHTMAP* lmr = new CD3D8MaterialRenderer_LIGHTMAP(pID3DDevice, this); addMaterialRenderer(lmr); // for EMT_LIGHTMAP: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_ADD: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M2: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M4: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M2: addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M4: lmr->drop(); // add remaining material renderers addAndDropMaterialRenderer(new CD3D8MaterialRenderer_DETAIL_MAP(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D8MaterialRenderer_SPHERE_MAP(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D8MaterialRenderer_REFLECTION_2_LAYER(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D8MaterialRenderer_TRANSPARENT_ADD_COLOR(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D8MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(pID3DDevice, this)); addAndDropMaterialRenderer(new CD3D8MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(pID3DDevice, this)); // add normal map renderers s32 tmp = 0; video::IMaterialRenderer* renderer = 0; renderer = new CD3D8NormalMapRenderer(pID3DDevice, this, tmp, MaterialRenderers[EMT_SOLID].Renderer); renderer->drop(); renderer = new CD3D8NormalMapRenderer(pID3DDevice, this, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer); renderer->drop(); renderer = new CD3D8NormalMapRenderer(pID3DDevice, this, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); renderer->drop(); // add parallax map renderers renderer = new CD3D8ParallaxMapRenderer(pID3DDevice, this, tmp, MaterialRenderers[EMT_SOLID].Renderer); renderer->drop(); renderer = new CD3D8ParallaxMapRenderer(pID3DDevice, this, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer); renderer->drop(); renderer = new CD3D8ParallaxMapRenderer(pID3DDevice, this, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); renderer->drop(); // add basic 1 texture blending addAndDropMaterialRenderer(new CD3D8MaterialRenderer_ONETEXTURE_BLEND(pID3DDevice, this)); } //! initialises the Direct3D API bool CD3D8Driver::initDriver(HWND hwnd, bool pureSoftware) { HRESULT hr; typedef IDirect3D8 * (__stdcall *D3DCREATETYPE)(UINT); #if defined( _IRR_XBOX_PLATFORM_) D3DCREATETYPE d3dCreate = (D3DCREATETYPE) &Direct3DCreate8; #else D3DLibrary = LoadLibrary( __TEXT("d3d8.dll") ); if (!D3DLibrary) { os::Printer::log("Error, could not load d3d8.dll.", ELL_ERROR); return false; } D3DCREATETYPE d3dCreate = (D3DCREATETYPE) GetProcAddress(D3DLibrary, "Direct3DCreate8"); if (!d3dCreate) { os::Printer::log("Error, could not get proc adress of Direct3DCreate8.", ELL_ERROR); return false; } #endif //just like pID3D = Direct3DCreate8(D3D_SDK_VERSION); pID3D = (*d3dCreate)(D3D_SDK_VERSION); if (!pID3D) { os::Printer::log("Error initializing D3D.", ELL_ERROR); return false; } // print device information D3DADAPTER_IDENTIFIER8 dai; if (!FAILED(pID3D->GetAdapterIdentifier(Params.DisplayAdapter, D3DENUM_NO_WHQL_LEVEL, &dai))) { char tmp[512]; s32 Product = HIWORD(dai.DriverVersion.HighPart); s32 Version = LOWORD(dai.DriverVersion.HighPart); s32 SubVersion = HIWORD(dai.DriverVersion.LowPart); s32 Build = LOWORD(dai.DriverVersion.LowPart); sprintf(tmp, "%s %s %d.%d.%d.%d", dai.Description, dai.Driver, Product, Version, SubVersion, Build); os::Printer::log(tmp, ELL_INFORMATION); } D3DDISPLAYMODE d3ddm; hr = pID3D->GetAdapterDisplayMode(Params.DisplayAdapter, &d3ddm); if (FAILED(hr)) { os::Printer::log("Error: Could not get Adapter Display mode.", ELL_ERROR); return false; } ZeroMemory(&present, sizeof(present)); present.SwapEffect = D3DSWAPEFFECT_DISCARD; present.Windowed = TRUE; present.BackBufferFormat = d3ddm.Format; present.EnableAutoDepthStencil = TRUE; if (Params.Fullscreen) { present.SwapEffect = D3DSWAPEFFECT_FLIP; present.Windowed = FALSE; present.BackBufferWidth = Params.WindowSize.Width; present.BackBufferHeight = Params.WindowSize.Height; present.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; if (Params.Vsync) present.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; else present.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; if (Params.Bits == 32) present.BackBufferFormat = D3DFMT_X8R8G8B8; else present.BackBufferFormat = D3DFMT_R5G6B5; } D3DDEVTYPE devtype = D3DDEVTYPE_HAL; #ifndef _IRR_D3D_NO_SHADER_DEBUGGING devtype = D3DDEVTYPE_REF; #endif // enable anti alias if possible and whished if (Params.AntiAlias > 0) { if(Params.AntiAlias > 16) Params.AntiAlias = 16; while(Params.AntiAlias > 0) { if(!FAILED(pID3D->CheckDeviceMultiSampleType(Params.DisplayAdapter, devtype , present.BackBufferFormat, !Params.Fullscreen, (D3DMULTISAMPLE_TYPE)Params.AntiAlias))) { present.MultiSampleType = (D3DMULTISAMPLE_TYPE)Params.AntiAlias; present.SwapEffect = D3DSWAPEFFECT_DISCARD; break; } --Params.AntiAlias; } if(Params.AntiAlias==0) os::Printer::log("Anti aliasing disabled because hardware/driver lacks necessary caps.", ELL_WARNING); } // check stencil buffer compatibility if (Params.Stencilbuffer) { present.AutoDepthStencilFormat = D3DFMT_D24S8; if(FAILED(pID3D->CheckDeviceFormat(Params.DisplayAdapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { #if !defined( _IRR_XBOX_PLATFORM_) present.AutoDepthStencilFormat = D3DFMT_D24X4S4; if(FAILED(pID3D->CheckDeviceFormat(Params.DisplayAdapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { present.AutoDepthStencilFormat = D3DFMT_D15S1; if(FAILED(pID3D->CheckDeviceFormat(Params.DisplayAdapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { os::Printer::log("Device does not support stencilbuffer, disabling stencil buffer.", ELL_WARNING); Params.Stencilbuffer = false; } } #endif } else if(FAILED(pID3D->CheckDepthStencilMatch(Params.DisplayAdapter, devtype, present.BackBufferFormat, present.BackBufferFormat, present.AutoDepthStencilFormat))) { os::Printer::log("Depth-stencil format is not compatible with display format, disabling stencil buffer.", ELL_WARNING); Params.Stencilbuffer = false; } } // do not use else here to cope with flag change in previous block if (!Params.Stencilbuffer) { #if !defined( _IRR_XBOX_PLATFORM_) present.AutoDepthStencilFormat = D3DFMT_D32; if(FAILED(pID3D->CheckDeviceFormat(Params.DisplayAdapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { present.AutoDepthStencilFormat = D3DFMT_D24X8; if(FAILED(pID3D->CheckDeviceFormat(Params.DisplayAdapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { present.AutoDepthStencilFormat = D3DFMT_D16; if(FAILED(pID3D->CheckDeviceFormat(Params.DisplayAdapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { os::Printer::log("Device does not support required depth buffer.", ELL_WARNING); return false; } } } #else present.AutoDepthStencilFormat = D3DFMT_D16; if(FAILED(pID3D->CheckDeviceFormat(Params.DisplayAdapter, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { os::Printer::log("Device does not support required depth buffer.", ELL_WARNING); return false; } #endif } // create device #if defined( _IRR_XBOX_PLATFORM_) DWORD fpuPrecision = 0; #else DWORD fpuPrecision = Params.HighPrecisionFPU ? D3DCREATE_FPU_PRESERVE : 0; DWORD multithreaded = Params.DriverMultithreaded ? D3DCREATE_MULTITHREADED : 0; #endif if (pureSoftware) { hr = pID3D->CreateDevice(Params.DisplayAdapter, D3DDEVTYPE_REF, hwnd, fpuPrecision | multithreaded | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &pID3DDevice); if (FAILED(hr)) os::Printer::log("Was not able to create Direct3D8 software device.", ELL_ERROR); } else { hr = pID3D->CreateDevice(Params.DisplayAdapter, devtype, hwnd, fpuPrecision | multithreaded | D3DCREATE_HARDWARE_VERTEXPROCESSING, &present, &pID3DDevice); if(FAILED(hr)) hr = pID3D->CreateDevice(Params.DisplayAdapter, devtype, hwnd, fpuPrecision | multithreaded | D3DCREATE_MIXED_VERTEXPROCESSING , &present, &pID3DDevice); if(FAILED(hr)) hr = pID3D->CreateDevice(Params.DisplayAdapter, devtype, hwnd, fpuPrecision | multithreaded | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &pID3DDevice); if (FAILED(hr)) os::Printer::log("Was not able to create Direct3D8 device.", ELL_ERROR); } if (!pID3DDevice) { os::Printer::log("Was not able to create Direct3D8 device.", ELL_ERROR); return false; } // get caps pID3DDevice->GetDeviceCaps(&Caps); if (Params.Stencilbuffer && (!(Caps.StencilCaps & D3DSTENCILCAPS_DECRSAT) || !(Caps.StencilCaps & D3DSTENCILCAPS_INCRSAT) || !(Caps.StencilCaps & D3DSTENCILCAPS_KEEP))) { os::Printer::log("Device not able to use stencil buffer, disabling stencil buffer.", ELL_WARNING); Params.Stencilbuffer = false; } // set default vertex shader setVertexShader(EVT_STANDARD); // enable antialiasing if (Params.AntiAlias>0) pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); // set fog mode setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog); // set exposed data ExposedData.D3D8.D3D8 = pID3D; ExposedData.D3D8.D3DDev8 = pID3DDevice; ExposedData.D3D8.HWnd = hwnd; ResetRenderStates = true; // create materials createMaterialRenderers(); MaxTextureUnits = core::min_((u32)Caps.MaxSimultaneousTextures, MATERIAL_MAX_TEXTURES); MaxUserClipPlanes = (u32)Caps.MaxUserClipPlanes; DriverAttributes->setAttribute("MaxTextures", (s32)MaxTextureUnits); DriverAttributes->setAttribute("MaxSupportedTextures", (s32)Caps.MaxSimultaneousTextures); DriverAttributes->setAttribute("MaxLights", (s32)Caps.MaxActiveLights); DriverAttributes->setAttribute("MaxAnisotropy", (s32)Caps.MaxAnisotropy); DriverAttributes->setAttribute("MaxUserClipPlanes", (s32)Caps.MaxUserClipPlanes); DriverAttributes->setAttribute("MaxIndices", (s32)Caps.MaxVertexIndex); DriverAttributes->setAttribute("MaxTextureSize", (s32)core::min_(Caps.MaxTextureHeight,Caps.MaxTextureWidth)); DriverAttributes->setAttribute("MaxTextureLODBias", 16.f); DriverAttributes->setAttribute("Version", 800); DriverAttributes->setAttribute("ShaderLanguageVersion", (s32)Caps.VertexShaderVersion*100); DriverAttributes->setAttribute("AntiAlias", Params.AntiAlias); // set the renderstates setRenderStates3DMode(); // so far so good. return true; } //! applications must call this method before performing any rendering. returns false if failed. bool CD3D8Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, const SExposedVideoData& videoData, core::rect* sourceRect) { CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); WindowId = (HWND)videoData.D3D8.HWnd; SceneSourceRect = sourceRect; if (!pID3DDevice) return false; HRESULT hr; if (DeviceLost) { #ifndef _IRR_XBOX_PLATFORM_ if(FAILED(hr = pID3DDevice->TestCooperativeLevel())) { if (hr == D3DERR_DEVICELOST) { Sleep(100); hr = pID3DDevice->TestCooperativeLevel(); if (hr == D3DERR_DEVICELOST) return false; } if ((hr == D3DERR_DEVICENOTRESET) && !reset()) return false; } #endif } DWORD flags = 0; if (backBuffer) flags |= D3DCLEAR_TARGET; if (zBuffer) flags |= D3DCLEAR_ZBUFFER; if (Params.Stencilbuffer) flags |= D3DCLEAR_STENCIL; if (flags) { hr = pID3DDevice->Clear( 0, NULL, flags, color.color, 1.0, 0); if (FAILED(hr)) os::Printer::log("Direct3D8 clear failed.", ELL_WARNING); } hr = pID3DDevice->BeginScene(); if (FAILED(hr)) { os::Printer::log("Direct3D8 begin scene failed.", ELL_WARNING); return false; } return true; } //! applications must call this method after performing any rendering. returns false if failed. bool CD3D8Driver::endScene() { CNullDriver::endScene(); DriverWasReset=false; HRESULT hr = pID3DDevice->EndScene(); if (FAILED(hr)) { os::Printer::log("DIRECT3D8 end scene failed.", ELL_WARNING); return false; } RECT* srcRct = 0; RECT sourceRectData; if ( SceneSourceRect) { srcRct = &sourceRectData; sourceRectData.left = SceneSourceRect->UpperLeftCorner.X; sourceRectData.top = SceneSourceRect->UpperLeftCorner.Y; sourceRectData.right = SceneSourceRect->LowerRightCorner.X; sourceRectData.bottom = SceneSourceRect->LowerRightCorner.Y; } hr = pID3DDevice->Present(srcRct, NULL, WindowId, NULL); if (SUCCEEDED(hr)) return true; if (hr == D3DERR_DEVICELOST) { DeviceLost = true; os::Printer::log("DIRECT3D8 device lost.", ELL_WARNING); } else os::Printer::log("DIRECT3D8 present failed.", ELL_WARNING); return false; } //! resets the device bool CD3D8Driver::reset() { u32 i; os::Printer::log("Resetting D3D8 device.", ELL_INFORMATION); for (i=0; iisRenderTarget()) { IDirect3DTexture8* tex = ((CD3D8Texture*)(Textures[i].Surface))->getDX8Texture(); if (tex) tex->Release(); } } DriverWasReset=true; HRESULT hr = pID3DDevice->Reset(&present); for (i=0; iisRenderTarget()) ((CD3D8Texture*)(Textures[i].Surface))->createRenderTarget(); } if (FAILED(hr)) { if (hr == D3DERR_DEVICELOST) { DeviceLost = true; os::Printer::log("Resetting failed due to device lost.", ELL_WARNING); } else os::Printer::log("Resetting failed.", ELL_WARNING); return false; } DeviceLost = false; ResetRenderStates = true; LastVertexType = (E_VERTEX_TYPE)-1; for (i=0; i= D3DVS_VERSION(1,1); case EVDF_VERTEX_SHADER_2_0: return Caps.VertexShaderVersion >= D3DVS_VERSION(2,0); case EVDF_VERTEX_SHADER_3_0: return Caps.VertexShaderVersion >= D3DVS_VERSION(3,0); case EVDF_PIXEL_SHADER_1_1: return Caps.PixelShaderVersion >= D3DPS_VERSION(1,1); case EVDF_PIXEL_SHADER_1_2: return Caps.PixelShaderVersion >= D3DPS_VERSION(1,2); case EVDF_PIXEL_SHADER_1_3: return Caps.PixelShaderVersion >= D3DPS_VERSION(1,3); case EVDF_PIXEL_SHADER_1_4: return Caps.PixelShaderVersion >= D3DPS_VERSION(1,4); case EVDF_PIXEL_SHADER_2_0: return Caps.PixelShaderVersion >= D3DPS_VERSION(2,0); case EVDF_PIXEL_SHADER_3_0: return Caps.PixelShaderVersion >= D3DPS_VERSION(3,0); case EVDF_TEXTURE_NSQUARE: return (Caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) == 0; case EVDF_TEXTURE_NPOT: return (Caps.TextureCaps & D3DPTEXTURECAPS_POW2) == 0; case EVDF_COLOR_MASK: return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) != 0; case EVDF_BLEND_OPERATIONS: case EVDF_TEXTURE_MATRIX: return true; default: return false; }; } //! sets transformation void CD3D8Driver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) { switch(state) { case ETS_VIEW: pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)mat.pointer())); Transformation3DChanged = true; break; case ETS_WORLD: pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)mat.pointer())); Transformation3DChanged = true; break; case ETS_PROJECTION: pID3DDevice->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)((void*)mat.pointer())); Transformation3DChanged = true; break; case ETS_COUNT: return; default: if (state-ETS_TEXTURE_0 < MATERIAL_MAX_TEXTURES) { pID3DDevice->SetTextureStageState( state - ETS_TEXTURE_0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); pID3DDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+ ( state - ETS_TEXTURE_0 )), (D3DMATRIX*)((void*)mat.pointer())); } break; } Matrices[state] = mat; } //! sets the current Texture bool CD3D8Driver::setActiveTexture(u32 stage, const video::ITexture* texture) { if (CurrentTexture[stage] == texture) return true; if (texture && (texture->getDriverType() != EDT_DIRECT3D8)) { os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); return false; } CurrentTexture[stage] = texture; if (!texture) { pID3DDevice->SetTexture(stage, 0); pID3DDevice->SetTextureStageState( stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); } else { pID3DDevice->SetTexture(stage, ((const CD3D8Texture*)texture)->getDX8Texture()); } return true; } //! sets a material void CD3D8Driver::setMaterial(const SMaterial& material) { Material = material; OverrideMaterial.apply(Material); for (u32 i=0; igetDriverType() != EDT_DIRECT3D8) { os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); return false; } // check for valid render target CD3D8Texture* tex = (CD3D8Texture*)texture; if (texture && !tex->isRenderTarget()) { os::Printer::log("Fatal Error: Tried to set a non render target texture as render target.", ELL_ERROR); return false; } if (texture && (tex->getSize().Width > ScreenSize.Width || tex->getSize().Height > ScreenSize.Height )) { os::Printer::log("Error: Tried to set a render target texture which is bigger than the screen.", ELL_ERROR); return false; } // check if we should set the previous RT back bool ret = true; if (tex == 0) { if (PrevRenderTarget) { IDirect3DSurface8* dss = 0; pID3DDevice->GetDepthStencilSurface(&dss); if (FAILED(pID3DDevice->SetRenderTarget(PrevRenderTarget, dss))) { os::Printer::log("Error: Could not set back to previous render target.", ELL_ERROR); ret = false; } if (dss) dss->Release(); CurrentRendertargetSize = core::dimension2d(0,0); PrevRenderTarget->Release(); PrevRenderTarget = 0; } } else { // we want to set a new target. so do this. // store previous target if (!PrevRenderTarget && (FAILED(pID3DDevice->GetRenderTarget(&PrevRenderTarget)))) { os::Printer::log("Could not get previous render target.", ELL_ERROR); return false; } // set new render target IDirect3DSurface8* dss = 0; pID3DDevice->GetDepthStencilSurface(&dss); if (FAILED(pID3DDevice->SetRenderTarget(tex->getRenderTargetSurface(), dss))) { os::Printer::log("Error: Could not set render target.", ELL_ERROR); ret = false; } if (dss) dss->Release(); CurrentRendertargetSize = tex->getSize(); } Transformation3DChanged = true; if (clearBackBuffer || clearZBuffer) { DWORD flags = 0; if (clearBackBuffer) flags |= D3DCLEAR_TARGET; if (clearZBuffer) flags |= D3DCLEAR_ZBUFFER; pID3DDevice->Clear(0, NULL, flags, color.color, 1.0f, 0); } return ret; } //! Creates a render target texture. ITexture* CD3D8Driver::addRenderTargetTexture( const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format) { CD3D8Texture* tex = new CD3D8Texture(this, size, name); if (tex) { if (!tex->Texture) { tex->drop(); return 0; } addTexture(tex); tex->drop(); } return tex; } //! sets a viewport void CD3D8Driver::setViewPort(const core::rect& area) { core::rect vp(area); core::rect rendert(0,0, ScreenSize.Width, ScreenSize.Height); vp.clipAgainst(rendert); D3DVIEWPORT8 viewPort; viewPort.X = vp.UpperLeftCorner.X; viewPort.Y = vp.UpperLeftCorner.Y; viewPort.Width = vp.getWidth(); viewPort.Height = vp.getHeight(); viewPort.MinZ = 0.0f; viewPort.MaxZ = 1.0f; HRESULT hr = D3DERR_INVALIDCALL; if (vp.getHeight()>0 && vp.getWidth()>0) hr = pID3DDevice->SetViewport(&viewPort); if (FAILED(hr)) os::Printer::log("Failed setting the viewport.", ELL_WARNING); ViewPort = vp; } //! gets the area of the current viewport const core::rect& CD3D8Driver::getViewPort() const { return ViewPort; } //! draws a vertex primitive list void CD3D8Driver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { if (!checkPrimitiveCount(primitiveCount)) return; CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType,iType); if (!vertexCount || !primitiveCount) return; draw2D3DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType, true); } //! draws a vertex primitive list in 2d void CD3D8Driver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) { if (!checkPrimitiveCount(primitiveCount)) return; CNullDriver::draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType,iType); if (!vertexCount || !primitiveCount) return; draw2D3DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType, false); } void CD3D8Driver::draw2D3DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType, bool is3D) { setVertexShader(vType); const u32 stride = getVertexPitchFromType(vType); D3DFORMAT indexType=D3DFMT_UNKNOWN; switch (iType) { case (EIT_16BIT): { indexType=D3DFMT_INDEX16; break; } case (EIT_32BIT): { indexType=D3DFMT_INDEX32; break; } } if (is3D) { if (!setRenderStates3DMode()) return; } else { if (Material.MaterialType==EMT_ONETEXTURE_BLEND) { E_BLEND_FACTOR srcFact; E_BLEND_FACTOR dstFact; E_MODULATE_FUNC modulo; u32 alphaSource; unpack_textureBlendFunc ( srcFact, dstFact, modulo, alphaSource, Material.MaterialTypeParam); setRenderStates2DMode(alphaSource&video::EAS_VERTEX_COLOR, (Material.getTexture(0) != 0), (alphaSource&video::EAS_TEXTURE) != 0); } else setRenderStates2DMode(Material.MaterialType==EMT_TRANSPARENT_VERTEX_ALPHA, (Material.getTexture(0) != 0), Material.MaterialType==EMT_TRANSPARENT_ALPHA_CHANNEL); } switch (pType) { case scene::EPT_POINT_SPRITES: case scene::EPT_POINTS: { f32 tmp=Material.Thickness/getScreenSize().Height; if (pType==scene::EPT_POINT_SPRITES) pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_POINTSIZE, *(DWORD*)(&tmp)); tmp=1.0f; pID3DDevice->SetRenderState(D3DRS_POINTSCALE_A, *(DWORD*)(&tmp)); pID3DDevice->SetRenderState(D3DRS_POINTSCALE_B, *(DWORD*)(&tmp)); pID3DDevice->SetRenderState(D3DRS_POINTSIZE_MIN, *(DWORD*)(&tmp)); tmp=0.0f; pID3DDevice->SetRenderState(D3DRS_POINTSCALE_C, *(DWORD*)(&tmp)); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_POINTLIST, 0, vertexCount, primitiveCount, indexList, indexType, vertices, stride); pID3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE); if (pType==scene::EPT_POINT_SPRITES) pID3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE); } break; case scene::EPT_LINE_STRIP: pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount, primitiveCount, indexList, indexType, vertices, stride); break; case scene::EPT_LINE_LOOP: { pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINESTRIP, 0, vertexCount, primitiveCount - 1, indexList, indexType, vertices, stride); u16 tmpIndices[] = {primitiveCount - 1, 0}; pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount, 1, tmpIndices, indexType, vertices, stride); } break; case scene::EPT_LINES: pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_LINELIST, 0, vertexCount, primitiveCount, indexList, indexType, vertices, stride); break; case scene::EPT_TRIANGLE_STRIP: pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLESTRIP, 0, vertexCount, primitiveCount, indexList, indexType, vertices, stride); break; case scene::EPT_TRIANGLE_FAN: pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLEFAN, 0, vertexCount, primitiveCount, indexList, indexType, vertices, stride); break; case scene::EPT_TRIANGLES: pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, vertexCount, primitiveCount, indexList, indexType, vertices, stride); break; } } //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. void CD3D8Driver::draw2DImage(const video::ITexture* texture, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect, SColor color, bool useAlphaChannelOfTexture) { if (!texture) return; if (!sourceRect.isValid()) return; if (!setActiveTexture(0, texture)) return; core::position2d targetPos = pos; core::position2d sourcePos = sourceRect.UpperLeftCorner; // This needs to be signed as it may go negative. core::dimension2d sourceSize(sourceRect.getSize()); const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); if (clipRect) { if (targetPos.X < clipRect->UpperLeftCorner.X) { sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; if (sourceSize.Width <= 0) return; sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; targetPos.X = clipRect->UpperLeftCorner.X; } if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; if (sourceSize.Width <= 0) return; } if (targetPos.Y < clipRect->UpperLeftCorner.Y) { sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; if (sourceSize.Height <= 0) return; sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; targetPos.Y = clipRect->UpperLeftCorner.Y; } if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; if (sourceSize.Height <= 0) return; } } // clip these coordinates if (targetPos.X<0) { sourceSize.Width += targetPos.X; if (sourceSize.Width <= 0) return; sourcePos.X -= targetPos.X; targetPos.X = 0; } if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) { sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; if (sourceSize.Width <= 0) return; } if (targetPos.Y<0) { sourceSize.Height += targetPos.Y; if (sourceSize.Height <= 0) return; sourcePos.Y -= targetPos.Y; targetPos.Y = 0; } if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) { sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; if (sourceSize.Height <= 0) return; } // ok, we've clipped everything. // now draw it. core::rect tcoords; tcoords.UpperLeftCorner.X = (f32)sourcePos.X / texture->getOriginalSize().Width ; tcoords.UpperLeftCorner.Y = (f32)sourcePos.Y / texture->getOriginalSize().Height; tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + (f32)sourceSize.Width / texture->getOriginalSize().Width; tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + (f32)sourceSize.Height / texture->getOriginalSize().Height; const core::rect poss(targetPos, sourceSize); setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); S3DVertex vtx[4]; vtx[0] = S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); vtx[1] = S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); vtx[2] = S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); vtx[3] = S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); const s16 indices[6] = {0,1,2,0,2,3}; setVertexShader(EVT_STANDARD); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex)); } void CD3D8Driver::draw2DImage(const video::ITexture* texture, const core::rect& destRect, const core::rect& sourceRect, const core::rect* clipRect, const video::SColor* const colors, bool useAlphaChannelOfTexture) { if(!texture) return; const core::dimension2d& ss = texture->getOriginalSize(); core::rect tcoords; tcoords.UpperLeftCorner.X = (f32)sourceRect.UpperLeftCorner.X / (f32)ss.Width; tcoords.UpperLeftCorner.Y = (f32)sourceRect.UpperLeftCorner.Y / (f32)ss.Height; tcoords.LowerRightCorner.X = (f32)sourceRect.LowerRightCorner.X / (f32)ss.Width; tcoords.LowerRightCorner.Y = (f32)sourceRect.LowerRightCorner.Y / (f32)ss.Height; core::rect clippedRect(destRect); if (clipRect) { clippedRect.clipAgainst(*clipRect); //tcoords must be clipped by the same factors const f32 tcWidth = tcoords.getWidth(); const f32 tcHeight = tcoords.getHeight(); const f32 invDestRectWidth = 1.f / (f32)(destRect.getWidth()); f32 scale = (f32)(clippedRect.UpperLeftCorner.X - destRect.UpperLeftCorner.X) * invDestRectWidth; tcoords.UpperLeftCorner.X += scale * tcWidth; scale = (f32)(destRect.LowerRightCorner.X - clippedRect.LowerRightCorner.X) * invDestRectWidth; tcoords.LowerRightCorner.X -= scale * tcWidth; const f32 invDestRectHeight = 1.f / (f32)(destRect.getHeight()); scale = (f32)(clippedRect.UpperLeftCorner.Y - destRect.UpperLeftCorner.Y) * invDestRectHeight; tcoords.UpperLeftCorner.Y += scale * tcHeight; scale = (f32)(destRect.LowerRightCorner.Y - clippedRect.LowerRightCorner.Y) * invDestRectHeight; tcoords.LowerRightCorner.Y -= scale * tcHeight; } const video::SColor temp[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; const video::SColor* const useColor = colors ? colors : temp; S3DVertex vtx[4]; // clock wise vtx[0] = S3DVertex((f32)clippedRect.UpperLeftCorner.X, (f32)clippedRect.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[0], tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); vtx[1] = S3DVertex((f32)clippedRect.LowerRightCorner.X, (f32)clippedRect.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[3], tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); vtx[2] = S3DVertex((f32)clippedRect.LowerRightCorner.X, (f32)clippedRect.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[2], tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); vtx[3] = S3DVertex((f32)clippedRect.UpperLeftCorner.X, (f32)clippedRect.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, useColor[1], tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); const s16 indices[6] = {0,1,2,0,2,3}; setRenderStates2DMode(useColor[0].getAlpha()<255 || useColor[1].getAlpha()<255 || useColor[2].getAlpha()<255 || useColor[3].getAlpha()<255, true, useAlphaChannelOfTexture); setActiveTexture(0, texture); setVertexShader(EVT_STANDARD); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex)); } //!Draws an 2d rectangle with a gradient. void CD3D8Driver::draw2DRectangle(const core::rect& position, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip) { core::rect pos(position); if (clip) pos.clipAgainst(*clip); if (!pos.isValid()) return; S3DVertex vtx[4]; vtx[0] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorLeftUp, 0.0f, 0.0f); vtx[1] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.UpperLeftCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorRightUp, 0.0f, 1.0f); vtx[2] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorRightDown, 1.0f, 0.0f); vtx[3] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.LowerRightCorner.Y, 0.0f, 0.0f, 0.0f, 0.0f, colorLeftDown, 1.0f, 1.0f); const s16 indices[6] = {0,1,2,0,2,3}; setRenderStates2DMode( colorLeftUp.getAlpha() < 255 || colorRightUp.getAlpha() < 255 || colorLeftDown.getAlpha() < 255 || colorRightDown.getAlpha() < 255, false, false); setActiveTexture(0,0); setVertexShader(EVT_STANDARD); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex)); } //! Draws a 2d line. void CD3D8Driver::draw2DLine(const core::position2d& start, const core::position2d& end, SColor color) { if (start==end) drawPixel(start.X, start.Y, color); else { // thanks to Vash TheStampede who sent in his implementation S3DVertex vtx[2]; vtx[0] = S3DVertex((f32)start.X+0.375f, (f32)start.Y+0.375f, 0.0f, 0.0f, 0.0f, 0.0f, // normal color, 0.0f, 0.0f); // texture vtx[1] = S3DVertex((f32)end.X+0.375f, (f32)end.Y+0.375f, 0.0f, 0.0f, 0.0f, 0.0f, color, 0.0f, 0.0f); setRenderStates2DMode(color.getAlpha() < 255, false, false); setActiveTexture(0,0); setVertexShader(EVT_STANDARD); pID3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, &vtx[0], sizeof(S3DVertex)); } } //! Draws a pixel void CD3D8Driver::drawPixel(u32 x, u32 y, const SColor & color) { const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); if (x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height) return; setRenderStates2DMode(color.getAlpha() < 255, false, false); setActiveTexture(0,0); setVertexShader(EVT_STANDARD); S3DVertex vertex((f32)x+0.375f, (f32)y+0.375f, 0.f, 0.f, 0.f, 0.f, color, 0.f, 0.f); pID3DDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, &vertex, sizeof(vertex)); } //! sets right vertex shader void CD3D8Driver::setVertexShader(E_VERTEX_TYPE newType) { // Because we don't know if a vertex shader was set in a material instead of a // fvf, this call cannot be prevented in D3D8. //if (newType != LastVertexType) { LastVertexType = newType; HRESULT hr = 0; switch(newType) { case EVT_STANDARD: hr = pID3DDevice->SetVertexShader(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1); break; case EVT_2TCOORDS: hr = pID3DDevice->SetVertexShader(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2); break; case EVT_TANGENTS: hr = pID3DDevice->SetVertexShader(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE2(0) | // real texture coord D3DFVF_TEXCOORDSIZE3(1) | // misuse texture coord 2 for tangent D3DFVF_TEXCOORDSIZE3(2) // misuse texture coord 3 for binormal ); break; } if (FAILED(hr)) { os::Printer::log("Could not set vertex Shader.", ELL_ERROR); return; } } } //! sets the needed renderstates bool CD3D8Driver::setRenderStates3DMode() { if (!pID3DDevice) return false; if (CurrentRenderMode != ERM_3D) { // switch back the matrices pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)&Matrices[ETS_VIEW])); pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)&Matrices[ETS_WORLD])); pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)&Matrices[ETS_PROJECTION])); pID3DDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); ResetRenderStates = true; } if (ResetRenderStates || LastMaterial != Material) { // unset old material if (CurrentRenderMode == ERM_3D && LastMaterial.MaterialType != Material.MaterialType && LastMaterial.MaterialType >= 0 && LastMaterial.MaterialType < (s32)MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); // set new material. if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) MaterialRenderers[Material.MaterialType].Renderer->OnSetMaterial( Material, LastMaterial, ResetRenderStates, this); } bool shaderOK = true; if (Material.MaterialType >= 0 && Material.MaterialType < (s32)MaterialRenderers.size()) shaderOK = MaterialRenderers[Material.MaterialType].Renderer->OnRender(this, LastVertexType); LastMaterial = Material; ResetRenderStates = false; CurrentRenderMode = ERM_3D; return shaderOK; } //! Map Irrlicht texture wrap mode to native values D3DTEXTUREADDRESS CD3D8Driver::getTextureWrapMode(const u8 clamp) { switch (clamp) { case ETC_REPEAT: if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP) return D3DTADDRESS_WRAP; case ETC_CLAMP: case ETC_CLAMP_TO_EDGE: if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_CLAMP) return D3DTADDRESS_CLAMP; case ETC_MIRROR: if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR) return D3DTADDRESS_MIRROR; case ETC_CLAMP_TO_BORDER: if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER) return D3DTADDRESS_BORDER; else return D3DTADDRESS_CLAMP; case ETC_MIRROR_CLAMP: case ETC_MIRROR_CLAMP_TO_EDGE: case ETC_MIRROR_CLAMP_TO_BORDER: if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRRORONCE) return D3DTADDRESS_MIRRORONCE; else return D3DTADDRESS_CLAMP; default: return D3DTADDRESS_WRAP; } } //! Can be called by an IMaterialRenderer to make its work easier. void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderstates) { if (resetAllRenderstates || lastmaterial.AmbientColor != material.AmbientColor || lastmaterial.DiffuseColor != material.DiffuseColor || lastmaterial.SpecularColor != material.SpecularColor || lastmaterial.EmissiveColor != material.EmissiveColor || lastmaterial.Shininess != material.Shininess) { D3DMATERIAL8 mat; mat.Diffuse = colorToD3D(material.DiffuseColor); mat.Ambient = colorToD3D(material.AmbientColor); mat.Specular = colorToD3D(material.SpecularColor); mat.Emissive = colorToD3D(material.EmissiveColor); mat.Power = material.Shininess; pID3DDevice->SetMaterial(&mat); } if (lastmaterial.ColorMaterial != material.ColorMaterial) { pID3DDevice->SetRenderState(D3DRS_COLORVERTEX, (material.ColorMaterial != ECM_NONE)); pID3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, ((material.ColorMaterial == ECM_DIFFUSE)|| (material.ColorMaterial == ECM_DIFFUSE_AND_AMBIENT))?D3DMCS_COLOR1:D3DMCS_MATERIAL); pID3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, ((material.ColorMaterial == ECM_AMBIENT)|| (material.ColorMaterial == ECM_DIFFUSE_AND_AMBIENT))?D3DMCS_COLOR1:D3DMCS_MATERIAL); pID3DDevice->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, (material.ColorMaterial == ECM_EMISSIVE)?D3DMCS_COLOR1:D3DMCS_MATERIAL); pID3DDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, (material.ColorMaterial == ECM_SPECULAR)?D3DMCS_COLOR1:D3DMCS_MATERIAL); } // fillmode if (resetAllRenderstates || lastmaterial.Wireframe != material.Wireframe || lastmaterial.PointCloud != material.PointCloud) { if (material.Wireframe) pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); else if (material.PointCloud) pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_POINT); else pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); } // shademode if (resetAllRenderstates || lastmaterial.GouraudShading != material.GouraudShading) { if (material.GouraudShading) pID3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); else pID3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); } // lighting if (resetAllRenderstates || lastmaterial.Lighting != material.Lighting) { if (material.Lighting) pID3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE); else pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); } // zbuffer if (resetAllRenderstates || lastmaterial.ZBuffer != material.ZBuffer) { switch (material.ZBuffer) { case ECFN_NEVER: pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE); break; case ECFN_LESSEQUAL: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); break; case ECFN_EQUAL: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL); break; case ECFN_LESS: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS); break; case ECFN_NOTEQUAL: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_NOTEQUAL); break; case ECFN_GREATEREQUAL: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATEREQUAL); break; case ECFN_GREATER: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATER); break; case ECFN_ALWAYS: pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); break; } } // zwrite // if (resetAllRenderstates || lastmaterial.ZWriteEnable != material.ZWriteEnable) { if (material.ZWriteEnable && (AllowZWriteOnTransparent || !material.isTransparent())) pID3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE); else pID3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE); } // back face culling if (resetAllRenderstates || (lastmaterial.FrontfaceCulling != material.FrontfaceCulling) || (lastmaterial.BackfaceCulling != material.BackfaceCulling)) { // if (material.FrontfaceCulling && material.BackfaceCulling) // pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW|D3DCULL_CCW); // else if (material.FrontfaceCulling) pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); else if (material.BackfaceCulling) pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); else pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); } // fog if (resetAllRenderstates || lastmaterial.FogEnable != material.FogEnable) { pID3DDevice->SetRenderState(D3DRS_FOGENABLE, material.FogEnable); } // specular highlights if (resetAllRenderstates || !core::equals(lastmaterial.Shininess, material.Shininess)) { bool enable = (material.Shininess!=0); pID3DDevice->SetRenderState(D3DRS_SPECULARENABLE, enable); pID3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, enable); pID3DDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL); } // normalization if (resetAllRenderstates || lastmaterial.NormalizeNormals != material.NormalizeNormals) { pID3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, material.NormalizeNormals); } // Color Mask if (queryFeature(EVDF_COLOR_MASK) && (resetAllRenderstates || lastmaterial.ColorMask != material.ColorMask)) { const DWORD flag = ((material.ColorMask & ECP_RED)?D3DCOLORWRITEENABLE_RED:0) | ((material.ColorMask & ECP_GREEN)?D3DCOLORWRITEENABLE_GREEN:0) | ((material.ColorMask & ECP_BLUE)?D3DCOLORWRITEENABLE_BLUE:0) | ((material.ColorMask & ECP_ALPHA)?D3DCOLORWRITEENABLE_ALPHA:0); pID3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, flag); } if (queryFeature(EVDF_BLEND_OPERATIONS) && (resetAllRenderstates|| lastmaterial.BlendOperation != material.BlendOperation)) { if (material.BlendOperation==EBO_NONE) pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); else { pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); switch (material.BlendOperation) { case EBO_MAX: case EBO_MAX_FACTOR: case EBO_MAX_ALPHA: pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MAX); break; case EBO_MIN: case EBO_MIN_FACTOR: case EBO_MIN_ALPHA: pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MIN); break; case EBO_SUBTRACT: pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT); break; case EBO_REVSUBTRACT: pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT); break; default: pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); break; } } } // Polygon offset if (queryFeature(EVDF_POLYGON_OFFSET) && (resetAllRenderstates || lastmaterial.PolygonOffsetDirection != material.PolygonOffsetDirection || lastmaterial.PolygonOffsetFactor != material.PolygonOffsetFactor)) { pID3DDevice->SetRenderState(D3DRS_ZBIAS, material.PolygonOffsetFactor); } // thickness if (resetAllRenderstates || lastmaterial.Thickness != material.Thickness) { pID3DDevice->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&material.Thickness)); } // texture address mode for (u32 st=0; stSetTextureStageState(st, D3DTSS_MIPMAPLODBIAS, *(DWORD*)(&tmp)); } if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapU != material.TextureLayer[st].TextureWrapU) pID3DDevice->SetTextureStageState(st, D3DTSS_ADDRESSU, getTextureWrapMode(material.TextureLayer[st].TextureWrapU)); // If separate UV not supported reuse U for V if (!(Caps.TextureAddressCaps & D3DPTADDRESSCAPS_INDEPENDENTUV)) pID3DDevice->SetTextureStageState(st, D3DTSS_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapU)); else if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapV != material.TextureLayer[st].TextureWrapV) pID3DDevice->SetTextureStageState(st, D3DTSS_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapV)); // Bilinear and/or trilinear if (resetAllRenderstates || lastmaterial.TextureLayer[st].BilinearFilter != material.TextureLayer[st].BilinearFilter || lastmaterial.TextureLayer[st].TrilinearFilter != material.TextureLayer[st].TrilinearFilter || lastmaterial.TextureLayer[st].AnisotropicFilter != material.TextureLayer[st].AnisotropicFilter || lastmaterial.UseMipMaps != material.UseMipMaps) { if (material.TextureLayer[st].BilinearFilter || material.TextureLayer[st].TrilinearFilter || material.TextureLayer[st].AnisotropicFilter>1) { const D3DTEXTUREFILTERTYPE tftMag = ((Caps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) && material.TextureLayer[st].AnisotropicFilter) ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR; const D3DTEXTUREFILTERTYPE tftMin = ((Caps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) && material.TextureLayer[st].AnisotropicFilter) ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR; const D3DTEXTUREFILTERTYPE tftMip = material.UseMipMaps? (material.TextureLayer[st].TrilinearFilter ? D3DTEXF_LINEAR : D3DTEXF_POINT) : D3DTEXF_NONE; if (tftMag==D3DTEXF_ANISOTROPIC || tftMin == D3DTEXF_ANISOTROPIC) pID3DDevice->SetTextureStageState(st, D3DTSS_MAXANISOTROPY, core::min_((DWORD)material.TextureLayer[st].AnisotropicFilter, Caps.MaxAnisotropy)); pID3DDevice->SetTextureStageState(st, D3DTSS_MAGFILTER, tftMag); pID3DDevice->SetTextureStageState(st, D3DTSS_MINFILTER, tftMin); pID3DDevice->SetTextureStageState(st, D3DTSS_MIPFILTER, tftMip); } else { pID3DDevice->SetTextureStageState(st, D3DTSS_MINFILTER, D3DTEXF_POINT); pID3DDevice->SetTextureStageState(st, D3DTSS_MIPFILTER, D3DTEXF_NONE); pID3DDevice->SetTextureStageState(st, D3DTSS_MAGFILTER, D3DTEXF_POINT); } } } } //! sets the needed renderstates void CD3D8Driver::setRenderStatesStencilShadowMode(bool zfail, u32 debugDataVisible) { if ((CurrentRenderMode != ERM_SHADOW_VOLUME_ZFAIL && CurrentRenderMode != ERM_SHADOW_VOLUME_ZPASS) || Transformation3DChanged) { // unset last 3d material if (CurrentRenderMode == ERM_3D && static_cast(Material.MaterialType) < MaterialRenderers.size()) { MaterialRenderers[Material.MaterialType].Renderer->OnUnsetMaterial(); ResetRenderStates = true; } // switch back the matrices pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)&Matrices[ETS_VIEW])); pID3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)((void*)&Matrices[ETS_WORLD])); pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)&Matrices[ETS_PROJECTION])); Transformation3DChanged = false; setActiveTexture(0,0); setActiveTexture(1,0); setActiveTexture(2,0); setActiveTexture(3,0); pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetVertexShader(D3DFVF_XYZ); LastVertexType = (video::E_VERTEX_TYPE)(-1); pID3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); pID3DDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //pID3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); //pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); pID3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); pID3DDevice->SetRenderState(D3DRS_STENCILREF, 0x0); pID3DDevice->SetRenderState(D3DRS_STENCILMASK, 0xffffffff); pID3DDevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff); if (!(debugDataVisible & (scene::EDS_SKELETON|scene::EDS_MESH_WIRE_OVERLAY))) pID3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); if ((debugDataVisible & scene::EDS_MESH_WIRE_OVERLAY)) pID3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); } if (CurrentRenderMode != ERM_SHADOW_VOLUME_ZPASS && !zfail) { // USE THE ZPASS METHOD pID3DDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP); pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR); } else if (CurrentRenderMode != ERM_SHADOW_VOLUME_ZFAIL && zfail) { // USE THE ZFAIL METHOD pID3DDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR); pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); } CurrentRenderMode = zfail ? ERM_SHADOW_VOLUME_ZFAIL : ERM_SHADOW_VOLUME_ZPASS; } //! sets the needed renderstates void CD3D8Driver::setRenderStatesStencilFillMode(bool alpha) { if (CurrentRenderMode != ERM_STENCIL_FILL || Transformation3DChanged) { pID3DDevice->SetTransform(D3DTS_VIEW, &UnitMatrixD3D8); pID3DDevice->SetTransform(D3DTS_WORLD, &UnitMatrixD3D8); pID3DDevice->SetTransform(D3DTS_PROJECTION, &UnitMatrixD3D8); pID3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE); pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); pID3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_STENCILREF, 0x1 ); pID3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL); //pID3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATEREQUAL); pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP ); pID3DDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP ); pID3DDevice->SetRenderState( D3DRS_STENCILMASK, 0xffffffff ); pID3DDevice->SetRenderState( D3DRS_STENCILWRITEMASK, 0xffffffff ); pID3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW); Transformation3DChanged = false; if (alpha) { pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE ); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); } else { pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE ); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } } CurrentRenderMode = ERM_STENCIL_FILL; } //! sets the needed renderstates void CD3D8Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel) { if (!pID3DDevice) return; if (CurrentRenderMode != ERM_2D || Transformation3DChanged) { // unset last 3d material if (CurrentRenderMode == ERM_3D) { if (static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); } if (!OverrideMaterial2DEnabled) { setBasicRenderStates(InitMaterial2D, LastMaterial, true); LastMaterial=InitMaterial2D; // fix everything that is wrongly set by SMaterial default pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); pID3DDevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); pID3DDevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); pID3DDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE ); } pID3DDevice->SetTransform(D3DTS_WORLD, &UnitMatrixD3D8); core::matrix4 m; m.setTranslation(core::vector3df(-0.5f,-0.5f,0)); pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)m.pointer())); const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0, 1.0); m.setTranslation(core::vector3df(-1,1,0)); pID3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)((void*)m.pointer())); Transformation3DChanged = false; } if (OverrideMaterial2DEnabled) { OverrideMaterial2D.Lighting=false; setBasicRenderStates(OverrideMaterial2D, LastMaterial, false); LastMaterial = OverrideMaterial2D; } // no alphaChannel without texture alphaChannel &= texture; if (alpha || alphaChannel) { pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); } else pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); if (texture) { setTransform(ETS_TEXTURE_0, core::IdentityMatrix); // Due to the transformation change, the previous line would call a reset each frame // but we can safely reset the variable as it was false before Transformation3DChanged=false; } if (alphaChannel) { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); if (alpha) { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); } else { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); } } else { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); if (alpha) { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); } else { pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); } } CurrentRenderMode = ERM_2D; } //! deletes all dynamic lights there are void CD3D8Driver::deleteAllDynamicLights() { for (s32 i=0; iLightEnable(i, false); LastSetLight = -1; CNullDriver::deleteAllDynamicLights(); } //! adds a dynamic light s32 CD3D8Driver::addDynamicLight(const SLight& dl) { CNullDriver::addDynamicLight(dl); D3DLIGHT8 light; switch (dl.Type) { case ELT_POINT: light.Type = D3DLIGHT_POINT; break; case ELT_SPOT: light.Type = D3DLIGHT_SPOT; break; case ELT_DIRECTIONAL: light.Type = D3DLIGHT_DIRECTIONAL; break; } light.Position = *(D3DVECTOR*)((void*)(&dl.Position)); light.Direction = *(D3DVECTOR*)((void*)(&dl.Direction)); light.Range = core::min_(dl.Radius, MaxLightDistance); light.Falloff = dl.Falloff; light.Diffuse = *(D3DCOLORVALUE*)((void*)(&dl.DiffuseColor)); light.Specular = *(D3DCOLORVALUE*)((void*)(&dl.SpecularColor)); light.Ambient = *(D3DCOLORVALUE*)((void*)(&dl.AmbientColor)); light.Attenuation0 = dl.Attenuation.X; light.Attenuation1 = dl.Attenuation.Y; light.Attenuation2 = dl.Attenuation.Z; light.Theta = dl.InnerCone * 2.0f * core::DEGTORAD; light.Phi = dl.OuterCone * 2.0f * core::DEGTORAD; ++LastSetLight; if(D3D_OK == pID3DDevice->SetLight(LastSetLight, &light)) { // I don't care if this succeeds (void)pID3DDevice->LightEnable(LastSetLight, true); return LastSetLight; } return -1; } void CD3D8Driver::turnLightOn(s32 lightIndex, bool turnOn) { if(lightIndex < 0 || lightIndex > LastSetLight) return; (void)pID3DDevice->LightEnable(lightIndex, turnOn); } //! returns the maximal amount of dynamic lights the device can handle u32 CD3D8Driver::getMaximalDynamicLightAmount() const { return Caps.MaxActiveLights; } //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. void CD3D8Driver::setAmbientLight(const SColorf& color) { if (!pID3DDevice) return; AmbientLight = color; D3DCOLOR col = color.toSColor().color; pID3DDevice->SetRenderState(D3DRS_AMBIENT, col); } //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8 //! driver, it would return "Direct3D8.1". const wchar_t* CD3D8Driver::getName() const { return L"Direct3D 8.1"; } //! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do //! this: First, draw all geometry. Then use this method, to draw the shadow //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. void CD3D8Driver::drawStencilShadowVolume(const core::array& triangles, bool zfail, u32 debugDataVisible) { const u32 count = triangles.size(); if (!Params.Stencilbuffer || !count) return; setRenderStatesStencilShadowMode(zfail, debugDataVisible); if (!zfail) { // ZPASS Method // Draw front-side of shadow volume in stencil only pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW ); pID3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCRSAT); pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles.const_pointer(), sizeof(core::vector3df)); // Now reverse cull order so front sides of shadow volume are written. pID3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW ); pID3DDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_DECRSAT); pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles.const_pointer(), sizeof(core::vector3df)); } else { // ZFAIL Method // Draw front-side of shadow volume in stencil only pID3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW ); pID3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_INCRSAT ); pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles.const_pointer(), sizeof(core::vector3df)); // Now reverse cull order so front sides of shadow volume are written. pID3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); pID3DDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_DECRSAT ); pID3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count / 3, triangles.const_pointer(), sizeof(core::vector3df)); } } //! Fills the stencil shadow with color. After the shadow volume has been drawn //! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this //! to draw the color of the shadow. void CD3D8Driver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge, video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge) { if (!Params.Stencilbuffer) return; S3DVertex vtx[4]; vtx[0] = S3DVertex(1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, leftUpEdge, 0.0f, 0.0f); vtx[1] = S3DVertex(1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, rightUpEdge, 0.0f, 1.0f); vtx[2] = S3DVertex(-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, leftDownEdge, 1.0f, 0.0f); vtx[3] = S3DVertex(-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, rightDownEdge, 1.0f, 1.0f); const s16 indices[6] = {0,1,2,1,3,2}; setRenderStatesStencilFillMode( leftUpEdge.getAlpha() < 255 || rightUpEdge.getAlpha() < 255 || leftDownEdge.getAlpha() < 255 || rightDownEdge.getAlpha() < 255); setActiveTexture(0,0); setVertexShader(EVT_STANDARD); pID3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], D3DFMT_INDEX16, &vtx[0], sizeof(S3DVertex)); if (clearStencilBuffer) pID3DDevice->Clear(0, NULL, D3DCLEAR_STENCIL,0, 1.0, 0); } //! Returns the maximum amount of primitives (mostly vertices) which //! the device is able to render with one drawIndexedTriangleList //! call. u32 CD3D8Driver::getMaximalPrimitiveCount() const { return Caps.MaxPrimitiveCount; } //! Sets the fog mode. void CD3D8Driver::setFog(SColor color, E_FOG_TYPE fogType, f32 start, f32 end, f32 density, bool pixelFog, bool rangeFog) { CNullDriver::setFog(color, fogType, start, end, density, pixelFog, rangeFog); if (!pID3DDevice) return; pID3DDevice->SetRenderState(D3DRS_FOGCOLOR, color.color); pID3DDevice->SetRenderState( #if defined( _IRR_XBOX_PLATFORM_) D3DRS_FOGTABLEMODE, #else pixelFog ? D3DRS_FOGTABLEMODE : D3DRS_FOGVERTEXMODE, #endif (fogType==EFT_FOG_LINEAR)? D3DFOG_LINEAR : (fogType==EFT_FOG_EXP)?D3DFOG_EXP:D3DFOG_EXP2); if (fogType==EFT_FOG_LINEAR) { pID3DDevice->SetRenderState(D3DRS_FOGSTART, *(DWORD*)(&start)); pID3DDevice->SetRenderState(D3DRS_FOGEND, *(DWORD*)(&end)); } else pID3DDevice->SetRenderState(D3DRS_FOGDENSITY, *(DWORD*)(&density)); if(!pixelFog) pID3DDevice->SetRenderState(D3DRS_RANGEFOGENABLE, rangeFog); } //! Draws a 3d line. void CD3D8Driver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color) { setVertexShader(EVT_STANDARD); setRenderStates3DMode(); video::S3DVertex v[2]; v[0].Color = color; v[1].Color = color; v[0].Pos = start; v[1].Pos = end; pID3DDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, v, sizeof(S3DVertex)); } void CD3D8Driver::OnResize(const core::dimension2d& size) { if (!pID3DDevice) return; CNullDriver::OnResize(size); reset(); } //! Returns type of video driver E_DRIVER_TYPE CD3D8Driver::getDriverType() const { return EDT_DIRECT3D8; } //! Returns the transformation set by setTransform const core::matrix4& CD3D8Driver::getTransform(E_TRANSFORMATION_STATE state) const { return Matrices[state]; } //! Sets a vertex shader constant. void CD3D8Driver::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { if (data) pID3DDevice->SetVertexShaderConstant(startRegister, data, constantAmount); } //! Sets a pixel shader constant. void CD3D8Driver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { if (data) pID3DDevice->SetPixelShaderConstant(startRegister, data, constantAmount); } //! Sets a constant for the vertex shader based on a name. bool CD3D8Driver::setVertexShaderConstant(const c8* name, const f32* floats, int count) { os::Printer::log("Cannot set constant, no HLSL supported in D3D8"); return false; } //! Bool interface for the above. bool CD3D8Driver::setVertexShaderConstant(const c8* name, const bool* bools, int count) { os::Printer::log("Cannot set constant, no HLSL supported in D3D8"); return false; } //! Int interface for the above. bool CD3D8Driver::setVertexShaderConstant(const c8* name, const s32* ints, int count) { os::Printer::log("Cannot set constant, no HLSL supported in D3D8"); return false; } //! Sets a constant for the pixel shader based on a name. bool CD3D8Driver::setPixelShaderConstant(const c8* name, const f32* floats, int count) { os::Printer::log("Cannot set constant, no HLSL supported in D3D8"); return false; } //! Bool interface for the above. bool CD3D8Driver::setPixelShaderConstant(const c8* name, const bool* bools, int count) { os::Printer::log("Cannot set constant, no HLSL supported in D3D8"); return false; } //! Int interface for the above. bool CD3D8Driver::setPixelShaderConstant(const c8* name, const s32* ints, int count) { os::Printer::log("Cannot set constant, no HLSL supported in D3D8"); return false; } //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. s32 CD3D8Driver::addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) { s32 nr = -1; CD3D8ShaderMaterialRenderer* r = new CD3D8ShaderMaterialRenderer( pID3DDevice, this, nr, vertexShaderProgram, pixelShaderProgram, callback, getMaterialRenderer(baseMaterial), userData); r->drop(); return nr; } //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) IVideoDriver* CD3D8Driver::getVideoDriver() { return this; } //! Clears the ZBuffer. void CD3D8Driver::clearZBuffer() { const HRESULT hr = pID3DDevice->Clear( 0, NULL, D3DCLEAR_ZBUFFER, 0, 1.0, 0); if (FAILED(hr)) os::Printer::log("CD3D8Driver clearZBuffer() failed.", ELL_WARNING); } //! Returns an image created from the last rendered frame. IImage* CD3D8Driver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target) { #if defined( _IRR_XBOX_PLATFORM_) return 0; #else if (target != video::ERT_FRAME_BUFFER) return 0; // query the screen dimensions of the current adapter D3DDISPLAYMODE displayMode; pID3DDevice->GetDisplayMode(&displayMode); if (format==video::ECF_UNKNOWN) format=video::ECF_A8R8G8B8; // create the image surface to store the front buffer image [always A8R8G8B8] HRESULT hr; LPDIRECT3DSURFACE8 lpSurface; if (FAILED(hr = pID3DDevice->CreateImageSurface(displayMode.Width, displayMode.Height, D3DFMT_A8R8G8B8, &lpSurface))) return 0; // read the front buffer into the image surface if (FAILED(hr = pID3DDevice->GetFrontBuffer(lpSurface))) { lpSurface->Release(); return 0; } RECT clientRect; { POINT clientPoint; clientPoint.x = 0; clientPoint.y = 0; ClientToScreen( (HWND)getExposedVideoData().D3D8.HWnd, &clientPoint ); clientRect.left = clientPoint.x; clientRect.top = clientPoint.y; clientRect.right = clientRect.left + ScreenSize.Width; clientRect.bottom = clientRect.top + ScreenSize.Height; // window can be off-screen partly, we can't take screenshots from that clientRect.left = core::max_(clientRect.left, 0l); clientRect.top = core::max_(clientRect.top, 0l); clientRect.right = core::min_(clientRect.right, (long)displayMode.Width); clientRect.bottom = core::min_(clientRect.bottom, (long)displayMode.Height ); } // lock our area of the surface D3DLOCKED_RECT lockedRect; if (FAILED(lpSurface->LockRect(&lockedRect, &clientRect, D3DLOCK_READONLY))) { lpSurface->Release(); return 0; } irr::core::dimension2d shotSize; shotSize.Width = core::min_( ScreenSize.Width, (u32)(clientRect.right-clientRect.left) ); shotSize.Height = core::min_( ScreenSize.Height, (u32)(clientRect.bottom-clientRect.top) ); // this could throw, but we aren't going to worry about that case very much IImage* newImage = createImage(format, shotSize); if (newImage) { // d3d pads the image, so we need to copy the correct number of bytes u32* dP = (u32*)newImage->lock(); u8 * sP = (u8 *)lockedRect.pBits; // If the display mode format doesn't promise anything about the Alpha value // and it appears that it's not presenting 255, then we should manually // set each pixel alpha value to 255. if(D3DFMT_X8R8G8B8 == displayMode.Format && (0xFF000000 != (*dP & 0xFF000000))) { for (u32 y = 0; y < shotSize.Height; ++y) { for(u32 x = 0; x < shotSize.Width; ++x) { newImage->setPixel(x,y,*((u32*)sP) | 0xFF000000); sP += 4; } sP += lockedRect.Pitch - (4 * shotSize.Width); } } else { for (u32 y = 0; y < shotSize.Height; ++y) { convertColor(sP, video::ECF_A8R8G8B8, shotSize.Width, dP, format); sP += lockedRect.Pitch; dP += shotSize.Width; } } newImage->unlock(); } // we can unlock and release the surface lpSurface->UnlockRect(); // release the image surface lpSurface->Release(); // return status of save operation to caller return newImage; #endif } // returns the current size of the screen or rendertarget const core::dimension2d& CD3D8Driver::getCurrentRenderTargetSize() const { if ( CurrentRendertargetSize.Width == 0 ) return ScreenSize; else return CurrentRendertargetSize; } // Set/unset a clipping plane. bool CD3D8Driver::setClipPlane(u32 index, const core::plane3df& plane, bool enable) { #if defined( _IRR_XBOX_PLATFORM_) return false; #else if (index >= MaxUserClipPlanes) return false; pID3DDevice->SetClipPlane(index, (const float*)&plane); enableClipPlane(index, enable); return true; #endif } // Enable/disable a clipping plane. void CD3D8Driver::enableClipPlane(u32 index, bool enable) { #if defined( _IRR_XBOX_PLATFORM_) return; #else if (index >= MaxUserClipPlanes) return; DWORD renderstate; pID3DDevice->GetRenderState(D3DRS_CLIPPLANEENABLE, &renderstate); if (enable) renderstate |= (1 << index); else renderstate &= ~(1 << index); pID3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, renderstate); #endif } core::dimension2du CD3D8Driver::getMaxTextureSize() const { return core::dimension2du(Caps.MaxTextureWidth, Caps.MaxTextureHeight); } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ namespace irr { namespace video { #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ //! creates a video driver IVideoDriver* createDirectX8Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, HWND window) { const bool pureSoftware = false; CD3D8Driver* dx8 = new CD3D8Driver(params, io); if (!dx8->initDriver(window, pureSoftware)) { dx8->drop(); dx8 = 0; } return dx8; } #endif // _IRR_COMPILE_WITH_DIRECT3D_8_ } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CCubeSceneNode.h0000644000000000000000000000632612574354552020062 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_CUBE_SCENE_NODE_H_INCLUDED__ #define __C_CUBE_SCENE_NODE_H_INCLUDED__ #include "IMeshSceneNode.h" #include "SMesh.h" namespace irr { namespace scene { class CCubeSceneNode : public IMeshSceneNode { public: //! constructor CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); virtual ~CCubeSceneNode(); virtual void OnRegisterSceneNode(); //! renders the node. virtual void render(); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. virtual video::SMaterial& getMaterial(u32 i); //! returns amount of materials used by this scene node. virtual u32 getMaterialCount() const; //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_CUBE; } //! Creates shadow volume scene node as child of this node //! and returns a pointer to it. virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh, s32 id, bool zfailmethod=true, f32 infinity=10000.0f); //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); //! Sets a new mesh to display virtual void setMesh(IMesh* mesh) {} //! Returns the current mesh virtual IMesh* getMesh(void) { return Mesh; } //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. /* In this way it is possible to change the materials a mesh causing all mesh scene nodes referencing this mesh to change too. */ virtual void setReadOnlyMaterials(bool readonly) {} //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style virtual bool isReadOnlyMaterials() const { return false; } //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. virtual bool removeChild(ISceneNode* child); private: void setSize(); IMesh* Mesh; IShadowVolumeSceneNode* Shadow; f32 Size; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CCubeSceneNode.cpp0000644000000000000000000001331212574354552020406 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CCubeSceneNode.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "S3DVertex.h" #include "SMeshBuffer.h" #include "os.h" #include "CShadowVolumeSceneNode.h" namespace irr { namespace scene { /* 011 111 /6,8------/5 y / | / | ^ z / | / | | / 010 3,9-------2 | |/ | 7- - -10,4 101 *---->x | / | / |/ | / 0------11,1/ 000 100 */ //! constructor CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) : IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), Shadow(0), Size(size) { #ifdef _DEBUG setDebugName("CCubeSceneNode"); #endif setSize(); } CCubeSceneNode::~CCubeSceneNode() { if (Shadow) Shadow->drop(); if (Mesh) Mesh->drop(); } void CCubeSceneNode::setSize() { if (Mesh) Mesh->drop(); Mesh = SceneManager->getGeometryCreator()->createCubeMesh(core::vector3df(Size)); } //! renders the node. void CCubeSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); if (Shadow) Shadow->updateShadowVolumes(); // for debug purposes only: video::SMaterial mat = Mesh->getMeshBuffer(0)->getMaterial(); // overwrite half transparency if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY) mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; driver->setMaterial(mat); driver->drawMeshBuffer(Mesh->getMeshBuffer(0)); // for debug purposes only: if (DebugDataVisible) { video::SMaterial m; m.Lighting = false; m.AntiAliasing=0; driver->setMaterial(m); if (DebugDataVisible & scene::EDS_BBOX) { driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(), video::SColor(255,255,255,255)); } if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) { driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(), video::SColor(255,190,128,128)); } if (DebugDataVisible & scene::EDS_NORMALS) { // draw normals const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); const u32 count = Mesh->getMeshBufferCount(); for (u32 i=0; i != count; ++i) { driver->drawMeshBufferNormals(Mesh->getMeshBuffer(i), debugNormalLength, debugNormalColor); } } // show mesh if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) { m.Wireframe = true; driver->setMaterial(m); driver->drawMeshBuffer(Mesh->getMeshBuffer(0)); } } } //! returns the axis aligned bounding box of this node const core::aabbox3d& CCubeSceneNode::getBoundingBox() const { return Mesh->getMeshBuffer(0)->getBoundingBox(); } //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. bool CCubeSceneNode::removeChild(ISceneNode* child) { if (child && Shadow == child) { Shadow->drop(); Shadow = 0; } return ISceneNode::removeChild(child); } //! Creates shadow volume scene node as child of this node //! and returns a pointer to it. IShadowVolumeSceneNode* CCubeSceneNode::addShadowVolumeSceneNode( const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity) { if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) return 0; if (!shadowMesh) shadowMesh = Mesh; // if null is given, use the mesh of node if (Shadow) Shadow->drop(); Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity); return Shadow; } void CCubeSceneNode::OnRegisterSceneNode() { if (IsVisible) SceneManager->registerNodeForRendering(this); ISceneNode::OnRegisterSceneNode(); } //! returns the material based on the zero based index i. video::SMaterial& CCubeSceneNode::getMaterial(u32 i) { return Mesh->getMeshBuffer(0)->getMaterial(); } //! returns amount of materials used by this scene node. u32 CCubeSceneNode::getMaterialCount() const { return 1; } //! Writes attributes of the scene node. void CCubeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { ISceneNode::serializeAttributes(out, options); out->addFloat("Size", Size); } //! Reads attributes of the scene node. void CCubeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { f32 newSize = in->getAttributeAsFloat("Size"); newSize = core::max_(newSize, 0.0001f); if (newSize != Size) { Size = newSize; setSize(); } ISceneNode::deserializeAttributes(in, options); } //! Creates a clone of this scene node and its children. ISceneNode* CCubeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CCubeSceneNode* nb = new CCubeSceneNode(Size, newParent, newManager, ID, RelativeTranslation); nb->cloneMembers(this, newManager); nb->getMaterial(0) = getMaterial(0); nb->Shadow = Shadow; if ( nb->Shadow ) nb->Shadow->grab(); if ( newParent ) nb->drop(); return nb; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CCSMLoader.h0000644000000000000000000000544312574354552017170 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // This Loader has been originally written by Saurav Mohapatra. I (Nikolaus Gebhardt) // modified some minor things and integrated it into Irrlicht 0.9. Thanks a lot // to Saurav Mohapatra for his work on this and that he gave me his permission to // add it into Irrlicht. // I did some changes to Saurav Mohapatra's loader, so I'm writing this down here: // - Replaced all dependencies to STL and stdio with irr:: methods/constructs. // - Moved everything into namespace irr::scene // - Replaced logging with Irrlicht's internal logger. // - Removed dependency to IrrlichtDevice // - Moved all internal structures into CCSMLoader.cpp // - Made the texture root parameter dependent on a ISceneManager string parameter // - removed exceptions // - Implemented CCCSMLoader as IMeshLoader // - Fixed some problems with memory leaks // - Fixed bounding box calculation // // The original readme of this file looks like this: // // This component provides a loader for the Cartography shop 4.x .csm maps for Irrlicht Engine. // This is a part of the M_TRIX Project. // This is licensed under the ZLib/LibPNG license // The IrrCSM library is written by Saurav Mohapatra. // // Features // // The IrrCSM library features the following capabilities // // * Loads the .csm 4.0 and 4.1 files transparently // * Presents the loaded file as irr::scene::IAnimatedMesh for easy creation of IOctreeSceneNode // * Loads the textures given the correct texture root. hence map and textures can be in separate directories // // For more informations go to http://www.geocities.com/standard_template/irrcsm/downloads.html #ifndef __CSM_LOADER_H_INCLUDED__ #define __CSM_LOADER_H_INCLUDED__ #include "irrArray.h" #include "IMesh.h" #include "irrString.h" #include "IFileSystem.h" #include "IMeshLoader.h" namespace irr { namespace scene { class CSMFile; class ISceneManager; class CCSMLoader : public scene::IMeshLoader { public: CCSMLoader(ISceneManager* manager, io::IFileSystem* fs); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: scene::IMesh* createCSMMesh(io::IReadFile* file); scene::IMesh* createIrrlichtMesh(const CSMFile* csmFile, const core::stringc& textureRoot, const io::path& lmprefix); io::IFileSystem* FileSystem; scene::ISceneManager* SceneManager; }; } // end namespace } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/CCSMLoader.cpp0000644000000000000000000004631012574354552017521 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // This file was written by Saurav Mohapatra and modified by Nikolaus Gebhardt. // See CCSMLoader.h for details. #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_CSM_LOADER_ #include "CCSMLoader.h" #include "os.h" #include "IFileSystem.h" #include "IReadFile.h" #include "ISceneManager.h" #include "IAttributes.h" #include "SMesh.h" #include "IVideoDriver.h" #include "SAnimatedMesh.h" #include "SMeshBufferLightMap.h" #ifdef _DEBUG #define _IRR_DEBUG_CSM_LOADER_ #endif namespace irr { namespace scene { // // the CSM data types // struct color_rgb_t { s32 red; s32 green; s32 blue; color_rgb_t() : red(0), green(0), blue(0) {} void clear() { red=0; green=0; blue=0; } video::SColor toSColor() const { return video::SColor(255, red, green, blue); } }; // // A Binary File Reader // struct BinaryFileReader { BinaryFileReader(io::IReadFile* pFile) : file(pFile) { } s32 readBuffer(void* buffer, s32 len) { return file->read(buffer,len); } s32 readLong(); f32 readFloat(); void readString(core::stringc &str); void readVec3f(core::vector3df* v); void readVec2f(core::vector2df* v); void readColorRGB(color_rgb_t* color); io::IReadFile *file; }; // // The file header // class Header { public: enum E_CSM_VERSION { VERSION_4 = 4, VERSION_4_1 = 5 }; Header(){ clear(); } s32 getVersion() const { return version; } void clear(){ version = 0; } void load(BinaryFileReader* pReader) { version = pReader->readLong(); } private: s32 version; }; // // The groups // class Group { public: Group(){ clear(); } ~Group(){ clear(); } void clear(); void load(BinaryFileReader* pReader); s32 getFlags() const { return flags; } s32 getParentGroupID() const { return parentGroup; } const core::stringc& getProperties() const { return props; } video::SColor getColor() const { return color.toSColor(); } private: s32 flags; s32 parentGroup; core::stringc props; color_rgb_t color; }; // // The visgroups // class VisGroup { public: VisGroup(){ clear(); } ~VisGroup(){ clear(); } void clear(); void load(BinaryFileReader* pReader); s32 getFlags() const{ return flags; } const core::stringc& getName() const{ return name; } video::SColor getColor() const{ return color.toSColor(); } private: core::stringc name; s32 flags; color_rgb_t color; }; // // Lightmaps // class LightMap { public: LightMap() : pixelData(0){ clear(); } ~LightMap(){ clear(); } void clear(); void load(BinaryFileReader* pReader); s32 getWidth() const{ return width; } s32 getHeight() const{ return height; } s32* getPixelData() const{ return pixelData; } private: s32 width; s32 height; s32* pixelData; }; struct Triangle { s32 a,b,c; }; struct Line { s32 a,b; }; class Vertex { public: Vertex(){ clear(); } ~Vertex(){ clear(); } void clear(); void load(BinaryFileReader* pReader); const core::vector3df& getPosition() const { return position; } const core::vector3df& getNormal() const { return normal; } video::SColor getColor() const { return color.toSColor(); } const core::vector3df& getTextureCoordinates() const { return texCoords; } const core::vector3df& getLightMapCoordinates() const { return lmapCoords; } private: core::vector3df position; core::vector3df normal; color_rgb_t color; core::vector3df texCoords; core::vector3df lmapCoords; }; class Surface { public: Surface() { clear(); } ~Surface(){ clear(); } void clear(); void load(BinaryFileReader *pReader); s32 getFlags() const{ return flags; } const core::stringc& getTextureName() const{ return textureName; } s32 getLightMapId() const{ return lightMapId; } const core::vector2df* getUVOffset() const{ return &uvOffset; } const core::vector2df* getUVScale() const{ return &uvScale; } f32 getUVRotation() const{ return uvRotation; } u32 getVertexCount() const{ return vertices.size(); } const Vertex& getVertexAt(const s32 index) const{ return vertices[index]; } u32 getTriangleCount() const{ return triangles.size(); } const Triangle& getTriangleAt(const s32 index) const{ return triangles[index]; } private: s32 flags; core::stringc textureName; s32 lightMapId; core::vector2df uvOffset; core::vector2df uvScale; f32 uvRotation; core::array vertices; core::array triangles; core::array lines; }; class Mesh { public: Mesh(){ clear(); } ~Mesh(){ clear(); } void clear(); void load(BinaryFileReader* pReader, bool bReadVisGroups); s32 getFlags() const { return flags; } s32 getGroupID() const { return groupId; } const core::stringc& getProperties() const { return props; } video::SColor getColor() const { return color.toSColor(); } const core::vector3df* getPosition() const { return &position; } s32 getVisgroupID() const { return visgroupId; } s32 getSurfaceCount() const { return surfaces.size(); } const Surface* getSurfaceAt(const s32 index) const { return surfaces[index]; } private: s32 flags; s32 groupId; core::stringc props; color_rgb_t color; core::vector3df position; s32 visgroupId; core::array surfaces; }; class Entity { public: Entity() { clear(); } ~Entity() { clear(); } void clear(); void load(BinaryFileReader* pReader); s32 getVisgroupID() const { return visgroupId; } s32 getGroupID() const { return groupId; } const core::stringc& getProperties() const { return props; } const core::vector3df* getPosition() const { return &position; } private: s32 visgroupId; s32 groupId; core::stringc props; core::vector3df position; }; class CameraData { public: CameraData(){ clear(); } ~CameraData(){ clear(); } void clear(); void load(BinaryFileReader* pReader); const core::vector3df* getPosition(){ return &position; } f32 getPitch(){ return pitch; } f32 getYaw(){ return yaw; } private: core::vector3df position; f32 pitch; f32 yaw; }; // // A CSM File // class CSMFile { public: CSMFile(){ clear(); } ~CSMFile(){ clear(); } void clear(); void load(BinaryFileReader* pReader); const Header* getHeader() const{ return &header; } u32 getGroupCount() const{ return groups.size(); } const Group* getGroupAt(const s32 index) const{ return groups[index]; } u32 getVisGroupCount() const{ return visgroups.size(); } const VisGroup* getVisGroupAt(const s32 index) const{ return visgroups[index]; } u32 getLightMapCount() const{ return lightmaps.size(); } const LightMap* getLightMapAt(const s32 index) const { return lightmaps[index]; } u32 getMeshCount() const{ return meshes.size(); } const Mesh* getMeshAt(const s32 index) const{ return meshes[index]; } u32 getEntityCount() const{ return entities.size(); } const Entity* getEntityAt(const s32 index) const{ return entities[index]; } const CameraData* getCameraData() const{ return &cameraData; } private: Header header; core::array groups; core::array visgroups; core::array lightmaps; core::array meshes; core::array entities; CameraData cameraData; }; CCSMLoader::CCSMLoader(scene::ISceneManager* manager, io::IFileSystem* fs) : FileSystem(fs), SceneManager(manager) { #ifdef _DEBUG setDebugName("CCSMLoader"); #endif } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool CCSMLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "csm" ); } //! creates/loads an animated mesh from the file. IAnimatedMesh* CCSMLoader::createMesh(io::IReadFile* file) { scene::IMesh* m = createCSMMesh(file); if (!m) return 0; SAnimatedMesh* am = new SAnimatedMesh(); am->Type = EAMT_CSM; am->addMesh(m); m->drop(); am->recalculateBoundingBox(); return am; } scene::IMesh* CCSMLoader::createCSMMesh(io::IReadFile* file) { if (!file) return 0; BinaryFileReader reader(file); CSMFile csmFile; csmFile.load(&reader); return createIrrlichtMesh(&csmFile, SceneManager->getParameters()->getAttributeAsString(CSM_TEXTURE_PATH), file->getFileName()); } scene::IMesh* CCSMLoader::createIrrlichtMesh(const CSMFile* csmFile, const core::stringc& textureRoot, const io::path& lmprefix) { scene::SMesh *pMesh = new scene::SMesh(); video::IVideoDriver* driver = SceneManager->getVideoDriver(); for(u32 l = 0; lgetLightMapCount(); l++) { const LightMap* lmap = csmFile->getLightMapAt(l); io::path lmapName = lmprefix; lmapName += "LMAP_"; lmapName += io::path(l+1); os::Printer::log("CCSMLoader loading light map", lmapName.c_str()); video::IImage* lmapImg = driver->createImageFromData( video::ECF_A8R8G8B8, core::dimension2d(lmap->getWidth(),lmap->getHeight()), lmap->getPixelData()); driver->addTexture(lmapName.c_str(), lmapImg); lmapImg->drop(); } for(u32 m = 0; mgetMeshCount(); m++) { const Mesh* mshPtr = csmFile->getMeshAt(m); for(s32 s = 0; s < mshPtr->getSurfaceCount(); s++) { const Surface* surface = mshPtr->getSurfaceAt(s); core::stringc texName; if (textureRoot.size()) { texName += textureRoot; texName += "/"; } texName+= surface->getTextureName(); video::ITexture* texture = 0; if (texName.size()) { if (FileSystem->existFile(texName)) texture = driver->getTexture(texName); else if (FileSystem->existFile(surface->getTextureName())) texture = driver->getTexture(surface->getTextureName()); else if (FileSystem->existFile(FileSystem->getFileBasename(surface->getTextureName()))) texture = driver->getTexture(FileSystem->getFileBasename(surface->getTextureName())); else if (FileSystem->existFile(FileSystem->getFileDir(lmprefix)+"/"+surface->getTextureName())) texture = driver->getTexture(FileSystem->getFileDir(lmprefix)+"/"+surface->getTextureName()); else texture = driver->getTexture(FileSystem->getFileDir(lmprefix)+"/"+FileSystem->getFileBasename(surface->getTextureName())); } //material io::path lmapName = lmprefix; lmapName += "LMAP_"; lmapName += io::path(surface->getLightMapId()); scene::SMeshBufferLightMap *buffer = new scene::SMeshBufferLightMap(); buffer->Material.setTexture(0, texture); if (surface->getLightMapId()) { buffer->Material.setTexture(1, driver->getTexture(lmapName)); buffer->Material.Lighting = false; buffer->Material.MaterialType = video::EMT_LIGHTMAP_ADD; } buffer->Vertices.reallocate(surface->getVertexCount()); for(u32 v = 0; v < surface->getVertexCount(); ++v) { const Vertex& vtxPtr = surface->getVertexAt(v); video::S3DVertex2TCoords vtx; vtx.Pos = vtxPtr.getPosition(); vtx.Normal = vtxPtr.getPosition(); vtx.Color=vtxPtr.getColor(); vtx.TCoords.set(vtxPtr.getTextureCoordinates().X, 1.f-vtxPtr.getTextureCoordinates().Y); vtx.TCoords2.set(vtxPtr.getLightMapCoordinates().X, 1.f-vtxPtr.getLightMapCoordinates().Y); buffer->Vertices.push_back(vtx); } buffer->Indices.reallocate(surface->getTriangleCount()*3); for(u32 t = 0; t < surface->getTriangleCount(); ++t) { const Triangle& tri = surface->getTriangleAt(t); buffer->Indices.push_back(tri.c); buffer->Indices.push_back(tri.b); buffer->Indices.push_back(tri.a); } buffer->recalculateBoundingBox(); pMesh->addMeshBuffer(buffer); buffer->drop(); } } pMesh->recalculateBoundingBox(); return pMesh; } void Group::clear() { color.clear(); flags = 0; parentGroup = 0; props = ""; } void Group::load(BinaryFileReader* pReader) { flags = pReader->readLong(); parentGroup = pReader->readLong(); pReader->readString(props); pReader->readColorRGB(&color); } void VisGroup::clear() { color.clear(); flags = 0; name = ""; } void VisGroup::load(BinaryFileReader* pReader) { pReader->readString(name); flags = pReader->readLong(); pReader->readColorRGB(&color); } void LightMap::clear() { delete[] pixelData; pixelData = 0; width = height = 0; } void LightMap::load(BinaryFileReader* pReader) { width = pReader->readLong(); height = pReader->readLong(); pixelData = new s32[width * height]; pReader->readBuffer(pixelData, width * height * sizeof(s32)); } void Mesh::clear() { flags = 0; groupId = 0; visgroupId = 0; props = ""; color.clear(); position.set(0,0,0); for(u32 s = 0; s < surfaces.size(); s++) { delete surfaces[s]; } surfaces.clear(); } void Mesh::load(BinaryFileReader* pReader, bool bReadVisGroups) { flags = pReader->readLong(); groupId = pReader->readLong(); pReader->readString(props); pReader->readColorRGB(&color); pReader->readVec3f(&position); if(bReadVisGroups) visgroupId = pReader->readLong(); else visgroupId = 0; s32 count = pReader->readLong(); for(s32 i = 0; i < count; i++) { Surface* surf = new Surface(); surf->load(pReader); surfaces.push_back(surf); } } void Surface::clear() { flags = 0; lightMapId = 0; textureName = ""; uvOffset.set(0.0f,0.0f); uvScale.set(0.0f,0.0f); uvRotation = 0.0f; triangles.clear(); lines.clear(); vertices.clear(); } void Surface::load(BinaryFileReader* pReader) { flags = pReader->readLong(); pReader->readString(textureName); textureName.replace('\\', '/'); lightMapId = pReader->readLong(); pReader->readVec2f(&uvOffset); pReader->readVec2f(&uvScale); uvRotation = pReader->readFloat(); s32 vtxCount = pReader->readLong(); s32 triCount = pReader->readLong(); s32 lineCount = pReader->readLong(); for(s32 v = 0; v < vtxCount; v++) { vertices.push_back(Vertex()); vertices.getLast().load(pReader); } for(s32 t = 0; t < triCount; t++) { Triangle tri; pReader->readBuffer(&tri, sizeof(tri)); triangles.push_back(tri); } for(s32 l = 0; l < lineCount; l++) { Line line; pReader->readBuffer(&line,sizeof(line)); lines.push_back(line); } } void Vertex::clear() { position.set(0,0,0); normal.set(0,0,0); color.clear(); texCoords.set(0,0,0); lmapCoords.set(0,0,0); } void Vertex::load(BinaryFileReader* pReader) { pReader->readVec3f(&position); pReader->readVec3f(&normal); pReader->readColorRGB(&color); pReader->readVec3f(&texCoords); pReader->readVec3f(&lmapCoords); } void Entity::clear() { visgroupId = groupId = 0; props = ""; position.set(0,0,0); } void Entity::load(BinaryFileReader* pReader) { visgroupId = pReader->readLong(); groupId = pReader->readLong(); pReader->readString(props); pReader->readVec3f(&position); } void CameraData::clear() { position.set(0,0,0); pitch = 0; yaw = 0; } void CameraData::load(BinaryFileReader* pReader) { pReader->readVec3f(&position); pitch = pReader->readFloat(); yaw = pReader->readFloat(); } void CSMFile::clear() { header.clear(); cameraData.clear(); u32 x =0; for( x= 0; x < groups.size(); x++) delete groups[x]; groups.clear(); for(x= 0; x < visgroups.size(); x++) delete visgroups[x]; visgroups.clear(); for(x= 0; x < lightmaps.size(); x++) delete lightmaps[x]; lightmaps.clear(); for(x= 0; x < meshes.size(); x++) delete meshes[x]; meshes.clear(); for(x= 0; x < entities.size(); x++) delete entities[x]; entities.clear(); } void CSMFile::load(BinaryFileReader* pReader) { clear(); header.load(pReader); //groups { const s32 count = pReader->readLong(); #ifdef _IRR_DEBUG_CSM_LOADER_ os::Printer::log("CSM Version", core::stringc(header.getVersion()).c_str()); os::Printer::log("Loading groups. Count", core::stringc(count)); #endif groups.reallocate(count); for (s32 i = 0; i < count; i++) { Group* grp = new Group(); grp->load(pReader); groups.push_back(grp); } } const bool bHasVGroups = (header.getVersion() == Header::VERSION_4_1); if (bHasVGroups) { //visgroups const s32 count = pReader->readLong(); #ifdef _IRR_DEBUG_CSM_LOADER_ os::Printer::log("Loading visgroups. Count", core::stringc(count)); #endif visgroups.reallocate(count); for (s32 i = 0; i < count; i++) { VisGroup* grp = new VisGroup(); grp->load(pReader); visgroups.push_back(grp); } } //lightmaps { const s32 count = pReader->readLong(); #ifdef _IRR_DEBUG_CSM_LOADER_ os::Printer::log("Loading lightmaps. Count", core::stringc(count)); #endif lightmaps.reallocate(count); for(s32 i = 0; i < count; i++) { LightMap* lm = new LightMap(); lm->load(pReader); lightmaps.push_back(lm); } } //meshes { const s32 count = pReader->readLong(); #ifdef _IRR_DEBUG_CSM_LOADER_ os::Printer::log("Loading meshes. Count", core::stringc(count)); #endif meshes.reallocate(count); for(s32 i = 0; i < count; i++) { Mesh* mesh = new Mesh(); mesh->load(pReader,bHasVGroups); meshes.push_back(mesh); } } //entities { const s32 count = pReader->readLong(); #ifdef _IRR_DEBUG_CSM_LOADER_ os::Printer::log("Loading entitites. Count", core::stringc(count)); #endif entities.reallocate(count); for(s32 i = 0; i < count; i++) { Entity* ent = new Entity(); ent->load(pReader); entities.push_back(ent); } } //camera data #ifdef _IRR_DEBUG_CSM_LOADER_ os::Printer::log("Loading camera data."); #endif cameraData.load(pReader); } s32 BinaryFileReader::readLong() { int ret = 0; readBuffer(&ret,sizeof(int)); #ifdef __BIG_ENDIAN__ ret = os::Byteswap::byteswap(ret); #endif return ret; } f32 BinaryFileReader::readFloat() { float ret = 0; readBuffer(&ret,sizeof(float)); #ifdef __BIG_ENDIAN__ ret = os::Byteswap::byteswap(ret); #endif return ret; } void BinaryFileReader::readString(core::stringc &str) { str = ""; c8 c; readBuffer(&c,sizeof(char)); while(c != 0) { str += c; readBuffer(&c,sizeof(char)); } } void BinaryFileReader::readVec3f(core::vector3df* v) { v->X = readFloat(); v->Y = readFloat(); v->Z = readFloat(); } void BinaryFileReader::readVec2f(core::vector2df* v) { v->X = readFloat(); v->Y = readFloat(); } void BinaryFileReader::readColorRGB(color_rgb_t* color) { readBuffer(color,sizeof(color_rgb_t)); } } // end namespace } // end namespace #endif // _IRR_COMPILE_WITH_CSM_LOADER_ irrlicht-1.8.3/source/Irrlicht/CColorConverter.h0000644000000000000000000001042012574354552020354 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_COLOR_CONVERTER_H_INCLUDED__ #define __C_COLOR_CONVERTER_H_INCLUDED__ #include "irrTypes.h" #include "IImage.h" namespace irr { namespace video { class CColorConverter { public: //! converts a monochrome bitmap to A1R5G5B5 static void convert1BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, s32 linepad=0, bool flip=false); //! converts a 4 bit palettized image to A1R5G5B5 static void convert4BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad=0, bool flip=false); //! converts a 8 bit palettized image to A1R5G5B5 static void convert8BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad=0, bool flip=false); //! converts a 8 bit palettized or non palettized image (A8) into R8G8B8 static void convert8BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad = 0, bool flip=false); //! converts a 8 bit palettized or non palettized image (A8) into A8R8G8B8 static void convert8BitTo32Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad = 0, bool flip=false); //! converts R8G8B8 16 bit data to A1R5G5B5 data static void convert16BitTo16Bit(const s16* in, s16* out, s32 width, s32 height, s32 linepad=0, bool flip=false); //! copies R8G8B8 24 bit data to 24 data, and flips and //! mirrors the image during the process. static void convert24BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, s32 linepad=0, bool flip=false, bool bgr=false); //! Resizes the surface to a new size and converts it at the same time //! to an A8R8G8B8 format, returning the pointer to the new buffer. static void convert16bitToA8R8G8B8andResize(const s16* in, s32* out, s32 newWidth, s32 newHeight, s32 currentWidth, s32 currentHeight); //! copies X8R8G8B8 32 bit data, and flips and //! mirrors the image during the process. static void convert32BitTo32Bit(const s32* in, s32* out, s32 width, s32 height, s32 linepad, bool flip=false); //! functions for converting one image format to another efficiently //! and hopefully correctly. //! //! \param sP pointer to source pixel data //! \param sN number of source pixels to copy //! \param dP pointer to destination data buffer. must be big enough //! to hold sN pixels in the output format. static void convert_A1R5G5B5toR8G8B8(const void* sP, s32 sN, void* dP); static void convert_A1R5G5B5toB8G8R8(const void* sP, s32 sN, void* dP); static void convert_A1R5G5B5toA8R8G8B8(const void* sP, s32 sN, void* dP); static void convert_A1R5G5B5toA1R5G5B5(const void* sP, s32 sN, void* dP); static void convert_A1R5G5B5toR5G6B5(const void* sP, s32 sN, void* dP); static void convert_A8R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP); static void convert_A8R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP); static void convert_A8R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP); static void convert_A8R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP); static void convert_A8R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP); static void convert_A8R8G8B8toR3G3B2(const void* sP, s32 sN, void* dP); static void convert_R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP); static void convert_R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP); static void convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP); static void convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP); static void convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP); static void convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP); static void convert_R5G6B5toR5G6B5(const void* sP, s32 sN, void* dP); static void convert_R5G6B5toR8G8B8(const void* sP, s32 sN, void* dP); static void convert_R5G6B5toB8G8R8(const void* sP, s32 sN, void* dP); static void convert_R5G6B5toA8R8G8B8(const void* sP, s32 sN, void* dP); static void convert_R5G6B5toA1R5G5B5(const void* sP, s32 sN, void* dP); static void convert_viaFormat(const void* sP, ECOLOR_FORMAT sF, s32 sN, void* dP, ECOLOR_FORMAT dF); }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CColorConverter.cpp0000644000000000000000000003265412574354552020724 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CColorConverter.h" #include "SColor.h" #include "os.h" #include "irrString.h" namespace irr { namespace video { //! converts a monochrome bitmap to A1R5G5B5 data void CColorConverter::convert1BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, s32 linepad, bool flip) { if (!in || !out) return; if (flip) out += width * height; for (s32 y=0; y>shift & 0x01 ? (s16)0xffff : (s16)0x8000; if ((--shift)<0) // 8 pixel done { shift=7; ++in; } } if (shift != 7) // width did not fill last byte ++in; if (!flip) out += width; in += linepad; } } //! converts a 4 bit palettized image to A1R5G5B5 void CColorConverter::convert4BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad, bool flip) { if (!in || !out || !palette) return; if (flip) out += width*height; for (s32 y=0; y> shift) & 0xf)]); if (shift==0) { shift = 4; ++in; } else shift = 0; } if (shift == 0) // odd width ++in; if (!flip) out += width; in += linepad; } } //! converts a 8 bit palettized image into A1R5G5B5 void CColorConverter::convert8BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad, bool flip) { if (!in || !out || !palette) return; if (flip) out += width * height; for (s32 y=0; y> 15)&0x1)<<31) | (((t >> 10)&0x1F)<<19) | (((t >> 5)&0x1F)<<11) | (t&0x1F)<<3; out[(s32)(y*newWidth + x)] = t; sy+=sourceYStep; } } } //! copies X8R8G8B8 32 bit data void CColorConverter::convert32BitTo32Bit(const s32* in, s32* out, s32 width, s32 height, s32 linepad, bool flip) { if (!in || !out) return; if (flip) out += width * height; for (s32 y=0; y> 7; dB[1] = (*sB & 0x03e0) >> 2; dB[0] = (*sB & 0x1f) << 3; sB += 1; dB += 3; } } void CColorConverter::convert_A1R5G5B5toB8G8R8(const void* sP, s32 sN, void* dP) { u16* sB = (u16*)sP; u8 * dB = (u8 *)dP; for (s32 x = 0; x < sN; ++x) { dB[0] = (*sB & 0x7c00) >> 7; dB[1] = (*sB & 0x03e0) >> 2; dB[2] = (*sB & 0x1f) << 3; sB += 1; dB += 3; } } void CColorConverter::convert_A1R5G5B5toA8R8G8B8(const void* sP, s32 sN, void* dP) { u16* sB = (u16*)sP; u32* dB = (u32*)dP; for (s32 x = 0; x < sN; ++x) *dB++ = A1R5G5B5toA8R8G8B8(*sB++); } void CColorConverter::convert_A1R5G5B5toA1R5G5B5(const void* sP, s32 sN, void* dP) { memcpy(dP, sP, sN * 2); } void CColorConverter::convert_A1R5G5B5toR5G6B5(const void* sP, s32 sN, void* dP) { u16* sB = (u16*)sP; u16* dB = (u16*)dP; for (s32 x = 0; x < sN; ++x) *dB++ = A1R5G5B5toR5G6B5(*sB++); } void CColorConverter::convert_A8R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP) { u8* sB = (u8*)sP; u8* dB = (u8*)dP; for (s32 x = 0; x < sN; ++x) { // sB[3] is alpha dB[0] = sB[2]; dB[1] = sB[1]; dB[2] = sB[0]; sB += 4; dB += 3; } } void CColorConverter::convert_A8R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP) { u8* sB = (u8*)sP; u8* dB = (u8*)dP; for (s32 x = 0; x < sN; ++x) { // sB[3] is alpha dB[0] = sB[0]; dB[1] = sB[1]; dB[2] = sB[2]; sB += 4; dB += 3; } } void CColorConverter::convert_A8R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP) { memcpy(dP, sP, sN * 4); } void CColorConverter::convert_A8R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP) { u32* sB = (u32*)sP; u16* dB = (u16*)dP; for (s32 x = 0; x < sN; ++x) *dB++ = A8R8G8B8toA1R5G5B5(*sB++); } void CColorConverter::convert_A8R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP) { u8 * sB = (u8 *)sP; u16* dB = (u16*)dP; for (s32 x = 0; x < sN; ++x) { s32 r = sB[2] >> 3; s32 g = sB[1] >> 2; s32 b = sB[0] >> 3; dB[0] = (r << 11) | (g << 5) | (b); sB += 4; dB += 1; } } void CColorConverter::convert_A8R8G8B8toR3G3B2(const void* sP, s32 sN, void* dP) { u8* sB = (u8*)sP; u8* dB = (u8*)dP; for (s32 x = 0; x < sN; ++x) { u8 r = sB[2] & 0xe0; u8 g = (sB[1] & 0xe0) >> 3; u8 b = (sB[0] & 0xc0) >> 6; dB[0] = (r | g | b); sB += 4; dB += 1; } } void CColorConverter::convert_R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP) { memcpy(dP, sP, sN * 3); } void CColorConverter::convert_R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP) { u8* sB = (u8* )sP; u32* dB = (u32*)dP; for (s32 x = 0; x < sN; ++x) { *dB = 0xff000000 | (sB[0]<<16) | (sB[1]<<8) | sB[2]; sB += 3; ++dB; } } void CColorConverter::convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP) { u8 * sB = (u8 *)sP; u16* dB = (u16*)dP; for (s32 x = 0; x < sN; ++x) { s32 r = sB[0] >> 3; s32 g = sB[1] >> 3; s32 b = sB[2] >> 3; dB[0] = (0x8000) | (r << 10) | (g << 5) | (b); sB += 3; dB += 1; } } void CColorConverter::convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP) { u8* sB = (u8* )sP; u32* dB = (u32*)dP; for (s32 x = 0; x < sN; ++x) { *dB = 0xff000000 | (sB[2]<<16) | (sB[1]<<8) | sB[0]; sB += 3; ++dB; } } void CColorConverter::convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP) { u8* sB = (u8*)sP; u8* dB = (u8*)dP; for (s32 x = 0; x < sN; ++x) { dB[0] = sB[3]; dB[1] = sB[2]; dB[2] = sB[1]; dB[3] = sB[0]; sB += 4; dB += 4; } } void CColorConverter::convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP) { u8 * sB = (u8 *)sP; u16* dB = (u16*)dP; for (s32 x = 0; x < sN; ++x) { s32 r = sB[0] >> 3; s32 g = sB[1] >> 2; s32 b = sB[2] >> 3; dB[0] = (r << 11) | (g << 5) | (b); sB += 3; dB += 1; } } void CColorConverter::convert_R5G6B5toR5G6B5(const void* sP, s32 sN, void* dP) { memcpy(dP, sP, sN * 2); } void CColorConverter::convert_R5G6B5toR8G8B8(const void* sP, s32 sN, void* dP) { u16* sB = (u16*)sP; u8 * dB = (u8 *)dP; for (s32 x = 0; x < sN; ++x) { dB[0] = (*sB & 0xf800) >> 8; dB[1] = (*sB & 0x07e0) >> 3; dB[2] = (*sB & 0x001f) << 3; sB += 1; dB += 3; } } void CColorConverter::convert_R5G6B5toB8G8R8(const void* sP, s32 sN, void* dP) { u16* sB = (u16*)sP; u8 * dB = (u8 *)dP; for (s32 x = 0; x < sN; ++x) { dB[2] = (*sB & 0xf800) >> 8; dB[1] = (*sB & 0x07e0) >> 3; dB[0] = (*sB & 0x001f) << 3; sB += 1; dB += 3; } } void CColorConverter::convert_R5G6B5toA8R8G8B8(const void* sP, s32 sN, void* dP) { u16* sB = (u16*)sP; u32* dB = (u32*)dP; for (s32 x = 0; x < sN; ++x) *dB++ = R5G6B5toA8R8G8B8(*sB++); } void CColorConverter::convert_R5G6B5toA1R5G5B5(const void* sP, s32 sN, void* dP) { u16* sB = (u16*)sP; u16* dB = (u16*)dP; for (s32 x = 0; x < sN; ++x) *dB++ = R5G6B5toA1R5G5B5(*sB++); } void CColorConverter::convert_viaFormat(const void* sP, ECOLOR_FORMAT sF, s32 sN, void* dP, ECOLOR_FORMAT dF) { switch (sF) { case ECF_A1R5G5B5: switch (dF) { case ECF_A1R5G5B5: convert_A1R5G5B5toA1R5G5B5(sP, sN, dP); break; case ECF_R5G6B5: convert_A1R5G5B5toR5G6B5(sP, sN, dP); break; case ECF_A8R8G8B8: convert_A1R5G5B5toA8R8G8B8(sP, sN, dP); break; case ECF_R8G8B8: convert_A1R5G5B5toR8G8B8(sP, sN, dP); break; #ifndef _DEBUG default: break; #endif } break; case ECF_R5G6B5: switch (dF) { case ECF_A1R5G5B5: convert_R5G6B5toA1R5G5B5(sP, sN, dP); break; case ECF_R5G6B5: convert_R5G6B5toR5G6B5(sP, sN, dP); break; case ECF_A8R8G8B8: convert_R5G6B5toA8R8G8B8(sP, sN, dP); break; case ECF_R8G8B8: convert_R5G6B5toR8G8B8(sP, sN, dP); break; #ifndef _DEBUG default: break; #endif } break; case ECF_A8R8G8B8: switch (dF) { case ECF_A1R5G5B5: convert_A8R8G8B8toA1R5G5B5(sP, sN, dP); break; case ECF_R5G6B5: convert_A8R8G8B8toR5G6B5(sP, sN, dP); break; case ECF_A8R8G8B8: convert_A8R8G8B8toA8R8G8B8(sP, sN, dP); break; case ECF_R8G8B8: convert_A8R8G8B8toR8G8B8(sP, sN, dP); break; #ifndef _DEBUG default: break; #endif } break; case ECF_R8G8B8: switch (dF) { case ECF_A1R5G5B5: convert_R8G8B8toA1R5G5B5(sP, sN, dP); break; case ECF_R5G6B5: convert_R8G8B8toR5G6B5(sP, sN, dP); break; case ECF_A8R8G8B8: convert_R8G8B8toA8R8G8B8(sP, sN, dP); break; case ECF_R8G8B8: convert_R8G8B8toR8G8B8(sP, sN, dP); break; #ifndef _DEBUG default: break; #endif } break; } } } // end namespace video } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CColladaMeshWriter.h0000644000000000000000000002654112574354552020772 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__ #define __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__ #include "IColladaMeshWriter.h" #include "S3DVertex.h" #include "irrMap.h" #include "IVideoDriver.h" namespace irr { namespace io { class IXMLWriter; class IFileSystem; } namespace scene { //! Callback interface for properties which can be used to influence collada writing // (Implementer note: keep namespace labels here to make it easier for users copying this one) class CColladaMeshWriterProperties : public virtual IColladaMeshWriterProperties { public: //! Which lighting model should be used in the technique (FX) section when exporting effects (materials) virtual irr::scene::E_COLLADA_TECHNIQUE_FX getTechniqueFx(const irr::video::SMaterial& material) const; //! Which texture index should be used when writing the texture of the given sampler color. virtual irr::s32 getTextureIdx(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const; //! Return which color from Irrlicht should be used for the color requested by collada virtual irr::scene::E_COLLADA_IRR_COLOR getColorMapping(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const; //! Return custom colors for certain color types requested by collada. virtual irr::video::SColor getCustomColor(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const; //! Return the settings for transparence virtual irr::scene::E_COLLADA_TRANSPARENT_FX getTransparentFx(const irr::video::SMaterial& material) const; //! Transparency value for that material. virtual irr::f32 getTransparency(const irr::video::SMaterial& material) const; //! Reflectivity value for that material virtual irr::f32 getReflectivity(const irr::video::SMaterial& material) const; //! Return index of refraction for that material virtual irr::f32 getIndexOfRefraction(const irr::video::SMaterial& material) const; //! Should node be used in scene export? By default all visible nodes are exported. virtual bool isExportable(const irr::scene::ISceneNode * node) const; //! Return the mesh for the given nod. If it has no mesh or shouldn't export it's mesh return 0. virtual irr::scene::IMesh* getMesh(irr::scene::ISceneNode * node); //! Return if the node has it's own material overwriting the mesh-materials virtual bool useNodeMaterial(const scene::ISceneNode* node) const; }; class CColladaMeshWriterNames : public virtual IColladaMeshWriterNames { public: CColladaMeshWriterNames(IColladaMeshWriter * writer); virtual irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance); virtual irr::core::stringw nameForNode(const scene::ISceneNode* node); virtual irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node); protected: irr::core::stringw nameForPtr(const void* ptr) const; private: IColladaMeshWriter * ColladaMeshWriter; }; //! class to write meshes, implementing a COLLADA (.dae, .xml) writer /** This writer implementation has been originally developed for irrEdit and then merged out to the Irrlicht Engine */ class CColladaMeshWriter : public IColladaMeshWriter { public: CColladaMeshWriter(ISceneManager * smgr, video::IVideoDriver* driver, io::IFileSystem* fs); virtual ~CColladaMeshWriter(); //! Returns the type of the mesh writer virtual EMESH_WRITER_TYPE getType() const; //! writes a scene starting with the given node virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root); //! writes a mesh virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE); // Restrict the characters of oldString a set of allowed characters in xs::NCName and add the prefix. virtual irr::core::stringw toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix=irr::core::stringw(L"_NC_")) const; protected: void reset(); bool hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const; void writeUv(const irr::core::vector2df& vec); void writeVector(const irr::core::vector2df& vec); void writeVector(const irr::core::vector3df& vec); void writeColor(const irr::video::SColorf& colorf, bool writeAlpha=true); inline irr::core::stringw toString(const irr::video::ECOLOR_FORMAT format) const; inline irr::core::stringw toString(const irr::video::E_TEXTURE_CLAMP clamp) const; inline irr::core::stringw toString(const irr::scene::E_COLLADA_TRANSPARENT_FX opaque) const; inline irr::core::stringw toRef(const irr::core::stringw& source) const; bool isCamera(const scene::ISceneNode* node) const; irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance) const; irr::core::stringw nameForNode(const scene::ISceneNode* node) const; irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node); irr::core::stringw nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const; irr::core::stringw findCachedMaterialName(const irr::video::SMaterial& material) const; irr::core::stringw minTexfilterToString(bool bilinear, bool trilinear) const; irr::core::stringw magTexfilterToString(bool bilinear, bool trilinear) const; irr::core::stringw pathToURI(const irr::io::path& path) const; inline bool isXmlNameStartChar(wchar_t c) const; inline bool isXmlNameChar(wchar_t c) const; s32 getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs); video::SColor getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType); void writeAsset(); void makeMeshNames(irr::scene::ISceneNode * node); void writeNodeMaterials(irr::scene::ISceneNode * node); void writeNodeEffects(irr::scene::ISceneNode * node); void writeNodeLights(irr::scene::ISceneNode * node); void writeNodeCameras(irr::scene::ISceneNode * node); void writeAllMeshGeometries(); void writeSceneNode(irr::scene::ISceneNode * node); void writeMeshMaterials(scene::IMesh* mesh, irr::core::array * materialNamesOut=0); void writeMeshEffects(scene::IMesh* mesh); void writeMaterialEffect(const irr::core::stringw& materialname, const video::SMaterial & material); void writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh); void writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node=0); void writeMaterial(const irr::core::stringw& materialname); void writeLightInstance(const irr::core::stringw& lightName); void writeCameraInstance(const irr::core::stringw& cameraName); void writeLibraryImages(); void writeColorFx(const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name=0, const wchar_t* attr1Value=0); void writeAmbientLightElement(const video::SColorf & col); void writeColorElement(const video::SColor & col, bool writeAlpha=true); void writeColorElement(const video::SColorf & col, bool writeAlpha=true); void writeTextureSampler(s32 textureIdx); void writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx); void writeNode(const wchar_t * nodeName, const wchar_t * content); void writeFloatElement(irr::f32 value); void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle); void writeScaleElement(const irr::core::vector3df& scale); void writeTranslateElement(const irr::core::vector3df& translate); void writeMatrixElement(const irr::core::matrix4& matrix); struct SComponentGlobalStartPos { SComponentGlobalStartPos() : PosStartIndex(-1), PosLastIndex(-1), NormalStartIndex(-1), NormalLastIndex(-1), TCoord0StartIndex(-1), TCoord0LastIndex(-1), TCoord1StartIndex(-1), TCoord1LastIndex(-1) { } s32 PosStartIndex; s32 PosLastIndex; s32 NormalStartIndex; s32 NormalLastIndex; s32 TCoord0StartIndex; s32 TCoord0LastIndex; s32 TCoord1StartIndex; s32 TCoord1LastIndex; }; io::IFileSystem* FileSystem; video::IVideoDriver* VideoDriver; io::IXMLWriter* Writer; core::array LibraryImages; io::path Directory; // Helper struct for creating geometry copies for the ECGI_PER_MESH_AND_MATERIAL settings. struct SGeometryMeshMaterials { bool equals(const core::array& names) const { if ( names.size() != MaterialNames.size() ) return false; for ( irr::u32 i=0; i MaterialNames; // Material names exported for this instance core::array MaterialOwners; // Nodes using this specific mesh-material combination }; // Check per mesh-ptr if stuff has been written for this mesh already struct SColladaMesh { SColladaMesh() : MaterialsWritten(false), EffectsWritten(false) { } SGeometryMeshMaterials * findGeometryMeshMaterials(const irr::core::array materialNames) { for ( irr::u32 i=0; i= 0 ) return GeometryMeshMaterials[i].GeometryName; } return Name; // (shouldn't get here usually) } irr::core::stringw Name; bool MaterialsWritten; // just an optimization doing that here in addition to the MaterialsWritten map bool EffectsWritten; // just an optimization doing that here in addition to the EffectsWritten map core::array GeometryMeshMaterials; }; typedef core::map::Node MeshNode; core::map Meshes; // structure for the lights library struct SColladaLight { SColladaLight() {} irr::core::stringw Name; }; typedef core::map::Node LightNode; core::map LightNodes; // structure for the camera library typedef core::map::Node CameraNode; core::map CameraNodes; // Check per name if stuff has been written already // TODO: second parameter not needed, we just don't have a core::set class yet in Irrlicht core::map MaterialsWritten; core::map EffectsWritten; // Cache material names struct MaterialName { MaterialName(const irr::video::SMaterial & material, const irr::core::stringw& name) : Material(material), Name(name) {} irr::video::SMaterial Material; irr::core::stringw Name; }; irr::core::array< MaterialName > MaterialNameCache; }; } // end namespace } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/CColladaMeshWriter.cpp0000644000000000000000000020211212574354552021313 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // TODO: second UV-coordinates currently ignored in textures #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_ #include "CColladaMeshWriter.h" #include "os.h" #include "IFileSystem.h" #include "IWriteFile.h" #include "IXMLWriter.h" #include "IMesh.h" #include "IAttributes.h" #include "IAnimatedMeshSceneNode.h" #include "IMeshSceneNode.h" #include "ITerrainSceneNode.h" #include "ILightSceneNode.h" #include "ICameraSceneNode.h" #include "ISceneManager.h" namespace irr { namespace scene { //! Which lighting model should be used in the technique (FX) section when exporting effects (materials) E_COLLADA_TECHNIQUE_FX CColladaMeshWriterProperties::getTechniqueFx(const video::SMaterial& material) const { return ECTF_BLINN; } //! Which texture index should be used when writing the texture of the given sampler color. s32 CColladaMeshWriterProperties::getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const { // So far we just export in a way which is similar to how we import colladas. // There might be better ways to do this, but I suppose it depends a lot for which target // application we export, so in most cases it will have to be done in user-code anyway. switch ( cs ) { case ECCS_DIFFUSE: return 2; case ECCS_AMBIENT: return 1; case ECCS_EMISSIVE: return 0; case ECCS_SPECULAR: return 3; case ECCS_TRANSPARENT: return -1; case ECCS_REFLECTIVE: return -1; }; return -1; } E_COLLADA_IRR_COLOR CColladaMeshWriterProperties::getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const { switch ( cs ) { case ECCS_DIFFUSE: return ECIC_DIFFUSE; case ECCS_AMBIENT: return ECIC_AMBIENT; case ECCS_EMISSIVE: return ECIC_EMISSIVE; case ECCS_SPECULAR: return ECIC_SPECULAR; case ECCS_TRANSPARENT: return ECIC_NONE; case ECCS_REFLECTIVE: return ECIC_CUSTOM; }; return ECIC_NONE; } //! Return custom colors for certain color types requested by collada. video::SColor CColladaMeshWriterProperties::getCustomColor(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const { return video::SColor(255, 0, 0, 0); } //! Return the settings for transparence E_COLLADA_TRANSPARENT_FX CColladaMeshWriterProperties::getTransparentFx(const video::SMaterial& material) const { // TODO: figure out best default mapping return ECOF_A_ONE; } //! Transparency value for the material. f32 CColladaMeshWriterProperties::getTransparency(const video::SMaterial& material) const { // TODO: figure out best default mapping return -1.f; } //! Reflectivity value for that material f32 CColladaMeshWriterProperties::getReflectivity(const video::SMaterial& material) const { // TODO: figure out best default mapping return 0.f; } //! Return index of refraction for that material f32 CColladaMeshWriterProperties::getIndexOfRefraction(const video::SMaterial& material) const { return -1.f; } bool CColladaMeshWriterProperties::isExportable(const irr::scene::ISceneNode * node) const { return node && node->isVisible(); } IMesh* CColladaMeshWriterProperties::getMesh(irr::scene::ISceneNode * node) { if ( !node ) return 0; if ( node->getType() == ESNT_ANIMATED_MESH ) return static_cast(node)->getMesh()->getMesh(0); // TODO: we need some ISceneNode::hasType() function to get rid of those checks if ( node->getType() == ESNT_MESH || node->getType() == ESNT_CUBE || node->getType() == ESNT_SPHERE || node->getType() == ESNT_WATER_SURFACE || node->getType() == ESNT_Q3SHADER_SCENE_NODE ) return static_cast(node)->getMesh(); if ( node->getType() == ESNT_TERRAIN ) return static_cast(node)->getMesh(); return 0; } // Check if the node has it's own material overwriting the mesh-materials bool CColladaMeshWriterProperties::useNodeMaterial(const scene::ISceneNode* node) const { if ( !node ) return false; // TODO: we need some ISceneNode::hasType() function to get rid of those checks bool useMeshMaterial = ( (node->getType() == ESNT_MESH || node->getType() == ESNT_CUBE || node->getType() == ESNT_SPHERE || node->getType() == ESNT_WATER_SURFACE || node->getType() == ESNT_Q3SHADER_SCENE_NODE) && static_cast(node)->isReadOnlyMaterials()) || (node->getType() == ESNT_ANIMATED_MESH && static_cast(node)->isReadOnlyMaterials() ); return !useMeshMaterial; } CColladaMeshWriterNames::CColladaMeshWriterNames(IColladaMeshWriter * writer) : ColladaMeshWriter(writer) { } irr::core::stringw CColladaMeshWriterNames::nameForMesh(const scene::IMesh* mesh, int instance) { irr::core::stringw name(L"mesh"); name += nameForPtr(mesh); if ( instance > 0 ) { name += L"i"; name += irr::core::stringw(instance); } return ColladaMeshWriter->toNCName(name); } irr::core::stringw CColladaMeshWriterNames::nameForNode(const scene::ISceneNode* node) { irr::core::stringw name; // Prefix, because xs::ID can't start with a number, also nicer name if ( node && node->getType() == ESNT_LIGHT ) name = L"light"; else name = L"node"; name += nameForPtr(node); if ( node ) { name += irr::core::stringw(node->getName()); } return ColladaMeshWriter->toNCName(name); } irr::core::stringw CColladaMeshWriterNames::nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) { core::stringw strMat(L"mat"); bool nodeMaterial = ColladaMeshWriter->getProperties()->useNodeMaterial(node); if ( nodeMaterial ) { strMat += L"node"; strMat += nameForPtr(node); strMat += irr::core::stringw(node->getName()); } strMat += L"mesh"; strMat += nameForPtr(mesh); strMat += materialId; return ColladaMeshWriter->toNCName(strMat); } irr::core::stringw CColladaMeshWriterNames::nameForPtr(const void* ptr) const { wchar_t buf[32]; swprintf(buf, 32, L"%p", ptr); return irr::core::stringw(buf); } CColladaMeshWriter::CColladaMeshWriter( ISceneManager * smgr, video::IVideoDriver* driver, io::IFileSystem* fs) : FileSystem(fs), VideoDriver(driver), Writer(0) { #ifdef _DEBUG setDebugName("CColladaMeshWriter"); #endif if (VideoDriver) VideoDriver->grab(); if (FileSystem) FileSystem->grab(); if ( smgr ) setAmbientLight( smgr->getAmbientLight() ); CColladaMeshWriterProperties * p = new CColladaMeshWriterProperties(); setDefaultProperties(p); setProperties(p); p->drop(); CColladaMeshWriterNames * nameGenerator = new CColladaMeshWriterNames(this); setDefaultNameGenerator(nameGenerator); setNameGenerator(nameGenerator); nameGenerator->drop(); } CColladaMeshWriter::~CColladaMeshWriter() { if (VideoDriver) VideoDriver->drop(); if (FileSystem) FileSystem->drop(); } void CColladaMeshWriter::reset() { LibraryImages.clear(); Meshes.clear(); LightNodes.clear(); CameraNodes.clear(); MaterialsWritten.clear(); EffectsWritten.clear(); MaterialNameCache.clear(); } //! Returns the type of the mesh writer EMESH_WRITER_TYPE CColladaMeshWriter::getType() const { return EMWT_COLLADA; } //! writes a scene starting with the given node bool CColladaMeshWriter::writeScene(io::IWriteFile* file, scene::ISceneNode* root) { if (!file || !root) return false; reset(); Writer = FileSystem->createXMLWriter(file); if (!Writer) { os::Printer::log("Could not write file", file->getFileName()); return false; } Directory = FileSystem->getFileDir(FileSystem->getAbsolutePath( file->getFileName() )); // make names for all nodes with exportable meshes makeMeshNames(root); os::Printer::log("Writing scene", file->getFileName()); // write COLLADA header Writer->writeXMLHeader(); Writer->writeElement(L"COLLADA", false, L"xmlns", L"http://www.collada.org/2005/11/COLLADASchema", L"version", L"1.4.1"); Writer->writeLineBreak(); // write asset data writeAsset(); // write all materials Writer->writeElement(L"library_materials", false); Writer->writeLineBreak(); writeNodeMaterials(root); Writer->writeClosingTag(L"library_materials"); Writer->writeLineBreak(); Writer->writeElement(L"library_effects", false); Writer->writeLineBreak(); writeNodeEffects(root); Writer->writeClosingTag(L"library_effects"); Writer->writeLineBreak(); // images writeLibraryImages(); // lights Writer->writeElement(L"library_lights", false); Writer->writeLineBreak(); writeAmbientLightElement( getAmbientLight() ); writeNodeLights(root); Writer->writeClosingTag(L"library_lights"); Writer->writeLineBreak(); // cameras Writer->writeElement(L"library_cameras", false); Writer->writeLineBreak(); writeNodeCameras(root); Writer->writeClosingTag(L"library_cameras"); Writer->writeLineBreak(); // write meshes Writer->writeElement(L"library_geometries", false); Writer->writeLineBreak(); writeAllMeshGeometries(); Writer->writeClosingTag(L"library_geometries"); Writer->writeLineBreak(); // write scene Writer->writeElement(L"library_visual_scenes", false); Writer->writeLineBreak(); Writer->writeElement(L"visual_scene", false, L"id", L"default_scene"); Writer->writeLineBreak(); // ambient light (instance_light also needs a node as parent so we have to create one) Writer->writeElement(L"node", false); Writer->writeLineBreak(); Writer->writeElement(L"instance_light", true, L"url", L"#ambientlight"); Writer->writeLineBreak(); Writer->writeClosingTag(L"node"); Writer->writeLineBreak(); // Write the scenegraph. if ( root->getType() != ESNT_SCENE_MANAGER ) { // TODO: Not certain if we should really write the root or if we should just always only write the children. // For now writing root to keep backward compatibility for this case, but if anyone needs to _not_ write // that root-node we can add a parameter for this later on in writeScene. writeSceneNode(root); } else { // The visual_scene element is identical to our scenemanager and acts as root, // so we do not write the root itself if it points to the scenemanager. const core::list& rootChildren = root->getChildren(); for ( core::list::ConstIterator it = rootChildren.begin(); it != rootChildren.end(); ++ it ) { writeSceneNode(*it); } } Writer->writeClosingTag(L"visual_scene"); Writer->writeLineBreak(); Writer->writeClosingTag(L"library_visual_scenes"); Writer->writeLineBreak(); // instance scene Writer->writeElement(L"scene", false); Writer->writeLineBreak(); Writer->writeElement(L"instance_visual_scene", true, L"url", L"#default_scene"); Writer->writeLineBreak(); Writer->writeClosingTag(L"scene"); Writer->writeLineBreak(); // close everything Writer->writeClosingTag(L"COLLADA"); Writer->drop(); return true; } void CColladaMeshWriter::makeMeshNames(irr::scene::ISceneNode * node) { if ( !node || !getProperties() || !getProperties()->isExportable(node) || !getNameGenerator()) return; IMesh* mesh = getProperties()->getMesh(node); if ( mesh ) { if ( !Meshes.find(mesh) ) { SColladaMesh cm; cm.Name = nameForMesh(mesh, 0); Meshes.insert(mesh, cm); } } const core::list& children = node->getChildren(); for ( core::list::ConstIterator it = children.begin(); it != children.end(); ++it ) { makeMeshNames(*it); } } void CColladaMeshWriter::writeNodeMaterials(irr::scene::ISceneNode * node) { if ( !node || !getProperties() || !getProperties()->isExportable(node) ) return; core::array materialNames; IMesh* mesh = getProperties()->getMesh(node); if ( mesh ) { MeshNode * n = Meshes.find(mesh); if ( !getProperties()->useNodeMaterial(node) ) { // no material overrides - write mesh materials if ( n && !n->getValue().MaterialsWritten ) { writeMeshMaterials(mesh, getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL ? &materialNames : NULL); n->getValue().MaterialsWritten = true; } } else { // write node materials for (u32 i=0; igetMaterialCount(); ++i) { video::SMaterial & material = node->getMaterial(i); core::stringw strMat(nameForMaterial(material, i, mesh, node)); writeMaterial(strMat); if ( getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL ) materialNames.push_back(strMat); } } // When we write another mesh-geometry for each new material-list we have // to figure out here if we need another geometry copy and create a new name here. if ( n && getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL ) { SGeometryMeshMaterials * geomMat = n->getValue().findGeometryMeshMaterials(materialNames); if ( geomMat ) geomMat->MaterialOwners.push_back(node); else { SGeometryMeshMaterials gmm; if ( n->getValue().GeometryMeshMaterials.empty() ) gmm.GeometryName = n->getValue().Name; // first one can use the original name else gmm.GeometryName = nameForMesh(mesh, n->getValue().GeometryMeshMaterials.size()); gmm.MaterialNames = materialNames; gmm.MaterialOwners.push_back(node); n->getValue().GeometryMeshMaterials.push_back(gmm); } } } const core::list& children = node->getChildren(); for ( core::list::ConstIterator it = children.begin(); it != children.end(); ++it ) { writeNodeMaterials( *it ); } } void CColladaMeshWriter::writeMaterial(const irr::core::stringw& materialname) { if ( MaterialsWritten.find(materialname) ) return; MaterialsWritten.insert(materialname, true); Writer->writeElement(L"material", false, L"id", materialname.c_str(), L"name", materialname.c_str()); Writer->writeLineBreak(); // We don't make a difference between material and effect on export. // Every material is just using an instance of an effect. core::stringw strFx(materialname); strFx += L"-fx"; Writer->writeElement(L"instance_effect", true, L"url", (core::stringw(L"#") + strFx).c_str()); Writer->writeLineBreak(); Writer->writeClosingTag(L"material"); Writer->writeLineBreak(); } void CColladaMeshWriter::writeNodeEffects(irr::scene::ISceneNode * node) { if ( !node || !getProperties() || !getProperties()->isExportable(node) || !getNameGenerator() ) return; IMesh* mesh = getProperties()->getMesh(node); if ( mesh ) { if ( !getProperties()->useNodeMaterial(node) ) { // no material overrides - write mesh materials MeshNode * n = Meshes.find(mesh); if ( n && !n->getValue().EffectsWritten ) { writeMeshEffects(mesh); n->getValue().EffectsWritten = true; } } else { // write node materials for (u32 i=0; igetMaterialCount(); ++i) { video::SMaterial & material = node->getMaterial(i); irr::core::stringw materialfxname(nameForMaterial(material, i, mesh, node)); materialfxname += L"-fx"; writeMaterialEffect(materialfxname, material); } } } const core::list& children = node->getChildren(); for ( core::list::ConstIterator it = children.begin(); it != children.end(); ++it ) { writeNodeEffects( *it ); } } void CColladaMeshWriter::writeNodeLights(irr::scene::ISceneNode * node) { if ( !node || !getProperties() || !getProperties()->isExportable(node)) return; if ( node->getType() == ESNT_LIGHT ) { ILightSceneNode * lightNode = static_cast(node); const video::SLight& lightData = lightNode->getLightData(); SColladaLight cLight; cLight.Name = nameForNode(node); LightNodes.insert(node, cLight); Writer->writeElement(L"light", false, L"id", cLight.Name.c_str()); Writer->writeLineBreak(); Writer->writeElement(L"technique_common", false); Writer->writeLineBreak(); switch ( lightNode->getLightType() ) { case video::ELT_POINT: Writer->writeElement(L"point", false); Writer->writeLineBreak(); writeColorElement(lightData.DiffuseColor, false); writeNode(L"constant_attenuation ", core::stringw(lightData.Attenuation.X).c_str()); writeNode(L"linear_attenuation ", core::stringw(lightData.Attenuation.Y).c_str()); writeNode(L"quadratic_attenuation", core::stringw(lightData.Attenuation.Z).c_str()); Writer->writeClosingTag(L"point"); Writer->writeLineBreak(); break; case video::ELT_SPOT: Writer->writeElement(L"spot", false); Writer->writeLineBreak(); writeColorElement(lightData.DiffuseColor, false); writeNode(L"constant_attenuation ", core::stringw(lightData.Attenuation.X).c_str()); writeNode(L"linear_attenuation ", core::stringw(lightData.Attenuation.Y).c_str()); writeNode(L"quadratic_attenuation", core::stringw(lightData.Attenuation.Z).c_str()); writeNode(L"falloff_angle", core::stringw(lightData.OuterCone * core::RADTODEG).c_str()); writeNode(L"falloff_exponent", core::stringw(lightData.Falloff).c_str()); Writer->writeClosingTag(L"spot"); Writer->writeLineBreak(); break; case video::ELT_DIRECTIONAL: Writer->writeElement(L"directional", false); Writer->writeLineBreak(); writeColorElement(lightData.DiffuseColor, false); Writer->writeClosingTag(L"directional"); Writer->writeLineBreak(); break; default: break; } Writer->writeClosingTag(L"technique_common"); Writer->writeLineBreak(); Writer->writeClosingTag(L"light"); Writer->writeLineBreak(); } const core::list& children = node->getChildren(); for ( core::list::ConstIterator it = children.begin(); it != children.end(); ++it ) { writeNodeLights( *it ); } } void CColladaMeshWriter::writeNodeCameras(irr::scene::ISceneNode * node) { if ( !node || !getProperties() || !getProperties()->isExportable(node) ) return; if ( isCamera(node) ) { ICameraSceneNode * cameraNode = static_cast(node); irr::core::stringw name = nameForNode(node); CameraNodes.insert(cameraNode, name); Writer->writeElement(L"camera", false, L"id", name.c_str()); Writer->writeLineBreak(); Writer->writeElement(L"optics", false); Writer->writeLineBreak(); Writer->writeElement(L"technique_common", false); Writer->writeLineBreak(); if ( cameraNode->isOrthogonal() ) { Writer->writeElement(L"orthographic", false); Writer->writeLineBreak(); // writeNode(L"xmag", core::stringw("1.0").c_str()); // TODO: do we need xmag, ymag? // writeNode(L"ymag", core::stringw("1.0").c_str()); writeNode(L"aspect_ratio", core::stringw(cameraNode->getAspectRatio()).c_str()); writeNode(L"znear", core::stringw(cameraNode->getNearValue()).c_str()); writeNode(L"zfar", core::stringw(cameraNode->getFarValue()).c_str()); Writer->writeClosingTag(L"orthographic"); Writer->writeLineBreak(); } else { Writer->writeElement(L"perspective", false); Writer->writeLineBreak(); writeNode(L"yfov", core::stringw(cameraNode->getFOV()*core::RADTODEG).c_str()); writeNode(L"aspect_ratio", core::stringw(cameraNode->getAspectRatio()).c_str()); writeNode(L"znear", core::stringw(cameraNode->getNearValue()).c_str()); writeNode(L"zfar", core::stringw(cameraNode->getFarValue()).c_str()); Writer->writeClosingTag(L"perspective"); Writer->writeLineBreak(); } Writer->writeClosingTag(L"technique_common"); Writer->writeLineBreak(); Writer->writeClosingTag(L"optics"); Writer->writeLineBreak(); Writer->writeClosingTag(L"camera"); Writer->writeLineBreak(); } const core::list& children = node->getChildren(); for ( core::list::ConstIterator it = children.begin(); it != children.end(); ++it ) { writeNodeCameras( *it ); } } void CColladaMeshWriter::writeAllMeshGeometries() { core::map::ConstIterator it = Meshes.getConstIterator(); for(; !it.atEnd(); it++ ) { IMesh* mesh = it->getKey(); const SColladaMesh& colladaMesh = it->getValue(); if ( getGeometryWriting() == ECGI_PER_MESH_AND_MATERIAL && colladaMesh.GeometryMeshMaterials.size() > 1 ) { for ( u32 i=0; iisExportable(node) ) return; // Collada doesn't require to set the id, but some other tools have problems if none exists, so we just add it. irr::core::stringw nameId(nameForNode(node)); Writer->writeElement(L"node", false, L"id", nameId.c_str()); Writer->writeLineBreak(); // DummyTransformationSceneNode don't have rotation, position, scale information // But also don't always export the transformation matrix as that forces us creating // new DummyTransformationSceneNode's on import. if ( node->getType() == ESNT_DUMMY_TRANSFORMATION ) { writeMatrixElement(node->getRelativeTransformation()); } else { irr::core::vector3df rot(node->getRotation()); if ( isCamera(node) && !static_cast(node)->getTargetAndRotationBinding() ) { ICameraSceneNode * camNode = static_cast(node); const core::vector3df toTarget = camNode->getTarget() - camNode->getAbsolutePosition(); rot = toTarget.getHorizontalAngle(); } writeTranslateElement( node->getPosition() ); writeRotateElement( irr::core::vector3df(1.f, 0.f, 0.f), rot.X ); writeRotateElement( irr::core::vector3df(0.f, 1.f, 0.f), rot.Y ); writeRotateElement( irr::core::vector3df(0.f, 0.f, 1.f), rot.Z ); writeScaleElement( node->getScale() ); } // instance geometry IMesh* mesh = getProperties()->getMesh(node); if ( mesh ) { MeshNode * n = Meshes.find(mesh); if ( n ) { const SColladaMesh& colladaMesh = n->getValue(); writeMeshInstanceGeometry(colladaMesh.findGeometryNameForNode(node), mesh, node); } } // instance light if ( node->getType() == ESNT_LIGHT ) { LightNode * n = LightNodes.find(node); if ( n ) writeLightInstance(n->getValue().Name); } // instance camera if ( isCamera(node) ) { CameraNode * camNode = CameraNodes.find(node); if ( camNode ) writeCameraInstance(camNode->getValue()); } const core::list& children = node->getChildren(); for ( core::list::ConstIterator it = children.begin(); it != children.end(); ++it ) { writeSceneNode( *it ); } Writer->writeClosingTag(L"node"); Writer->writeLineBreak(); } //! writes a mesh bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { if (!file) return false; reset(); Writer = FileSystem->createXMLWriter(file); if (!Writer) { os::Printer::log("Could not write file", file->getFileName()); return false; } Directory = FileSystem->getFileDir(FileSystem->getAbsolutePath( file->getFileName() )); os::Printer::log("Writing mesh", file->getFileName()); // write COLLADA header Writer->writeXMLHeader(); Writer->writeElement(L"COLLADA", false, L"xmlns", L"http://www.collada.org/2005/11/COLLADASchema", L"version", L"1.4.1"); Writer->writeLineBreak(); // write asset data writeAsset(); // write all materials Writer->writeElement(L"library_materials", false); Writer->writeLineBreak(); writeMeshMaterials(mesh); Writer->writeClosingTag(L"library_materials"); Writer->writeLineBreak(); Writer->writeElement(L"library_effects", false); Writer->writeLineBreak(); writeMeshEffects(mesh); Writer->writeClosingTag(L"library_effects"); Writer->writeLineBreak(); // images writeLibraryImages(); // write mesh Writer->writeElement(L"library_geometries", false); Writer->writeLineBreak(); irr::core::stringw meshname(nameForMesh(mesh, 0)); writeMeshGeometry(meshname, mesh); Writer->writeClosingTag(L"library_geometries"); Writer->writeLineBreak(); // write scene_library if ( getWriteDefaultScene() ) { Writer->writeElement(L"library_visual_scenes", false); Writer->writeLineBreak(); Writer->writeElement(L"visual_scene", false, L"id", L"default_scene"); Writer->writeLineBreak(); Writer->writeElement(L"node", false); Writer->writeLineBreak(); writeMeshInstanceGeometry(meshname, mesh); Writer->writeClosingTag(L"node"); Writer->writeLineBreak(); Writer->writeClosingTag(L"visual_scene"); Writer->writeLineBreak(); Writer->writeClosingTag(L"library_visual_scenes"); Writer->writeLineBreak(); // write scene Writer->writeElement(L"scene", false); Writer->writeLineBreak(); Writer->writeElement(L"instance_visual_scene", true, L"url", L"#default_scene"); Writer->writeLineBreak(); Writer->writeClosingTag(L"scene"); Writer->writeLineBreak(); } // close everything Writer->writeClosingTag(L"COLLADA"); Writer->drop(); return true; } void CColladaMeshWriter::writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node) { // Writer->writeElement(L"instance_geometry", false, L"url", toRef(meshname).c_str()); Writer->writeLineBreak(); Writer->writeElement(L"bind_material", false); Writer->writeLineBreak(); Writer->writeElement(L"technique_common", false); Writer->writeLineBreak(); // instance materials // bool useNodeMaterials = node && node->getMaterialCount() == mesh->getMeshBufferCount(); for (u32 i=0; igetMeshBufferCount(); ++i) { irr::core::stringw strMatSymbol(nameForMaterialSymbol(mesh, i)); core::stringw strMatTarget = "#"; video::SMaterial & material = useNodeMaterials ? node->getMaterial(i) : mesh->getMeshBuffer(i)->getMaterial(); strMatTarget += nameForMaterial(material, i, mesh, node); Writer->writeElement(L"instance_material", false, L"symbol", strMatSymbol.c_str(), L"target", strMatTarget.c_str()); Writer->writeLineBreak(); // TODO: need to handle second UV-set // Writer->writeElement(L"bind_vertex_input", true, L"semantic", L"uv", L"input_semantic", L"TEXCOORD", L"input_set", L"0" ); Writer->writeLineBreak(); Writer->writeClosingTag(L"instance_material"); Writer->writeLineBreak(); } Writer->writeClosingTag(L"technique_common"); Writer->writeLineBreak(); Writer->writeClosingTag(L"bind_material"); Writer->writeLineBreak(); Writer->writeClosingTag(L"instance_geometry"); Writer->writeLineBreak(); } void CColladaMeshWriter::writeLightInstance(const irr::core::stringw& lightName) { Writer->writeElement(L"instance_light", true, L"url", toRef(lightName).c_str()); Writer->writeLineBreak(); } void CColladaMeshWriter::writeCameraInstance(const irr::core::stringw& cameraName) { Writer->writeElement(L"instance_camera", true, L"url", toRef(cameraName).c_str()); Writer->writeLineBreak(); } bool CColladaMeshWriter::hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const { return type == video::EVT_2TCOORDS; } void CColladaMeshWriter::writeVector(const irr::core::vector3df& vec) { wchar_t tmpbuf[255]; swprintf(tmpbuf, 255, L"%f %f %f", vec.X, vec.Y, vec.Z); Writer->writeText(tmpbuf); } void CColladaMeshWriter::writeUv(const irr::core::vector2df& vec) { // change handedness wchar_t tmpbuf[255]; swprintf(tmpbuf, 255, L"%f %f", vec.X, 1.f-vec.Y); Writer->writeText(tmpbuf); } void CColladaMeshWriter::writeVector(const irr::core::vector2df& vec) { wchar_t tmpbuf[255]; swprintf(tmpbuf, 255, L"%f %f", vec.X, vec.Y); Writer->writeText(tmpbuf); } void CColladaMeshWriter::writeColor(const irr::video::SColorf& colorf, bool writeAlpha) { wchar_t tmpbuf[255]; if ( writeAlpha ) swprintf(tmpbuf, 255, L"%f %f %f %f", colorf.getRed(), colorf.getGreen(), colorf.getBlue(), colorf.getAlpha()); else swprintf(tmpbuf, 255, L"%f %f %f", colorf.getRed(), colorf.getGreen(), colorf.getBlue()); Writer->writeText(tmpbuf); } irr::core::stringw CColladaMeshWriter::toString(const irr::video::ECOLOR_FORMAT format) const { switch ( format ) { case video::ECF_A1R5G5B5: return irr::core::stringw(L"A1R5G5B5"); case video::ECF_R5G6B5: return irr::core::stringw(L"R5G6B5"); case video::ECF_R8G8B8: return irr::core::stringw(L"R8G8B8"); case video::ECF_A8R8G8B8: return irr::core::stringw(L"A8R8G8B8"); default: return irr::core::stringw(L""); } } irr::core::stringw CColladaMeshWriter::toString(const irr::video::E_TEXTURE_CLAMP clamp) const { switch ( clamp ) { case video::ETC_REPEAT: return core::stringw(L"WRAP"); case video::ETC_CLAMP: case video::ETC_CLAMP_TO_EDGE: return core::stringw(L"CLAMP"); case video::ETC_CLAMP_TO_BORDER: return core::stringw(L"BORDER"); case video::ETC_MIRROR: case video::ETC_MIRROR_CLAMP: case video::ETC_MIRROR_CLAMP_TO_EDGE: case video::ETC_MIRROR_CLAMP_TO_BORDER: return core::stringw(L"MIRROR"); } return core::stringw(L"NONE"); } irr::core::stringw CColladaMeshWriter::toString(const irr::scene::E_COLLADA_TRANSPARENT_FX transparent) const { if ( transparent & ECOF_RGB_ZERO ) return core::stringw(L"RGB_ZERO"); else return core::stringw(L"A_ONE"); } irr::core::stringw CColladaMeshWriter::toRef(const irr::core::stringw& source) const { irr::core::stringw ref(L"#"); ref += source; return ref; } bool CColladaMeshWriter::isCamera(const scene::ISceneNode* node) const { // TODO: we need some ISceneNode::hasType() function to get rid of those checks if ( node->getType() == ESNT_CAMERA || node->getType() == ESNT_CAMERA_MAYA || node->getType() == ESNT_CAMERA_FPS ) return true; return false; } irr::core::stringw CColladaMeshWriter::nameForMesh(const scene::IMesh* mesh, int instance) const { IColladaMeshWriterNames * nameGenerator = getNameGenerator(); if ( nameGenerator ) { return nameGenerator->nameForMesh(mesh, instance); } return irr::core::stringw(L"missing_name_generator"); } irr::core::stringw CColladaMeshWriter::nameForNode(const scene::ISceneNode* node) const { IColladaMeshWriterNames * nameGenerator = getNameGenerator(); if ( nameGenerator ) { return nameGenerator->nameForNode(node); } return irr::core::stringw(L"missing_name_generator"); } irr::core::stringw CColladaMeshWriter::nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) { irr::core::stringw matName; if ( getExportSMaterialsOnlyOnce() ) { matName = findCachedMaterialName(material); if ( !matName.empty() ) return matName; } IColladaMeshWriterNames * nameGenerator = getNameGenerator(); if ( nameGenerator ) { matName = nameGenerator->nameForMaterial(material, materialId, mesh, node); } else matName = irr::core::stringw(L"missing_name_generator"); if ( getExportSMaterialsOnlyOnce() ) MaterialNameCache.push_back (MaterialName(material, matName)); return matName; } // Each mesh-material has one symbol which is replaced on instantiation irr::core::stringw CColladaMeshWriter::nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const { wchar_t buf[100]; swprintf(buf, 100, L"mat_symb_%p_%d", mesh, materialId); return irr::core::stringw(buf); } irr::core::stringw CColladaMeshWriter::findCachedMaterialName(const irr::video::SMaterial& material) const { for ( u32 i=0; i= 'A' && c <= 'Z') || c == L'_' || (c >= 'a' && c <= 'z') || (c >= 0xC0 && c <= 0xD6) || (c >= 0xD8 && c <= 0xF6) || (c >= 0xF8 && c <= 0x2FF) || (c >= 0x370 && c <= 0x37D) || (c >= 0x37F && c <= 0x1FFF) || (c >= 0x200C && c <= 0x200D) || (c >= 0x2070 && c <= 0x218F) || (c >= 0x2C00 && c <= 0x2FEF) || (c >= 0x3001 && c <= 0xD7FF) || (c >= 0xF900 && c <= 0xFDCF) || (c >= 0xFDF0 && c <= 0xFFFD) #if __SIZEOF_WCHAR_T__ == 4 || __WCHAR_MAX__ > 0x10000 || (c >= 0x10000 && c <= 0xEFFFF) #endif ; } bool CColladaMeshWriter::isXmlNameChar(wchar_t c) const { return isXmlNameStartChar(c) || c == L'-' || c == L'.' || (c >= '0' && c <= '9') || c == 0xB7 || (c >= 0x0300 && c <= 0x036F) || (c >= 0x203F && c <= 0x2040); } // Restrict the characters to a set of allowed characters in xs::NCName. irr::core::stringw CColladaMeshWriter::toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix) const { irr::core::stringw result(prefix); // help to ensure id starts with a valid char and reduce chance of name-conflicts if ( oldString.empty() ) return result; result.append( oldString ); // We replace all characters not allowed by a replacement char const wchar_t REPLACMENT = L'-'; for ( irr::u32 i=1; i < result.size(); ++i ) { if ( result[i] == L':' || !isXmlNameChar(result[i]) ) { result[i] = REPLACMENT; } } return result; } // Restrict the characters to a set of allowed characters in xs::NCName. irr::core::stringw CColladaMeshWriter::pathToURI(const irr::io::path& path) const { irr::core::stringw result; // is this a relative path? if ( path.size() > 1 && path[0] != _IRR_TEXT('/') && path[0] != _IRR_TEXT('\\') && path[1] != _IRR_TEXT(':') ) { // not already starting with "./" ? if ( path[0] != _IRR_TEXT('.') || path[1] != _IRR_TEXT('/') ) { result.append(L"./"); } } result.append(path); // TODO: make correct URI (without whitespaces) return result; } void CColladaMeshWriter::writeAsset() { Writer->writeElement(L"asset", false); Writer->writeLineBreak(); Writer->writeElement(L"contributor", false); Writer->writeLineBreak(); Writer->writeElement(L"authoring_tool", false); Writer->writeText(L"Irrlicht Engine / irrEdit"); // this code has originated from irrEdit 0.7 Writer->writeClosingTag(L"authoring_tool"); Writer->writeLineBreak(); Writer->writeClosingTag(L"contributor"); Writer->writeLineBreak(); // The next two are required Writer->writeElement(L"created", false); Writer->writeText(L"2008-01-31T00:00:00Z"); Writer->writeClosingTag(L"created"); Writer->writeLineBreak(); Writer->writeElement(L"modified", false); Writer->writeText(L"2008-01-31T00:00:00Z"); Writer->writeClosingTag(L"modified"); Writer->writeLineBreak(); Writer->writeElement(L"revision", false); Writer->writeText(L"1.0"); Writer->writeClosingTag(L"revision"); Writer->writeLineBreak(); Writer->writeClosingTag(L"asset"); Writer->writeLineBreak(); } void CColladaMeshWriter::writeMeshMaterials(scene::IMesh* mesh, irr::core::array * materialNamesOut) { u32 i; for (i=0; igetMeshBufferCount(); ++i) { video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial(); core::stringw strMat(nameForMaterial(material, i, mesh, NULL)); writeMaterial(strMat); if ( materialNamesOut ) materialNamesOut->push_back(strMat); } } void CColladaMeshWriter::writeMaterialEffect(const irr::core::stringw& materialfxname, const video::SMaterial & material) { if ( EffectsWritten.find(materialfxname) ) return; EffectsWritten.insert(materialfxname, true); Writer->writeElement(L"effect", false, L"id", materialfxname.c_str(), L"name", materialfxname.c_str()); Writer->writeLineBreak(); Writer->writeElement(L"profile_COMMON", false); Writer->writeLineBreak(); int numTextures = 0; if ( getWriteTextures() ) { // write texture surfaces and samplers and buffer all used imagess for ( int t=0; t<4; ++t ) { const video::SMaterialLayer& layer = material.TextureLayer[t]; if ( !layer.Texture ) break; ++numTextures; if ( LibraryImages.linear_search(layer.Texture) < 0 ) LibraryImages.push_back( layer.Texture ); irr::core::stringw texName("tex"); texName += irr::core::stringw(t); // write texture surface // irr::core::stringw texSurface(texName); texSurface += L"-surface"; Writer->writeElement(L"newparam", false, L"sid", texSurface.c_str()); Writer->writeLineBreak(); // Writer->writeElement(L"surface", false, L"type", L"2D"); Writer->writeLineBreak(); // internal_texturename Writer->writeElement(L"init_from", false); irr::io::path p(FileSystem->getRelativeFilename(layer.Texture->getName().getPath(), Directory)); Writer->writeText(toNCName(irr::core::stringw(p)).c_str()); Writer->writeClosingTag(L"init_from"); Writer->writeLineBreak(); // A8R8G8B8 Writer->writeElement(L"format", false); video::ECOLOR_FORMAT format = layer.Texture->getColorFormat(); Writer->writeText(toString(format).c_str()); Writer->writeClosingTag(L"format"); Writer->writeLineBreak(); // Writer->writeClosingTag(L"surface"); Writer->writeLineBreak(); // Writer->writeClosingTag(L"newparam"); Writer->writeLineBreak(); // write texture sampler // irr::core::stringw texSampler(texName); texSampler += L"-sampler"; Writer->writeElement(L"newparam", false, L"sid", texSampler.c_str()); Writer->writeLineBreak(); // Writer->writeElement(L"sampler2D", false); Writer->writeLineBreak(); // tex0-surface Writer->writeElement(L"source", false); Writer->writeText(texSurface.c_str()); Writer->writeClosingTag(L"source"); Writer->writeLineBreak(); // WRAP Writer->writeElement(L"wrap_s", false); Writer->writeText(toString((video::E_TEXTURE_CLAMP)layer.TextureWrapU).c_str()); Writer->writeClosingTag(L"wrap_s"); Writer->writeLineBreak(); // WRAP Writer->writeElement(L"wrap_t", false); Writer->writeText(toString((video::E_TEXTURE_CLAMP)layer.TextureWrapV).c_str()); Writer->writeClosingTag(L"wrap_t"); Writer->writeLineBreak(); // LINEAR_MIPMAP_LINEAR Writer->writeElement(L"minfilter", false); Writer->writeText(minTexfilterToString(layer.BilinearFilter, layer.TrilinearFilter).c_str()); Writer->writeClosingTag(L"minfilter"); Writer->writeLineBreak(); // LINEAR Writer->writeElement(L"magfilter", false); Writer->writeText(magTexfilterToString(layer.BilinearFilter, layer.TrilinearFilter).c_str()); Writer->writeClosingTag(L"magfilter"); Writer->writeLineBreak(); // TBD - actually not sure how anisotropic should be written, so for now it writes in a way // that works with the way the loader reads it again. if ( layer.AnisotropicFilter ) { // LINEAR_MIPMAP_LINEAR Writer->writeElement(L"mipfilter", false); Writer->writeText(L"LINEAR_MIPMAP_LINEAR"); Writer->writeClosingTag(L"mipfilter"); Writer->writeLineBreak(); } // Writer->writeClosingTag(L"sampler2D"); Writer->writeLineBreak(); // Writer->writeClosingTag(L"newparam"); Writer->writeLineBreak(); } } Writer->writeElement(L"technique", false, L"sid", L"common"); Writer->writeLineBreak(); E_COLLADA_TECHNIQUE_FX techFx = getProperties() ? getProperties()->getTechniqueFx(material) : ECTF_BLINN; writeFxElement(material, techFx); Writer->writeClosingTag(L"technique"); Writer->writeLineBreak(); Writer->writeClosingTag(L"profile_COMMON"); Writer->writeLineBreak(); Writer->writeClosingTag(L"effect"); Writer->writeLineBreak(); } void CColladaMeshWriter::writeMeshEffects(scene::IMesh* mesh) { for (u32 i=0; igetMeshBufferCount(); ++i) { video::SMaterial & material = mesh->getMeshBuffer(i)->getMaterial(); irr::core::stringw materialfxname(nameForMaterial(material, i, mesh, NULL)); materialfxname += L"-fx"; writeMaterialEffect(materialfxname, material); } } void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh) { core::stringw meshId(meshname); Writer->writeElement(L"geometry", false, L"id", meshId.c_str(), L"name", meshId.c_str()); Writer->writeLineBreak(); Writer->writeElement(L"mesh"); Writer->writeLineBreak(); // do some statistics for the mesh to know which stuff needs to be saved into // the file: // - count vertices // - check for the need of a second texture coordinate // - count amount of second texture coordinates // - check for the need of tangents (TODO) u32 totalVertexCount = 0; u32 totalTCoords2Count = 0; bool needsTangents = false; // TODO: tangents not supported here yet u32 i=0; for (i=0; igetMeshBufferCount(); ++i) { totalVertexCount += mesh->getMeshBuffer(i)->getVertexCount(); if (hasSecondTextureCoordinates(mesh->getMeshBuffer(i)->getVertexType())) totalTCoords2Count += mesh->getMeshBuffer(i)->getVertexCount(); if (!needsTangents) needsTangents = mesh->getMeshBuffer(i)->getVertexType() == video::EVT_TANGENTS; } SComponentGlobalStartPos* globalIndices = new SComponentGlobalStartPos[mesh->getMeshBufferCount()]; // write positions core::stringw meshPosId(meshId); meshPosId += L"-Pos"; Writer->writeElement(L"source", false, L"id", meshPosId.c_str()); Writer->writeLineBreak(); core::stringw vertexCountStr(totalVertexCount*3); core::stringw meshPosArrayId(meshPosId); meshPosArrayId += L"-array"; Writer->writeElement(L"float_array", false, L"id", meshPosArrayId.c_str(), L"count", vertexCountStr.c_str()); Writer->writeLineBreak(); for (i=0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); u32 vertexCount = buffer->getVertexCount(); globalIndices[i].PosStartIndex = 0; if (i!=0) globalIndices[i].PosStartIndex = globalIndices[i-1].PosLastIndex + 1; globalIndices[i].PosLastIndex = globalIndices[i].PosStartIndex + vertexCount - 1; switch(vtxType) { case video::EVT_STANDARD: { video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); for (u32 j=0; jwriteLineBreak(); } } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); for (u32 j=0; jwriteLineBreak(); } } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); for (u32 j=0; jwriteLineBreak(); } } break; } } Writer->writeClosingTag(L"float_array"); Writer->writeLineBreak(); Writer->writeElement(L"technique_common", false); Writer->writeLineBreak(); vertexCountStr = core::stringw(totalVertexCount); Writer->writeElement(L"accessor", false, L"source", toRef(meshPosArrayId).c_str(), L"count", vertexCountStr.c_str(), L"stride", L"3"); Writer->writeLineBreak(); Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float"); Writer->writeLineBreak(); Writer->writeElement(L"param", true, L"name", L"Y", L"type", L"float"); Writer->writeLineBreak(); Writer->writeElement(L"param", true, L"name", L"Z", L"type", L"float"); Writer->writeLineBreak(); Writer->writeClosingTag(L"accessor"); Writer->writeLineBreak(); Writer->writeClosingTag(L"technique_common"); Writer->writeLineBreak(); Writer->writeClosingTag(L"source"); Writer->writeLineBreak(); // write texture coordinates core::stringw meshTexCoord0Id(meshId); meshTexCoord0Id += L"-TexCoord0"; Writer->writeElement(L"source", false, L"id", meshTexCoord0Id.c_str()); Writer->writeLineBreak(); vertexCountStr = core::stringw(totalVertexCount*2); core::stringw meshTexCoordArrayId(meshTexCoord0Id); meshTexCoordArrayId += L"-array"; Writer->writeElement(L"float_array", false, L"id", meshTexCoordArrayId.c_str(), L"count", vertexCountStr.c_str()); Writer->writeLineBreak(); for (i=0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); u32 vertexCount = buffer->getVertexCount(); globalIndices[i].TCoord0StartIndex = 0; if (i!=0) globalIndices[i].TCoord0StartIndex = globalIndices[i-1].TCoord0LastIndex + 1; globalIndices[i].TCoord0LastIndex = globalIndices[i].TCoord0StartIndex + vertexCount - 1; switch(vtxType) { case video::EVT_STANDARD: { video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); for (u32 j=0; jwriteLineBreak(); } } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); for (u32 j=0; jwriteLineBreak(); } } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); for (u32 j=0; jwriteLineBreak(); } } break; } } Writer->writeClosingTag(L"float_array"); Writer->writeLineBreak(); Writer->writeElement(L"technique_common", false); Writer->writeLineBreak(); vertexCountStr = core::stringw(totalVertexCount); Writer->writeElement(L"accessor", false, L"source", toRef(meshTexCoordArrayId).c_str(), L"count", vertexCountStr.c_str(), L"stride", L"2"); Writer->writeLineBreak(); Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float"); Writer->writeLineBreak(); Writer->writeElement(L"param", true, L"name", L"V", L"type", L"float"); Writer->writeLineBreak(); Writer->writeClosingTag(L"accessor"); Writer->writeLineBreak(); Writer->writeClosingTag(L"technique_common"); Writer->writeLineBreak(); Writer->writeClosingTag(L"source"); Writer->writeLineBreak(); // write normals core::stringw meshNormalId(meshId); meshNormalId += L"-Normal"; Writer->writeElement(L"source", false, L"id", meshNormalId.c_str()); Writer->writeLineBreak(); vertexCountStr = core::stringw(totalVertexCount*3); core::stringw meshNormalArrayId(meshNormalId); meshNormalArrayId += L"-array"; Writer->writeElement(L"float_array", false, L"id", meshNormalArrayId.c_str(), L"count", vertexCountStr.c_str()); Writer->writeLineBreak(); for (i=0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); u32 vertexCount = buffer->getVertexCount(); globalIndices[i].NormalStartIndex = 0; if (i!=0) globalIndices[i].NormalStartIndex = globalIndices[i-1].NormalLastIndex + 1; globalIndices[i].NormalLastIndex = globalIndices[i].NormalStartIndex + vertexCount - 1; switch(vtxType) { case video::EVT_STANDARD: { video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); for (u32 j=0; jwriteLineBreak(); } } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); for (u32 j=0; jwriteLineBreak(); } } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); for (u32 j=0; jwriteLineBreak(); } } break; } } Writer->writeClosingTag(L"float_array"); Writer->writeLineBreak(); Writer->writeElement(L"technique_common", false); Writer->writeLineBreak(); vertexCountStr = core::stringw(totalVertexCount); Writer->writeElement(L"accessor", false, L"source", toRef(meshNormalArrayId).c_str(), L"count", vertexCountStr.c_str(), L"stride", L"3"); Writer->writeLineBreak(); Writer->writeElement(L"param", true, L"name", L"X", L"type", L"float"); Writer->writeLineBreak(); Writer->writeElement(L"param", true, L"name", L"Y", L"type", L"float"); Writer->writeLineBreak(); Writer->writeElement(L"param", true, L"name", L"Z", L"type", L"float"); Writer->writeLineBreak(); Writer->writeClosingTag(L"accessor"); Writer->writeLineBreak(); Writer->writeClosingTag(L"technique_common"); Writer->writeLineBreak(); Writer->writeClosingTag(L"source"); Writer->writeLineBreak(); // write second set of texture coordinates core::stringw meshTexCoord1Id(meshId); meshTexCoord1Id += L"-TexCoord1"; if (totalTCoords2Count) { Writer->writeElement(L"source", false, L"id", meshTexCoord1Id.c_str()); Writer->writeLineBreak(); vertexCountStr = core::stringw(totalTCoords2Count*2); core::stringw meshTexCoord1ArrayId(meshTexCoord1Id); meshTexCoord1ArrayId += L"-array"; Writer->writeElement(L"float_array", false, L"id", meshTexCoord1ArrayId.c_str(), L"count", vertexCountStr.c_str()); Writer->writeLineBreak(); for (i=0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); video::E_VERTEX_TYPE vtxType = buffer->getVertexType(); u32 vertexCount = buffer->getVertexCount(); if (hasSecondTextureCoordinates(vtxType)) { globalIndices[i].TCoord1StartIndex = 0; if (i!=0 && globalIndices[i-1].TCoord1LastIndex != -1) globalIndices[i].TCoord1StartIndex = globalIndices[i-1].TCoord1LastIndex + 1; globalIndices[i].TCoord1LastIndex = globalIndices[i].TCoord1StartIndex + vertexCount - 1; switch(vtxType) { case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); for (u32 j=0; jwriteLineBreak(); } } break; default: break; } } // end this buffer has 2 texture coordinates } Writer->writeClosingTag(L"float_array"); Writer->writeLineBreak(); Writer->writeElement(L"technique_common", false); Writer->writeLineBreak(); vertexCountStr = core::stringw(totalTCoords2Count); Writer->writeElement(L"accessor", false, L"source", toRef(meshTexCoord1ArrayId).c_str(), L"count", vertexCountStr.c_str(), L"stride", L"2"); Writer->writeLineBreak(); Writer->writeElement(L"param", true, L"name", L"U", L"type", L"float"); Writer->writeLineBreak(); Writer->writeElement(L"param", true, L"name", L"V", L"type", L"float"); Writer->writeLineBreak(); Writer->writeClosingTag(L"accessor"); Writer->writeLineBreak(); Writer->writeClosingTag(L"technique_common"); Writer->writeLineBreak(); Writer->writeClosingTag(L"source"); Writer->writeLineBreak(); } // write tangents // TODO // write vertices core::stringw meshVtxId(meshId); meshVtxId += L"-Vtx"; Writer->writeElement(L"vertices", false, L"id", meshVtxId.c_str()); Writer->writeLineBreak(); Writer->writeElement(L"input", true, L"semantic", L"POSITION", L"source", toRef(meshPosId).c_str()); Writer->writeLineBreak(); Writer->writeClosingTag(L"vertices"); Writer->writeLineBreak(); // write polygons for (i=0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i); const u32 polyCount = buffer->getIndexCount() / 3; core::stringw strPolyCount(polyCount); irr::core::stringw strMat(nameForMaterialSymbol(mesh, i)); Writer->writeElement(L"triangles", false, L"count", strPolyCount.c_str(), L"material", strMat.c_str()); Writer->writeLineBreak(); Writer->writeElement(L"input", true, L"semantic", L"VERTEX", L"source", toRef(meshVtxId).c_str(), L"offset", L"0"); Writer->writeLineBreak(); Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", toRef(meshTexCoord0Id).c_str(), L"offset", L"1", L"set", L"0"); Writer->writeLineBreak(); Writer->writeElement(L"input", true, L"semantic", L"NORMAL", L"source", toRef(meshNormalId).c_str(), L"offset", L"2"); Writer->writeLineBreak(); bool has2ndTexCoords = hasSecondTextureCoordinates(buffer->getVertexType()); if (has2ndTexCoords) { // TODO: when working on second uv-set - my suspicion is that this one should be called "TEXCOORD2" // to allow bind_vertex_input to differentiate the uv-sets. Writer->writeElement(L"input", true, L"semantic", L"TEXCOORD", L"source", toRef(meshTexCoord1Id).c_str(), L"idx", L"3"); Writer->writeLineBreak(); } // write indices now s32 posIdx = globalIndices[i].PosStartIndex; s32 tCoordIdx = globalIndices[i].TCoord0StartIndex; s32 normalIdx = globalIndices[i].NormalStartIndex; s32 tCoord2Idx = globalIndices[i].TCoord1StartIndex; Writer->writeElement(L"p", false); core::stringw strP; strP.reserve(100); for (u32 p=0; pgetIndices()[(p*3) + 0] + posIdx; strP += " "; strP += buffer->getIndices()[(p*3) + 0] + tCoordIdx; strP += " "; strP += buffer->getIndices()[(p*3) + 0] + normalIdx; strP += " "; if (has2ndTexCoords) { strP += buffer->getIndices()[(p*3) + 0] + tCoord2Idx; strP += " "; } strP += buffer->getIndices()[(p*3) + 1] + posIdx; strP += " "; strP += buffer->getIndices()[(p*3) + 1] + tCoordIdx; strP += " "; strP += buffer->getIndices()[(p*3) + 1] + normalIdx; strP += " "; if (has2ndTexCoords) { strP += buffer->getIndices()[(p*3) + 1] + tCoord2Idx; strP += " "; } strP += buffer->getIndices()[(p*3) + 2] + posIdx; strP += " "; strP += buffer->getIndices()[(p*3) + 2] + tCoordIdx; strP += " "; strP += buffer->getIndices()[(p*3) + 2] + normalIdx; if (has2ndTexCoords) { strP += " "; strP += buffer->getIndices()[(p*3) + 2] + tCoord2Idx; } strP += " "; Writer->writeText(strP.c_str()); } Writer->writeClosingTag(L"p"); Writer->writeLineBreak(); // close index buffer section Writer->writeClosingTag(L"triangles"); Writer->writeLineBreak(); } // close mesh and geometry delete [] globalIndices; Writer->writeClosingTag(L"mesh"); Writer->writeLineBreak(); Writer->writeClosingTag(L"geometry"); Writer->writeLineBreak(); } void CColladaMeshWriter::writeLibraryImages() { if ( getWriteTextures() && !LibraryImages.empty() ) { Writer->writeElement(L"library_images", false); Writer->writeLineBreak(); for ( irr::u32 i=0; igetRelativeFilename(LibraryImages[i]->getName().getPath(), Directory)); // irr::core::stringw ncname( toNCName(irr::core::stringw(p)) ); Writer->writeElement(L"image", false, L"id", ncname.c_str(), L"name", ncname.c_str()); Writer->writeLineBreak(); // ../flowers/rose01.jpg Writer->writeElement(L"init_from", false); Writer->writeText(pathToURI(p).c_str()); Writer->writeClosingTag(L"init_from"); Writer->writeLineBreak(); // Writer->writeClosingTag(L"image"); Writer->writeLineBreak(); } Writer->writeClosingTag(L"library_images"); Writer->writeLineBreak(); } } void CColladaMeshWriter::writeColorElement(const video::SColorf & col, bool writeAlpha) { Writer->writeElement(L"color", false); writeColor(col, writeAlpha); Writer->writeClosingTag(L"color"); Writer->writeLineBreak(); } void CColladaMeshWriter::writeColorElement(const video::SColor & col, bool writeAlpha) { writeColorElement( video::SColorf(col), writeAlpha ); } void CColladaMeshWriter::writeAmbientLightElement(const video::SColorf & col) { Writer->writeElement(L"light", false, L"id", L"ambientlight"); Writer->writeLineBreak(); Writer->writeElement(L"technique_common", false); Writer->writeLineBreak(); Writer->writeElement(L"ambient", false); Writer->writeLineBreak(); writeColorElement(col, false); Writer->writeClosingTag(L"ambient"); Writer->writeLineBreak(); Writer->writeClosingTag(L"technique_common"); Writer->writeLineBreak(); Writer->writeClosingTag(L"light"); Writer->writeLineBreak(); } s32 CColladaMeshWriter::getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) { if ( !getWriteTextures() || !getProperties() ) return -1; s32 idx = getProperties()->getTextureIdx(material, cs); if ( idx >= 0 && !material.TextureLayer[idx].Texture ) return -1; return idx; } video::SColor CColladaMeshWriter::getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType) { switch ( colType ) { case ECIC_NONE: return video::SColor(255, 0, 0, 0); case ECIC_CUSTOM: return getProperties()->getCustomColor(material, cs); case ECIC_DIFFUSE: return material.DiffuseColor; case ECIC_AMBIENT: return material.AmbientColor; case ECIC_EMISSIVE: return material.EmissiveColor; case ECIC_SPECULAR: return material.SpecularColor; } return video::SColor(255, 0, 0, 0); } void CColladaMeshWriter::writeTextureSampler(s32 textureIdx) { irr::core::stringw sampler(L"tex"); sampler += irr::core::stringw(textureIdx); sampler += L"-sampler"; // Writer->writeElement(L"texture", true, L"texture", sampler.c_str(), L"texcoord", L"uv" ); Writer->writeLineBreak(); } void CColladaMeshWriter::writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx) { core::stringw fxLabel; bool writeEmission = true; bool writeAmbient = true; bool writeDiffuse = true; bool writeSpecular = true; bool writeShininess = true; bool writeReflective = true; bool writeReflectivity = true; bool writeTransparent = true; bool writeTransparency = true; bool writeIndexOfRefraction = true; switch ( techFx ) { case ECTF_BLINN: fxLabel = L"blinn"; break; case ECTF_PHONG: fxLabel = L"phong"; break; case ECTF_LAMBERT: fxLabel = L"lambert"; writeSpecular = false; writeShininess = false; break; case ECTF_CONSTANT: fxLabel = L"constant"; writeAmbient = false; writeDiffuse = false; writeSpecular = false; writeShininess = false; break; } Writer->writeElement(fxLabel.c_str(), false); Writer->writeLineBreak(); // write all interesting material parameters // attributes must be written in fixed order if ( getProperties() ) { if ( writeEmission ) { writeColorFx(material, L"emission", ECCS_EMISSIVE); } if ( writeAmbient ) { writeColorFx(material, L"ambient", ECCS_AMBIENT); } if ( writeDiffuse ) { writeColorFx(material, L"diffuse", ECCS_DIFFUSE); } if ( writeSpecular ) { writeColorFx(material, L"specular", ECCS_SPECULAR); } if ( writeShininess ) { Writer->writeElement(L"shininess", false); Writer->writeLineBreak(); writeFloatElement(material.Shininess); Writer->writeClosingTag(L"shininess"); Writer->writeLineBreak(); } if ( writeReflective ) { writeColorFx(material, L"reflective", ECCS_REFLECTIVE); } if ( writeReflectivity ) { f32 t = getProperties()->getReflectivity(material); if ( t >= 0.f ) { // 1.000000 Writer->writeElement(L"reflectivity", false); Writer->writeLineBreak(); writeFloatElement(t); Writer->writeClosingTag(L"reflectivity"); Writer->writeLineBreak(); } } if ( writeTransparent ) { E_COLLADA_TRANSPARENT_FX transparentFx = getProperties()->getTransparentFx(material); writeColorFx(material, L"transparent", ECCS_TRANSPARENT, L"opaque", toString(transparentFx).c_str()); } if ( writeTransparency ) { f32 t = getProperties()->getTransparency(material); if ( t >= 0.f ) { // 1.000000 Writer->writeElement(L"transparency", false); Writer->writeLineBreak(); writeFloatElement(t); Writer->writeClosingTag(L"transparency"); Writer->writeLineBreak(); } } if ( writeIndexOfRefraction ) { f32 t = getProperties()->getIndexOfRefraction(material); if ( t >= 0.f ) { Writer->writeElement(L"index_of_refraction", false); Writer->writeLineBreak(); writeFloatElement(t); Writer->writeClosingTag(L"index_of_refraction"); Writer->writeLineBreak(); } } } Writer->writeClosingTag(fxLabel.c_str()); Writer->writeLineBreak(); } void CColladaMeshWriter::writeColorFx(const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name, const wchar_t* attr1Value) { irr::s32 idx = getCheckedTextureIdx(material, cs); E_COLLADA_IRR_COLOR colType = idx < 0 ? getProperties()->getColorMapping(material, cs) : ECIC_NONE; if ( idx >= 0 || colType != ECIC_NONE ) { Writer->writeElement(colorname, false, attr1Name, attr1Value); Writer->writeLineBreak(); if ( idx >= 0 ) writeTextureSampler(idx); else writeColorElement(getColorMapping(material, cs, colType)); Writer->writeClosingTag(colorname); Writer->writeLineBreak(); } } void CColladaMeshWriter::writeNode(const wchar_t * nodeName, const wchar_t * content) { Writer->writeElement(nodeName, false); Writer->writeText(content); Writer->writeClosingTag(nodeName); Writer->writeLineBreak(); } void CColladaMeshWriter::writeFloatElement(irr::f32 value) { Writer->writeElement(L"float", false); Writer->writeText(core::stringw((double)value).c_str()); Writer->writeClosingTag(L"float"); Writer->writeLineBreak(); } void CColladaMeshWriter::writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle) { Writer->writeElement(L"rotate", false); irr::core::stringw txt(axis.X); txt += L" "; txt += irr::core::stringw(axis.Y); txt += L" "; txt += irr::core::stringw(axis.Z); txt += L" "; txt += irr::core::stringw((double)angle); Writer->writeText(txt.c_str()); Writer->writeClosingTag(L"rotate"); Writer->writeLineBreak(); } void CColladaMeshWriter::writeScaleElement(const irr::core::vector3df& scale) { Writer->writeElement(L"scale", false); irr::core::stringw txt(scale.X); txt += L" "; txt += irr::core::stringw(scale.Y); txt += L" "; txt += irr::core::stringw(scale.Z); Writer->writeText(txt.c_str()); Writer->writeClosingTag(L"scale"); Writer->writeLineBreak(); } void CColladaMeshWriter::writeTranslateElement(const irr::core::vector3df& translate) { Writer->writeElement(L"translate", false); irr::core::stringw txt(translate.X); txt += L" "; txt += irr::core::stringw(translate.Y); txt += L" "; txt += irr::core::stringw(translate.Z); Writer->writeText(txt.c_str()); Writer->writeClosingTag(L"translate"); Writer->writeLineBreak(); } void CColladaMeshWriter::writeMatrixElement(const irr::core::matrix4& matrix) { Writer->writeElement(L"matrix", false); Writer->writeLineBreak(); for ( int a=0; a<4; ++a ) { irr::core::stringw txt; for ( int b=0; b<4; ++b ) { if ( b > 0 ) txt += " "; // row-column switched compared to Irrlicht txt += irr::core::stringw(matrix[b*4+a]); } Writer->writeText(txt.c_str()); Writer->writeLineBreak(); } Writer->writeClosingTag(L"matrix"); Writer->writeLineBreak(); } } // end namespace } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/CColladaFileLoader.h0000644000000000000000000002600012574354552020675 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__ #define __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "IFileSystem.h" #include "IVideoDriver.h" #include "irrString.h" #include "SMesh.h" #include "SMeshBuffer.h" #include "ISceneManager.h" #include "irrMap.h" #include "CAttributes.h" namespace irr { namespace scene { #ifdef _DEBUG //#define COLLADA_READER_DEBUG #endif class IColladaPrefab; enum ECOLLADA_PARAM_NAME { ECPN_COLOR = 0, ECPN_AMBIENT, ECPN_DIFFUSE, ECPN_SPECULAR, ECPN_SHININESS, ECPN_TRANSPARENCY, ECPN_YFOV, ECPN_ZNEAR, ECPN_ZFAR, ECPN_COUNT }; enum ECOLLADA_PARAM_TYPE { ECPT_FLOAT = 0, ECPT_FLOAT2, ECPT_FLOAT3, ECPT_FLOAT4, ECPT_COUNT }; //! Collada Parameter struct SColladaParam { SColladaParam() : Name(ECPN_COUNT), Type(ECPT_COUNT) { for (int i=0; i<4; ++i) Floats[i] = 0; } ECOLLADA_PARAM_NAME Name; ECOLLADA_PARAM_TYPE Type; f32 Floats[4]; }; enum ECOLLADA_INPUT_SEMANTIC { ECIS_POSITION = 0, ECIS_VERTEX, ECIS_NORMAL, ECIS_TEXCOORD, ECIS_UV, ECIS_TANGENT, ECIS_IMAGE, ECIS_TEXTURE, ECIS_COUNT }; //! Collada Input struct SColladaInput { SColladaInput() : Semantic(ECIS_COUNT), Data(0), Offset(0), Set(0), Stride(1) { } ECOLLADA_INPUT_SEMANTIC Semantic; core::stringc Source; f32* Data; u32 Offset; u32 Set; u32 Stride; }; //! Collada images struct SColladaImage { core::stringc Id; core::stringc Source; core::dimension2du Dimension; bool SourceIsFilename; }; //! Collada texture struct SColladaTexture { video::ITexture* Texture; core::stringc Id; }; //! Collada material struct SColladaMaterial { video::SMaterial Mat; core::stringc Id; core::stringc InstanceEffectId; f32 Transparency; inline bool operator< (const SColladaMaterial & other) const { return Id < other.Id; } }; //! Collada effect (materials, shaders, and programs) struct SColladaEffect { core::stringc Id; f32 Transparency; core::array Textures; video::SMaterial Mat; // TODO: Parameters looks somewhat lazy workaround, I think we should really read all parameters correct. io::IAttributes * Parameters; inline bool operator< (const SColladaEffect & other) const { return Id < other.Id; } }; struct SNumberArray // for storing float and int arrays { core::stringc Name; core::array Data; }; struct SAccessor { SAccessor() : Count(0), Offset(0), Stride(1) {} // I don't store the source of the accessor here because I assume // it to use the array of the source this accessor is located in. int Count; int Offset; int Stride; core::array Parameters; // parameters defining the accessor }; struct SSource { core::stringc Id; SNumberArray Array; core::array Accessors; }; class CScenePrefab; //! Meshloader capable of loading COLLADA meshes and scene descriptions into Irrlicht. class CColladaFileLoader : public IMeshLoader { public: //! Constructor CColladaFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs); //! destructor virtual ~CColladaFileLoader(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: //! skips an (unknown) section in the collada document void skipSection(io::IXMLReaderUTF8* reader, bool reportSkipping); //! reads the section and its content void readColladaSection(io::IXMLReaderUTF8* reader); //! reads a section and its content void readLibrarySection(io::IXMLReaderUTF8* reader); //! reads a element and stores it as a prefab void readVisualScene(io::IXMLReaderUTF8* reader); //! reads a section and its content void readSceneSection(io::IXMLReaderUTF8* reader); //! reads a section and its content void readAssetSection(io::IXMLReaderUTF8* reader); //! reads a section and its content //! if a prefab pointer is passed the nodes are created as scene prefabs children of that prefab void readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p=0); //! reads a element and its content and creates a matrix from it core::matrix4 readLookAtNode(io::IXMLReaderUTF8* reader); //! reads a element and its content and creates a matrix from it core::matrix4 readMatrixNode(io::IXMLReaderUTF8* reader); //! reads a element and its content and creates a matrix from it core::matrix4 readPerspectiveNode(io::IXMLReaderUTF8* reader); //! reads a element and its content and creates a matrix from it core::matrix4 readRotateNode(io::IXMLReaderUTF8* reader); //! reads a element and its content and creates a matrix from it core::matrix4 readSkewNode(io::IXMLReaderUTF8* reader); //! reads a element and its content and stores it in bbox void readBboxNode(io::IXMLReaderUTF8* reader, core::aabbox3df& bbox); //! reads a element and its content and creates a matrix from it core::matrix4 readScaleNode(io::IXMLReaderUTF8* reader); //! reads a element and its content and creates a matrix from it core::matrix4 readTranslateNode(io::IXMLReaderUTF8* reader); //! reads a element video::SColorf readColorNode(io::IXMLReaderUTF8* reader); //! reads a element f32 readFloatNode(io::IXMLReaderUTF8* reader); //! reads a node void readInstanceNode(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, scene::ISceneNode** outNode, CScenePrefab* p=0, const core::stringc& type=core::stringc()); //! creates a scene node from Prefabs (with name given in 'url') void instantiateNode(scene::ISceneNode* parent, scene::ISceneNode** outNode=0, CScenePrefab* p=0, const core::stringc& url="", const core::stringc& type=core::stringc()); //! reads a element and stores it as prefab void readLightPrefab(io::IXMLReaderUTF8* reader); //! reads a element and stores it as prefab void readCameraPrefab(io::IXMLReaderUTF8* reader); //! reads a element and stores it in the image section void readImage(io::IXMLReaderUTF8* reader); //! reads a element and stores it in the texture section void readTexture(io::IXMLReaderUTF8* reader); //! reads a element and stores it in the material section void readMaterial(io::IXMLReaderUTF8* reader); //! reads a element and stores it in the effects section void readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect = 0); //! reads a element and stores it as mesh if possible void readGeometry(io::IXMLReaderUTF8* reader); //! parses a float from a char pointer and moves the pointer to //! the end of the parsed float inline f32 readFloat(const c8** p); //! parses an int from a char pointer and moves the pointer to //! the end of the parsed float inline s32 readInt(const c8** p); //! places pointer to next begin of a token void findNextNoneWhiteSpace(const c8** p); //! reads floats from inside of xml element until end of xml element void readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count); //! reads ints from inside of xml element until end of xml element void readIntsInsideElement(io::IXMLReaderUTF8* reader, s32* ints, u32 count); //! clears all loaded data void clearData(); //! parses all collada parameters inside an element and stores them in ColladaParameters void readColladaParameters(io::IXMLReaderUTF8* reader, const core::stringc& parentName); //! returns a collada parameter or none if not found SColladaParam* getColladaParameter(ECOLLADA_PARAM_NAME name); //! parses all collada inputs inside an element and stores them in Inputs. Reads //! until first tag which is not an input tag or the end of the parent is reached void readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName); //! reads a collada input tag and adds it to the input parameter void readColladaInput(io::IXMLReaderUTF8* reader, core::array& inputs); //! returns a collada input or none if not found SColladaInput* getColladaInput(ECOLLADA_INPUT_SEMANTIC input); //! read Collada Id, uses id or name if id is missing core::stringc readId(io::IXMLReaderUTF8* reader); //! changes the XML URI into an internal id void uriToId(core::stringc& str); //! reads a polygons section and creates a mesh from it void readPolygonSection(io::IXMLReaderUTF8* reader, core::array& sources, scene::SMesh* mesh, const core::stringc& geometryId); //! finds a material, possible instancing it const SColladaMaterial * findMaterial(const core::stringc & materialName); //! reads and bind materials as given by the symbol->target bind mapping void readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id); //! create an Irrlicht texture from the SColladaImage video::ITexture* getTextureFromImage(core::stringc uri, SColladaEffect * effect); //! read a parameter and value void readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters); scene::ISceneManager* SceneManager; io::IFileSystem* FileSystem; scene::IAnimatedMesh* DummyMesh; core::stringc CurrentlyLoadingMesh; scene::IAnimatedMesh* FirstLoadedMesh; io::path FirstLoadedMeshName; s32 LoadedMeshCount; u32 Version; bool FlipAxis; core::array Prefabs; core::array ColladaParameters; core::array Images; core::array Textures; core::array Materials; core::array Inputs; core::array Effects; //! meshbuffer reference ("geomid/matname") -> index into MeshesToBind core::map MaterialsToBind; //! Array of buffers for each material binding core::array< core::array > MeshesToBind; bool CreateInstances; }; //! following class is for holding and createing instances of library objects, //! named prefabs in this loader. class IColladaPrefab : public virtual IReferenceCounted { public: //! creates an instance of this prefab virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, scene::ISceneManager* mgr) = 0; //! returns id of this prefab virtual const core::stringc& getId() = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CColladaFileLoader.cpp0000644000000000000000000024604412574354552021244 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_ #include "CColladaFileLoader.h" #include "os.h" #include "IXMLReader.h" #include "IDummyTransformationSceneNode.h" #include "SAnimatedMesh.h" #include "fast_atof.h" #include "quaternion.h" #include "ILightSceneNode.h" #include "ICameraSceneNode.h" #include "IMeshManipulator.h" #include "IReadFile.h" #include "IAttributes.h" #include "IMeshCache.h" #include "IMeshSceneNode.h" #include "SMeshBufferLightMap.h" #include "irrMap.h" #ifdef _DEBUG #define COLLADA_READER_DEBUG #endif namespace irr { namespace scene { namespace { // currently supported COLLADA tag names const core::stringc colladaSectionName = "COLLADA"; const core::stringc librarySectionName = "library"; const core::stringc libraryNodesSectionName = "library_nodes"; const core::stringc libraryGeometriesSectionName = "library_geometries"; const core::stringc libraryMaterialsSectionName = "library_materials"; const core::stringc libraryImagesSectionName = "library_images"; const core::stringc libraryVisualScenesSectionName = "library_visual_scenes"; const core::stringc libraryCamerasSectionName = "library_cameras"; const core::stringc libraryLightsSectionName = "library_lights"; const core::stringc libraryEffectsSectionName = "library_effects"; const core::stringc assetSectionName = "asset"; const core::stringc sceneSectionName = "scene"; const core::stringc visualSceneSectionName = "visual_scene"; const core::stringc lightPrefabName = "light"; const core::stringc cameraPrefabName = "camera"; const core::stringc materialSectionName = "material"; const core::stringc geometrySectionName = "geometry"; const core::stringc imageSectionName = "image"; const core::stringc textureSectionName = "texture"; const core::stringc effectSectionName = "effect"; const core::stringc pointSectionName = "point"; const core::stringc directionalSectionName ="directional"; const core::stringc spotSectionName = "spot"; const core::stringc ambientSectionName = "ambient"; const core::stringc meshSectionName = "mesh"; const core::stringc sourceSectionName = "source"; const core::stringc arraySectionName = "array"; const core::stringc floatArraySectionName ="float_array"; const core::stringc intArraySectionName = "int_array"; const core::stringc techniqueCommonSectionName = "technique_common"; const core::stringc accessorSectionName = "accessor"; const core::stringc verticesSectionName = "vertices"; const core::stringc inputTagName = "input"; const core::stringc polylistSectionName = "polylist"; const core::stringc trianglesSectionName = "triangles"; const core::stringc polygonsSectionName = "polygons"; const core::stringc primitivesName = "p"; const core::stringc vcountName = "vcount"; const core::stringc upAxisNodeName = "up_axis"; const core::stringc nodeSectionName = "node"; const core::stringc lookatNodeName = "lookat"; const core::stringc matrixNodeName = "matrix"; const core::stringc perspectiveNodeName = "perspective"; const core::stringc rotateNodeName = "rotate"; const core::stringc scaleNodeName = "scale"; const core::stringc translateNodeName = "translate"; const core::stringc skewNodeName = "skew"; const core::stringc bboxNodeName = "boundingbox"; const core::stringc minNodeName = "min"; const core::stringc maxNodeName = "max"; const core::stringc instanceName = "instance"; const core::stringc instanceGeometryName = "instance_geometry"; const core::stringc instanceSceneName = "instance_visual_scene"; const core::stringc instanceEffectName = "instance_effect"; const core::stringc instanceMaterialName = "instance_material"; const core::stringc instanceLightName = "instance_light"; const core::stringc instanceNodeName = "instance_node"; const core::stringc bindMaterialName = "bind_material"; const core::stringc extraNodeName = "extra"; const core::stringc techniqueNodeName = "technique"; const core::stringc colorNodeName = "color"; const core::stringc floatNodeName = "float"; const core::stringc float2NodeName = "float2"; const core::stringc float3NodeName = "float3"; const core::stringc newParamName = "newparam"; const core::stringc paramTagName = "param"; const core::stringc initFromName = "init_from"; const core::stringc dataName = "data"; const core::stringc wrapsName = "wrap_s"; const core::stringc wraptName = "wrap_t"; const core::stringc minfilterName = "minfilter"; const core::stringc magfilterName = "magfilter"; const core::stringc mipfilterName = "mipfilter"; const core::stringc textureNodeName = "texture"; const core::stringc doubleSidedNodeName = "double_sided"; const core::stringc constantAttenuationNodeName = "constant_attenuation"; const core::stringc linearAttenuationNodeName = "linear_attenuation"; const core::stringc quadraticAttenuationNodeName = "quadratic_attenuation"; const core::stringc falloffAngleNodeName = "falloff_angle"; const core::stringc falloffExponentNodeName = "falloff_exponent"; const core::stringc profileCOMMONSectionName = "profile_COMMON"; const core::stringc profileCOMMONAttributeName = "COMMON"; const char* const inputSemanticNames[] = {"POSITION", "VERTEX", "NORMAL", "TEXCOORD", "UV", "TANGENT", "IMAGE", "TEXTURE", 0}; // We have to read ambient lights like other light types here, so we need a type for it const video::E_LIGHT_TYPE ELT_AMBIENT = video::E_LIGHT_TYPE(video::ELT_COUNT+1); } //! following class is for holding and creating instances of library //! objects, named prefabs in this loader. class CPrefab : public IColladaPrefab { public: CPrefab(const core::stringc& id) : Id(id) { } //! creates an instance of this prefab virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, scene::ISceneManager* mgr) { // empty implementation return 0; } //! returns id of this prefab virtual const core::stringc& getId() { return Id; } protected: core::stringc Id; }; //! prefab for a light scene node class CLightPrefab : public CPrefab { public: CLightPrefab(const core::stringc& id) : CPrefab(id) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA: loaded light prefab", Id.c_str(), ELL_DEBUG); #endif } video::SLight LightData; // publically accessible //! creates an instance of this prefab virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, scene::ISceneManager* mgr) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA: Constructing light instance", Id.c_str(), ELL_DEBUG); #endif if ( LightData.Type == ELT_AMBIENT ) { mgr->setAmbientLight( LightData.DiffuseColor ); return 0; } scene::ILightSceneNode* l = mgr->addLightSceneNode(parent); if (l) { l->setLightData ( LightData ); l->setName(getId()); } return l; } }; //! prefab for a mesh scene node class CGeometryPrefab : public CPrefab { public: CGeometryPrefab(const core::stringc& id) : CPrefab(id) { } scene::IMesh* Mesh; //! creates an instance of this prefab virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, scene::ISceneManager* mgr) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA: Constructing mesh instance", Id.c_str(), ELL_DEBUG); #endif scene::ISceneNode* m = mgr->addMeshSceneNode(Mesh, parent); if (m) { m->setName(getId()); // m->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false); // m->setDebugDataVisible(scene::EDS_FULL); } return m; } }; //! prefab for a camera scene node class CCameraPrefab : public CPrefab { public: CCameraPrefab(const core::stringc& id) : CPrefab(id), YFov(core::PI / 2.5f), ZNear(1.0f), ZFar(3000.0f) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA: loaded camera prefab", Id.c_str(), ELL_DEBUG); #endif } // publicly accessible data f32 YFov; f32 ZNear; f32 ZFar; //! creates an instance of this prefab virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, scene::ISceneManager* mgr) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA: Constructing camera instance", Id.c_str(), ELL_DEBUG); #endif scene::ICameraSceneNode* c = mgr->addCameraSceneNode(parent); if (c) { c->setFOV(YFov); c->setNearValue(ZNear); c->setFarValue(ZFar); c->setName(getId()); } return c; } }; //! prefab for a container scene node //! Collects other prefabs and instantiates them upon instantiation //! Uses a dummy scene node to return the children as one scene node class CScenePrefab : public CPrefab { public: CScenePrefab(const core::stringc& id) : CPrefab(id) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA: loaded scene prefab", Id.c_str(), ELL_DEBUG); #endif } //! creates an instance of this prefab virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, scene::ISceneManager* mgr) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA: Constructing scene instance", Id.c_str(), ELL_DEBUG); #endif if (Children.size()==0) return 0; scene::IDummyTransformationSceneNode* s = mgr->addDummyTransformationSceneNode(parent); if (s) { s->setName(getId()); s->getRelativeTransformationMatrix() = Transformation; s->updateAbsolutePosition(); core::stringc t; for (u32 i=0; i<16; ++i) { t+=core::stringc((double)Transformation[i]); t+=" "; } #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA: Transformation", t.c_str(), ELL_DEBUG); #endif for (u32 i=0; iaddInstance(s, mgr); } return s; } core::array Children; core::matrix4 Transformation; }; //! Constructor CColladaFileLoader::CColladaFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) : SceneManager(smgr), FileSystem(fs), DummyMesh(0), FirstLoadedMesh(0), LoadedMeshCount(0), CreateInstances(false) { #ifdef _DEBUG setDebugName("CColladaFileLoader"); #endif } //! destructor CColladaFileLoader::~CColladaFileLoader() { if (DummyMesh) DummyMesh->drop(); if (FirstLoadedMesh) FirstLoadedMesh->drop(); } //! Returns true if the file maybe is able to be loaded by this class. /** This decision should be based only on the file extension (e.g. ".cob") */ bool CColladaFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "xml", "dae" ); } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* CColladaFileLoader::createMesh(io::IReadFile* file) { io::IXMLReaderUTF8* reader = FileSystem->createXMLReaderUTF8(file); if (!reader) return 0; CurrentlyLoadingMesh = file->getFileName(); CreateInstances = SceneManager->getParameters()->getAttributeAsBool( scene::COLLADA_CREATE_SCENE_INSTANCES); Version = 0; FlipAxis = false; // read until COLLADA section, skip other parts while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { if (colladaSectionName == reader->getNodeName()) readColladaSection(reader); else skipSection(reader, true); // unknown section } } reader->drop(); if (!Version) return 0; // because this loader loads and creates a complete scene instead of // a single mesh, return an empty dummy mesh to make the scene manager // know that everything went well. if (!DummyMesh) DummyMesh = new SAnimatedMesh(); scene::IAnimatedMesh* returnMesh = DummyMesh; if (Version < 10400) instantiateNode(SceneManager->getRootSceneNode()); // add the first loaded mesh into the mesh cache too, if more than one // meshes have been loaded from the file if (LoadedMeshCount>1 && FirstLoadedMesh) { os::Printer::log("Added COLLADA mesh", FirstLoadedMeshName.c_str()); SceneManager->getMeshCache()->addMesh(FirstLoadedMeshName.c_str(), FirstLoadedMesh); } // clean up temporary loaded data clearData(); returnMesh->grab(); // store until this loader is destroyed DummyMesh->drop(); DummyMesh = 0; if (FirstLoadedMesh) FirstLoadedMesh->drop(); FirstLoadedMesh = 0; LoadedMeshCount = 0; return returnMesh; } //! skips an (unknown) section in the collada document void CColladaFileLoader::skipSection(io::IXMLReaderUTF8* reader, bool reportSkipping) { #ifndef COLLADA_READER_DEBUG if (reportSkipping) // always report in COLLADA_READER_DEBUG mode #endif os::Printer::log("COLLADA skipping section", core::stringc(reader->getNodeName()).c_str(), ELL_DEBUG); // skip if this element is empty anyway. if (reader->isEmptyElement()) return; // read until we've reached the last element in this section u32 tagCounter = 1; while(tagCounter && reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT && !reader->isEmptyElement()) { #ifdef COLLADA_READER_DEBUG if (reportSkipping) os::Printer::log("Skipping COLLADA unknown element", core::stringc(reader->getNodeName()).c_str(), ELL_DEBUG); #endif ++tagCounter; } else if (reader->getNodeType() == io::EXN_ELEMENT_END) --tagCounter; } } //! reads the section and its content void CColladaFileLoader::readColladaSection(io::IXMLReaderUTF8* reader) { if (reader->isEmptyElement()) return; // todo: patch level needs to be handled const f32 version = core::fast_atof(core::stringc(reader->getAttributeValue("version")).c_str()); Version = core::floor32(version)*10000+core::round32(core::fract(version)*1000.0f); // Version 1.4 can be checked for by if (Version >= 10400) while(reader->read()) if (reader->getNodeType() == io::EXN_ELEMENT) { if (assetSectionName == reader->getNodeName()) readAssetSection(reader); else if (librarySectionName == reader->getNodeName()) readLibrarySection(reader); else if (libraryNodesSectionName == reader->getNodeName()) readLibrarySection(reader); else if (libraryGeometriesSectionName == reader->getNodeName()) readLibrarySection(reader); else if (libraryMaterialsSectionName == reader->getNodeName()) readLibrarySection(reader); else if (libraryEffectsSectionName == reader->getNodeName()) readLibrarySection(reader); else if (libraryImagesSectionName == reader->getNodeName()) readLibrarySection(reader); else if (libraryCamerasSectionName == reader->getNodeName()) readLibrarySection(reader); else if (libraryLightsSectionName == reader->getNodeName()) readLibrarySection(reader); else if (libraryVisualScenesSectionName == reader->getNodeName()) readVisualScene(reader); else if (assetSectionName == reader->getNodeName()) readAssetSection(reader); else if (sceneSectionName == reader->getNodeName()) readSceneSection(reader); else { os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING); skipSection(reader, true); // unknown section } } } //! reads a section and its content void CColladaFileLoader::readLibrarySection(io::IXMLReaderUTF8* reader) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading library", ELL_DEBUG); #endif if (reader->isEmptyElement()) return; while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { // animation section tbd if (cameraPrefabName == reader->getNodeName()) readCameraPrefab(reader); else // code section tbd // controller section tbd if (geometrySectionName == reader->getNodeName()) readGeometry(reader); else if (imageSectionName == reader->getNodeName()) readImage(reader); else if (lightPrefabName == reader->getNodeName()) readLightPrefab(reader); else if (materialSectionName == reader->getNodeName()) readMaterial(reader); else if (nodeSectionName == reader->getNodeName()) { CScenePrefab p(""); readNodeSection(reader, SceneManager->getRootSceneNode(), &p); } else if (effectSectionName == reader->getNodeName()) readEffect(reader); else // program section tbd if (textureSectionName == reader->getNodeName()) readTexture(reader); else skipSection(reader, true); // unknown section, not all allowed supported yet } else if (reader->getNodeType() == io::EXN_ELEMENT_END) { if (librarySectionName == reader->getNodeName()) break; // end reading. if (libraryNodesSectionName == reader->getNodeName()) break; // end reading. if (libraryGeometriesSectionName == reader->getNodeName()) break; // end reading. if (libraryMaterialsSectionName == reader->getNodeName()) break; // end reading. if (libraryEffectsSectionName == reader->getNodeName()) break; // end reading. if (libraryImagesSectionName == reader->getNodeName()) break; // end reading. if (libraryLightsSectionName == reader->getNodeName()) break; // end reading. if (libraryCamerasSectionName == reader->getNodeName()) break; // end reading. } } } //! reads a element and stores it as a prefab void CColladaFileLoader::readVisualScene(io::IXMLReaderUTF8* reader) { CScenePrefab* p = 0; while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { if (visualSceneSectionName == reader->getNodeName()) p = new CScenePrefab(readId(reader)); else if (p && nodeSectionName == reader->getNodeName()) // as a child of visual_scene readNodeSection(reader, SceneManager->getRootSceneNode(), p); else if (assetSectionName == reader->getNodeName()) readAssetSection(reader); else if (extraNodeName == reader->getNodeName()) skipSection(reader, false); // ignore all other sections else { os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING); skipSection(reader, true); // ignore all other sections } } else if (reader->getNodeType() == io::EXN_ELEMENT_END) { if (libraryVisualScenesSectionName == reader->getNodeName()) return; else if ((visualSceneSectionName == reader->getNodeName()) && p) { Prefabs.push_back(p); p = 0; } } } } //! reads a section and its content void CColladaFileLoader::readSceneSection(io::IXMLReaderUTF8* reader) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading scene", ELL_DEBUG); #endif if (reader->isEmptyElement()) return; // read the scene core::matrix4 transform; // transformation of this node core::aabbox3df bbox; scene::IDummyTransformationSceneNode* node = 0; while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { if (lookatNodeName == reader->getNodeName()) transform *= readLookAtNode(reader); else if (matrixNodeName == reader->getNodeName()) transform *= readMatrixNode(reader); else if (perspectiveNodeName == reader->getNodeName()) transform *= readPerspectiveNode(reader); else if (rotateNodeName == reader->getNodeName()) transform *= readRotateNode(reader); else if (scaleNodeName == reader->getNodeName()) transform *= readScaleNode(reader); else if (skewNodeName == reader->getNodeName()) transform *= readSkewNode(reader); else if (translateNodeName == reader->getNodeName()) transform *= readTranslateNode(reader); else if (bboxNodeName == reader->getNodeName()) readBboxNode(reader, bbox); else if (nodeSectionName == reader->getNodeName()) { // create dummy node if there is none yet. if (!node) node = SceneManager->addDummyTransformationSceneNode(SceneManager->getRootSceneNode()); readNodeSection(reader, node); } else if ((instanceSceneName == reader->getNodeName())) readInstanceNode(reader, SceneManager->getRootSceneNode(), 0, 0,instanceSceneName); else if (extraNodeName == reader->getNodeName()) skipSection(reader, false); else { os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING); skipSection(reader, true); // ignore all other sections } } else if ((reader->getNodeType() == io::EXN_ELEMENT_END) && (sceneSectionName == reader->getNodeName())) return; } if (node) node->getRelativeTransformationMatrix() = transform; } //! reads a section and its content void CColladaFileLoader::readAssetSection(io::IXMLReaderUTF8* reader) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading asset", ELL_DEBUG); #endif if (reader->isEmptyElement()) return; while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { if (upAxisNodeName == reader->getNodeName()) { reader->read(); FlipAxis = (core::stringc("Z_UP") == reader->getNodeData()); } } else if ((reader->getNodeType() == io::EXN_ELEMENT_END) && (assetSectionName == reader->getNodeName())) return; } } //! reads a section and its content void CColladaFileLoader::readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p) { if (reader->isEmptyElement()) { return; #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading empty node", ELL_DEBUG); #endif } core::stringc name = readId(reader); #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading node", name, ELL_DEBUG); #endif core::matrix4 transform; // transformation of this node core::aabbox3df bbox; scene::ISceneNode* node = 0; // instance CScenePrefab* nodeprefab = 0; // prefab for library_nodes usage if (p) { nodeprefab = new CScenePrefab(readId(reader)); p->Children.push_back(nodeprefab); Prefabs.push_back(nodeprefab); // in order to delete them later on } // read the node while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { if (assetSectionName == reader->getNodeName()) readAssetSection(reader); else if (lookatNodeName == reader->getNodeName()) transform *= readLookAtNode(reader); else if (matrixNodeName == reader->getNodeName()) transform *= readMatrixNode(reader); else if (perspectiveNodeName == reader->getNodeName()) transform *= readPerspectiveNode(reader); else if (rotateNodeName == reader->getNodeName()) transform *= readRotateNode(reader); else if (scaleNodeName == reader->getNodeName()) transform *= readScaleNode(reader); else if (skewNodeName == reader->getNodeName()) transform *= readSkewNode(reader); else if (translateNodeName == reader->getNodeName()) transform *= readTranslateNode(reader); else if (bboxNodeName == reader->getNodeName()) readBboxNode(reader, bbox); else if ((instanceName == reader->getNodeName()) || (instanceNodeName == reader->getNodeName()) || (instanceGeometryName == reader->getNodeName()) || (instanceLightName == reader->getNodeName())) { scene::ISceneNode* newnode = 0; readInstanceNode(reader, parent, &newnode, nodeprefab, reader->getNodeName()); if (node && newnode) { // move children from dummy to new node ISceneNodeList::ConstIterator it = node->getChildren().begin(); for (; it != node->getChildren().end(); it = node->getChildren().begin()) (*it)->setParent(newnode); // remove previous dummy node node->remove(); node = newnode; } } else if (nodeSectionName == reader->getNodeName()) { // create dummy node if there is none yet. if (CreateInstances && !node) { scene::IDummyTransformationSceneNode* dummy = SceneManager->addDummyTransformationSceneNode(parent); dummy->getRelativeTransformationMatrix() = transform; node = dummy; } else node = parent; // read and add child readNodeSection(reader, node, nodeprefab); } else if (extraNodeName == reader->getNodeName()) skipSection(reader, false); else skipSection(reader, true); // ignore all other sections } // end if node else if (reader->getNodeType() == io::EXN_ELEMENT_END) { if (nodeSectionName == reader->getNodeName()) break; } } if (nodeprefab) nodeprefab->Transformation = transform; else if (node) { // set transformation correctly into node. node->setPosition(transform.getTranslation()); node->setRotation(transform.getRotationDegrees()); node->setScale(transform.getScale()); node->updateAbsolutePosition(); node->setName(name); } } //! reads a element and its content and creates a matrix from it core::matrix4 CColladaFileLoader::readLookAtNode(io::IXMLReaderUTF8* reader) { core::matrix4 mat; if (reader->isEmptyElement()) return mat; #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading look at node", ELL_DEBUG); #endif f32 floats[9]; readFloatsInsideElement(reader, floats, 9); mat.buildCameraLookAtMatrixLH( core::vector3df(floats[0], floats[1], floats[2]), core::vector3df(floats[3], floats[4], floats[5]), core::vector3df(floats[6], floats[7], floats[8])); return mat; } //! reads a element and its content and creates a matrix from it core::matrix4 CColladaFileLoader::readSkewNode(io::IXMLReaderUTF8* reader) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading skew node", ELL_DEBUG); #endif core::matrix4 mat; if (reader->isEmptyElement()) return mat; f32 floats[7]; // angle rotation-axis translation-axis readFloatsInsideElement(reader, floats, 7); // build skew matrix from these 7 floats core::quaternion q; q.fromAngleAxis(floats[0]*core::DEGTORAD, core::vector3df(floats[1], floats[2], floats[3])); mat = q.getMatrix(); if (floats[4]==1.f) // along x-axis { mat[4]=0.f; mat[6]=0.f; mat[8]=0.f; mat[9]=0.f; } else if (floats[5]==1.f) // along y-axis { mat[1]=0.f; mat[2]=0.f; mat[8]=0.f; mat[9]=0.f; } else if (floats[6]==1.f) // along z-axis { mat[1]=0.f; mat[2]=0.f; mat[4]=0.f; mat[6]=0.f; } return mat; } //! reads a element and its content and stores it in bbox void CColladaFileLoader::readBboxNode(io::IXMLReaderUTF8* reader, core::aabbox3df& bbox) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading boundingbox node", ELL_DEBUG); #endif bbox.reset(core::aabbox3df()); if (reader->isEmptyElement()) return; f32 floats[3]; while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { if (minNodeName == reader->getNodeName()) { readFloatsInsideElement(reader, floats, 3); bbox.MinEdge.set(floats[0], floats[1], floats[2]); } else if (maxNodeName == reader->getNodeName()) { readFloatsInsideElement(reader, floats, 3); bbox.MaxEdge.set(floats[0], floats[1], floats[2]); } else skipSection(reader, true); // ignore all other sections } else if (reader->getNodeType() == io::EXN_ELEMENT_END) { if (bboxNodeName == reader->getNodeName()) break; } } } //! reads a element and its content and creates a matrix from it core::matrix4 CColladaFileLoader::readMatrixNode(io::IXMLReaderUTF8* reader) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading matrix node", ELL_DEBUG); #endif core::matrix4 mat; if (reader->isEmptyElement()) return mat; readFloatsInsideElement(reader, mat.pointer(), 16); // put translation into the correct place if (FlipAxis) { core::matrix4 mat2(mat, core::matrix4::EM4CONST_TRANSPOSED); mat2[1]=mat[8]; mat2[2]=mat[4]; mat2[4]=mat[2]; mat2[5]=mat[10]; mat2[6]=mat[6]; mat2[8]=mat[1]; mat2[9]=mat[9]; mat2[10]=mat[5]; mat2[12]=mat[3]; mat2[13]=mat[11]; mat2[14]=mat[7]; return mat2; } else return core::matrix4(mat, core::matrix4::EM4CONST_TRANSPOSED); } //! reads a element and its content and creates a matrix from it core::matrix4 CColladaFileLoader::readPerspectiveNode(io::IXMLReaderUTF8* reader) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading perspective node", ELL_DEBUG); #endif core::matrix4 mat; if (reader->isEmptyElement()) return mat; f32 floats[1]; readFloatsInsideElement(reader, floats, 1); // TODO: build perspecitve matrix from this float os::Printer::log("COLLADA loader warning: not implemented yet.", ELL_WARNING); return mat; } //! reads a element and its content and creates a matrix from it core::matrix4 CColladaFileLoader::readRotateNode(io::IXMLReaderUTF8* reader) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading rotate node", ELL_DEBUG); #endif core::matrix4 mat; if (reader->isEmptyElement()) return mat; f32 floats[4]; readFloatsInsideElement(reader, floats, 4); if (!core::iszero(floats[3])) { core::quaternion q; if (FlipAxis) q.fromAngleAxis(floats[3]*core::DEGTORAD, core::vector3df(floats[0], floats[2], floats[1])); else q.fromAngleAxis(floats[3]*core::DEGTORAD, core::vector3df(floats[0], floats[1], floats[2])); return q.getMatrix(); } else return core::IdentityMatrix; } //! reads a element and its content and creates a matrix from it core::matrix4 CColladaFileLoader::readScaleNode(io::IXMLReaderUTF8* reader) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading scale node", ELL_DEBUG); #endif core::matrix4 mat; if (reader->isEmptyElement()) return mat; f32 floats[3]; readFloatsInsideElement(reader, floats, 3); if (FlipAxis) mat.setScale(core::vector3df(floats[0], floats[2], floats[1])); else mat.setScale(core::vector3df(floats[0], floats[1], floats[2])); return mat; } //! reads a element and its content and creates a matrix from it core::matrix4 CColladaFileLoader::readTranslateNode(io::IXMLReaderUTF8* reader) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading translate node", ELL_DEBUG); #endif core::matrix4 mat; if (reader->isEmptyElement()) return mat; f32 floats[3]; readFloatsInsideElement(reader, floats, 3); if (FlipAxis) mat.setTranslation(core::vector3df(floats[0], floats[2], floats[1])); else mat.setTranslation(core::vector3df(floats[0], floats[1], floats[2])); return mat; } //! reads any kind of node void CColladaFileLoader::readInstanceNode(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, scene::ISceneNode** outNode, CScenePrefab* p, const core::stringc& type) { // find prefab of the specified id core::stringc url = reader->getAttributeValue("url"); uriToId(url); #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading instance", url, ELL_DEBUG); #endif if (!reader->isEmptyElement()) { while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { if (bindMaterialName == reader->getNodeName()) readBindMaterialSection(reader,url); else if (extraNodeName == reader->getNodeName()) skipSection(reader, false); } else if (reader->getNodeType() == io::EXN_ELEMENT_END) break; } } instantiateNode(parent, outNode, p, url, type); } void CColladaFileLoader::instantiateNode(scene::ISceneNode* parent, scene::ISceneNode** outNode, CScenePrefab* p, const core::stringc& url, const core::stringc& type) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA instantiate node", ELL_DEBUG); #endif for (u32 i=0; igetId()) { if (p) p->Children.push_back(Prefabs[i]); else if (CreateInstances) { scene::ISceneNode * newNode = Prefabs[i]->addInstance(parent, SceneManager); if (outNode) { *outNode = newNode; if (*outNode) (*outNode)->setName(url); } } return; } } if (p) { if (instanceGeometryName==type) { Prefabs.push_back(new CGeometryPrefab(url)); p->Children.push_back(Prefabs.getLast()); } } } //! reads a element and stores it as prefab void CColladaFileLoader::readCameraPrefab(io::IXMLReaderUTF8* reader) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading camera prefab", ELL_DEBUG); #endif CCameraPrefab* prefab = new CCameraPrefab(readId(reader)); if (!reader->isEmptyElement()) { // read techniques optics and imager (the latter is completely ignored, though) readColladaParameters(reader, cameraPrefabName); SColladaParam* p; // XFOV not yet supported p = getColladaParameter(ECPN_YFOV); if (p && p->Type == ECPT_FLOAT) prefab->YFov = p->Floats[0]; p = getColladaParameter(ECPN_ZNEAR); if (p && p->Type == ECPT_FLOAT) prefab->ZNear = p->Floats[0]; p = getColladaParameter(ECPN_ZFAR); if (p && p->Type == ECPT_FLOAT) prefab->ZFar = p->Floats[0]; // orthographic camera uses LEFT, RIGHT, TOP, and BOTTOM } Prefabs.push_back(prefab); } //! reads a element and stores it in the image section void CColladaFileLoader::readImage(io::IXMLReaderUTF8* reader) { // add image to list of loaded images. Images.push_back(SColladaImage()); SColladaImage& image=Images.getLast(); image.Id = readId(reader); #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading image", core::stringc(image.Id), ELL_DEBUG); #endif image.Dimension.Height = (u32)reader->getAttributeValueAsInt("height"); image.Dimension.Width = (u32)reader->getAttributeValueAsInt("width"); if (Version >= 10400) // start with 1.4 { while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { if (assetSectionName == reader->getNodeName()) skipSection(reader, false); else if (initFromName == reader->getNodeName()) { reader->read(); image.Source = reader->getNodeData(); image.Source.trim(); image.SourceIsFilename=true; } else if (dataName == reader->getNodeName()) { reader->read(); image.Source = reader->getNodeData(); image.Source.trim(); image.SourceIsFilename=false; } else if (extraNodeName == reader->getNodeName()) skipSection(reader, false); } else if (reader->getNodeType() == io::EXN_ELEMENT_END) { if (initFromName == reader->getNodeName()) return; } } } else { image.Source = reader->getAttributeValue("source"); image.Source.trim(); image.SourceIsFilename=false; } } //! reads a element and stores it in the texture section void CColladaFileLoader::readTexture(io::IXMLReaderUTF8* reader) { // add texture to list of loaded textures. Textures.push_back(SColladaTexture()); SColladaTexture& texture=Textures.getLast(); texture.Id = readId(reader); #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading texture", core::stringc(texture.Id), ELL_DEBUG); #endif if (!reader->isEmptyElement()) { readColladaInputs(reader, textureSectionName); SColladaInput* input = getColladaInput(ECIS_IMAGE); if (input) { const core::stringc imageName = input->Source; texture.Texture = getTextureFromImage(imageName, NULL); } } } //! reads a element and stores it in the material section void CColladaFileLoader::readMaterial(io::IXMLReaderUTF8* reader) { // add material to list of loaded materials. Materials.push_back(SColladaMaterial()); SColladaMaterial& material = Materials.getLast(); material.Id = readId(reader); #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading material", core::stringc(material.Id), ELL_DEBUG); #endif if (Version >= 10400) { while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT && instanceEffectName == reader->getNodeName()) { material.InstanceEffectId = reader->getAttributeValue("url"); uriToId(material.InstanceEffectId); } else if (reader->getNodeType() == io::EXN_ELEMENT_END && materialSectionName == reader->getNodeName()) { break; } } // end while reader->read(); } else { if (!reader->isEmptyElement()) { readColladaInputs(reader, materialSectionName); SColladaInput* input = getColladaInput(ECIS_TEXTURE); if (input) { core::stringc textureName = input->Source; uriToId(textureName); for (u32 i=0; iType == ECPT_FLOAT3) material.Mat.AmbientColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor(); p = getColladaParameter(ECPN_DIFFUSE); if (p && p->Type == ECPT_FLOAT3) material.Mat.DiffuseColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor(); p = getColladaParameter(ECPN_SPECULAR); if (p && p->Type == ECPT_FLOAT3) material.Mat.DiffuseColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor(); p = getColladaParameter(ECPN_SHININESS); if (p && p->Type == ECPT_FLOAT) material.Mat.Shininess = p->Floats[0]; #endif } } } void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect) { static const core::stringc constantNode("constant"); static const core::stringc lambertNode("lambert"); static const core::stringc phongNode("phong"); static const core::stringc blinnNode("blinn"); static const core::stringc emissionNode("emission"); static const core::stringc ambientNode("ambient"); static const core::stringc diffuseNode("diffuse"); static const core::stringc specularNode("specular"); static const core::stringc shininessNode("shininess"); static const core::stringc reflectiveNode("reflective"); static const core::stringc reflectivityNode("reflectivity"); static const core::stringc transparentNode("transparent"); static const core::stringc transparencyNode("transparency"); static const core::stringc indexOfRefractionNode("index_of_refraction"); if (!effect) { Effects.push_back(SColladaEffect()); effect = &Effects.getLast(); effect->Parameters = new io::CAttributes(); effect->Id = readId(reader); effect->Transparency = 1.f; effect->Mat.Lighting=true; effect->Mat.NormalizeNormals=true; #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading effect", core::stringc(effect->Id), ELL_DEBUG); #endif } while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { // first come the tags we descend, but ignore the top-levels if (!reader->isEmptyElement() && ((profileCOMMONSectionName == reader->getNodeName()) || (techniqueNodeName == reader->getNodeName()))) readEffect(reader,effect); else if (newParamName == reader->getNodeName()) readParameter(reader, effect->Parameters); else // these are the actual materials inside technique if (constantNode == reader->getNodeName() || lambertNode == reader->getNodeName() || phongNode == reader->getNodeName() || blinnNode == reader->getNodeName()) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading effect part", reader->getNodeName(), ELL_DEBUG); #endif effect->Mat.setFlag(irr::video::EMF_GOURAUD_SHADING, phongNode == reader->getNodeName() || blinnNode == reader->getNodeName()); while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { const core::stringc node = reader->getNodeName(); if (emissionNode == node || ambientNode == node || diffuseNode == node || specularNode == node || reflectiveNode == node || transparentNode == node ) { // color or texture types while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT && colorNodeName == reader->getNodeName()) { const video::SColorf colorf = readColorNode(reader); const video::SColor color = colorf.toSColor(); if (emissionNode == node) effect->Mat.EmissiveColor = color; else if (ambientNode == node) effect->Mat.AmbientColor = color; else if (diffuseNode == node) effect->Mat.DiffuseColor = color; else if (specularNode == node) effect->Mat.SpecularColor = color; else if (transparentNode == node) effect->Transparency = colorf.getAlpha(); } else if (reader->getNodeType() == io::EXN_ELEMENT && textureNodeName == reader->getNodeName()) { effect->Textures.push_back(reader->getAttributeValue("texture")); break; } else if (reader->getNodeType() == io::EXN_ELEMENT) skipSection(reader, false); else if (reader->getNodeType() == io::EXN_ELEMENT_END && node == reader->getNodeName()) break; } } else if (shininessNode == node || reflectivityNode == node || transparencyNode == node || indexOfRefractionNode == node ) { // float or param types while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT && floatNodeName == reader->getNodeName()) { f32 f = readFloatNode(reader); if (shininessNode == node) effect->Mat.Shininess = f; else if (transparencyNode == node) effect->Transparency *= f; } else if (reader->getNodeType() == io::EXN_ELEMENT) skipSection(reader, false); else if (reader->getNodeType() == io::EXN_ELEMENT_END && node == reader->getNodeName()) break; } } else skipSection(reader, true); // ignore all other nodes } else if (reader->getNodeType() == io::EXN_ELEMENT_END && ( constantNode == reader->getNodeName() || lambertNode == reader->getNodeName() || phongNode == reader->getNodeName() || blinnNode == reader->getNodeName() )) break; } } else if (!reader->isEmptyElement() && (extraNodeName == reader->getNodeName())) readEffect(reader,effect); else if (doubleSidedNodeName == reader->getNodeName()) { // read the GoogleEarth extra flag for double sided polys s32 doubleSided = 0; readIntsInsideElement(reader,&doubleSided,1); if (doubleSided) { #ifdef COLLADA_READER_DEBUG os::Printer::log("Setting double sided flag for effect.", ELL_DEBUG); #endif effect->Mat.setFlag(irr::video::EMF_BACK_FACE_CULLING,false); } } else skipSection(reader, true); // ignore all other sections } else if (reader->getNodeType() == io::EXN_ELEMENT_END) { if (effectSectionName == reader->getNodeName()) break; else if (profileCOMMONSectionName == reader->getNodeName()) break; else if (techniqueNodeName == reader->getNodeName()) break; else if (extraNodeName == reader->getNodeName()) break; } } if (effect->Mat.AmbientColor == video::SColor(0) && effect->Mat.DiffuseColor != video::SColor(0)) effect->Mat.AmbientColor = effect->Mat.DiffuseColor; if (effect->Mat.DiffuseColor == video::SColor(0) && effect->Mat.AmbientColor != video::SColor(0)) effect->Mat.DiffuseColor = effect->Mat.AmbientColor; if ((effect->Transparency != 0.0f) && (effect->Transparency != 1.0f)) { effect->Mat.MaterialType = irr::video::EMT_TRANSPARENT_VERTEX_ALPHA; effect->Mat.ZWriteEnable = false; } video::E_TEXTURE_CLAMP twu = video::ETC_REPEAT; s32 idx = effect->Parameters->findAttribute(wrapsName.c_str()); if ( idx >= 0 ) twu = (video::E_TEXTURE_CLAMP)(effect->Parameters->getAttributeAsInt(idx)); video::E_TEXTURE_CLAMP twv = video::ETC_REPEAT; idx = effect->Parameters->findAttribute(wraptName.c_str()); if ( idx >= 0 ) twv = (video::E_TEXTURE_CLAMP)(effect->Parameters->getAttributeAsInt(idx)); for (u32 i=0; iMat.TextureLayer[i].TextureWrapU = twu; effect->Mat.TextureLayer[i].TextureWrapV = twv; } effect->Mat.setFlag(video::EMF_BILINEAR_FILTER, effect->Parameters->getAttributeAsBool("bilinear")); effect->Mat.setFlag(video::EMF_TRILINEAR_FILTER, effect->Parameters->getAttributeAsBool("trilinear")); effect->Mat.setFlag(video::EMF_ANISOTROPIC_FILTER, effect->Parameters->getAttributeAsBool("anisotropic")); } const SColladaMaterial* CColladaFileLoader::findMaterial(const core::stringc& materialName) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA find material", materialName, ELL_DEBUG); #endif // do a quick lookup in the materials SColladaMaterial matToFind; matToFind.Id = materialName; s32 mat = Materials.binary_search(matToFind); if (mat == -1) return 0; // instantiate the material effect if needed if (Materials[mat].InstanceEffectId.size() != 0) { // do a quick lookup in the effects SColladaEffect effectToFind; effectToFind.Id = Materials[mat].InstanceEffectId; s32 effect = Effects.binary_search(effectToFind); if (effect != -1) { // found the effect, instantiate by copying into the material Materials[mat].Mat = Effects[effect].Mat; if (Effects[effect].Textures.size()) Materials[mat].Mat.setTexture(0, getTextureFromImage(Effects[effect].Textures[0], &(Effects[effect]))); Materials[mat].Transparency = Effects[effect].Transparency; // and indicate the material is instantiated by removing the effect ref Materials[mat].InstanceEffectId = ""; } else return 0; } return &Materials[mat]; } void CColladaFileLoader::readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading bind material", ELL_DEBUG); #endif while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { if (instanceMaterialName == reader->getNodeName()) { // the symbol to retarget, and the target material core::stringc meshbufferReference = reader->getAttributeValue("symbol"); if (meshbufferReference.size()==0) continue; core::stringc target = reader->getAttributeValue("target"); uriToId(target); if (target.size()==0) continue; const SColladaMaterial * material = findMaterial(target); if (!material) continue; // bind any pending materials for this node meshbufferReference = id+"/"+meshbufferReference; #ifdef COLLADA_READER_DEBUG os::Printer::log((core::stringc("Material binding: ")+meshbufferReference+" "+target).c_str(), ELL_DEBUG); #endif if (MaterialsToBind.find(meshbufferReference)) { core::array & toBind = MeshesToBind[MaterialsToBind[meshbufferReference]]; #ifdef COLLADA_READER_DEBUG os::Printer::log("Material binding now ",material->Id.c_str(), ELL_DEBUG); os::Printer::log("#meshbuffers",core::stringc(toBind.size()).c_str(), ELL_DEBUG); #endif SMesh tmpmesh; for (u32 i = 0; i < toBind.size(); ++i) { toBind[i]->getMaterial() = material->Mat; tmpmesh.addMeshBuffer(toBind[i]); if ((material->Transparency!=0.0f) && (material->Transparency!=1.0f)) { toBind[i]->getMaterial().MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; toBind[i]->getMaterial().ZWriteEnable = false; } } SceneManager->getMeshManipulator()->setVertexColors(&tmpmesh,material->Mat.DiffuseColor); if ((material->Transparency!=0.0f) && (material->Transparency!=1.0f)) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA found transparency material", core::stringc(material->Transparency).c_str(), ELL_DEBUG); #endif SceneManager->getMeshManipulator()->setVertexColorAlpha(&tmpmesh, core::floor32(material->Transparency*255.0f)); } } } } else if (reader->getNodeType() == io::EXN_ELEMENT_END && bindMaterialName == reader->getNodeName()) break; } } //! reads a element and stores it as mesh if possible void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader) { core::stringc id = readId(reader); #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading geometry", id, ELL_DEBUG); #endif SAnimatedMesh* amesh = new SAnimatedMesh(); scene::SMesh* mesh = new SMesh(); amesh->addMesh(mesh); core::array sources; bool okToReadArray = false; // handles geometry node and the mesh children in this loop // read sources with arrays and accessor for each mesh if (!reader->isEmptyElement()) while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { const char* nodeName = reader->getNodeName(); if (meshSectionName == nodeName) { // inside a mesh section. Don't have to do anything here. } else if (sourceSectionName == nodeName) { // create a new source sources.push_back(SSource()); sources.getLast().Id = readId(reader); #ifdef COLLADA_READER_DEBUG os::Printer::log("Reading source", sources.getLast().Id.c_str(), ELL_DEBUG); #endif } else if (arraySectionName == nodeName || floatArraySectionName == nodeName || intArraySectionName == nodeName) { // create a new array and read it. if (!sources.empty()) { sources.getLast().Array.Name = readId(reader); int count = reader->getAttributeValueAsInt("count"); sources.getLast().Array.Data.set_used(count); // pre allocate // check if type of array is ok const char* type = reader->getAttributeValue("type"); okToReadArray = (type && (!strcmp("float", type) || !strcmp("int", type))) || floatArraySectionName == nodeName || intArraySectionName == nodeName; #ifdef COLLADA_READER_DEBUG os::Printer::log("Read array", sources.getLast().Array.Name.c_str(), ELL_DEBUG); #endif } #ifdef COLLADA_READER_DEBUG else os::Printer::log("Warning, array outside source found", readId(reader).c_str(), ELL_DEBUG); #endif } else if (accessorSectionName == nodeName) // child of source (below a technique tag) { #ifdef COLLADA_READER_DEBUG os::Printer::log("Reading accessor", ELL_DEBUG); #endif SAccessor accessor; accessor.Count = reader->getAttributeValueAsInt("count"); accessor.Offset = reader->getAttributeValueAsInt("offset"); accessor.Stride = reader->getAttributeValueAsInt("stride"); if (accessor.Stride == 0) accessor.Stride = 1; // the accessor contains some information on how to access (boi!) the array, // the info is stored in collada style parameters, so just read them. readColladaParameters(reader, accessorSectionName); if (!sources.empty()) { sources.getLast().Accessors.push_back(accessor); sources.getLast().Accessors.getLast().Parameters = ColladaParameters; } } else if (verticesSectionName == nodeName) { #ifdef COLLADA_READER_DEBUG os::Printer::log("Reading vertices", ELL_DEBUG); #endif // read vertex input position source readColladaInputs(reader, verticesSectionName); } else // lines and linestrips missing if (polygonsSectionName == nodeName || polylistSectionName == nodeName || trianglesSectionName == nodeName) { // read polygons section readPolygonSection(reader, sources, mesh, id); } else // trifans, and tristrips missing if (doubleSidedNodeName == reader->getNodeName()) { // read the extra flag for double sided polys s32 doubleSided = 0; readIntsInsideElement(reader,&doubleSided,1); if (doubleSided) { #ifdef COLLADA_READER_DEBUG os::Printer::log("Setting double sided flag for mesh.", ELL_DEBUG); #endif amesh->setMaterialFlag(irr::video::EMF_BACK_FACE_CULLING,false); } } else // techniqueCommon or 'technique profile=common' must not be skipped if ((techniqueCommonSectionName != nodeName) // Collada 1.2/1.3 && (techniqueNodeName != nodeName) // Collada 1.4+ && (extraNodeName != nodeName)) { os::Printer::log("COLLADA loader warning: Wrong tag usage found in geometry", reader->getNodeName(), ELL_WARNING); skipSection(reader, true); // ignore all other sections } } // end if node type is element else if (reader->getNodeType() == io::EXN_TEXT) { // read array data if (okToReadArray && !sources.empty()) { core::array& a = sources.getLast().Array.Data; core::stringc data = reader->getNodeData(); data.trim(); const c8* p = &data[0]; for (u32 i=0; igetNodeType() == io::EXN_ELEMENT_END) { if (geometrySectionName == reader->getNodeName()) { // end of geometry section reached, cancel out break; } } } // end while reader->read(); // add mesh as geometry mesh->recalculateBoundingBox(); amesh->recalculateBoundingBox(); // create virtual file name io::path filename = CurrentlyLoadingMesh; filename += '#'; filename += id; // add to scene manager if (LoadedMeshCount) { SceneManager->getMeshCache()->addMesh(filename.c_str(), amesh); os::Printer::log("Added COLLADA mesh", filename.c_str(), ELL_DEBUG); } else { FirstLoadedMeshName = filename; FirstLoadedMesh = amesh; FirstLoadedMesh->grab(); } ++LoadedMeshCount; mesh->drop(); amesh->drop(); // create geometry prefab u32 i; for (i=0; igetId()==id) { ((CGeometryPrefab*)Prefabs[i])->Mesh=mesh; break; } } if (i==Prefabs.size()) { CGeometryPrefab* prefab = new CGeometryPrefab(id); prefab->Mesh = mesh; Prefabs.push_back(prefab); } // store as dummy mesh if no instances will be created if (!CreateInstances && !DummyMesh) { DummyMesh = amesh; DummyMesh->grab(); } } struct SPolygon { core::array Indices; }; //! reads a polygons section and creates a mesh from it void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, core::array& sources, scene::SMesh* mesh, const core::stringc& geometryId) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading polygon section", ELL_DEBUG); #endif core::stringc materialName = reader->getAttributeValue("material"); core::stringc polygonType = reader->getNodeName(); const int polygonCount = reader->getAttributeValueAsInt("count"); // Not useful because it only determines the number of primitives, which have arbitrary vertices in case of polygon core::array polygons; if (polygonType == polygonsSectionName) polygons.reallocate(polygonCount); core::array vCounts; bool parsePolygonOK = false; bool parseVcountOK = false; u32 inputSemanticCount = 0; bool unresolvedInput=false; u32 maxOffset = 0; core::array localInputs; // read all and primitives if (!reader->isEmptyElement()) while(reader->read()) { const char* nodeName = reader->getNodeName(); if (reader->getNodeType() == io::EXN_ELEMENT) { // polygon node may contain params if (inputTagName == nodeName) { // read input tag readColladaInput(reader, localInputs); // resolve input source SColladaInput& inp = localInputs.getLast(); // get input source array id, if it is a vertex input, take // the -source attribute. if (inp.Semantic == ECIS_VERTEX) { inp.Source = Inputs[0].Source; for (u32 i=1; igetNodeType() == io::EXN_ELEMENT_END) { if (primitivesName == nodeName) parsePolygonOK = false; // end parsing a polygon else if (vcountName == nodeName) parseVcountOK = false; // end parsing vcounts else if (polygonType == nodeName) break; // cancel out and create mesh } // end is element end else if (reader->getNodeType() == io::EXN_TEXT) { if (parseVcountOK) { core::stringc data = reader->getNodeData(); data.trim(); const c8* p = &data[0]; while(*p) { findNextNoneWhiteSpace(&p); if (*p) vCounts.push_back(readInt(&p)); } parseVcountOK = false; } else if (parsePolygonOK && polygons.size()) { core::stringc data = reader->getNodeData(); data.trim(); const c8* p = &data[0]; SPolygon& poly = polygons.getLast(); if (polygonType == polygonsSectionName) poly.Indices.reallocate((maxOffset+1)*3); else poly.Indices.reallocate(polygonCount*(maxOffset+1)*3); if (vCounts.empty()) { while(*p) { findNextNoneWhiteSpace(&p); poly.Indices.push_back(readInt(&p)); } } else { for (u32 i = 0; i < vCounts.size(); i++) { const int polyVCount = vCounts[i]; core::array polyCorners; for (u32 j = 0; j < polyVCount * inputSemanticCount; j++) { if (!*p) break; findNextNoneWhiteSpace(&p); polyCorners.push_back(readInt(&p)); } while (polyCorners.size() >= 3 * inputSemanticCount) { // add one triangle's worth of indices for (u32 k = 0; k < inputSemanticCount * 3; ++k) { poly.Indices.push_back(polyCorners[k]); } // remove one corner from our poly polyCorners.erase(inputSemanticCount,inputSemanticCount); } polyCorners.clear(); } vCounts.clear(); } parsePolygonOK = false; } } } // end while reader->read() // find source array (we'll ignore accessors for this implementation) for (u32 i=0; i vertMap; for (u32 i=0; i indices; const u32 vertexCount = polygons[i].Indices.size() / maxOffset; mbuffer->Vertices.reallocate(mbuffer->Vertices.size()+vertexCount); // for all index/semantic groups for (u32 v=0; v::Node* n = vertMap.find(vtx); if (n) { indices.push_back(n->getValue()); } else { indices.push_back(mbuffer->getVertexCount()); mbuffer->Vertices.push_back(vtx); vertMap.insert(vtx, mbuffer->getVertexCount()-1); } } // end for all vertices if (polygonsSectionName == polygonType && indices.size() > 3) { // need to tesselate for polygons of 4 or more vertices // for now we naively turn interpret it as a triangle fan // as full tesselation is problematic if (FlipAxis) { for (u32 ind = indices.size()-3; ind>0 ; --ind) { mbuffer->Indices.push_back(indices[0]); mbuffer->Indices.push_back(indices[ind+2]); mbuffer->Indices.push_back(indices[ind+1]); } } else { for (u32 ind = 0; ind+2 < indices.size(); ++ind) { mbuffer->Indices.push_back(indices[0]); mbuffer->Indices.push_back(indices[ind+1]); mbuffer->Indices.push_back(indices[ind+2]); } } } else { // it's just triangles for (u32 ind = 0; ind < indices.size(); ind+=3) { if (FlipAxis) { mbuffer->Indices.push_back(indices[ind+2]); mbuffer->Indices.push_back(indices[ind+1]); mbuffer->Indices.push_back(indices[ind+0]); } else { mbuffer->Indices.push_back(indices[ind+0]); mbuffer->Indices.push_back(indices[ind+1]); mbuffer->Indices.push_back(indices[ind+2]); } } } } // end for all polygons } else { // lightmap mesh buffer scene::SMeshBufferLightMap* mbuffer = new SMeshBufferLightMap(); buffer = mbuffer; for (u32 i=0; iVertices.reallocate(mbuffer->Vertices.size()+vertexCount); // for all vertices in array for (u32 v=0; vVertices.push_back(vtx); } // end for all vertices // add vertex indices const u32 oldVertexCount = mbuffer->Vertices.size() - vertexCount; for (u32 face=0; faceIndices.push_back(oldVertexCount + 0); mbuffer->Indices.push_back(oldVertexCount + 1 + face); mbuffer->Indices.push_back(oldVertexCount + 2 + face); } } // end for all polygons } const SColladaMaterial* m = findMaterial(materialName); if (m) { buffer->getMaterial() = m->Mat; SMesh tmpmesh; tmpmesh.addMeshBuffer(buffer); SceneManager->getMeshManipulator()->setVertexColors(&tmpmesh,m->Mat.DiffuseColor); if (m->Transparency != 1.0f) SceneManager->getMeshManipulator()->setVertexColorAlpha(&tmpmesh,core::floor32(m->Transparency*255.0f)); } // add future bind reference for the material core::stringc meshbufferReference = geometryId+"/"+materialName; if (!MaterialsToBind.find(meshbufferReference)) { MaterialsToBind[meshbufferReference] = MeshesToBind.size(); MeshesToBind.push_back(core::array()); } MeshesToBind[MaterialsToBind[meshbufferReference]].push_back(buffer); // calculate normals if there is no slot for it if (!normalSlotCount) SceneManager->getMeshManipulator()->recalculateNormals(buffer, true); // recalculate bounding box buffer->recalculateBoundingBox(); // add mesh buffer mesh->addMeshBuffer(buffer); #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA added meshbuffer", core::stringc(buffer->getVertexCount())+" vertices, "+core::stringc(buffer->getIndexCount())+" indices.", ELL_DEBUG); #endif buffer->drop(); } //! reads a element and stores it as prefab void CColladaFileLoader::readLightPrefab(io::IXMLReaderUTF8* reader) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading light prefab", ELL_DEBUG); #endif CLightPrefab* prefab = new CLightPrefab(readId(reader)); if (!reader->isEmptyElement()) { if (Version >= 10400) // start with 1.4 { while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { if (pointSectionName == reader->getNodeName()) prefab->LightData.Type=video::ELT_POINT; else if (directionalSectionName == reader->getNodeName()) prefab->LightData.Type=video::ELT_DIRECTIONAL; else if (spotSectionName == reader->getNodeName()) prefab->LightData.Type=video::ELT_SPOT; else if (ambientSectionName == reader->getNodeName()) prefab->LightData.Type=ELT_AMBIENT; else if (colorNodeName == reader->getNodeName()) prefab->LightData.DiffuseColor=readColorNode(reader); else if (constantAttenuationNodeName == reader->getNodeName()) readFloatsInsideElement(reader,&prefab->LightData.Attenuation.X,1); else if (linearAttenuationNodeName == reader->getNodeName()) readFloatsInsideElement(reader,&prefab->LightData.Attenuation.Y,1); else if (quadraticAttenuationNodeName == reader->getNodeName()) readFloatsInsideElement(reader,&prefab->LightData.Attenuation.Z,1); else if (falloffAngleNodeName == reader->getNodeName()) { readFloatsInsideElement(reader,&prefab->LightData.OuterCone,1); prefab->LightData.OuterCone *= core::DEGTORAD; } else if (falloffExponentNodeName == reader->getNodeName()) readFloatsInsideElement(reader,&prefab->LightData.Falloff,1); } else if (reader->getNodeType() == io::EXN_ELEMENT_END) { if ((pointSectionName == reader->getNodeName()) || (directionalSectionName == reader->getNodeName()) || (spotSectionName == reader->getNodeName()) || (ambientSectionName == reader->getNodeName())) break; } } } else { readColladaParameters(reader, lightPrefabName); SColladaParam* p = getColladaParameter(ECPN_COLOR); if (p && p->Type == ECPT_FLOAT3) prefab->LightData.DiffuseColor.set(p->Floats[0], p->Floats[1], p->Floats[2]); } } Prefabs.push_back(prefab); } //! returns a collada parameter or none if not found SColladaParam* CColladaFileLoader::getColladaParameter(ECOLLADA_PARAM_NAME name) { for (u32 i=0; i& inputs) { // parse param SColladaInput p; // get type core::stringc semanticName = reader->getAttributeValue("semantic"); for (u32 i=0; inputSemanticNames[i]; ++i) { if (semanticName == inputSemanticNames[i]) { p.Semantic = (ECOLLADA_INPUT_SEMANTIC)i; break; } } // get source p.Source = reader->getAttributeValue("source"); if (reader->getAttributeValue("offset")) // Collada 1.4+ p.Offset = (u32)reader->getAttributeValueAsInt("offset"); else // Collada 1.2/1.3 p.Offset = (u32)reader->getAttributeValueAsInt("idx"); p.Set = (u32)reader->getAttributeValueAsInt("set"); // add input inputs.push_back(p); } //! parses all collada inputs inside an element and stores them in Inputs void CColladaFileLoader::readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName) { Inputs.clear(); while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT && inputTagName == reader->getNodeName()) { readColladaInput(reader, Inputs); } else if (reader->getNodeType() == io::EXN_ELEMENT_END) { if (parentName == reader->getNodeName()) return; // end of parent reached } } // end while reader->read(); } //! parses all collada parameters inside an element and stores them in ColladaParameters void CColladaFileLoader::readColladaParameters(io::IXMLReaderUTF8* reader, const core::stringc& parentName) { ColladaParameters.clear(); const char* const paramNames[] = {"COLOR", "AMBIENT", "DIFFUSE", "SPECULAR", "SHININESS", "YFOV", "ZNEAR", "ZFAR", 0}; const char* const typeNames[] = {"float", "float2", "float3", 0}; while(reader->read()) { const char* nodeName = reader->getNodeName(); if (reader->getNodeType() == io::EXN_ELEMENT && paramTagName == nodeName) { // parse param SColladaParam p; // get type u32 i; core::stringc typeName = reader->getAttributeValue("type"); for (i=0; typeNames[i]; ++i) if (typeName == typeNames[i]) { p.Type = (ECOLLADA_PARAM_TYPE)i; break; } // get name core::stringc nameName = reader->getAttributeValue("name"); for (i=0; typeNames[i]; ++i) if (nameName == paramNames[i]) { p.Name = (ECOLLADA_PARAM_NAME)i; break; } // read parameter data inside parameter tags switch(p.Type) { case ECPT_FLOAT: case ECPT_FLOAT2: case ECPT_FLOAT3: case ECPT_FLOAT4: readFloatsInsideElement(reader, p.Floats, p.Type - ECPT_FLOAT + 1); break; // TODO: other types of data (ints, bools or whatever) default: break; } // add param ColladaParameters.push_back(p); } else if (reader->getNodeType() == io::EXN_ELEMENT_END) { if (parentName == reader->getNodeName()) return; // end of parent reached } } // end while reader->read(); } //! parses a float from a char pointer and moves the pointer //! to the end of the parsed float inline f32 CColladaFileLoader::readFloat(const c8** p) { f32 ftmp; *p = core::fast_atof_move(*p, ftmp); return ftmp; } //! parses an int from a char pointer and moves the pointer to //! the end of the parsed float inline s32 CColladaFileLoader::readInt(const c8** p) { return (s32)readFloat(p); } //! places pointer to next begin of a token void CColladaFileLoader::findNextNoneWhiteSpace(const c8** start) { const c8* p = *start; while(*p && (*p==' ' || *p=='\n' || *p=='\r' || *p=='\t')) ++p; // TODO: skip comments *start = p; } //! reads floats from inside of xml element until end of xml element void CColladaFileLoader::readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count) { if (reader->isEmptyElement()) return; while(reader->read()) { // TODO: check for comments inside the element // and ignore them. if (reader->getNodeType() == io::EXN_TEXT) { // parse float data core::stringc data = reader->getNodeData(); data.trim(); const c8* p = &data[0]; for (u32 i=0; igetNodeType() == io::EXN_ELEMENT_END) break; // end parsing text } } //! reads ints from inside of xml element until end of xml element void CColladaFileLoader::readIntsInsideElement(io::IXMLReaderUTF8* reader, s32* ints, u32 count) { if (reader->isEmptyElement()) return; while(reader->read()) { // TODO: check for comments inside the element // and ignore them. if (reader->getNodeType() == io::EXN_TEXT) { // parse float data core::stringc data = reader->getNodeData(); data.trim(); const c8* p = &data[0]; for (u32 i=0; igetNodeType() == io::EXN_ELEMENT_END) break; // end parsing text } } video::SColorf CColladaFileLoader::readColorNode(io::IXMLReaderUTF8* reader) { if (reader->getNodeType() == io::EXN_ELEMENT && colorNodeName == reader->getNodeName()) { f32 color[4]; readFloatsInsideElement(reader,color,4); return video::SColorf(color[0], color[1], color[2], color[3]); } return video::SColorf(); } f32 CColladaFileLoader::readFloatNode(io::IXMLReaderUTF8* reader) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading ", ELL_DEBUG); #endif f32 result = 0.0f; if (reader->getNodeType() == io::EXN_ELEMENT && floatNodeName == reader->getNodeName()) { readFloatsInsideElement(reader,&result,1); } return result; } //! clears all loaded data void CColladaFileLoader::clearData() { // delete all prefabs for (u32 i=0; idrop(); Prefabs.clear(); // clear all parameters ColladaParameters.clear(); // clear all materials Images.clear(); // clear all materials Textures.clear(); // clear all materials Materials.clear(); // clear all inputs Inputs.clear(); // clear all effects for ( u32 i=0; idrop(); Effects.clear(); // clear all the materials to bind MaterialsToBind.clear(); MeshesToBind.clear(); } //! changes the XML URI into an internal id void CColladaFileLoader::uriToId(core::stringc& str) { // currently, we only remove the # from the begin if there // because we simply don't support referencing other files. if (!str.size()) return; if (str[0] == '#') str.erase(0); } //! read Collada Id, uses id or name if id is missing core::stringc CColladaFileLoader::readId(io::IXMLReaderUTF8* reader) { core::stringc id = reader->getAttributeValue("id"); if (id.size()==0) id = reader->getAttributeValue("name"); return id; } //! create an Irrlicht texture from the reference video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri, SColladaEffect * effect) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA searching texture", uri, ELL_DEBUG); #endif video::IVideoDriver* driver = SceneManager->getVideoDriver(); for (;;) { uriToId(uri); for (u32 i=0; iexistFile(Images[i].Source)) return driver->getTexture(Images[i].Source); return driver->getTexture((FileSystem->getFileDir(CurrentlyLoadingMesh)+"/"+Images[i].Source)); } else if (Images[i].Source.size()) { //const u32 size = Images[i].Dimension.getArea(); const u32 size = Images[i].Dimension.Width * Images[i].Dimension.Height;; u32* data = new u32[size]; // we assume RGBA u32* ptrdest = data; const c8* ptrsrc = Images[i].Source.c_str(); for (u32 j=0; jcreateImageFromData(video::ECF_A8R8G8B8, Images[i].Dimension, data, true, true); video::ITexture* tex = driver->addTexture((CurrentlyLoadingMesh+"#"+Images[i].Id).c_str(), img); img->drop(); return tex; } break; } } if (effect && effect->Parameters->getAttributeType(uri.c_str())==io::EAT_STRING) { uri = effect->Parameters->getAttributeAsString(uri.c_str()); #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA now searching texture", uri.c_str(), ELL_DEBUG); #endif } else break; } return 0; } //! read a parameter and value void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters) { #ifdef COLLADA_READER_DEBUG os::Printer::log("COLLADA reading parameter", ELL_DEBUG); #endif if ( !parameters ) return; const core::stringc name = reader->getAttributeValue("sid"); if (!reader->isEmptyElement()) { while(reader->read()) { if (reader->getNodeType() == io::EXN_ELEMENT) { if (floatNodeName == reader->getNodeName()) { const f32 f = readFloatNode(reader); parameters->addFloat(name.c_str(), f); } else if (float2NodeName == reader->getNodeName()) { f32 f[2]; readFloatsInsideElement(reader, f, 2); // Parameters.addVector2d(name.c_str(), core::vector2df(f[0],f[1])); } else if (float3NodeName == reader->getNodeName()) { f32 f[3]; readFloatsInsideElement(reader, f, 3); parameters->addVector3d(name.c_str(), core::vector3df(f[0],f[1],f[2])); } else if ((initFromName == reader->getNodeName()) || (sourceSectionName == reader->getNodeName())) { reader->read(); parameters->addString(name.c_str(), reader->getNodeData()); } else if (wrapsName == reader->getNodeName()) { reader->read(); const core::stringc val = reader->getNodeData(); if (val == "WRAP") parameters->addInt(wrapsName.c_str(), (int)video::ETC_REPEAT); else if ( val== "MIRROR") parameters->addInt(wrapsName.c_str(), (int)video::ETC_MIRROR); else if ( val== "CLAMP") parameters->addInt(wrapsName.c_str(), (int)video::ETC_CLAMP_TO_EDGE); else if ( val== "BORDER") parameters->addInt(wrapsName.c_str(), (int)video::ETC_CLAMP_TO_BORDER); else if ( val== "NONE") parameters->addInt(wrapsName.c_str(), (int)video::ETC_CLAMP_TO_BORDER); } else if (wraptName == reader->getNodeName()) { reader->read(); const core::stringc val = reader->getNodeData(); if (val == "WRAP") parameters->addInt(wraptName.c_str(), (int)video::ETC_REPEAT); else if ( val== "MIRROR") parameters->addInt(wraptName.c_str(), (int)video::ETC_MIRROR); else if ( val== "CLAMP") parameters->addInt(wraptName.c_str(), (int)video::ETC_CLAMP_TO_EDGE); else if ( val== "BORDER") parameters->addInt(wraptName.c_str(), (int)video::ETC_CLAMP_TO_BORDER); else if ( val== "NONE") parameters->addInt(wraptName.c_str(), (int)video::ETC_CLAMP_TO_BORDER); } else if (minfilterName == reader->getNodeName()) { reader->read(); const core::stringc val = reader->getNodeData(); if (val == "LINEAR_MIPMAP_LINEAR") parameters->addBool("trilinear", true); else if (val == "LINEAR_MIPMAP_NEAREST") parameters->addBool("bilinear", true); } else if (magfilterName == reader->getNodeName()) { reader->read(); const core::stringc val = reader->getNodeData(); if (val != "LINEAR") { parameters->addBool("bilinear", false); parameters->addBool("trilinear", false); } } else if (mipfilterName == reader->getNodeName()) { parameters->addBool("anisotropic", true); } } else if(reader->getNodeType() == io::EXN_ELEMENT_END) { if (newParamName == reader->getNodeName()) break; } } } } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_COLLADA_LOADER_ irrlicht-1.8.3/source/Irrlicht/CCgMaterialRenderer.h0000644000000000000000000001134412574354552021113 0ustar rootroot// Copyright (C) 2012 Patryk Nadrowski // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_CG_MATERIAL_RENDERER_H_INCLUDED__ #define __C_CG_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_CG_ #include "IMaterialRenderer.h" #include "IMaterialRendererServices.h" #include "IShaderConstantSetCallBack.h" #include "IGPUProgrammingServices.h" #include "irrArray.h" #include "irrString.h" #include "IVideoDriver.h" #include "os.h" #include "Cg/cg.h" #ifdef _MSC_VER #pragma comment(lib, "cg.lib") #endif namespace irr { namespace video { class CCgUniform { public: CCgUniform(const CGparameter& parameter, bool global); const core::stringc& getName() const; const CGparameter& getParameter() const; CGenum getSpace() const; CGtype getType() const; virtual void update(const void* data, const SMaterial& material) const = 0; protected: core::stringc Name; CGparameter Parameter; CGenum Space; CGtype Type; }; class CCgUniform1f : public CCgUniform { public: CCgUniform1f(const CGparameter& parameter, bool global); void update(const void* data, const SMaterial& material) const; }; class CCgUniform2f : public CCgUniform { public: CCgUniform2f(const CGparameter& parameter, bool global); void update(const void* data, const SMaterial& material) const; }; class CCgUniform3f : public CCgUniform { public: CCgUniform3f(const CGparameter& parameter, bool global); void update(const void* data, const SMaterial& material) const; }; class CCgUniform4f : public CCgUniform { public: CCgUniform4f(const CGparameter& parameter, bool global); void update(const void* data, const SMaterial& material) const; }; class CCgUniform1i : public CCgUniform { public: CCgUniform1i(const CGparameter& parameter, bool global); void update(const void* data, const SMaterial& material) const; }; class CCgUniform2i : public CCgUniform { public: CCgUniform2i(const CGparameter& parameter, bool global); void update(const void* data, const SMaterial& material) const; }; class CCgUniform3i : public CCgUniform { public: CCgUniform3i(const CGparameter& parameter, bool global); void update(const void* data, const SMaterial& material) const; }; class CCgUniform4i : public CCgUniform { public: CCgUniform4i(const CGparameter& parameter, bool global); void update(const void* data, const SMaterial& material) const; }; class CCgUniform4x4f : public CCgUniform { public: CCgUniform4x4f(const CGparameter& parameter, bool global); void update(const void* data, const SMaterial& material) const; }; class CCgUniformSampler2D : public CCgUniform { public: CCgUniformSampler2D(const CGparameter& parameter, bool global); void update(const void* data, const SMaterial& material) const; }; class CCgMaterialRenderer : public IMaterialRenderer, public IMaterialRendererServices { public: CCgMaterialRenderer(IShaderConstantSetCallBack* callback = 0, IMaterialRenderer* baseMaterial = 0, s32 userData = 0); virtual ~CCgMaterialRenderer(); virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) = 0; virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) = 0; virtual void OnUnsetMaterial() = 0; virtual bool isTransparent() const; virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) = 0; virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count); virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count); virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count); virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1); virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count); virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count); virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count); virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1); virtual IVideoDriver* getVideoDriver() = 0; protected: void getUniformList(); IShaderConstantSetCallBack* CallBack; IMaterialRenderer* BaseMaterial; s32 UserData; core::array UniformInfo; CGprogram VertexProgram; CGprogram FragmentProgram; CGprogram GeometryProgram; CGprofile VertexProfile; CGprofile FragmentProfile; CGprofile GeometryProfile; SMaterial Material; CGerror Error; }; } } #endif #endif irrlicht-1.8.3/source/Irrlicht/CCgMaterialRenderer.cpp0000644000000000000000000002070712574354552021451 0ustar rootroot// Copyright (C) 2012 Patryk Nadrowski // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_CG_ #include "CCgMaterialRenderer.h" namespace irr { namespace video { CCgUniform::CCgUniform(const CGparameter& parameter, bool global) : Parameter(parameter), Type(CG_UNKNOWN_TYPE) { Name = cgGetParameterName(Parameter); if(global) Space = CG_GLOBAL; else Space = CG_PROGRAM; } const core::stringc& CCgUniform::getName() const { return Name; } const CGparameter& CCgUniform::getParameter() const { return Parameter; } CGenum CCgUniform::getSpace() const { return Space; } CGtype CCgUniform::getType() const { return Type; } CCgUniform1f::CCgUniform1f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global) { Type = CG_FLOAT; } void CCgUniform1f::update(const void* data, const SMaterial& material) const { f32* Data = (f32*)data; cgSetParameter1f(Parameter, *Data); } CCgUniform2f::CCgUniform2f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global) { Type = CG_FLOAT2; } void CCgUniform2f::update(const void* data, const SMaterial& material) const { f32* Data = (f32*)data; cgSetParameter2f(Parameter, *Data, *(Data+1)); } CCgUniform3f::CCgUniform3f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global) { Type = CG_FLOAT3; } void CCgUniform3f::update(const void* data, const SMaterial& material) const { f32* Data = (f32*)data; cgSetParameter3f(Parameter, *Data, *(Data+1), *(Data+2)); } CCgUniform4f::CCgUniform4f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global) { Type = CG_FLOAT4; } void CCgUniform4f::update(const void* data, const SMaterial& material) const { f32* Data = (f32*)data; cgSetParameter4f(Parameter, *Data, *(Data+1), *(Data+2), *(Data+3)); } CCgUniform1i::CCgUniform1i(const CGparameter& parameter, bool global) : CCgUniform(parameter, global) { Type = CG_INT; } void CCgUniform1i::update(const void* data, const SMaterial& material) const { s32* Data = (s32*)data; cgSetParameter1i(Parameter, *Data); } CCgUniform2i::CCgUniform2i(const CGparameter& parameter, bool global) : CCgUniform(parameter, global) { Type = CG_INT2; } void CCgUniform2i::update(const void* data, const SMaterial& material) const { s32* Data = (s32*)data; cgSetParameter2i(Parameter, *Data, *(Data+1)); } CCgUniform3i::CCgUniform3i(const CGparameter& parameter, bool global) : CCgUniform(parameter, global) { Type = CG_INT3; } void CCgUniform3i::update(const void* data, const SMaterial& material) const { s32* Data = (s32*)data; cgSetParameter3i(Parameter, *Data, *(Data+1), *(Data+2)); } CCgUniform4i::CCgUniform4i(const CGparameter& parameter, bool global) : CCgUniform(parameter, global) { Type = CG_INT4; } void CCgUniform4i::update(const void* data, const SMaterial& material) const { s32* Data = (s32*)data; cgSetParameter4i(Parameter, *Data, *(Data+1), *(Data+2), *(Data+3)); } CCgUniform4x4f::CCgUniform4x4f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global) { Type = CG_FLOAT4x4; } void CCgUniform4x4f::update(const void* data, const SMaterial& material) const { f32* Data = (f32*)data; cgSetMatrixParameterfr(Parameter, Data); } CCgUniformSampler2D::CCgUniformSampler2D(const CGparameter& parameter, bool global) : CCgUniform(parameter, global) { Type = CG_SAMPLER2D; } void CCgUniformSampler2D::update(const void* data, const SMaterial& material) const { } CCgMaterialRenderer::CCgMaterialRenderer(IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) : CallBack(callback), BaseMaterial(baseMaterial), UserData(userData), VertexProgram(0), FragmentProgram(0), GeometryProgram(0), VertexProfile(CG_PROFILE_UNKNOWN), FragmentProfile(CG_PROFILE_UNKNOWN), GeometryProfile(CG_PROFILE_UNKNOWN), Material(IdentityMaterial), Error(CG_NO_ERROR) { #ifdef _DEBUG setDebugName("CCgMaterialRenderer"); #endif if(BaseMaterial) BaseMaterial->grab(); if(CallBack) CallBack->grab(); } CCgMaterialRenderer::~CCgMaterialRenderer() { if(CallBack) CallBack->drop(); if(BaseMaterial) BaseMaterial->drop(); for(unsigned int i = 0; i < UniformInfo.size(); ++i) delete UniformInfo[i]; UniformInfo.clear(); } bool CCgMaterialRenderer::isTransparent() const { return BaseMaterial ? BaseMaterial->isTransparent() : false; } void CCgMaterialRenderer::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { os::Printer::log("Cannot set constant, please use high level shader call instead.", ELL_WARNING); } bool CCgMaterialRenderer::setVertexShaderConstant(const c8* name, const f32* floats, int count) { return setPixelShaderConstant(name, floats, count); } bool CCgMaterialRenderer::setVertexShaderConstant(const c8* name, const bool* bools, int count) { return setPixelShaderConstant(name, bools, count); } bool CCgMaterialRenderer::setVertexShaderConstant(const c8* name, const s32* ints, int count) { return setPixelShaderConstant(name, ints, count); } void CCgMaterialRenderer::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) { os::Printer::log("Cannot set constant, please use high level shader call instead.", ELL_WARNING); } bool CCgMaterialRenderer::setPixelShaderConstant(const c8* name, const f32* floats, int count) { bool Status = false; for(unsigned int i = 0; i < UniformInfo.size(); ++i) { if(UniformInfo[i]->getName() == name) { UniformInfo[i]->update(floats, Material); Status = true; } } return Status; } bool CCgMaterialRenderer::setPixelShaderConstant(const c8* name, const s32* ints, int count) { bool Status = false; for(unsigned int i = 0; i < UniformInfo.size(); ++i) { if(UniformInfo[i]->getName() == name) { UniformInfo[i]->update(ints, Material); Status = true; } } return Status; } bool CCgMaterialRenderer::setPixelShaderConstant(const c8* name, const bool* bools, int count) { bool Status = false; for(unsigned int i = 0; i < UniformInfo.size(); ++i) { if(UniformInfo[i]->getName() == name) { UniformInfo[i]->update(bools, Material); Status = true; } } return Status; } void CCgMaterialRenderer::getUniformList() { for(unsigned int i = 0; i < UniformInfo.size(); ++i) delete UniformInfo[i]; UniformInfo.clear(); for(unsigned int i = 0; i < 2; ++i) { CGenum Space = CG_GLOBAL; bool IsGlobal = 1; if(i == 1) { Space = CG_PROGRAM; IsGlobal = 0; } for(unsigned int j = 0; j < 3; ++j) { CGprogram* Program = 0; switch(j) { case 0: Program = &VertexProgram; break; case 1: Program = &FragmentProgram; break; case 2: Program = &GeometryProgram; break; } if(*Program) { CGparameter Parameter = cgGetFirstParameter(*Program, Space); while(Parameter) { if(cgGetParameterVariability(Parameter) == CG_UNIFORM && cgGetParameterDirection(Parameter) == CG_IN) { CCgUniform* Uniform = 0; CGtype Type = cgGetParameterType(Parameter); switch(Type) { case CG_FLOAT: case CG_FLOAT1: Uniform = new CCgUniform1f(Parameter, IsGlobal); break; case CG_FLOAT2: Uniform = new CCgUniform2f(Parameter, IsGlobal); break; case CG_FLOAT3: Uniform = new CCgUniform3f(Parameter, IsGlobal); break; case CG_FLOAT4: Uniform = new CCgUniform4f(Parameter, IsGlobal); break; case CG_INT: case CG_INT1: Uniform = new CCgUniform1i(Parameter, IsGlobal); break; case CG_INT2: Uniform = new CCgUniform2i(Parameter, IsGlobal); break; case CG_INT3: Uniform = new CCgUniform3i(Parameter, IsGlobal); break; case CG_INT4: Uniform = new CCgUniform4i(Parameter, IsGlobal); break; case CG_FLOAT4x4: Uniform = new CCgUniform4x4f(Parameter, IsGlobal); break; case CG_SAMPLER2D: Uniform = new CCgUniformSampler2D(Parameter, IsGlobal); break; } if(Uniform) UniformInfo.push_back(Uniform); } Parameter = cgGetNextParameter(Parameter); } } } } } } } #endif irrlicht-1.8.3/source/Irrlicht/CCameraSceneNode.h0000644000000000000000000001457712574354552020403 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_CAMERA_SCENE_NODE_H_INCLUDED__ #define __C_CAMERA_SCENE_NODE_H_INCLUDED__ #include "ICameraSceneNode.h" #include "SViewFrustum.h" namespace irr { namespace scene { class CCameraSceneNode : public ICameraSceneNode { public: //! constructor CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& lookat = core::vector3df(0,0,100)); //! Sets the projection matrix of the camera. /** The core::matrix4 class has some methods to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH. Note that the matrix will only stay as set by this method until one of the following Methods are called: setNearValue, setFarValue, setAspectRatio, setFOV. \param projection The new projection matrix of the camera. \param isOrthogonal Set this to true if the matrix is an orthogonal one (e.g. from matrix4::buildProjectionMatrixOrthoLH(). */ virtual void setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal = false); //! Gets the current projection matrix of the camera //! \return Returns the current projection matrix of the camera. virtual const core::matrix4& getProjectionMatrix() const; //! Gets the current view matrix of the camera //! \return Returns the current view matrix of the camera. virtual const core::matrix4& getViewMatrix() const; //! Sets a custom view matrix affector. /** \param affector: The affector matrix. */ virtual void setViewMatrixAffector(const core::matrix4& affector); //! Gets the custom view matrix affector. virtual const core::matrix4& getViewMatrixAffector() const; //! It is possible to send mouse and key events to the camera. Most cameras //! may ignore this input, but camera scene nodes which are created for //! example with scene::ISceneManager::addMayaCameraSceneNode or //! scene::ISceneManager::addMeshViewerCameraSceneNode, may want to get this input //! for changing their position, look at target or whatever. virtual bool OnEvent(const SEvent& event); //! Sets the look at target of the camera /** If the camera's target and rotation are bound ( @see bindTargetAndRotation() ) then calling this will also change the camera's scene node rotation to match the target. \param pos: Look at target of the camera. */ virtual void setTarget(const core::vector3df& pos); //! Sets the rotation of the node. /** This only modifies the relative rotation of the node. If the camera's target and rotation are bound ( @see bindTargetAndRotation() ) then calling this will also change the camera's target to match the rotation. \param rotation New rotation of the node in degrees. */ virtual void setRotation(const core::vector3df& rotation); //! Gets the current look at target of the camera /** \return The current look at target of the camera */ virtual const core::vector3df& getTarget() const; //! Sets the up vector of the camera. //! \param pos: New upvector of the camera. virtual void setUpVector(const core::vector3df& pos); //! Gets the up vector of the camera. //! \return Returns the up vector of the camera. virtual const core::vector3df& getUpVector() const; //! Gets distance from the camera to the near plane. //! \return Value of the near plane of the camera. virtual f32 getNearValue() const; //! Gets the distance from the camera to the far plane. //! \return Value of the far plane of the camera. virtual f32 getFarValue() const; //! Get the aspect ratio of the camera. //! \return The aspect ratio of the camera. virtual f32 getAspectRatio() const; //! Gets the field of view of the camera. //! \return Field of view of the camera virtual f32 getFOV() const; //! Sets the value of the near clipping plane. (default: 1.0f) virtual void setNearValue(f32 zn); //! Sets the value of the far clipping plane (default: 2000.0f) virtual void setFarValue(f32 zf); //! Sets the aspect ratio (default: 4.0f / 3.0f) virtual void setAspectRatio(f32 aspect); //! Sets the field of view (Default: PI / 3.5f) virtual void setFOV(f32 fovy); //! PreRender event virtual void OnRegisterSceneNode(); //! Render virtual void render(); //! Returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! Returns the view area. Sometimes needed by bsp or lod render nodes. virtual const SViewFrustum* getViewFrustum() const; //! Disables or enables the camera to get key or mouse inputs. //! If this is set to true, the camera will respond to key inputs //! otherwise not. virtual void setInputReceiverEnabled(bool enabled); //! Returns if the input receiver of the camera is currently enabled. virtual bool isInputReceiverEnabled() const; //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_CAMERA; } //! Binds the camera scene node's rotation to its target position and vice vera, or unbinds them. virtual void bindTargetAndRotation(bool bound); //! Queries if the camera scene node's rotation and its target position are bound together. virtual bool getTargetAndRotationBinding(void) const; //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); protected: void recalculateProjectionMatrix(); void recalculateViewArea(); core::vector3df Target; core::vector3df UpVector; f32 Fovy; // Field of view, in radians. f32 Aspect; // Aspect ratio. f32 ZNear; // value of the near view-plane. f32 ZFar; // Z-value of the far view-plane. SViewFrustum ViewArea; core::matrix4 Affector; bool InputReceiverEnabled; bool TargetAndRotationAreBound; }; } // end namespace } // end namespace #endif irrlicht-1.8.3/source/Irrlicht/CCameraSceneNode.cpp0000644000000000000000000002377412574354552020735 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CCameraSceneNode.h" #include "ISceneManager.h" #include "IVideoDriver.h" #include "os.h" namespace irr { namespace scene { //! constructor CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& lookat) : ICameraSceneNode(parent, mgr, id, position), Target(lookat), UpVector(0.0f, 1.0f, 0.0f), ZNear(1.0f), ZFar(3000.0f), InputReceiverEnabled(true), TargetAndRotationAreBound(false) { #ifdef _DEBUG setDebugName("CCameraSceneNode"); #endif // set default projection Fovy = core::PI / 2.5f; // Field of view, in radians. const video::IVideoDriver* const d = mgr?mgr->getVideoDriver():0; if (d) Aspect = (f32)d->getCurrentRenderTargetSize().Width / (f32)d->getCurrentRenderTargetSize().Height; else Aspect = 4.0f / 3.0f; // Aspect ratio. recalculateProjectionMatrix(); recalculateViewArea(); } //! Disables or enables the camera to get key or mouse inputs. void CCameraSceneNode::setInputReceiverEnabled(bool enabled) { InputReceiverEnabled = enabled; } //! Returns if the input receiver of the camera is currently enabled. bool CCameraSceneNode::isInputReceiverEnabled() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return InputReceiverEnabled; } //! Sets the projection matrix of the camera. /** The core::matrix4 class has some methods to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH \param projection: The new projection matrix of the camera. */ void CCameraSceneNode::setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal) { IsOrthogonal = isOrthogonal; ViewArea.getTransform ( video::ETS_PROJECTION ) = projection; } //! Gets the current projection matrix of the camera //! \return Returns the current projection matrix of the camera. const core::matrix4& CCameraSceneNode::getProjectionMatrix() const { return ViewArea.getTransform ( video::ETS_PROJECTION ); } //! Gets the current view matrix of the camera //! \return Returns the current view matrix of the camera. const core::matrix4& CCameraSceneNode::getViewMatrix() const { return ViewArea.getTransform ( video::ETS_VIEW ); } //! Sets a custom view matrix affector. The matrix passed here, will be //! multiplied with the view matrix when it gets updated. //! This allows for custom camera setups like, for example, a reflection camera. /** \param affector: The affector matrix. */ void CCameraSceneNode::setViewMatrixAffector(const core::matrix4& affector) { Affector = affector; } //! Gets the custom view matrix affector. const core::matrix4& CCameraSceneNode::getViewMatrixAffector() const { return Affector; } //! It is possible to send mouse and key events to the camera. Most cameras //! may ignore this input, but camera scene nodes which are created for //! example with scene::ISceneManager::addMayaCameraSceneNode or //! scene::ISceneManager::addFPSCameraSceneNode, may want to get this input //! for changing their position, look at target or whatever. bool CCameraSceneNode::OnEvent(const SEvent& event) { if (!InputReceiverEnabled) return false; // send events to event receiving animators ISceneNodeAnimatorList::Iterator ait = Animators.begin(); for (; ait != Animators.end(); ++ait) if ((*ait)->isEventReceiverEnabled() && (*ait)->OnEvent(event)) return true; // if nobody processed the event, return false return false; } //! sets the look at target of the camera //! \param pos: Look at target of the camera. void CCameraSceneNode::setTarget(const core::vector3df& pos) { Target = pos; if(TargetAndRotationAreBound) { const core::vector3df toTarget = Target - getAbsolutePosition(); ISceneNode::setRotation(toTarget.getHorizontalAngle()); } } //! Sets the rotation of the node. /** This only modifies the relative rotation of the node. If the camera's target and rotation are bound ( @see bindTargetAndRotation() ) then calling this will also change the camera's target to match the rotation. \param rotation New rotation of the node in degrees. */ void CCameraSceneNode::setRotation(const core::vector3df& rotation) { if(TargetAndRotationAreBound) Target = getAbsolutePosition() + rotation.rotationToDirection(); ISceneNode::setRotation(rotation); } //! Gets the current look at target of the camera //! \return Returns the current look at target of the camera const core::vector3df& CCameraSceneNode::getTarget() const { return Target; } //! sets the up vector of the camera //! \param pos: New upvector of the camera. void CCameraSceneNode::setUpVector(const core::vector3df& pos) { UpVector = pos; } //! Gets the up vector of the camera. //! \return Returns the up vector of the camera. const core::vector3df& CCameraSceneNode::getUpVector() const { return UpVector; } f32 CCameraSceneNode::getNearValue() const { return ZNear; } f32 CCameraSceneNode::getFarValue() const { return ZFar; } f32 CCameraSceneNode::getAspectRatio() const { return Aspect; } f32 CCameraSceneNode::getFOV() const { return Fovy; } void CCameraSceneNode::setNearValue(f32 f) { ZNear = f; recalculateProjectionMatrix(); } void CCameraSceneNode::setFarValue(f32 f) { ZFar = f; recalculateProjectionMatrix(); } void CCameraSceneNode::setAspectRatio(f32 f) { Aspect = f; recalculateProjectionMatrix(); } void CCameraSceneNode::setFOV(f32 f) { Fovy = f; recalculateProjectionMatrix(); } void CCameraSceneNode::recalculateProjectionMatrix() { ViewArea.getTransform ( video::ETS_PROJECTION ).buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar); } //! prerender void CCameraSceneNode::OnRegisterSceneNode() { if ( SceneManager->getActiveCamera () == this ) SceneManager->registerNodeForRendering(this, ESNRP_CAMERA); ISceneNode::OnRegisterSceneNode(); } //! render void CCameraSceneNode::render() { core::vector3df pos = getAbsolutePosition(); core::vector3df tgtv = Target - pos; tgtv.normalize(); // if upvector and vector to the target are the same, we have a // problem. so solve this problem: core::vector3df up = UpVector; up.normalize(); f32 dp = tgtv.dotProduct(up); if ( core::equals(core::abs_(dp), 1.f) ) { up.X += 0.5f; } ViewArea.getTransform(video::ETS_VIEW).buildCameraLookAtMatrixLH(pos, Target, up); ViewArea.getTransform(video::ETS_VIEW) *= Affector; recalculateViewArea(); video::IVideoDriver* driver = SceneManager->getVideoDriver(); if ( driver) { driver->setTransform(video::ETS_PROJECTION, ViewArea.getTransform ( video::ETS_PROJECTION) ); driver->setTransform(video::ETS_VIEW, ViewArea.getTransform ( video::ETS_VIEW) ); } } //! returns the axis aligned bounding box of this node const core::aabbox3d& CCameraSceneNode::getBoundingBox() const { return ViewArea.getBoundingBox(); } //! returns the view frustum. needed sometimes by bsp or lod render nodes. const SViewFrustum* CCameraSceneNode::getViewFrustum() const { return &ViewArea; } void CCameraSceneNode::recalculateViewArea() { ViewArea.cameraPosition = getAbsolutePosition(); core::matrix4 m(core::matrix4::EM4CONST_NOTHING); m.setbyproduct_nocheck(ViewArea.getTransform(video::ETS_PROJECTION), ViewArea.getTransform(video::ETS_VIEW)); ViewArea.setFrom(m); } //! Writes attributes of the scene node. void CCameraSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { ICameraSceneNode::serializeAttributes(out, options); out->addVector3d("Target", Target); out->addVector3d("UpVector", UpVector); out->addFloat("Fovy", Fovy); out->addFloat("Aspect", Aspect); out->addFloat("ZNear", ZNear); out->addFloat("ZFar", ZFar); out->addBool("Binding", TargetAndRotationAreBound); out->addBool("ReceiveInput", InputReceiverEnabled); } //! Reads attributes of the scene node. void CCameraSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { ICameraSceneNode::deserializeAttributes(in, options); Target = in->getAttributeAsVector3d("Target"); UpVector = in->getAttributeAsVector3d("UpVector"); Fovy = in->getAttributeAsFloat("Fovy"); Aspect = in->getAttributeAsFloat("Aspect"); ZNear = in->getAttributeAsFloat("ZNear"); ZFar = in->getAttributeAsFloat("ZFar"); TargetAndRotationAreBound = in->getAttributeAsBool("Binding"); if ( in->findAttribute("ReceiveInput") ) InputReceiverEnabled = in->getAttributeAsBool("InputReceiverEnabled"); recalculateProjectionMatrix(); recalculateViewArea(); } //! Set the binding between the camera's rotation adn target. void CCameraSceneNode::bindTargetAndRotation(bool bound) { TargetAndRotationAreBound = bound; } //! Gets the binding between the camera's rotation and target. bool CCameraSceneNode::getTargetAndRotationBinding(void) const { return TargetAndRotationAreBound; } //! Creates a clone of this scene node and its children. ISceneNode* CCameraSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { ICameraSceneNode::clone(newParent, newManager); if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CCameraSceneNode* nb = new CCameraSceneNode(newParent, newManager, ID, RelativeTranslation, Target); nb->ISceneNode::cloneMembers(this, newManager); nb->ICameraSceneNode::cloneMembers(this); nb->Target = Target; nb->UpVector = UpVector; nb->Fovy = Fovy; nb->Aspect = Aspect; nb->ZNear = ZNear; nb->ZFar = ZFar; nb->ViewArea = ViewArea; nb->Affector = Affector; nb->InputReceiverEnabled = InputReceiverEnabled; nb->TargetAndRotationAreBound = TargetAndRotationAreBound; if ( newParent ) nb->drop(); return nb; } } // end namespace } // end namespace irrlicht-1.8.3/source/Irrlicht/CBurningShader_Raster_Reference.cpp0000644000000000000000000010755312574354552024010 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #include "IBurningShader.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ namespace irr { namespace video { /*! Render states define set-up states for all kinds of vertex and pixel processing. Some render states set up vertex processing, and some set up pixel processing (see Render States). Render states can be saved and restored using stateblocks (see State Blocks Save and Restore State). */ enum BD3DRENDERSTATETYPE { /*! BD3DRS_ZENABLE Depth-buffering state as one member of the BD3DZBUFFERTYPE enumerated type. Set this state to D3DZB_TRUE to enable z-buffering, D3DZB_USEW to enable w-buffering, or D3DZB_FALSE to disable depth buffering. The default value for this render state is D3DZB_TRUE if a depth stencil was created along with the swap chain by setting the EnableAutoDepthStencil member of the D3DPRESENT_PARAMETERS structure to TRUE, and D3DZB_FALSE otherwise. */ BD3DRS_ZENABLE, /*! BD3DRS_FILLMODE One or more members of the D3DFILLMODE enumerated type. The default value is D3DFILL_SOLID. */ BD3DRS_FILLMODE, /*! BD3DRS_SHADEMODE One or more members of the D3DSHADEMODE enumerated type. The default value is D3DSHADE_GOURAUD. */ BD3DRS_SHADEMODE, /*! BD3DRS_ZWRITEENABLE TRUE to enable the application to write to the depth buffer. The default value is TRUE. This member enables an application to prevent the system from updating the depth buffer with new depth values. If FALSE, depth comparisons are still made according to the render state D3DRS_ZFUNC, assuming that depth buffering is taking place, but depth values are not written to the buffer. */ BD3DRS_ZWRITEENABLE, /*! BD3DRS_ALPHATESTENABLE TRUE to enable per pixel alpha testing. If the test passes, the pixel is processed by the frame buffer. Otherwise, all frame-buffer processing is skipped for the pixel. The test is done by comparing the incoming alpha value with the reference alpha value, using the comparison function provided by the D3DRS_ALPHAFUNC render state. The reference alpha value is determined by the value set for D3DRS_ALPHAREF. For more information, see Alpha Testing State. The default value of this parameter is FALSE. */ BD3DRS_ALPHATESTENABLE, /*! BD3DRS_SRCBLEND One member of the BD3DBLEND enumerated type. The default value is BD3DBLEND_ONE. */ BD3DRS_SRCBLEND, /*! BD3DRS_DESTBLEND One member of the BD3DBLEND enumerated type. The default value is BD3DBLEND_ZERO. */ BD3DRS_DESTBLEND, /*! BD3DRS_CULLMODE Specifies how back-facing triangles are culled, if at all. This can be set to one member of the BD3DCULL enumerated type. The default value is BD3DCULL_CCW. */ BD3DRS_CULLMODE, /*! BD3DRS_ZFUNC One member of the BD3DCMPFUNC enumerated type. The default value is BD3DCMP_LESSEQUAL. This member enables an application to accept or reject a pixel, based on its distance from the camera. The depth value of the pixel is compared with the depth-buffer value. If the depth value of the pixel passes the comparison function, the pixel is written. The depth value is written to the depth buffer only if the render state is TRUE. Software rasterizers and many hardware accelerators work faster if the depth test fails, because there is no need to filter and modulate the texture if the pixel is not going to be rendered. */ BD3DRS_ZFUNC, /*! BD3DRS_ALPHAREF Value that specifies a reference alpha value against which pixels are tested when alpha testing is enabled. This is an 8-bit value placed in the low 8 bits of the DWORD render-state value. Values can range from 0x00000000 through 0x000000FF. The default value is 0. */ BD3DRS_ALPHAREF, /*! BD3DRS_ALPHAFUNC One member of the BD3DCMPFUNC enumerated type. The default value is BD3DCMP_ALWAYS. This member enables an application to accept or reject a pixel, based on its alpha value. */ BD3DRS_ALPHAFUNC, /*! BD3DRS_DITHERENABLE TRUE to enable dithering. The default value is FALSE. */ BD3DRS_DITHERENABLE, /*! BD3DRS_ALPHABLENDENABLE TRUE to enable alpha-blended transparency. The default value is FALSE. The type of alpha blending is determined by the BD3DRS_SRCBLEND and BD3DRS_DESTBLEND render states. */ BD3DRS_ALPHABLENDENABLE, /*! BD3DRS_FOGENABLE TRUE to enable fog blending. The default value is FALSE. For more information about using fog blending, see Fog. */ BD3DRS_FOGENABLE, /*! BD3DRS_SPECULARENABLE TRUE to enable specular highlights. The default value is FALSE. Specular highlights are calculated as though every vertex in the object being lit is at the object's origin. This gives the expected results as long as the object is modeled around the origin and the distance from the light to the object is relatively large. In other cases, the results as undefined. When this member is set to TRUE, the specular color is added to the base color after the texture cascade but before alpha blending. */ BD3DRS_SPECULARENABLE, /*! BD3DRS_FOGCOLOR Value whose type is D3DCOLOR. The default value is 0. For more information about fog color, see Fog Color. */ BD3DRS_FOGCOLOR, /*! BD3DRS_FOGTABLEMODE The fog formula to be used for pixel fog. Set to one of the members of the D3DFOGMODE enumerated type. The default value is D3DFOG_NONE. For more information about pixel fog, see Pixel Fog. */ BD3DRS_FOGTABLEMODE, /*! BD3DRS_FOGSTART Depth at which pixel or vertex fog effects begin for linear fog mode. The default value is 0.0f. Depth is specified in world space for vertex fog and either device space [0.0, 1.0] or world space for pixel fog. For pixel fog, these values are in device space when the system uses z for fog calculations and world-world space when the system is using eye-relative fog (w-fog). For more information, see Fog Parameters and Eye-Relative vs. Z-based Depth. Values for the this render state are floating-point values. Because the IDirect3DDevice9::SetRenderState method accepts DWORD values, your application must cast a variable that contains the value, as shown in the following code example. pDevice9->SetRenderState( BD3DRS_FOGSTART, *((DWORD*) (&fFogStart))); */ BD3DRS_FOGSTART, /*! BD3DRS_FOGEND Depth at which pixel or vertex fog effects end for linear fog mode. The default value is 1.0f. Depth is specified in world space for vertex fog and either device space [0.0, 1.0] or world space for pixel fog. For pixel fog, these values are in device space when the system uses z for fog calculations and in world space when the system is using eye-relative fog (w-fog). For more information, see Fog Parameters and Eye-Relative vs. Z-based Depth. Values for this render state are floating-point values. */ BD3DRS_FOGEND, /*! BD3DRS_FOGDENSITY Fog density for pixel or vertex fog used in the exponential fog modes (D3DFOG_EXP and D3DFOG_EXP2). Valid density values range from 0.0 through 1.0. The default value is 1.0. For more information, see Fog Parameters. Values for this render state are floating-point values. */ BD3DRS_FOGDENSITY, /*! BD3DRS_RANGEFOGENABLE TRUE to enable range-based vertex fog. The default value is FALSE, in which case the system uses depth-based fog. In range-based fog, the distance of an object from the viewer is used to compute fog effects, not the depth of the object (that is, the z-coordinate) in the scene. In range-based fog, all fog methods work as usual, except that they use range instead of depth in the computations. Range is the correct factor to use for fog computations, but depth is commonly used instead because range is time-consuming to compute and depth is generally already available. Using depth to calculate fog has the undesirable effect of having the fogginess of peripheral objects change as the viewer's eye moves - in this case, the depth changes and the range remains constant. Because no hardware currently supports per-pixel range-based fog, range correction is offered only for vertex fog. For more information, see Vertex Fog. */ BD3DRS_RANGEFOGENABLE = 48, /*! BD3DRS_STENCILENABLE TRUE to enable stenciling, or FALSE to disable stenciling. The default value is FALSE. For more information, see Stencil Buffer Techniques. */ BD3DRS_STENCILENABLE = 52, /*! BD3DRS_STENCILFAIL Stencil operation to perform if the stencil test fails. Values are from the D3DSTENCILOP enumerated type. The default value is D3DSTENCILOP_KEEP. */ BD3DRS_STENCILFAIL = 53, /*! BD3DRS_STENCILZFAIL Stencil operation to perform if the stencil test passes and the depth test (z-test) fails. Values are from the D3DSTENCILOP enumerated type. The default value is D3DSTENCILOP_KEEP. */ BD3DRS_STENCILZFAIL = 54, /*! BD3DRS_STENCILPASS Stencil operation to perform if both the stencil and the depth (z) tests pass. Values are from the D3DSTENCILOP enumerated type. The default value is D3DSTENCILOP_KEEP. */ BD3DRS_STENCILPASS = 55, /*! BD3DRS_STENCILFUNC Comparison function for the stencil test. Values are from the D3DCMPFUNC enumerated type. The default value is D3DCMP_ALWAYS. The comparison function is used to compare the reference value to a stencil buffer entry. This comparison applies only to the bits in the reference value and stencil buffer entry that are set in the stencil mask (set by the D3DRS_STENCILMASK render state). If TRUE, the stencil test passes. */ BD3DRS_STENCILFUNC = 56, /*! BD3DRS_STENCILREF An int reference value for the stencil test. The default value is 0. */ BD3DRS_STENCILREF = 57, /*! BD3DRS_STENCILMASK Mask applied to the reference value and each stencil buffer entry to determine the significant bits for the stencil test. The default mask is 0xFFFFFFFF. */ BD3DRS_STENCILMASK = 58, /*! BD3DRS_STENCILWRITEMASK Write mask applied to values written into the stencil buffer. The default mask is 0xFFFFFFFF. */ BD3DRS_STENCILWRITEMASK = 59, /*! BD3DRS_TEXTUREFACTOR Color used for multiple-texture blending with the D3DTA_TFACTOR texture-blending argument or the D3DTOP_BLENDFACTORALPHA texture-blending operation. The associated value is a D3DCOLOR variable. The default value is opaque white (0xFFFFFFFF). */ BD3DRS_TEXTUREFACTOR = 60, /*! BD3DRS_WRAP0 Texture-wrapping behavior for multiple sets of texture coordinates. Valid values for this render state can be any combination of the D3DWRAPCOORD_0 (or D3DWRAP_U), D3DWRAPCOORD_1 (or D3DWRAP_V), D3DWRAPCOORD_2 (or D3DWRAP_W), and D3DWRAPCOORD_3 flags. These cause the system to wrap in the direction of the first, second, third, and fourth dimensions, sometimes referred to as the s, t, r, and q directions, for a given texture. The default value for this render state is 0 (wrapping disabled in all directions). */ BD3DRS_WRAP0 = 128, BD3DRS_WRAP1 = 129, BD3DRS_WRAP2 = 130, BD3DRS_WRAP3 = 131, BD3DRS_WRAP4 = 132, BD3DRS_WRAP5 = 133, BD3DRS_WRAP6 = 134, BD3DRS_WRAP7 = 135, /*! BD3DRS_CLIPPING TRUE to enable primitive clipping by Direct3D, or FALSE to disable it. The default value is TRUE. */ BD3DRS_CLIPPING = 136, /*! BD3DRS_LIGHTING TRUE to enable Direct3D lighting, or FALSE to disable it. The default value is TRUE. Only vertices that include a vertex normal are properly lit; vertices that do not contain a normal employ a dot product of 0 in all lighting calculations. */ BD3DRS_LIGHTING = 137, /*! D3DRS_AMBIENT Ambient light color. This value is of type D3DCOLOR. The default value is 0. */ BD3DRS_AMBIENT = 139, /*! BD3DRS_FOGVERTEXMODE Fog formula to be used for vertex fog. Set to one member of the BD3DFOGMODE enumerated type. The default value is D3DFOG_NONE. */ BD3DRS_FOGVERTEXMODE = 140, /*! BD3DRS_COLORVERTEX TRUE to enable per-vertex color or FALSE to disable it. The default value is TRUE. Enabling per-vertex color allows the system to include the color defined for individual vertices in its lighting calculations. For more information, see the following render states: BD3DRS_DIFFUSEMATERIALSOURCE BD3DRS_SPECULARMATERIALSOURCE BD3DRS_AMBIENTMATERIALSOURCE BD3DRS_EMISSIVEMATERIALSOURCE */ BD3DRS_COLORVERTEX = 141, /*! BD3DRS_LOCALVIEWER TRUE to enable camera-relative specular highlights, or FALSE to use orthogonal specular highlights. The default value is TRUE. Applications that use orthogonal projection should specify false. */ BD3DRS_LOCALVIEWER = 142, /*! BD3DRS_NORMALIZENORMALS TRUE to enable automatic normalization of vertex normals, or FALSE to disable it. The default value is FALSE. Enabling this feature causes the system to normalize the vertex normals for vertices after transforming them to camera space, which can be computationally time-consuming. */ BD3DRS_NORMALIZENORMALS = 143, /*! BD3DRS_DIFFUSEMATERIALSOURCE Diffuse color source for lighting calculations. Valid values are members of the D3DMATERIALCOLORSOURCE enumerated type. The default value is D3DMCS_COLOR1. The value for this render state is used only if the D3DRS_COLORVERTEX render state is set to TRUE. */ BD3DRS_DIFFUSEMATERIALSOURCE = 145, /*! BD3DRS_SPECULARMATERIALSOURCE Specular color source for lighting calculations. Valid values are members of the D3DMATERIALCOLORSOURCE enumerated type. The default value is D3DMCS_COLOR2. */ BD3DRS_SPECULARMATERIALSOURCE = 146, /*! D3DRS_AMBIENTMATERIALSOURCE Ambient color source for lighting calculations. Valid values are members of the D3DMATERIALCOLORSOURCE enumerated type. The default value is D3DMCS_MATERIAL. */ BD3DRS_AMBIENTMATERIALSOURCE = 147, /*! D3DRS_EMISSIVEMATERIALSOURCE Emissive color source for lighting calculations. Valid values are members of the D3DMATERIALCOLORSOURCE enumerated type. The default value is D3DMCS_MATERIAL. */ BD3DRS_EMISSIVEMATERIALSOURCE = 148, /*! D3DRS_VERTEXBLEND Number of matrices to use to perform geometry blending, if any. Valid values are members of the D3DVERTEXBLENDFLAGS enumerated type. The default value is D3DVBF_DISABLE. */ BD3DRS_VERTEXBLEND = 151, /* D3DRS_CLIPPLANEENABLE Enables or disables user-defined clipping planes. Valid values are any DWORD in which the status of each bit (set or not set) toggles the activation state of a corresponding user-defined clipping plane. The least significant bit (bit 0) controls the first clipping plane at index 0, and subsequent bits control the activation of clipping planes at higher indexes. If a bit is set, the system applies the appropriate clipping plane during scene rendering. The default value is 0. The D3DCLIPPLANEn macros are defined to provide a convenient way to enable clipping planes. */ BD3DRS_CLIPPLANEENABLE = 152, BD3DRS_POINTSIZE = 154, BD3DRS_POINTSIZE_MIN = 155, BD3DRS_POINTSPRITEENABLE = 156, BD3DRS_POINTSCALEENABLE = 157, BD3DRS_POINTSCALE_A = 158, BD3DRS_POINTSCALE_B = 159, BD3DRS_POINTSCALE_C = 160, BD3DRS_MULTISAMPLEANTIALIAS = 161, BD3DRS_MULTISAMPLEMASK = 162, BD3DRS_PATCHEDGESTYLE = 163, BD3DRS_DEBUGMONITORTOKEN = 165, BD3DRS_POINTSIZE_MAX = 166, BD3DRS_INDEXEDVERTEXBLENDENABLE = 167, BD3DRS_COLORWRITEENABLE = 168, BD3DRS_TWEENFACTOR = 170, BD3DRS_BLENDOP = 171, BD3DRS_POSITIONDEGREE = 172, BD3DRS_NORMALDEGREE = 173, BD3DRS_SCISSORTESTENABLE = 174, BD3DRS_SLOPESCALEDEPTHBIAS = 175, BD3DRS_ANTIALIASEDLINEENABLE = 176, BD3DRS_MINTESSELLATIONLEVEL = 178, BD3DRS_MAXTESSELLATIONLEVEL = 179, BD3DRS_ADAPTIVETESS_X = 180, BD3DRS_ADAPTIVETESS_Y = 181, BD3DRS_ADAPTIVETESS_Z = 182, BD3DRS_ADAPTIVETESS_W = 183, BD3DRS_ENABLEADAPTIVETESSELLATION = 184, BD3DRS_TWOSIDEDSTENCILMODE = 185, BD3DRS_CCW_STENCILFAIL = 186, BD3DRS_CCW_STENCILZFAIL = 187, BD3DRS_CCW_STENCILPASS = 188, BD3DRS_CCW_STENCILFUNC = 189, BD3DRS_COLORWRITEENABLE1 = 190, BD3DRS_COLORWRITEENABLE2 = 191, BD3DRS_COLORWRITEENABLE3 = 192, BD3DRS_BLENDFACTOR = 193, BD3DRS_SRGBWRITEENABLE = 194, BD3DRS_DEPTHBIAS = 195, BD3DRS_WRAP8 = 198, BD3DRS_WRAP9 = 199, BD3DRS_WRAP10 = 200, BD3DRS_WRAP11 = 201, BD3DRS_WRAP12 = 202, BD3DRS_WRAP13 = 203, BD3DRS_WRAP14 = 204, BD3DRS_WRAP15 = 205, BD3DRS_SEPARATEALPHABLENDENABLE = 206, BD3DRS_SRCBLENDALPHA = 207, BD3DRS_DESTBLENDALPHA = 208, BD3DRS_BLENDOPALPHA = 209, BD3DRS_MAX_TYPE }; /*! Defines constants that describe depth-buffer formats Members of this enumerated type are used with the D3DRS_ZENABLE render state. */ enum BD3DZBUFFERTYPE { BD3DZB_FALSE = 0, // Disable depth buffering BD3DZB_TRUE = 1, // Enable z-buffering BD3DZB_USEW = 2 //Enable w-buffering. }; //! Defines the supported compare functions. enum BD3DCMPFUNC { BD3DCMP_NEVER = 1,// Always fail the test. BD3DCMP_LESS, // Accept the new pixel if its value is less than the value of the current pixel. BD3DCMP_EQUAL, // Accept the new pixel if its value equals the value of the current pixel. BD3DCMP_LESSEQUAL, // Accept the new pixel if its value is less than or equal to the value of the current pixel. BD3DCMP_GREATER, // Accept the new pixel if its value is greater than the value of the current pixel. BD3DCMP_NOTEQUAL, // Accept the new pixel if its value does not equal the value of the current pixel. BD3DCMP_GREATEREQUAL,// Accept the new pixel if its value is greater than or equal to the value of the current pixel. BD3DCMP_ALWAYS // Always pass the test. }; enum BD3DMATERIALCOLORSOURCE { BD3DMCS_MATERIAL = 0, // Use the color from the current material. BD3DMCS_COLOR1 = 1, // Use the diffuse vertex color. BD3DMCS_COLOR2 = 2 // Use the specular vertex color. }; //! Defines constants that describe the supported shading modes. enum BD3DSHADEMODE { /*! BD3DSHADE_FLAT Flat shading mode. The color and specular component of the first vertex in the triangle are used to determine the color and specular component of the face. These colors remain constant across the triangle; that is, they are not interpolated. The specular alpha is interpolated. */ BD3DSHADE_FLAT = 1, /*! BD3DSHADE_GOURAUD Gouraud shading mode. The color and specular components of the face are determined by a linear interpolation between all three of the triangle's vertices. */ BD3DSHADE_GOURAUD = 2, /*! BD3DSHADE_PHONG Not supported. */ BD3DSHADE_PHONG = 3 }; /*! Defines constants describing the fill mode The values in this enumerated type are used by the BD3DRS_FILLMODE render state */ enum BD3DFILLMODE { BD3DFILL_POINT = 1, // Fill points. BD3DFILL_WIREFRAME = 2, // Fill wireframes. BD3DFILL_SOLID = 3 // Fill solids. }; /*! Defines the supported culling modes. The values in this enumerated type are used by the B3DRS_CULLMODE render state. The culling modes define how back faces are culled when rendering a geometry. */ enum BD3DCULL { BD3DCULL_NONE = 1, // Do not cull back faces. BD3DCULL_CW = 2, // Cull back faces with clockwise vertices. BD3DCULL_CCW = 3 // Cull back faces with counterclockwise vertices. }; struct SShaderParam { u32 ColorUnits; u32 TextureUnits; u32 RenderState [ BD3DRS_MAX_TYPE ]; void SetRenderState ( BD3DRENDERSTATETYPE state, u32 value ); }; void SShaderParam::SetRenderState ( BD3DRENDERSTATETYPE state, u32 value ) { RenderState [ state ] = value; } class CBurningShader_Raster_Reference : public IBurningShader { public: //! constructor CBurningShader_Raster_Reference(CBurningVideoDriver* driver); //! draws an indexed triangle list virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); virtual void setMaterial ( const SBurningShaderMaterial &material ); private: void scanline (); void scanline2 (); sScanLineData line; sPixelShaderData pShader; void pShader_1 (); void pShader_EMT_LIGHTMAP_M4 (); SShaderParam ShaderParam; REALINLINE u32 depthFunc (); REALINLINE void depthWrite (); }; //! constructor CBurningShader_Raster_Reference::CBurningShader_Raster_Reference(CBurningVideoDriver* driver) : IBurningShader(driver) { #ifdef _DEBUG setDebugName("CBurningShader_Raster_Reference"); #endif } /*! */ void CBurningShader_Raster_Reference::pShader_EMT_LIGHTMAP_M4 () { tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; f32 inversew = fix_inverse32 ( line.w[0] ); getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); pShader.dst[pShader.i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); } /*! */ void CBurningShader_Raster_Reference::pShader_1 () { tFixPoint r0, g0, b0; tFixPoint tx0, ty0; const f32 inversew = fix_inverse32 ( line.w[0] ); tx0 = tofix ( line.t[0][0].x, inversew ); ty0 = tofix ( line.t[0][0].y, inversew ); getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); pShader.dst[pShader.i] = fix_to_color ( r0, g0, b0 ); } /*! */ void CBurningShader_Raster_Reference::setMaterial ( const SBurningShaderMaterial &material ) { const video::SMaterial &m = material.org; u32 i; u32 enable; ShaderParam.ColorUnits = 0; ShaderParam.TextureUnits = 0; for ( i = 0; i != BURNING_MATERIAL_MAX_TEXTURES; ++i ) { if ( m.getTexture( i ) ) ShaderParam.TextureUnits = i; } // shademode ShaderParam.SetRenderState( BD3DRS_SHADEMODE, m.GouraudShading ? BD3DSHADE_GOURAUD : BD3DSHADE_FLAT ); // fillmode ShaderParam.SetRenderState( BD3DRS_FILLMODE, m.Wireframe ? BD3DFILL_WIREFRAME : m.PointCloud ? BD3DFILL_POINT : BD3DFILL_SOLID ); // back face culling ShaderParam.SetRenderState( BD3DRS_CULLMODE, m.BackfaceCulling ? BD3DCULL_CCW : BD3DCULL_NONE ); // lighting ShaderParam.SetRenderState( BD3DRS_LIGHTING, m.Lighting ); // specular highlights enable = F32_LOWER_EQUAL_0 ( m.Shininess ); ShaderParam.SetRenderState( BD3DRS_SPECULARENABLE, enable); ShaderParam.SetRenderState( BD3DRS_NORMALIZENORMALS, enable); ShaderParam.SetRenderState( BD3DRS_SPECULARMATERIALSOURCE, (m.ColorMaterial==ECM_SPECULAR)?BD3DMCS_COLOR1:BD3DMCS_MATERIAL); // depth buffer enable and compare ShaderParam.SetRenderState( BD3DRS_ZENABLE, (material.org.ZBuffer==video::ECFN_NEVER) ? BD3DZB_FALSE : BD3DZB_USEW); switch (material.org.ZBuffer) { case ECFN_NEVER: ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_NEVER); break; case ECFN_LESSEQUAL: ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_LESSEQUAL); break; case ECFN_EQUAL: ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_EQUAL); break; case ECFN_LESS: ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_LESSEQUAL); break; case ECFN_NOTEQUAL: ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_NOTEQUAL); break; case ECFN_GREATEREQUAL: ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_GREATEREQUAL); break; case ECFN_GREATER: ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_GREATER); break; case ECFN_ALWAYS: ShaderParam.SetRenderState(BD3DRS_ZFUNC, BD3DCMP_ALWAYS); break; } // depth buffer write ShaderParam.SetRenderState( BD3DRS_ZWRITEENABLE, m.ZWriteEnable ); } /*! */ REALINLINE u32 CBurningShader_Raster_Reference::depthFunc () { if ( ShaderParam.RenderState [ BD3DRS_ZENABLE ] ) { switch ( ShaderParam.RenderState [ BD3DRS_ZFUNC ] ) { case BD3DCMP_LESSEQUAL: return line.w[0] >= pShader.z[ pShader.i]; case BD3DCMP_EQUAL: return line.w[0] == pShader.z[ pShader.i]; } } return 1; } /*! */ REALINLINE void CBurningShader_Raster_Reference::depthWrite () { if ( ShaderParam.RenderState [ BD3DRS_ZWRITEENABLE ] ) { pShader.z[pShader.i] = line.w[0]; } } /*! */ REALINLINE void CBurningShader_Raster_Reference::scanline2() { // apply top-left fill-convention, left pShader.xStart = core::ceil32( line.x[0] ); pShader.xEnd = core::ceil32( line.x[1] ) - 1; pShader.dx = pShader.xEnd - pShader.xStart; if ( pShader.dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal ( line.x[1] - line.x[0] ); const f32 subPixel = ( (f32) pShader.xStart ) - line.x[0]; // store slopes in endpoint, and correct first pixel line.w[0] += (line.w[1] = (line.w[1] - line.w[0]) * invDeltaX) * subPixel; u32 i; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { line.c[i][1] = (line.c[i][1] - line.c[i][0]) * invDeltaX; line.c[i][0] += line.c[i][1] * subPixel; } #endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { line.t[i][1] = (line.t[i][1] - line.t[i][0]) * invDeltaX; line.t[i][0] += line.t[i][1] * subPixel; } pShader.dst = (tVideoSample*) ( (u8*) RenderTarget->lock() + ( line.y * RenderTarget->getPitch() ) + ( pShader.xStart << VIDEO_SAMPLE_GRANULARITY ) ); pShader.z = (fp24*) ( (u8*) DepthBuffer->lock() + ( line.y * DepthBuffer->getPitch() ) + ( pShader.xStart << VIDEO_SAMPLE_GRANULARITY ) ); for ( pShader.i = 0; pShader.i <= pShader.dx; ++pShader.i ) { if ( depthFunc() ) { depthWrite (); } // advance next pixel line.w[0] += line.w[1]; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { line.c[i][0] += line.c[i][1]; } #endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { line.t[i][0] += line.t[i][1]; } } } /*! */ REALINLINE void CBurningShader_Raster_Reference::scanline () { u32 i; // apply top-left fill-convention, left pShader.xStart = core::ceil32( line.x[0] ); pShader.xEnd = core::ceil32( line.x[1] ) - 1; pShader.dx = pShader.xEnd - pShader.xStart; if ( pShader.dx < 0 ) return; // slopes const f32 invDeltaX = core::reciprocal ( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel pShader.z = (fp24*) ( (u8*) DepthBuffer->lock() + ( line.y * DepthBuffer->getPitch() ) + ( pShader.xStart << VIDEO_SAMPLE_GRANULARITY ) ); // subTexel const f32 subPixel = ( (f32) pShader.xStart ) - line.x[0]; const f32 b = (line.w[1] - line.w[0]) * invDeltaX; f32 a = line.w[0] + ( b * subPixel ); pShader.i = 0; if ( ShaderParam.RenderState [ BD3DRS_ZENABLE ] ) { u32 condition; switch ( ShaderParam.RenderState [ BD3DRS_ZFUNC ] ) { case BD3DCMP_LESSEQUAL: condition = a < pShader.z[pShader.i]; break; case BD3DCMP_EQUAL: condition = a != pShader.z[pShader.i]; break; } while ( a < pShader.z[pShader.i] ) { a += b; pShader.i += 1; if ( pShader.i > pShader.dx ) return; } } // lazy setup rest of scanline line.w[0] = a; line.w[1] = b; pShader.dst = (tVideoSample*) ( (u8*) RenderTarget->lock() + ( line.y * RenderTarget->getPitch() ) + ( pShader.xStart << VIDEO_SAMPLE_GRANULARITY ) ); a = (f32) pShader.i + subPixel; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { line.c[i][1] = (line.c[i][1] - line.c[i][0]) * invDeltaX; line.c[i][0] += line.c[i][1] * a; } #endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { line.t[i][1] = (line.t[i][1] - line.t[i][0]) * invDeltaX; line.t[i][0] += line.t[i][1] * a; } for ( ; pShader.i <= pShader.dx; ++pShader.i ) { if ( line.w[0] >= pShader.z[pShader.i] ) { pShader.z[pShader.i] = line.w[0]; pShader_EMT_LIGHTMAP_M4 (); } line.w[0] += line.w[1]; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { line.c[i][0] += line.c[i][1]; } #endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { line.t[i][0] += line.t[i][1]; } } } void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { sScanConvertData scan; u32 i; // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); scan.invDeltaY[1] = core::reciprocal ( b->Pos.y - a->Pos.y ); scan.invDeltaY[2] = core::reciprocal ( c->Pos.y - b->Pos.y ); if ( F32_LOWER_EQUAL_0 ( scan.invDeltaY[0] ) ) return; // find if the major edge is left or right aligned f32 temp[4]; temp[0] = a->Pos.x - c->Pos.x; temp[1] = a->Pos.y - c->Pos.y; temp[2] = b->Pos.x - a->Pos.x; temp[3] = b->Pos.y - a->Pos.y; scan.left = ( temp[0] * temp[3] - temp[1] * temp[2] ) > (f32) 0.0 ? 0 : 1; scan.right = 1 - scan.left; // calculate slopes for the major edge scan.slopeX[0] = (c->Pos.x - a->Pos.x) * scan.invDeltaY[0]; scan.x[0] = a->Pos.x; scan.slopeW[0] = (c->Pos.w - a->Pos.w) * scan.invDeltaY[0]; scan.w[0] = a->Pos.w; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][0] = a->Color[i]; scan.slopeC[i][0] = (c->Color[i] - a->Color[i]) * scan.invDeltaY[0]; } #endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.t[i][0] = a->Tex[i]; scan.slopeT[i][0] = (c->Tex[i] - a->Tex[i]) * scan.invDeltaY[0]; } // top left fill convention y run s32 yStart; s32 yEnd; f32 subPixel; // rasterize upper sub-triangle if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { // calculate slopes for top edge scan.slopeX[1] = (b->Pos.x - a->Pos.x) * scan.invDeltaY[1]; scan.x[1] = a->Pos.x; scan.slopeW[1] = (b->Pos.w - a->Pos.w) * scan.invDeltaY[1]; scan.w[1] = a->Pos.w; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][1] = a->Color[i]; scan.slopeC[i][1] = (b->Color[i] - a->Color[i]) * scan.invDeltaY[1]; } #endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.t[i][1] = a->Tex[i]; scan.slopeT[i][1] = (b->Tex[i] - a->Tex[i]) * scan.invDeltaY[1]; } // apply top-left fill convention, top part yStart = core::ceil32( a->Pos.y ); yEnd = core::ceil32( b->Pos.y ) - 1; subPixel = ( (f32) yStart ) - a->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][0] += scan.slopeC[i][0] * subPixel; scan.c[i][1] += scan.slopeC[i][1] * subPixel; } for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.t[i][0] += scan.slopeT[i][0] * subPixel; scan.t[i][1] += scan.slopeT[i][1] * subPixel; } // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.w[scan.left] = scan.w[0]; line.x[scan.right] = scan.x[1]; line.w[scan.right] = scan.w[1]; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { line.c[i][scan.left] = scan.c[i][0]; line.c[i][scan.right] = scan.c[i][1]; } #endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { line.t[i][scan.left] = scan.t[i][0]; line.t[i][scan.right] = scan.t[i][1]; } // render a scanline scanline (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][0] += scan.slopeC[i][0]; scan.c[i][1] += scan.slopeC[i][1]; } for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.t[i][0] += scan.slopeT[i][0]; scan.t[i][1] += scan.slopeT[i][1]; } } } // rasterize lower sub-triangle if ( F32_GREATER_0 ( scan.invDeltaY[2] ) ) { // advance to middle point if ( F32_GREATER_0 ( scan.invDeltaY[1] ) ) { temp[0] = b->Pos.y - a->Pos.y; // dy scan.x[0] = a->Pos.x + scan.slopeX[0] * temp[0]; scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][0] = a->Color[i] + scan.slopeC[i][0] * temp[0]; } #endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.t[i][0] = a->Tex[i] + scan.slopeT[i][0] * temp[0]; } } // calculate slopes for bottom edge scan.slopeX[1] = (c->Pos.x - b->Pos.x) * scan.invDeltaY[2]; scan.x[1] = b->Pos.x; scan.slopeW[1] = (c->Pos.w - b->Pos.w) * scan.invDeltaY[2]; scan.w[1] = b->Pos.w; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][1] = b->Color[i]; scan.slopeC[i][1] = (c->Color[i] - b->Color[i]) * scan.invDeltaY[2]; } #endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.t[i][1] = b->Tex[i]; scan.slopeT[i][1] = (c->Tex[i] - b->Tex[i]) * scan.invDeltaY[2]; } // apply top-left fill convention, top part yStart = core::ceil32( b->Pos.y ); yEnd = core::ceil32( c->Pos.y ) - 1; subPixel = ( (f32) yStart ) - b->Pos.y; // correct to pixel center scan.x[0] += scan.slopeX[0] * subPixel; scan.x[1] += scan.slopeX[1] * subPixel; scan.w[0] += scan.slopeW[0] * subPixel; scan.w[1] += scan.slopeW[1] * subPixel; for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { scan.c[i][0] += scan.slopeC[i][0] * subPixel; scan.c[i][1] += scan.slopeC[i][1] * subPixel; } for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.t[i][0] += scan.slopeT[i][0] * subPixel; scan.t[i][1] += scan.slopeT[i][1] * subPixel; } // rasterize the edge scanlines for( line.y = yStart; line.y <= yEnd; ++line.y) { line.x[scan.left] = scan.x[0]; line.w[scan.left] = scan.w[0]; line.x[scan.right] = scan.x[1]; line.w[scan.right] = scan.w[1]; #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR for ( i = 0; i != ShaderParam.ColorUnits; ++i ) { line.c[i][scan.left] = scan.c[i][0]; line.c[i][scan.right] = scan.c[i][1]; } #endif for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { line.t[i][scan.left] = scan.t[i][0]; line.t[i][scan.right] = scan.t[i][1]; } // render a scanline scanline (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; scan.w[0] += scan.slopeW[0]; scan.w[1] += scan.slopeW[1]; for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.c[i][0] += scan.slopeC[i][0]; scan.c[i][1] += scan.slopeC[i][1]; } for ( i = 0; i != ShaderParam.TextureUnits; ++i ) { scan.t[i][0] += scan.slopeT[i][0]; scan.t[i][1] += scan.slopeT[i][1]; } } } } } // end namespace video } // end namespace irr namespace irr { namespace video { //! creates a flat triangle renderer IBurningShader* createTriangleRendererReference(CBurningVideoDriver* driver) { return new CBurningShader_Raster_Reference(driver); } } // end namespace video } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ irrlicht-1.8.3/source/Irrlicht/CBSPMeshFileLoader.h0000644000000000000000000000261412574354552020604 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_BSP_MESH_FILE_LOADER_H_INCLUDED__ #define __C_BSP_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "IFileSystem.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "IQ3Shader.h" namespace irr { namespace scene { //! Meshloader capable of loading Quake 3 BSP files and shaders class CBSPMeshFileLoader : public IMeshLoader { public: //! Constructor CBSPMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs); //! destructor virtual ~CBSPMeshFileLoader(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: io::IFileSystem* FileSystem; scene::ISceneManager* SceneManager; quake3::Q3LevelLoadParameter LoadParam; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CBSPMeshFileLoader.cpp0000644000000000000000000000500712574354552021136 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ #include "CBSPMeshFileLoader.h" #include "CQ3LevelMesh.h" namespace irr { namespace scene { //! Constructor CBSPMeshFileLoader::CBSPMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) : FileSystem(fs), SceneManager(smgr) { #ifdef _DEBUG setDebugName("CBSPMeshFileLoader"); #endif if (FileSystem) FileSystem->grab(); } //! destructor CBSPMeshFileLoader::~CBSPMeshFileLoader() { if (FileSystem) FileSystem->drop(); } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool CBSPMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "bsp", "shader", "cfg" ); } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* CBSPMeshFileLoader::createMesh(io::IReadFile* file) { s32 type = core::isFileExtension ( file->getFileName(), "bsp", "shader", "cfg" ); CQ3LevelMesh* q = 0; switch ( type ) { case 1: q = new CQ3LevelMesh(FileSystem, SceneManager, LoadParam); // determine real shaders in LoadParam if ( 0 == LoadParam.loadAllShaders ) { q->getShader("scripts/common.shader"); q->getShader("scripts/sfx.shader"); q->getShader("scripts/gfx.shader"); q->getShader("scripts/liquid.shader"); q->getShader("scripts/models.shader"); q->getShader("scripts/walls.shader"); //q->getShader("scripts/sky.shader"); } if ( q->loadFile(file) ) return q; q->drop(); break; case 2: q = new CQ3LevelMesh(FileSystem, SceneManager,LoadParam); q->getShader( file ); return q; break; case 3: // load quake 3 loading parameter if ( file->getFileName() == "levelparameter.cfg" ) { file->read ( &LoadParam, sizeof ( LoadParam ) ); } else { q = new CQ3LevelMesh(FileSystem, SceneManager,LoadParam); q->getConfiguration( file ); return q; } break; } return 0; } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_BSP_LOADER_ irrlicht-1.8.3/source/Irrlicht/CBoneSceneNode.h0000644000000000000000000000411612574354552020062 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_BONE_SCENE_NODE_H_INCLUDED__ #define __C_BONE_SCENE_NODE_H_INCLUDED__ // Used with SkinnedMesh and IAnimatedMeshSceneNode, for boned meshes #include "IBoneSceneNode.h" namespace irr { namespace scene { class CBoneSceneNode : public IBoneSceneNode { public: //! constructor CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id=-1, u32 boneIndex=0, const c8* boneName=0); //! Returns the index of the bone virtual u32 getBoneIndex() const; //! Sets the animation mode of the bone. Returns true if successful. virtual bool setAnimationMode(E_BONE_ANIMATION_MODE mode); //! Gets the current animation mode of the bone virtual E_BONE_ANIMATION_MODE getAnimationMode() const; //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; /* //! Returns the relative transformation of the scene node. //virtual core::matrix4 getRelativeTransformation() const; */ virtual void OnAnimate(u32 timeMs); virtual void updateAbsolutePositionOfAllChildren(); //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! How the relative transformation of the bone is used virtual void setSkinningSpace( E_BONE_SKINNING_SPACE space ) { SkinningSpace=space; } virtual E_BONE_SKINNING_SPACE getSkinningSpace() const { return SkinningSpace; } private: void helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node); u32 BoneIndex; core::aabbox3d Box; E_BONE_ANIMATION_MODE AnimationMode; E_BONE_SKINNING_SPACE SkinningSpace; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CBoneSceneNode.cpp0000644000000000000000000000625312574354552020421 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ #include "CBoneSceneNode.h" namespace irr { namespace scene { //! constructor CBoneSceneNode::CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, u32 boneIndex, const c8* boneName) : IBoneSceneNode(parent, mgr, id), BoneIndex(boneIndex), AnimationMode(EBAM_AUTOMATIC), SkinningSpace(EBSS_LOCAL) { #ifdef _DEBUG setDebugName("CBoneSceneNode"); #endif setName(boneName); } //! Returns the index of the bone u32 CBoneSceneNode::getBoneIndex() const { return BoneIndex; } //! Sets the animation mode of the bone. Returns true if successful. bool CBoneSceneNode::setAnimationMode(E_BONE_ANIMATION_MODE mode) { AnimationMode = mode; return true; } //! Gets the current animation mode of the bone E_BONE_ANIMATION_MODE CBoneSceneNode::getAnimationMode() const { return AnimationMode; } //! returns the axis aligned bounding box of this node const core::aabbox3d& CBoneSceneNode::getBoundingBox() const { return Box; } /* //! Returns the relative transformation of the scene node. core::matrix4 CBoneSceneNode::getRelativeTransformation() const { return core::matrix4(); // RelativeTransformation; } */ void CBoneSceneNode::OnAnimate(u32 timeMs) { if (IsVisible) { // animate this node with all animators ISceneNodeAnimatorList::Iterator ait = Animators.begin(); for (; ait != Animators.end(); ++ait) (*ait)->animateNode(this, timeMs); // update absolute position //updateAbsolutePosition(); // perform the post render process on all children ISceneNodeList::Iterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->OnAnimate(timeMs); } } void CBoneSceneNode::helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node) { Node->updateAbsolutePosition(); ISceneNodeList::ConstIterator it = Node->getChildren().begin(); for (; it != Node->getChildren().end(); ++it) { helper_updateAbsolutePositionOfAllChildren( (*it) ); } } void CBoneSceneNode::updateAbsolutePositionOfAllChildren() { helper_updateAbsolutePositionOfAllChildren( this ); } void CBoneSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { IBoneSceneNode::serializeAttributes(out, options); out->addInt("BoneIndex", BoneIndex); out->addEnum("AnimationMode", AnimationMode, BoneAnimationModeNames); } void CBoneSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { BoneIndex = in->getAttributeAsInt("BoneIndex"); AnimationMode = (E_BONE_ANIMATION_MODE)in->getAttributeAsEnumeration("AnimationMode", BoneAnimationModeNames); // for legacy files (before 1.5) const core::stringc boneName = in->getAttributeAsString("BoneName"); setName(boneName); IBoneSceneNode::deserializeAttributes(in, options); // TODO: add/replace bone in parent with bone from mesh } } // namespace scene } // namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CBlit.h0000644000000000000000000006616612574354552016322 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef _C_BLIT_H_INCLUDED_ #define _C_BLIT_H_INCLUDED_ #include "SoftwareDriver2_helper.h" namespace irr { struct SBlitJob { AbsRectangle Dest; AbsRectangle Source; u32 argb; void * src; void * dst; s32 width; s32 height; u32 srcPitch; u32 dstPitch; u32 srcPixelMul; u32 dstPixelMul; bool stretch; float x_stretch; float y_stretch; SBlitJob() : stretch(false) {} }; // Bitfields Cohen Sutherland enum eClipCode { CLIPCODE_EMPTY = 0, CLIPCODE_BOTTOM = 1, CLIPCODE_TOP = 2, CLIPCODE_LEFT = 4, CLIPCODE_RIGHT = 8 }; inline u32 GetClipCode( const AbsRectangle &r, const core::position2d &p ) { u32 code = CLIPCODE_EMPTY; if ( p.X < r.x0 ) code = CLIPCODE_LEFT; else if ( p.X > r.x1 ) code = CLIPCODE_RIGHT; if ( p.Y < r.y0 ) code |= CLIPCODE_TOP; else if ( p.Y > r.y1 ) code |= CLIPCODE_BOTTOM; return code; } /*! Cohen Sutherland clipping @return: 1 if valid */ static int ClipLine(const AbsRectangle &clipping, core::position2d &p0, core::position2d &p1, const core::position2d& p0_in, const core::position2d& p1_in) { u32 code0; u32 code1; u32 code; p0 = p0_in; p1 = p1_in; code0 = GetClipCode( clipping, p0 ); code1 = GetClipCode( clipping, p1 ); // trivial accepted while ( code0 | code1 ) { s32 x=0; s32 y=0; // trivial reject if ( code0 & code1 ) return 0; if ( code0 ) { // clip first point code = code0; } else { // clip last point code = code1; } if ( (code & CLIPCODE_BOTTOM) == CLIPCODE_BOTTOM ) { // clip bottom viewport y = clipping.y1; x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y ); } else if ( (code & CLIPCODE_TOP) == CLIPCODE_TOP ) { // clip to viewport y = clipping.y0; x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y ); } else if ( (code & CLIPCODE_RIGHT) == CLIPCODE_RIGHT ) { // clip right viewport x = clipping.x1; y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X ); } else if ( (code & CLIPCODE_LEFT) == CLIPCODE_LEFT ) { // clip left viewport x = clipping.x0; y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X ); } if ( code == code0 ) { // modify first point p0.X = x; p0.Y = y; code0 = GetClipCode( clipping, p0 ); } else { // modify second point p1.X = x; p1.Y = y; code1 = GetClipCode( clipping, p1 ); } } return 1; } /* */ inline void GetClip(AbsRectangle &clipping, video::IImage * t) { clipping.x0 = 0; clipping.y0 = 0; clipping.x1 = t->getDimension().Width - 1; clipping.y1 = t->getDimension().Height - 1; } /* return alpha in [0;256] Granularity from 32-Bit ARGB add highbit alpha ( alpha > 127 ? + 1 ) */ static inline u32 extractAlpha(const u32 c) { return ( c >> 24 ) + ( c >> 31 ); } /* return alpha in [0;255] Granularity and 32-Bit ARGB add highbit alpha ( alpha > 127 ? + 1 ) */ static inline u32 packAlpha(const u32 c) { return (c > 127 ? c - 1 : c) << 24; } /*! Scale Color by (1/value) value 0 - 256 ( alpha ) */ inline u32 PixelLerp32(const u32 source, const u32 value) { u32 srcRB = source & 0x00FF00FF; u32 srcXG = (source & 0xFF00FF00) >> 8; srcRB *= value; srcXG *= value; srcRB >>= 8; //srcXG >>= 8; srcXG &= 0xFF00FF00; srcRB &= 0x00FF00FF; return srcRB | srcXG; } /* */ static void RenderLine32_Decal(video::IImage *t, const core::position2d &p0, const core::position2d &p1, u32 argb ) { s32 dx = p1.X - p0.X; s32 dy = p1.Y - p0.Y; s32 c; s32 m; s32 d = 0; s32 run; s32 xInc = 4; s32 yInc = (s32) t->getPitch(); if ( dx < 0 ) { xInc = -xInc; dx = -dx; } if ( dy < 0 ) { yInc = -yInc; dy = -dy; } u32 *dst; dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) ); if ( dy > dx ) { s32 tmp; tmp = dx; dx = dy; dy = tmp; tmp = xInc; xInc = yInc; yInc = tmp; } c = dx << 1; m = dy << 1; run = dx; do { *dst = argb; dst = (u32*) ( (u8*) dst + xInc ); // x += xInc d += m; if ( d > dx ) { dst = (u32*) ( (u8*) dst + yInc ); // y += yInc d -= c; } run -= 1; } while (run>=0); t->unlock(); } /* */ static void RenderLine32_Blend(video::IImage *t, const core::position2d &p0, const core::position2d &p1, u32 argb, u32 alpha) { s32 dx = p1.X - p0.X; s32 dy = p1.Y - p0.Y; s32 c; s32 m; s32 d = 0; s32 run; s32 xInc = 4; s32 yInc = (s32) t->getPitch(); if ( dx < 0 ) { xInc = -xInc; dx = -dx; } if ( dy < 0 ) { yInc = -yInc; dy = -dy; } u32 *dst; dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) ); if ( dy > dx ) { s32 tmp; tmp = dx; dx = dy; dy = tmp; tmp = xInc; xInc = yInc; yInc = tmp; } c = dx << 1; m = dy << 1; run = dx; const u32 packA = packAlpha ( alpha ); do { *dst = packA | PixelBlend32( *dst, argb, alpha ); dst = (u32*) ( (u8*) dst + xInc ); // x += xInc d += m; if ( d > dx ) { dst = (u32*) ( (u8*) dst + yInc ); // y += yInc d -= c; } run -= 1; } while (run>=0); t->unlock(); } /* */ static void RenderLine16_Decal(video::IImage *t, const core::position2d &p0, const core::position2d &p1, u32 argb ) { s32 dx = p1.X - p0.X; s32 dy = p1.Y - p0.Y; s32 c; s32 m; s32 d = 0; s32 run; s32 xInc = 2; s32 yInc = (s32) t->getPitch(); if ( dx < 0 ) { xInc = -xInc; dx = -dx; } if ( dy < 0 ) { yInc = -yInc; dy = -dy; } u16 *dst; dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) ); if ( dy > dx ) { s32 tmp; tmp = dx; dx = dy; dy = tmp; tmp = xInc; xInc = yInc; yInc = tmp; } c = dx << 1; m = dy << 1; run = dx; do { *dst = (u16)argb; dst = (u16*) ( (u8*) dst + xInc ); // x += xInc d += m; if ( d > dx ) { dst = (u16*) ( (u8*) dst + yInc ); // y += yInc d -= c; } run -= 1; } while (run>=0); t->unlock(); } /* */ static void RenderLine16_Blend(video::IImage *t, const core::position2d &p0, const core::position2d &p1, u16 argb, u16 alpha) { s32 dx = p1.X - p0.X; s32 dy = p1.Y - p0.Y; s32 c; s32 m; s32 d = 0; s32 run; s32 xInc = 2; s32 yInc = (s32) t->getPitch(); if ( dx < 0 ) { xInc = -xInc; dx = -dx; } if ( dy < 0 ) { yInc = -yInc; dy = -dy; } u16 *dst; dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) ); if ( dy > dx ) { s32 tmp; tmp = dx; dx = dy; dy = tmp; tmp = xInc; xInc = yInc; yInc = tmp; } c = dx << 1; m = dy << 1; run = dx; const u16 packA = alpha ? 0x8000 : 0; do { *dst = packA | PixelBlend16( *dst, argb, alpha ); dst = (u16*) ( (u8*) dst + xInc ); // x += xInc d += m; if ( d > dx ) { dst = (u16*) ( (u8*) dst + yInc ); // y += yInc d -= c; } run -= 1; } while (run>=0); t->unlock(); } /*! */ static void executeBlit_TextureCopy_x_to_x( const SBlitJob * job ) { const u32 w = job->width; const u32 h = job->height; if (job->stretch) { const u32 *src = static_cast(job->src); u32 *dst = static_cast(job->dst); const float wscale = 1.f/job->x_stretch; const float hscale = 1.f/job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { const u32 src_y = (u32)(dy*hscale); src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y ); for ( u32 dx = 0; dx < w; ++dx ) { const u32 src_x = (u32)(dx*wscale); dst[dx] = src[src_x]; } dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } else { const u32 widthPitch = job->width * job->dstPixelMul; const void *src = (void*) job->src; void *dst = (void*) job->dst; for ( u32 dy = 0; dy != h; ++dy ) { memcpy( dst, src, widthPitch ); src = (void*) ( (u8*) (src) + job->srcPitch ); dst = (void*) ( (u8*) (dst) + job->dstPitch ); } } } /*! */ static void executeBlit_TextureCopy_32_to_16( const SBlitJob * job ) { const u32 w = job->width; const u32 h = job->height; const u32 *src = static_cast(job->src); u16 *dst = static_cast(job->dst); if (job->stretch) { const float wscale = 1.f/job->x_stretch; const float hscale = 1.f/job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { const u32 src_y = (u32)(dy*hscale); src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y ); for ( u32 dx = 0; dx < w; ++dx ) { const u32 src_x = (u32)(dx*wscale); //16 bit Blitter depends on pre-multiplied color const u32 s = PixelLerp32( src[src_x] | 0xFF000000, extractAlpha( src[src_x] ) ); dst[dx] = video::A8R8G8B8toA1R5G5B5( s ); } dst = (u16*) ( (u8*) (dst) + job->dstPitch ); } } else { for ( u32 dy = 0; dy != h; ++dy ) { for ( u32 dx = 0; dx != w; ++dx ) { //16 bit Blitter depends on pre-multiplied color const u32 s = PixelLerp32( src[dx] | 0xFF000000, extractAlpha( src[dx] ) ); dst[dx] = video::A8R8G8B8toA1R5G5B5( s ); } src = (u32*) ( (u8*) (src) + job->srcPitch ); dst = (u16*) ( (u8*) (dst) + job->dstPitch ); } } } /*! */ static void executeBlit_TextureCopy_24_to_16( const SBlitJob * job ) { const u32 w = job->width; const u32 h = job->height; const u8 *src = static_cast(job->src); u16 *dst = static_cast(job->dst); if (job->stretch) { const float wscale = 3.f/job->x_stretch; const float hscale = 1.f/job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { const u32 src_y = (u32)(dy*hscale); src = (u8*)(job->src) + job->srcPitch*src_y; for ( u32 dx = 0; dx < w; ++dx ) { const u8* src_x = src+(u32)(dx*wscale); dst[dx] = video::RGBA16(src_x[0], src_x[1], src_x[2]); } dst = (u16*) ( (u8*) (dst) + job->dstPitch ); } } else { for ( u32 dy = 0; dy != h; ++dy ) { const u8* s = src; for ( u32 dx = 0; dx != w; ++dx ) { dst[dx] = video::RGBA16(s[0], s[1], s[2]); s += 3; } src = src+job->srcPitch; dst = (u16*) ( (u8*) (dst) + job->dstPitch ); } } } /*! */ static void executeBlit_TextureCopy_16_to_32( const SBlitJob * job ) { const u32 w = job->width; const u32 h = job->height; const u16 *src = static_cast(job->src); u32 *dst = static_cast(job->dst); if (job->stretch) { const float wscale = 1.f/job->x_stretch; const float hscale = 1.f/job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { const u32 src_y = (u32)(dy*hscale); src = (u16*) ( (u8*) (job->src) + job->srcPitch*src_y ); for ( u32 dx = 0; dx < w; ++dx ) { const u32 src_x = (u32)(dx*wscale); dst[dx] = video::A1R5G5B5toA8R8G8B8(src[src_x]); } dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } else { for ( u32 dy = 0; dy != h; ++dy ) { for ( u32 dx = 0; dx != w; ++dx ) { dst[dx] = video::A1R5G5B5toA8R8G8B8( src[dx] ); } src = (u16*) ( (u8*) (src) + job->srcPitch ); dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } } static void executeBlit_TextureCopy_16_to_24( const SBlitJob * job ) { const u32 w = job->width; const u32 h = job->height; const u16 *src = static_cast(job->src); u8 *dst = static_cast(job->dst); if (job->stretch) { const float wscale = 1.f/job->x_stretch; const float hscale = 1.f/job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { const u32 src_y = (u32)(dy*hscale); src = (u16*) ( (u8*) (job->src) + job->srcPitch*src_y ); for ( u32 dx = 0; dx < w; ++dx ) { const u32 src_x = (u32)(dx*wscale); u32 color = video::A1R5G5B5toA8R8G8B8(src[src_x]); u8 * writeTo = &dst[dx * 3]; *writeTo++ = (color >> 16)& 0xFF; *writeTo++ = (color >> 8) & 0xFF; *writeTo++ = color & 0xFF; } dst += job->dstPitch; } } else { for ( u32 dy = 0; dy != h; ++dy ) { for ( u32 dx = 0; dx != w; ++dx ) { u32 color = video::A1R5G5B5toA8R8G8B8(src[dx]); u8 * writeTo = &dst[dx * 3]; *writeTo++ = (color >> 16)& 0xFF; *writeTo++ = (color >> 8) & 0xFF; *writeTo++ = color & 0xFF; } src = (u16*) ( (u8*) (src) + job->srcPitch ); dst += job->dstPitch; } } } /*! */ static void executeBlit_TextureCopy_24_to_32( const SBlitJob * job ) { const u32 w = job->width; const u32 h = job->height; const u8 *src = static_cast(job->src); u32 *dst = static_cast(job->dst); if (job->stretch) { const float wscale = 3.f/job->x_stretch; const float hscale = 1.f/job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { const u32 src_y = (u32)(dy*hscale); src = (const u8*)job->src+(job->srcPitch*src_y); for ( u32 dx = 0; dx < w; ++dx ) { const u8* s = src+(u32)(dx*wscale); dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2]; } dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } else { for ( s32 dy = 0; dy != job->height; ++dy ) { const u8* s = src; for ( s32 dx = 0; dx != job->width; ++dx ) { dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2]; s += 3; } src = src + job->srcPitch; dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } } static void executeBlit_TextureCopy_32_to_24( const SBlitJob * job ) { const u32 w = job->width; const u32 h = job->height; const u32 *src = static_cast(job->src); u8 *dst = static_cast(job->dst); if (job->stretch) { const float wscale = 1.f/job->x_stretch; const float hscale = 1.f/job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { const u32 src_y = (u32)(dy*hscale); src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y); for ( u32 dx = 0; dx < w; ++dx ) { const u32 src_x = src[(u32)(dx*wscale)]; u8 * writeTo = &dst[dx * 3]; *writeTo++ = (src_x >> 16)& 0xFF; *writeTo++ = (src_x >> 8) & 0xFF; *writeTo++ = src_x & 0xFF; } dst += job->dstPitch; } } else { for ( u32 dy = 0; dy != h; ++dy ) { for ( u32 dx = 0; dx != w; ++dx ) { u8 * writeTo = &dst[dx * 3]; *writeTo++ = (src[dx] >> 16)& 0xFF; *writeTo++ = (src[dx] >> 8) & 0xFF; *writeTo++ = src[dx] & 0xFF; } src = (u32*) ( (u8*) (src) + job->srcPitch ); dst += job->dstPitch; } } } /*! */ static void executeBlit_TextureBlend_16_to_16( const SBlitJob * job ) { const u32 w = job->width; const u32 h = job->height; const u32 rdx = w>>1; const u32 *src = (u32*) job->src; u32 *dst = (u32*) job->dst; if (job->stretch) { const float wscale = 1.f/job->x_stretch; const float hscale = 1.f/job->y_stretch; const u32 off = core::if_c_a_else_b(w&1, (u32)((w-1)*wscale), 0); for ( u32 dy = 0; dy < h; ++dy ) { const u32 src_y = (u32)(dy*hscale); src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y ); for ( u32 dx = 0; dx < rdx; ++dx ) { const u32 src_x = (u32)(dx*wscale); dst[dx] = PixelBlend16_simd( dst[dx], src[src_x] ); } if ( off ) { ((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] ); } dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } else { const u32 off = core::if_c_a_else_b(w&1, w-1, 0); for (u32 dy = 0; dy != h; ++dy ) { for (u32 dx = 0; dx != rdx; ++dx ) { dst[dx] = PixelBlend16_simd( dst[dx], src[dx] ); } if ( off ) { ((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] ); } src = (u32*) ( (u8*) (src) + job->srcPitch ); dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } } /*! */ static void executeBlit_TextureBlend_32_to_32( const SBlitJob * job ) { const u32 w = job->width; const u32 h = job->height; const u32 *src = (u32*) job->src; u32 *dst = (u32*) job->dst; if (job->stretch) { const float wscale = 1.f/job->x_stretch; const float hscale = 1.f/job->y_stretch; for ( u32 dy = 0; dy < h; ++dy ) { const u32 src_y = (u32)(dy*hscale); src = (u32*) ( (u8*) (job->src) + job->srcPitch*src_y ); for ( u32 dx = 0; dx < w; ++dx ) { const u32 src_x = (u32)(dx*wscale); dst[dx] = PixelBlend32( dst[dx], src[src_x] ); } dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } else { for ( u32 dy = 0; dy != h; ++dy ) { for ( u32 dx = 0; dx != w; ++dx ) { dst[dx] = PixelBlend32( dst[dx], src[dx] ); } src = (u32*) ( (u8*) (src) + job->srcPitch ); dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } } /*! */ static void executeBlit_TextureBlendColor_16_to_16( const SBlitJob * job ) { u16 *src = (u16*) job->src; u16 *dst = (u16*) job->dst; u16 blend = video::A8R8G8B8toA1R5G5B5 ( job->argb ); for ( s32 dy = 0; dy != job->height; ++dy ) { for ( s32 dx = 0; dx != job->width; ++dx ) { if ( 0 == (src[dx] & 0x8000) ) continue; dst[dx] = PixelMul16_2( src[dx], blend ); } src = (u16*) ( (u8*) (src) + job->srcPitch ); dst = (u16*) ( (u8*) (dst) + job->dstPitch ); } } /*! */ static void executeBlit_TextureBlendColor_32_to_32( const SBlitJob * job ) { u32 *src = (u32*) job->src; u32 *dst = (u32*) job->dst; for ( s32 dy = 0; dy != job->height; ++dy ) { for ( s32 dx = 0; dx != job->width; ++dx ) { dst[dx] = PixelBlend32( dst[dx], PixelMul32_2( src[dx], job->argb ) ); } src = (u32*) ( (u8*) (src) + job->srcPitch ); dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } /*! */ static void executeBlit_Color_16_to_16( const SBlitJob * job ) { const u16 c = video::A8R8G8B8toA1R5G5B5(job->argb); u16 *dst = (u16*) job->dst; for ( s32 dy = 0; dy != job->height; ++dy ) { memset16(dst, c, job->srcPitch); dst = (u16*) ( (u8*) (dst) + job->dstPitch ); } } /*! */ static void executeBlit_Color_32_to_32( const SBlitJob * job ) { u32 *dst = (u32*) job->dst; for ( s32 dy = 0; dy != job->height; ++dy ) { memset32( dst, job->argb, job->srcPitch ); dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } /*! */ static void executeBlit_ColorAlpha_16_to_16( const SBlitJob * job ) { u16 *dst = (u16*) job->dst; const u16 alpha = extractAlpha( job->argb ) >> 3; if ( 0 == alpha ) return; const u32 src = video::A8R8G8B8toA1R5G5B5( job->argb ); for ( s32 dy = 0; dy != job->height; ++dy ) { for ( s32 dx = 0; dx != job->width; ++dx ) { dst[dx] = 0x8000 | PixelBlend16( dst[dx], src, alpha ); } dst = (u16*) ( (u8*) (dst) + job->dstPitch ); } } /*! */ static void executeBlit_ColorAlpha_32_to_32( const SBlitJob * job ) { u32 *dst = (u32*) job->dst; const u32 alpha = extractAlpha( job->argb ); const u32 src = job->argb; for ( s32 dy = 0; dy != job->height; ++dy ) { for ( s32 dx = 0; dx != job->width; ++dx ) { dst[dx] = (job->argb & 0xFF000000 ) | PixelBlend32( dst[dx], src, alpha ); } dst = (u32*) ( (u8*) (dst) + job->dstPitch ); } } // Blitter Operation enum eBlitter { BLITTER_INVALID = 0, BLITTER_COLOR, BLITTER_COLOR_ALPHA, BLITTER_TEXTURE, BLITTER_TEXTURE_ALPHA_BLEND, BLITTER_TEXTURE_ALPHA_COLOR_BLEND }; typedef void (*tExecuteBlit) ( const SBlitJob * job ); /*! */ struct blitterTable { eBlitter operation; s32 destFormat; s32 sourceFormat; tExecuteBlit func; }; static const blitterTable blitTable[] = { { BLITTER_TEXTURE, -2, -2, executeBlit_TextureCopy_x_to_x }, { BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_16 }, { BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_16 }, { BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_32 }, { BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_32 }, { BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_24 }, { BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_24 }, { BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlend_16_to_16 }, { BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlend_32_to_32 }, { BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlendColor_16_to_16 }, { BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlendColor_32_to_32 }, { BLITTER_COLOR, video::ECF_A1R5G5B5, -1, executeBlit_Color_16_to_16 }, { BLITTER_COLOR, video::ECF_A8R8G8B8, -1, executeBlit_Color_32_to_32 }, { BLITTER_COLOR_ALPHA, video::ECF_A1R5G5B5, -1, executeBlit_ColorAlpha_16_to_16 }, { BLITTER_COLOR_ALPHA, video::ECF_A8R8G8B8, -1, executeBlit_ColorAlpha_32_to_32 }, { BLITTER_INVALID, -1, -1, 0 } }; static inline tExecuteBlit getBlitter2( eBlitter operation,const video::IImage * dest,const video::IImage * source ) { video::ECOLOR_FORMAT sourceFormat = (video::ECOLOR_FORMAT) ( source ? source->getColorFormat() : -1 ); video::ECOLOR_FORMAT destFormat = (video::ECOLOR_FORMAT) ( dest ? dest->getColorFormat() : -1 ); const blitterTable * b = blitTable; while ( b->operation != BLITTER_INVALID ) { if ( b->operation == operation ) { if (( b->destFormat == -1 || b->destFormat == destFormat ) && ( b->sourceFormat == -1 || b->sourceFormat == sourceFormat ) ) return b->func; else if ( b->destFormat == -2 && ( sourceFormat == destFormat ) ) return b->func; } b += 1; } return 0; } // bounce clipping to texture inline void setClip ( AbsRectangle &out, const core::rect *clip, const video::IImage * tex, s32 passnative ) { if ( clip && 0 == tex && passnative ) { out.x0 = clip->UpperLeftCorner.X; out.x1 = clip->LowerRightCorner.X; out.y0 = clip->UpperLeftCorner.Y; out.y1 = clip->LowerRightCorner.Y; return; } const s32 w = tex ? tex->getDimension().Width : 0; const s32 h = tex ? tex->getDimension().Height : 0; if ( clip ) { out.x0 = core::s32_clamp ( clip->UpperLeftCorner.X, 0, w ); out.x1 = core::s32_clamp ( clip->LowerRightCorner.X, out.x0, w ); out.y0 = core::s32_clamp ( clip->UpperLeftCorner.Y, 0, h ); out.y1 = core::s32_clamp ( clip->LowerRightCorner.Y, out.y0, h ); } else { out.x0 = 0; out.y0 = 0; out.x1 = w; out.y1 = h; } } /*! a generic 2D Blitter */ static s32 Blit(eBlitter operation, video::IImage * dest, const core::rect *destClipping, const core::position2d *destPos, video::IImage * const source, const core::rect *sourceClipping, u32 argb) { tExecuteBlit blitter = getBlitter2( operation, dest, source ); if ( 0 == blitter ) { return 0; } // Clipping AbsRectangle sourceClip; AbsRectangle destClip; AbsRectangle v; SBlitJob job; setClip ( sourceClip, sourceClipping, source, 1 ); setClip ( destClip, destClipping, dest, 0 ); v.x0 = destPos ? destPos->X : 0; v.y0 = destPos ? destPos->Y : 0; v.x1 = v.x0 + ( sourceClip.x1 - sourceClip.x0 ); v.y1 = v.y0 + ( sourceClip.y1 - sourceClip.y0 ); if ( !intersect( job.Dest, destClip, v ) ) return 0; job.width = job.Dest.x1 - job.Dest.x0; job.height = job.Dest.y1 - job.Dest.y0; job.Source.x0 = sourceClip.x0 + ( job.Dest.x0 - v.x0 ); job.Source.x1 = job.Source.x0 + job.width; job.Source.y0 = sourceClip.y0 + ( job.Dest.y0 - v.y0 ); job.Source.y1 = job.Source.y0 + job.height; job.argb = argb; if ( source ) { job.srcPitch = source->getPitch(); job.srcPixelMul = source->getBytesPerPixel(); job.src = (void*) ( (u8*) source->lock() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) ); } else { // use srcPitch for color operation on dest job.srcPitch = job.width * dest->getBytesPerPixel(); } job.dstPitch = dest->getPitch(); job.dstPixelMul = dest->getBytesPerPixel(); job.dst = (void*) ( (u8*) dest->lock() + ( job.Dest.y0 * job.dstPitch ) + ( job.Dest.x0 * job.dstPixelMul ) ); blitter( &job ); if ( source ) source->unlock(); if ( dest ) dest->unlock(); return 1; } static s32 StretchBlit(eBlitter operation, video::IImage* dest, const core::rect *destRect, const core::rect *srcRect, video::IImage* const source, u32 argb) { tExecuteBlit blitter = getBlitter2( operation, dest, source ); if ( 0 == blitter ) { return 0; } SBlitJob job; // Clipping setClip ( job.Source, srcRect, source, 1 ); setClip ( job.Dest, destRect, dest, 0 ); job.width = job.Dest.x1-job.Dest.x0; job.height = job.Dest.y1-job.Dest.y0; job.argb = argb; // use original dest size, despite any clipping job.x_stretch = (float)destRect->getWidth() / (float)(job.Source.x1-job.Source.x0); job.y_stretch = (float)destRect->getHeight() / (float)(job.Source.y1-job.Source.y0); job.stretch = (job.x_stretch != 1.f) || (job.y_stretch != 1.f); if ( source ) { job.srcPitch = source->getPitch(); job.srcPixelMul = source->getBytesPerPixel(); job.src = (void*) ( (u8*) source->lock() + ( job.Source.y0 * job.srcPitch ) + ( job.Source.x0 * job.srcPixelMul ) ); } else { // use srcPitch for color operation on dest job.srcPitch = job.width * dest->getBytesPerPixel(); } job.dstPitch = dest->getPitch(); job.dstPixelMul = dest->getBytesPerPixel(); job.dst = (void*) ( (u8*) dest->lock() + ( job.Dest.y0 * job.dstPitch ) + ( job.Dest.x0 * job.dstPixelMul ) ); blitter( &job ); if ( source ) source->unlock(); if ( dest ) dest->unlock(); return 1; } // Methods for Software drivers //! draws a rectangle static void drawRectangle(video::IImage* img, const core::rect& rect, const video::SColor &color) { Blit(color.getAlpha() == 0xFF ? BLITTER_COLOR : BLITTER_COLOR_ALPHA, img, 0, &rect.UpperLeftCorner, 0, &rect, color.color); } //! draws a line from to with color static void drawLine(video::IImage* img, const core::position2d& from, const core::position2d& to, const video::SColor &color) { AbsRectangle clip; GetClip(clip, img); core::position2d p[2]; if (ClipLine( clip, p[0], p[1], from, to)) { u32 alpha = extractAlpha(color.color); switch(img->getColorFormat()) { case video::ECF_A1R5G5B5: if (alpha == 256) { RenderLine16_Decal(img, p[0], p[1], video::A8R8G8B8toA1R5G5B5(color.color)); } else { RenderLine16_Blend(img, p[0], p[1], video::A8R8G8B8toA1R5G5B5(color.color), alpha >> 3); } break; case video::ECF_A8R8G8B8: if (alpha == 256) { RenderLine32_Decal(img, p[0], p[1], color.color); } else { RenderLine32_Blend(img, p[0], p[1], color.color, alpha); } break; default: break; } } } } #endif irrlicht-1.8.3/source/Irrlicht/CBillboardSceneNode.h0000644000000000000000000000635412574354552021077 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_BILLBOARD_SCENE_NODE_H_INCLUDED__ #define __C_BILLBOARD_SCENE_NODE_H_INCLUDED__ #include "IBillboardSceneNode.h" #include "S3DVertex.h" namespace irr { namespace scene { //! Scene node which is a billboard. A billboard is like a 3d sprite: A 2d element, //! which always looks to the camera. class CBillboardSceneNode : virtual public IBillboardSceneNode { public: //! constructor CBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::dimension2d& size, video::SColor colorTop=video::SColor(0xFFFFFFFF), video::SColor colorBottom=video::SColor(0xFFFFFFFF)); //! pre render event virtual void OnRegisterSceneNode(); //! render virtual void render(); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! sets the size of the billboard virtual void setSize(const core::dimension2d& size); //! Sets the widths of the top and bottom edges of the billboard independently. virtual void setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth); //! gets the size of the billboard virtual const core::dimension2d& getSize() const; //! Gets the widths of the top and bottom edges of the billboard. virtual void getSize(f32& height, f32& bottomEdgeWidth, f32& topEdgeWidth) const; virtual video::SMaterial& getMaterial(u32 i); //! returns amount of materials used by this scene node. virtual u32 getMaterialCount() const; //! Set the color of all vertices of the billboard //! \param overallColor: the color to set virtual void setColor(const video::SColor& overallColor); //! Set the color of the top and bottom vertices of the billboard //! \param topColor: the color to set the top vertices //! \param bottomColor: the color to set the bottom vertices virtual void setColor(const video::SColor& topColor, const video::SColor& bottomColor); //! Gets the color of the top and bottom vertices of the billboard //! \param[out] topColor: stores the color of the top vertices //! \param[out] bottomColor: stores the color of the bottom vertices virtual void getColor(video::SColor& topColor, video::SColor& bottomColor) const; //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_BILLBOARD; } //! Creates a clone of this scene node and its children. virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); private: //! Size.Width is the bottom edge width core::dimension2d Size; f32 TopEdgeWidth; core::aabbox3d BBox; video::SMaterial Material; video::S3DVertex vertices[4]; u16 indices[6]; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CBillboardSceneNode.cpp0000644000000000000000000001655112574354552021432 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CBillboardSceneNode.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "ICameraSceneNode.h" #include "os.h" namespace irr { namespace scene { //! constructor CBillboardSceneNode::CBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::dimension2d& size, video::SColor colorTop, video::SColor colorBottom) : IBillboardSceneNode(parent, mgr, id, position) { #ifdef _DEBUG setDebugName("CBillboardSceneNode"); #endif setSize(size); indices[0] = 0; indices[1] = 2; indices[2] = 1; indices[3] = 0; indices[4] = 3; indices[5] = 2; vertices[0].TCoords.set(1.0f, 1.0f); vertices[0].Color = colorBottom; vertices[1].TCoords.set(1.0f, 0.0f); vertices[1].Color = colorTop; vertices[2].TCoords.set(0.0f, 0.0f); vertices[2].Color = colorTop; vertices[3].TCoords.set(0.0f, 1.0f); vertices[3].Color = colorBottom; } //! pre render event void CBillboardSceneNode::OnRegisterSceneNode() { if (IsVisible) SceneManager->registerNodeForRendering(this); ISceneNode::OnRegisterSceneNode(); } //! render void CBillboardSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); ICameraSceneNode* camera = SceneManager->getActiveCamera(); if (!camera || !driver) return; // make billboard look to camera core::vector3df pos = getAbsolutePosition(); core::vector3df campos = camera->getAbsolutePosition(); core::vector3df target = camera->getTarget(); core::vector3df up = camera->getUpVector(); core::vector3df view = target - campos; view.normalize(); core::vector3df horizontal = up.crossProduct(view); if ( horizontal.getLength() == 0 ) { horizontal.set(up.Y,up.X,up.Z); } horizontal.normalize(); core::vector3df topHorizontal = horizontal * 0.5f * TopEdgeWidth; horizontal *= 0.5f * Size.Width; // pointing down! core::vector3df vertical = horizontal.crossProduct(view); vertical.normalize(); vertical *= 0.5f * Size.Height; view *= -1.0f; for (s32 i=0; i<4; ++i) vertices[i].Normal = view; /* Vertices are: 2--1 |\ | | \| 3--0 */ vertices[0].Pos = pos + horizontal + vertical; vertices[1].Pos = pos + topHorizontal - vertical; vertices[2].Pos = pos - topHorizontal - vertical; vertices[3].Pos = pos - horizontal + vertical; // draw if (DebugDataVisible & scene::EDS_BBOX) { driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); video::SMaterial m; m.Lighting = false; driver->setMaterial(m); driver->draw3DBox(BBox, video::SColor(0,208,195,152)); } driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); driver->setMaterial(Material); driver->drawIndexedTriangleList(vertices, 4, indices, 2); } //! returns the axis aligned bounding box of this node const core::aabbox3d& CBillboardSceneNode::getBoundingBox() const { return BBox; } //! sets the size of the billboard void CBillboardSceneNode::setSize(const core::dimension2d& size) { Size = size; if (core::equals(Size.Width, 0.0f)) Size.Width = 1.0f; TopEdgeWidth = Size.Width; if (core::equals(Size.Height, 0.0f)) Size.Height = 1.0f; const f32 avg = (Size.Width + Size.Height)/6; BBox.MinEdge.set(-avg,-avg,-avg); BBox.MaxEdge.set(avg,avg,avg); } void CBillboardSceneNode::setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth) { Size.set(bottomEdgeWidth, height); TopEdgeWidth = topEdgeWidth; if (core::equals(Size.Height, 0.0f)) Size.Height = 1.0f; if (core::equals(Size.Width, 0.f) && core::equals(TopEdgeWidth, 0.f)) { Size.Width = 1.0f; TopEdgeWidth = 1.0f; } const f32 avg = (core::max_(Size.Width,TopEdgeWidth) + Size.Height)/6; BBox.MinEdge.set(-avg,-avg,-avg); BBox.MaxEdge.set(avg,avg,avg); } video::SMaterial& CBillboardSceneNode::getMaterial(u32 i) { return Material; } //! returns amount of materials used by this scene node. u32 CBillboardSceneNode::getMaterialCount() const { return 1; } //! gets the size of the billboard const core::dimension2d& CBillboardSceneNode::getSize() const { return Size; } //! Gets the widths of the top and bottom edges of the billboard. void CBillboardSceneNode::getSize(f32& height, f32& bottomEdgeWidth, f32& topEdgeWidth) const { height = Size.Height; bottomEdgeWidth = Size.Width; topEdgeWidth = TopEdgeWidth; } //! Writes attributes of the scene node. void CBillboardSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { IBillboardSceneNode::serializeAttributes(out, options); out->addFloat("Width", Size.Width); out->addFloat("TopEdgeWidth", TopEdgeWidth); out->addFloat("Height", Size.Height); out->addColor("Shade_Top", vertices[1].Color); out->addColor("Shade_Down", vertices[0].Color); } //! Reads attributes of the scene node. void CBillboardSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { IBillboardSceneNode::deserializeAttributes(in, options); Size.Width = in->getAttributeAsFloat("Width"); Size.Height = in->getAttributeAsFloat("Height"); if (in->existsAttribute("TopEdgeWidth")) { TopEdgeWidth = in->getAttributeAsFloat("TopEdgeWidth"); if (Size.Width != TopEdgeWidth) setSize(Size.Height, Size.Width, TopEdgeWidth); } else setSize(Size); vertices[1].Color = in->getAttributeAsColor("Shade_Top"); vertices[0].Color = in->getAttributeAsColor("Shade_Down"); vertices[2].Color = vertices[1].Color; vertices[3].Color = vertices[0].Color; } //! Set the color of all vertices of the billboard //! \param overallColor: the color to set void CBillboardSceneNode::setColor(const video::SColor& overallColor) { for(u32 vertex = 0; vertex < 4; ++vertex) vertices[vertex].Color = overallColor; } //! Set the color of the top and bottom vertices of the billboard //! \param topColor: the color to set the top vertices //! \param bottomColor: the color to set the bottom vertices void CBillboardSceneNode::setColor(const video::SColor& topColor, const video::SColor& bottomColor) { vertices[0].Color = bottomColor; vertices[1].Color = topColor; vertices[2].Color = topColor; vertices[3].Color = bottomColor; } //! Gets the color of the top and bottom vertices of the billboard //! \param[out] topColor: stores the color of the top vertices //! \param[out] bottomColor: stores the color of the bottom vertices void CBillboardSceneNode::getColor(video::SColor& topColor, video::SColor& bottomColor) const { bottomColor = vertices[0].Color; topColor = vertices[1].Color; } //! Creates a clone of this scene node and its children. ISceneNode* CBillboardSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CBillboardSceneNode* nb = new CBillboardSceneNode(newParent, newManager, ID, RelativeTranslation, Size); nb->cloneMembers(this, newManager); nb->Material = Material; nb->TopEdgeWidth = this->TopEdgeWidth; if ( newParent ) nb->drop(); return nb; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CB3DMeshFileLoader.h0000644000000000000000000000655212574354552020535 0ustar rootroot// Copyright (C) 2006-2012 Luke Hoschke // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // B3D Mesh loader // File format designed by Mark Sibly for the Blitz3D engine and has been // declared public domain #include "IrrCompileConfig.h" #ifndef __C_B3D_MESH_LOADER_H_INCLUDED__ #define __C_B3D_MESH_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "ISceneManager.h" #include "CSkinnedMesh.h" #include "IReadFile.h" namespace irr { namespace scene { //! Meshloader for B3D format class CB3DMeshFileLoader : public IMeshLoader { public: //! Constructor CB3DMeshFileLoader(scene::ISceneManager* smgr); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: struct SB3dChunkHeader { c8 name[4]; s32 size; }; struct SB3dChunk { SB3dChunk(const SB3dChunkHeader& header, long sp) : length(header.size+8), startposition(sp) { name[0]=header.name[0]; name[1]=header.name[1]; name[2]=header.name[2]; name[3]=header.name[3]; } c8 name[4]; s32 length; long startposition; }; struct SB3dTexture { core::stringc TextureName; s32 Flags; s32 Blend; f32 Xpos; f32 Ypos; f32 Xscale; f32 Yscale; f32 Angle; }; struct SB3dMaterial { SB3dMaterial() : red(1.0f), green(1.0f), blue(1.0f), alpha(1.0f), shininess(0.0f), blend(1), fx(0) { for (u32 i=0; i B3dStack; core::array Materials; core::array Textures; core::array AnimatedVertices_VertexID; core::array AnimatedVertices_BufferID; core::array BaseVertices; ISceneManager* SceneManager; CSkinnedMesh* AnimatedMesh; io::IReadFile* B3DFile; //B3Ds have Vertex ID's local within the mesh I don't want this // Variable needs to be class member due to recursion in calls u32 VerticesStart; bool NormalsInFile; bool HasVertexColors; bool ShowWarning; }; } // end namespace scene } // end namespace irr #endif // __C_B3D_MESH_LOADER_H_INCLUDED__ irrlicht-1.8.3/source/Irrlicht/CB3DMeshFileLoader.cpp0000644000000000000000000010076312574354552021067 0ustar rootroot// Copyright (C) 2006-2012 Luke Hoschke // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // B3D Mesh loader // File format designed by Mark Sibly for the Blitz3D engine and has been // declared public domain #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_B3D_LOADER_ #include "CB3DMeshFileLoader.h" #include "IVideoDriver.h" #include "IFileSystem.h" #include "os.h" #ifdef _DEBUG #define _B3D_READER_DEBUG #endif namespace irr { namespace scene { //! Constructor CB3DMeshFileLoader::CB3DMeshFileLoader(scene::ISceneManager* smgr) : SceneManager(smgr), AnimatedMesh(0), B3DFile(0), NormalsInFile(false), HasVertexColors(false), ShowWarning(true) { #ifdef _DEBUG setDebugName("CB3DMeshFileLoader"); #endif } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool CB3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "b3d" ); } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* CB3DMeshFileLoader::createMesh(io::IReadFile* f) { if (!f) return 0; B3DFile = f; AnimatedMesh = new scene::CSkinnedMesh(); ShowWarning = true; // If true a warning is issued if too many textures are used VerticesStart=0; if ( load() ) { AnimatedMesh->finalize(); } else { AnimatedMesh->drop(); AnimatedMesh = 0; } return AnimatedMesh; } bool CB3DMeshFileLoader::load() { B3dStack.clear(); NormalsInFile=false; HasVertexColors=false; //------ Get header ------ SB3dChunkHeader header; B3DFile->read(&header, sizeof(header)); #ifdef __BIG_ENDIAN__ header.size = os::Byteswap::byteswap(header.size); #endif if ( strncmp( header.name, "BB3D", 4 ) != 0 ) { os::Printer::log("File is not a b3d file. Loading failed (No header found)", B3DFile->getFileName(), ELL_ERROR); return false; } // Add main chunk... B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8)); // Get file version, but ignore it, as it's not important with b3d files... s32 fileVersion; B3DFile->read(&fileVersion, sizeof(fileVersion)); #ifdef __BIG_ENDIAN__ fileVersion = os::Byteswap::byteswap(fileVersion); #endif //------ Read main chunk ------ while ( (B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos() ) { B3DFile->read(&header, sizeof(header)); #ifdef __BIG_ENDIAN__ header.size = os::Byteswap::byteswap(header.size); #endif B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8)); if ( strncmp( B3dStack.getLast().name, "TEXS", 4 ) == 0 ) { if (!readChunkTEXS()) return false; } else if ( strncmp( B3dStack.getLast().name, "BRUS", 4 ) == 0 ) { if (!readChunkBRUS()) return false; } else if ( strncmp( B3dStack.getLast().name, "NODE", 4 ) == 0 ) { if (!readChunkNODE((CSkinnedMesh::SJoint*)0) ) return false; } else { os::Printer::log("Unknown chunk found in mesh base - skipping"); B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length); B3dStack.erase(B3dStack.size()-1); } } B3dStack.clear(); BaseVertices.clear(); AnimatedVertices_VertexID.clear(); AnimatedVertices_BufferID.clear(); Materials.clear(); Textures.clear(); return true; } bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *inJoint) { CSkinnedMesh::SJoint *joint = AnimatedMesh->addJoint(inJoint); readString(joint->Name); #ifdef _B3D_READER_DEBUG core::stringc logStr; for ( u32 i=1; i < B3dStack.size(); ++i ) logStr += "-"; logStr += "read ChunkNODE"; os::Printer::log(logStr.c_str(), joint->Name.c_str()); #endif f32 position[3], scale[3], rotation[4]; readFloats(position, 3); readFloats(scale, 3); readFloats(rotation, 4); joint->Animatedposition = core::vector3df(position[0],position[1],position[2]) ; joint->Animatedscale = core::vector3df(scale[0],scale[1],scale[2]); joint->Animatedrotation = core::quaternion(rotation[1], rotation[2], rotation[3], rotation[0]); //Build LocalMatrix: core::matrix4 positionMatrix; positionMatrix.setTranslation( joint->Animatedposition ); core::matrix4 scaleMatrix; scaleMatrix.setScale( joint->Animatedscale ); core::matrix4 rotationMatrix; joint->Animatedrotation.getMatrix_transposed(rotationMatrix); joint->LocalMatrix = positionMatrix * rotationMatrix * scaleMatrix; if (inJoint) joint->GlobalMatrix = inJoint->GlobalMatrix * joint->LocalMatrix; else joint->GlobalMatrix = joint->LocalMatrix; while(B3dStack.getLast().startposition + B3dStack.getLast().length > B3DFile->getPos()) // this chunk repeats { SB3dChunkHeader header; B3DFile->read(&header, sizeof(header)); #ifdef __BIG_ENDIAN__ header.size = os::Byteswap::byteswap(header.size); #endif B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8)); if ( strncmp( B3dStack.getLast().name, "NODE", 4 ) == 0 ) { if (!readChunkNODE(joint)) return false; } else if ( strncmp( B3dStack.getLast().name, "MESH", 4 ) == 0 ) { VerticesStart=BaseVertices.size(); if (!readChunkMESH(joint)) return false; } else if ( strncmp( B3dStack.getLast().name, "BONE", 4 ) == 0 ) { if (!readChunkBONE(joint)) return false; } else if ( strncmp( B3dStack.getLast().name, "KEYS", 4 ) == 0 ) { if(!readChunkKEYS(joint)) return false; } else if ( strncmp( B3dStack.getLast().name, "ANIM", 4 ) == 0 ) { if (!readChunkANIM()) return false; } else { os::Printer::log("Unknown chunk found in node chunk - skipping"); B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length); B3dStack.erase(B3dStack.size()-1); } } B3dStack.erase(B3dStack.size()-1); return true; } bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *inJoint) { #ifdef _B3D_READER_DEBUG core::stringc logStr; for ( u32 i=1; i < B3dStack.size(); ++i ) logStr += "-"; logStr += "read ChunkMESH"; os::Printer::log(logStr.c_str()); #endif s32 brushID; B3DFile->read(&brushID, sizeof(brushID)); #ifdef __BIG_ENDIAN__ brushID = os::Byteswap::byteswap(brushID); #endif NormalsInFile=false; HasVertexColors=false; while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats { SB3dChunkHeader header; B3DFile->read(&header, sizeof(header)); #ifdef __BIG_ENDIAN__ header.size = os::Byteswap::byteswap(header.size); #endif B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8)); if ( strncmp( B3dStack.getLast().name, "VRTS", 4 ) == 0 ) { if (!readChunkVRTS(inJoint)) return false; } else if ( strncmp( B3dStack.getLast().name, "TRIS", 4 ) == 0 ) { scene::SSkinMeshBuffer *meshBuffer = AnimatedMesh->addMeshBuffer(); if (brushID!=-1) { loadTextures(Materials[brushID]); meshBuffer->Material=Materials[brushID].Material; } if(readChunkTRIS(meshBuffer,AnimatedMesh->getMeshBuffers().size()-1, VerticesStart)==false) return false; if (!NormalsInFile) { s32 i; for ( i=0; i<(s32)meshBuffer->Indices.size(); i+=3) { core::plane3df p(meshBuffer->getVertex(meshBuffer->Indices[i+0])->Pos, meshBuffer->getVertex(meshBuffer->Indices[i+1])->Pos, meshBuffer->getVertex(meshBuffer->Indices[i+2])->Pos); meshBuffer->getVertex(meshBuffer->Indices[i+0])->Normal += p.Normal; meshBuffer->getVertex(meshBuffer->Indices[i+1])->Normal += p.Normal; meshBuffer->getVertex(meshBuffer->Indices[i+2])->Normal += p.Normal; } for ( i = 0; i<(s32)meshBuffer->getVertexCount(); ++i ) { meshBuffer->getVertex(i)->Normal.normalize(); BaseVertices[VerticesStart+i].Normal=meshBuffer->getVertex(i)->Normal; } } } else { os::Printer::log("Unknown chunk found in mesh - skipping"); B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length); B3dStack.erase(B3dStack.size()-1); } } B3dStack.erase(B3dStack.size()-1); return true; } /* VRTS: int flags ;1=normal values present, 2=rgba values present int tex_coord_sets ;texture coords per vertex (eg: 1 for simple U/V) max=8 but we only support 3 int tex_coord_set_size ;components per set (eg: 2 for simple U/V) max=4 { float x,y,z ;always present float nx,ny,nz ;vertex normal: present if (flags&1) float red,green,blue,alpha ;vertex color: present if (flags&2) float tex_coords[tex_coord_sets][tex_coord_set_size] ;tex coords } */ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *inJoint) { #ifdef _B3D_READER_DEBUG core::stringc logStr; for ( u32 i=1; i < B3dStack.size(); ++i ) logStr += "-"; logStr += "ChunkVRTS"; os::Printer::log(logStr.c_str()); #endif const s32 max_tex_coords = 3; s32 flags, tex_coord_sets, tex_coord_set_size; B3DFile->read(&flags, sizeof(flags)); B3DFile->read(&tex_coord_sets, sizeof(tex_coord_sets)); B3DFile->read(&tex_coord_set_size, sizeof(tex_coord_set_size)); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); tex_coord_sets = os::Byteswap::byteswap(tex_coord_sets); tex_coord_set_size = os::Byteswap::byteswap(tex_coord_set_size); #endif if (tex_coord_sets >= max_tex_coords || tex_coord_set_size >= 4) // Something is wrong { os::Printer::log("tex_coord_sets or tex_coord_set_size too big", B3DFile->getFileName(), ELL_ERROR); return false; } //------ Allocate Memory, for speed -----------// s32 numberOfReads = 3; if (flags & 1) { NormalsInFile = true; numberOfReads += 3; } if (flags & 2) { numberOfReads += 4; HasVertexColors=true; } numberOfReads += tex_coord_sets*tex_coord_set_size; const s32 memoryNeeded = (B3dStack.getLast().length / sizeof(f32)) / numberOfReads; BaseVertices.reallocate(memoryNeeded + BaseVertices.size() + 1); AnimatedVertices_VertexID.reallocate(memoryNeeded + AnimatedVertices_VertexID.size() + 1); //--------------------------------------------// while( (B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats { f32 position[3]; f32 normal[3]={0.f, 0.f, 0.f}; f32 color[4]={1.0f, 1.0f, 1.0f, 1.0f}; f32 tex_coords[max_tex_coords][4]; readFloats(position, 3); if (flags & 1) readFloats(normal, 3); if (flags & 2) readFloats(color, 4); for (s32 i=0; i= 1 && tex_coord_set_size >= 2) { tu=tex_coords[0][0]; tv=tex_coords[0][1]; } f32 tu2=0.0f, tv2=0.0f; if (tex_coord_sets>1 && tex_coord_set_size>1) { tu2=tex_coords[1][0]; tv2=tex_coords[1][1]; } // Create Vertex... video::S3DVertex2TCoords Vertex(position[0], position[1], position[2], normal[0], normal[1], normal[2], video::SColorf(color[0], color[1], color[2], color[3]).toSColor(), tu, tv, tu2, tv2); // Transform the Vertex position by nested node... inJoint->GlobalMatrix.transformVect(Vertex.Pos); inJoint->GlobalMatrix.rotateVect(Vertex.Normal); //Add it... BaseVertices.push_back(Vertex); AnimatedVertices_VertexID.push_back(-1); AnimatedVertices_BufferID.push_back(-1); } B3dStack.erase(B3dStack.size()-1); return true; } bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *meshBuffer, u32 meshBufferID, s32 vertices_Start) { #ifdef _B3D_READER_DEBUG core::stringc logStr; for ( u32 i=1; i < B3dStack.size(); ++i ) logStr += "-"; logStr += "ChunkTRIS"; os::Printer::log(logStr.c_str()); #endif bool showVertexWarning=false; s32 triangle_brush_id; // Note: Irrlicht can't have different brushes for each triangle (using a workaround) B3DFile->read(&triangle_brush_id, sizeof(triangle_brush_id)); #ifdef __BIG_ENDIAN__ triangle_brush_id = os::Byteswap::byteswap(triangle_brush_id); #endif SB3dMaterial *B3dMaterial; if (triangle_brush_id != -1) { loadTextures(Materials[triangle_brush_id]); B3dMaterial = &Materials[triangle_brush_id]; meshBuffer->Material = B3dMaterial->Material; } else B3dMaterial = 0; const s32 memoryNeeded = B3dStack.getLast().length / sizeof(s32); meshBuffer->Indices.reallocate(memoryNeeded + meshBuffer->Indices.size() + 1); while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats { s32 vertex_id[3]; B3DFile->read(vertex_id, 3*sizeof(s32)); #ifdef __BIG_ENDIAN__ vertex_id[0] = os::Byteswap::byteswap(vertex_id[0]); vertex_id[1] = os::Byteswap::byteswap(vertex_id[1]); vertex_id[2] = os::Byteswap::byteswap(vertex_id[2]); #endif //Make Ids global: vertex_id[0] += vertices_Start; vertex_id[1] += vertices_Start; vertex_id[2] += vertices_Start; for(s32 i=0; i<3; ++i) { if ((u32)vertex_id[i] >= AnimatedVertices_VertexID.size()) { os::Printer::log("Illegal vertex index found", B3DFile->getFileName(), ELL_ERROR); return false; } if (AnimatedVertices_VertexID[ vertex_id[i] ] != -1) { if ( AnimatedVertices_BufferID[ vertex_id[i] ] != (s32)meshBufferID ) //If this vertex is linked in a different meshbuffer { AnimatedVertices_VertexID[ vertex_id[i] ] = -1; AnimatedVertices_BufferID[ vertex_id[i] ] = -1; showVertexWarning=true; } } if (AnimatedVertices_VertexID[ vertex_id[i] ] == -1) //If this vertex is not in the meshbuffer { //Check for lightmapping: if (BaseVertices[ vertex_id[i] ].TCoords2 != core::vector2df(0.f,0.f)) meshBuffer->convertTo2TCoords(); //Will only affect the meshbuffer the first time this is called //Add the vertex to the meshbuffer: if (meshBuffer->VertexType == video::EVT_STANDARD) meshBuffer->Vertices_Standard.push_back( BaseVertices[ vertex_id[i] ] ); else meshBuffer->Vertices_2TCoords.push_back(BaseVertices[ vertex_id[i] ] ); //create vertex id to meshbuffer index link: AnimatedVertices_VertexID[ vertex_id[i] ] = meshBuffer->getVertexCount()-1; AnimatedVertices_BufferID[ vertex_id[i] ] = meshBufferID; if (B3dMaterial) { // Apply Material/Color/etc... video::S3DVertex *Vertex=meshBuffer->getVertex(meshBuffer->getVertexCount()-1); if (!HasVertexColors) Vertex->Color=B3dMaterial->Material.DiffuseColor; else if (Vertex->Color.getAlpha() == 255) Vertex->Color.setAlpha( (s32)(B3dMaterial->alpha * 255.0f) ); // Use texture's scale if (B3dMaterial->Textures[0]) { Vertex->TCoords.X *= B3dMaterial->Textures[0]->Xscale; Vertex->TCoords.Y *= B3dMaterial->Textures[0]->Yscale; } /* if (B3dMaterial->Textures[1]) { Vertex->TCoords2.X *=B3dMaterial->Textures[1]->Xscale; Vertex->TCoords2.Y *=B3dMaterial->Textures[1]->Yscale; } */ } } } meshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[0] ] ); meshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[1] ] ); meshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[2] ] ); } B3dStack.erase(B3dStack.size()-1); if (showVertexWarning) os::Printer::log("B3dMeshLoader: Warning, different meshbuffers linking to the same vertex, this will cause problems with animated meshes"); return true; } bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *inJoint) { #ifdef _B3D_READER_DEBUG core::stringc logStr; for ( u32 i=1; i < B3dStack.size(); ++i ) logStr += "-"; logStr += "read ChunkBONE"; os::Printer::log(logStr.c_str()); #endif if (B3dStack.getLast().length > 8) { while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats { u32 globalVertexID; f32 strength; B3DFile->read(&globalVertexID, sizeof(globalVertexID)); B3DFile->read(&strength, sizeof(strength)); #ifdef __BIG_ENDIAN__ globalVertexID = os::Byteswap::byteswap(globalVertexID); strength = os::Byteswap::byteswap(strength); #endif globalVertexID += VerticesStart; if (AnimatedVertices_VertexID[globalVertexID]==-1) { os::Printer::log("B3dMeshLoader: Weight has bad vertex id (no link to meshbuffer index found)"); } else if (strength >0) { CSkinnedMesh::SWeight *weight=AnimatedMesh->addWeight(inJoint); weight->strength=strength; //Find the meshbuffer and Vertex index from the Global Vertex ID: weight->vertex_id = AnimatedVertices_VertexID[globalVertexID]; weight->buffer_id = AnimatedVertices_BufferID[globalVertexID]; } } } B3dStack.erase(B3dStack.size()-1); return true; } bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *inJoint) { #ifdef _B3D_READER_DEBUG // Only print first, that's just too much output otherwise if ( !inJoint || (inJoint->PositionKeys.empty() && inJoint->ScaleKeys.empty() && inJoint->RotationKeys.empty()) ) { core::stringc logStr; for ( u32 i=1; i < B3dStack.size(); ++i ) logStr += "-"; logStr += "read ChunkKEYS"; os::Printer::log(logStr.c_str()); } #endif s32 flags; B3DFile->read(&flags, sizeof(flags)); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif CSkinnedMesh::SPositionKey *oldPosKey=0; core::vector3df oldPos[2]; CSkinnedMesh::SScaleKey *oldScaleKey=0; core::vector3df oldScale[2]; CSkinnedMesh::SRotationKey *oldRotKey=0; core::quaternion oldRot[2]; bool isFirst[3]={true,true,true}; while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats { s32 frame; B3DFile->read(&frame, sizeof(frame)); #ifdef __BIG_ENDIAN__ frame = os::Byteswap::byteswap(frame); #endif // Add key frames, frames in Irrlicht are zero-based f32 data[4]; if (flags & 1) { readFloats(data, 3); if ((oldPosKey!=0) && (oldPos[0]==oldPos[1])) { const core::vector3df pos(data[0], data[1], data[2]); if (oldPos[1]==pos) oldPosKey->frame = (f32)frame-1; else { oldPos[0]=oldPos[1]; oldPosKey=AnimatedMesh->addPositionKey(inJoint); oldPosKey->frame = (f32)frame-1; oldPos[1].set(oldPosKey->position.set(pos)); } } else if (oldPosKey==0 && isFirst[0]) { oldPosKey=AnimatedMesh->addPositionKey(inJoint); oldPosKey->frame = (f32)frame-1; oldPos[0].set(oldPosKey->position.set(data[0], data[1], data[2])); oldPosKey=0; isFirst[0]=false; } else { if (oldPosKey!=0) oldPos[0]=oldPos[1]; oldPosKey=AnimatedMesh->addPositionKey(inJoint); oldPosKey->frame = (f32)frame-1; oldPos[1].set(oldPosKey->position.set(data[0], data[1], data[2])); } } if (flags & 2) { readFloats(data, 3); if ((oldScaleKey!=0) && (oldScale[0]==oldScale[1])) { const core::vector3df scale(data[0], data[1], data[2]); if (oldScale[1]==scale) oldScaleKey->frame = (f32)frame-1; else { oldScale[0]=oldScale[1]; oldScaleKey=AnimatedMesh->addScaleKey(inJoint); oldScaleKey->frame = (f32)frame-1; oldScale[1].set(oldScaleKey->scale.set(scale)); } } else if (oldScaleKey==0 && isFirst[1]) { oldScaleKey=AnimatedMesh->addScaleKey(inJoint); oldScaleKey->frame = (f32)frame-1; oldScale[0].set(oldScaleKey->scale.set(data[0], data[1], data[2])); oldScaleKey=0; isFirst[1]=false; } else { if (oldScaleKey!=0) oldScale[0]=oldScale[1]; oldScaleKey=AnimatedMesh->addScaleKey(inJoint); oldScaleKey->frame = (f32)frame-1; oldScale[1].set(oldScaleKey->scale.set(data[0], data[1], data[2])); } } if (flags & 4) { readFloats(data, 4); if ((oldRotKey!=0) && (oldRot[0]==oldRot[1])) { // meant to be in this order since b3d stores W first const core::quaternion rot(data[1], data[2], data[3], data[0]); if (oldRot[1]==rot) oldRotKey->frame = (f32)frame-1; else { oldRot[0]=oldRot[1]; oldRotKey=AnimatedMesh->addRotationKey(inJoint); oldRotKey->frame = (f32)frame-1; oldRot[1].set(oldRotKey->rotation.set(data[1], data[2], data[3], data[0])); oldRot[1].normalize(); } } else if (oldRotKey==0 && isFirst[2]) { oldRotKey=AnimatedMesh->addRotationKey(inJoint); oldRotKey->frame = (f32)frame-1; // meant to be in this order since b3d stores W first oldRot[0].set(oldRotKey->rotation.set(data[1], data[2], data[3], data[0])); oldRot[0].normalize(); oldRotKey=0; isFirst[2]=false; } else { if (oldRotKey!=0) oldRot[0]=oldRot[1]; oldRotKey=AnimatedMesh->addRotationKey(inJoint); oldRotKey->frame = (f32)frame-1; // meant to be in this order since b3d stores W first oldRot[1].set(oldRotKey->rotation.set(data[1], data[2], data[3], data[0])); oldRot[1].normalize(); } } } B3dStack.erase(B3dStack.size()-1); return true; } bool CB3DMeshFileLoader::readChunkANIM() { #ifdef _B3D_READER_DEBUG core::stringc logStr; for ( u32 i=1; i < B3dStack.size(); ++i ) logStr += "-"; logStr += "read ChunkANIM"; os::Printer::log(logStr.c_str()); #endif s32 animFlags; //not stored\used s32 animFrames;//not stored\used f32 animFPS; //not stored\used B3DFile->read(&animFlags, sizeof(s32)); B3DFile->read(&animFrames, sizeof(s32)); readFloats(&animFPS, 1); if (animFPS>0.f) AnimatedMesh->setAnimationSpeed(animFPS); os::Printer::log("FPS", io::path((double)animFPS), ELL_DEBUG); #ifdef __BIG_ENDIAN__ animFlags = os::Byteswap::byteswap(animFlags); animFrames = os::Byteswap::byteswap(animFrames); #endif B3dStack.erase(B3dStack.size()-1); return true; } bool CB3DMeshFileLoader::readChunkTEXS() { #ifdef _B3D_READER_DEBUG core::stringc logStr; for ( u32 i=1; i < B3dStack.size(); ++i ) logStr += "-"; logStr += "read ChunkTEXS"; os::Printer::log(logStr.c_str()); #endif while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats { Textures.push_back(SB3dTexture()); SB3dTexture& B3dTexture = Textures.getLast(); readString(B3dTexture.TextureName); B3dTexture.TextureName.replace('\\','/'); #ifdef _B3D_READER_DEBUG os::Printer::log("read Texture", B3dTexture.TextureName.c_str()); #endif B3DFile->read(&B3dTexture.Flags, sizeof(s32)); B3DFile->read(&B3dTexture.Blend, sizeof(s32)); #ifdef __BIG_ENDIAN__ B3dTexture.Flags = os::Byteswap::byteswap(B3dTexture.Flags); B3dTexture.Blend = os::Byteswap::byteswap(B3dTexture.Blend); #endif #ifdef _B3D_READER_DEBUG os::Printer::log("Flags", core::stringc(B3dTexture.Flags).c_str()); os::Printer::log("Blend", core::stringc(B3dTexture.Blend).c_str()); #endif readFloats(&B3dTexture.Xpos, 1); readFloats(&B3dTexture.Ypos, 1); readFloats(&B3dTexture.Xscale, 1); readFloats(&B3dTexture.Yscale, 1); readFloats(&B3dTexture.Angle, 1); } B3dStack.erase(B3dStack.size()-1); return true; } bool CB3DMeshFileLoader::readChunkBRUS() { #ifdef _B3D_READER_DEBUG core::stringc logStr; for ( u32 i=1; i < B3dStack.size(); ++i ) logStr += "-"; logStr += "read ChunkBRUS"; os::Printer::log(logStr.c_str()); #endif u32 n_texs; B3DFile->read(&n_texs, sizeof(u32)); #ifdef __BIG_ENDIAN__ n_texs = os::Byteswap::byteswap(n_texs); #endif // number of texture ids read for Irrlicht const u32 num_textures = core::min_(n_texs, video::MATERIAL_MAX_TEXTURES); // number of bytes to skip (for ignored texture ids) const u32 n_texs_offset = (num_textures B3DFile->getPos()) //this chunk repeats { // This is what blitz basic calls a brush, like a Irrlicht Material core::stringc name; readString(name); #ifdef _B3D_READER_DEBUG os::Printer::log("read Material", name); #endif Materials.push_back(SB3dMaterial()); SB3dMaterial& B3dMaterial=Materials.getLast(); readFloats(&B3dMaterial.red, 1); readFloats(&B3dMaterial.green, 1); readFloats(&B3dMaterial.blue, 1); readFloats(&B3dMaterial.alpha, 1); readFloats(&B3dMaterial.shininess, 1); B3DFile->read(&B3dMaterial.blend, sizeof(B3dMaterial.blend)); B3DFile->read(&B3dMaterial.fx, sizeof(B3dMaterial.fx)); #ifdef __BIG_ENDIAN__ B3dMaterial.blend = os::Byteswap::byteswap(B3dMaterial.blend); B3dMaterial.fx = os::Byteswap::byteswap(B3dMaterial.fx); #endif #ifdef _B3D_READER_DEBUG os::Printer::log("Blend", core::stringc(B3dMaterial.blend).c_str()); os::Printer::log("FX", core::stringc(B3dMaterial.fx).c_str()); #endif u32 i; for (i=0; iread(&texture_id, sizeof(s32)); #ifdef __BIG_ENDIAN__ texture_id = os::Byteswap::byteswap(texture_id); #endif //--- Get pointers to the texture, based on the IDs --- if ((u32)texture_id < Textures.size()) { B3dMaterial.Textures[i]=&Textures[texture_id]; #ifdef _B3D_READER_DEBUG os::Printer::log("Layer", core::stringc(i).c_str()); os::Printer::log("using texture", Textures[texture_id].TextureName.c_str()); #endif } else B3dMaterial.Textures[i]=0; } // skip other texture ids for (i=0; iread(&texture_id, sizeof(s32)); #ifdef __BIG_ENDIAN__ texture_id = os::Byteswap::byteswap(texture_id); #endif if (ShowWarning && (texture_id != -1) && (n_texs>video::MATERIAL_MAX_TEXTURES)) { os::Printer::log("Too many textures used in one material", B3DFile->getFileName(), ELL_WARNING); ShowWarning = false; } } //Fixes problems when the lightmap is on the first texture: if (B3dMaterial.Textures[0] != 0) { if (B3dMaterial.Textures[0]->Flags & 65536) // 65536 = secondary UV { SB3dTexture *TmpTexture; TmpTexture = B3dMaterial.Textures[1]; B3dMaterial.Textures[1] = B3dMaterial.Textures[0]; B3dMaterial.Textures[0] = TmpTexture; } } //If a preceeding texture slot is empty move the others down: for (i=num_textures; i>0; --i) { for (u32 j=i-1; jBlend == 5) //(Multiply 2) B3dMaterial.Material.MaterialType = video::EMT_LIGHTMAP_M2; else B3dMaterial.Material.MaterialType = video::EMT_LIGHTMAP; B3dMaterial.Material.Lighting = false; } else { B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; B3dMaterial.Material.ZWriteEnable = false; } } else if (B3dMaterial.Textures[0]) //One texture: { // Flags & 0x1 is usual SOLID, 0x8 is mipmap (handled before) if (B3dMaterial.Textures[0]->Flags & 0x2) //(Alpha mapped) { B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; B3dMaterial.Material.ZWriteEnable = false; } else if (B3dMaterial.Textures[0]->Flags & 0x4) //(Masked) B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; // TODO: create color key texture else if (B3dMaterial.Textures[0]->Flags & 0x40) B3dMaterial.Material.MaterialType = video::EMT_SPHERE_MAP; else if (B3dMaterial.Textures[0]->Flags & 0x80) B3dMaterial.Material.MaterialType = video::EMT_SPHERE_MAP; // TODO: Should be cube map else if (B3dMaterial.alpha == 1.f) B3dMaterial.Material.MaterialType = video::EMT_SOLID; else { B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; B3dMaterial.Material.ZWriteEnable = false; } } else //No texture: { if (B3dMaterial.alpha == 1.f) B3dMaterial.Material.MaterialType = video::EMT_SOLID; else { B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; B3dMaterial.Material.ZWriteEnable = false; } } B3dMaterial.Material.DiffuseColor = video::SColorf(B3dMaterial.red, B3dMaterial.green, B3dMaterial.blue, B3dMaterial.alpha).toSColor(); B3dMaterial.Material.ColorMaterial=video::ECM_NONE; //------ Material fx ------ if (B3dMaterial.fx & 1) //full-bright { B3dMaterial.Material.AmbientColor = video::SColor(255, 255, 255, 255); B3dMaterial.Material.Lighting = false; } else B3dMaterial.Material.AmbientColor = B3dMaterial.Material.DiffuseColor; if (B3dMaterial.fx & 2) //use vertex colors instead of brush color B3dMaterial.Material.ColorMaterial=video::ECM_DIFFUSE_AND_AMBIENT; if (B3dMaterial.fx & 4) //flatshaded B3dMaterial.Material.GouraudShading = false; if (B3dMaterial.fx & 16) //disable backface culling B3dMaterial.Material.BackfaceCulling = false; if (B3dMaterial.fx & 32) //force vertex alpha-blending { B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; B3dMaterial.Material.ZWriteEnable = false; } B3dMaterial.Material.Shininess = B3dMaterial.shininess; } B3dStack.erase(B3dStack.size()-1); return true; } void CB3DMeshFileLoader::loadTextures(SB3dMaterial& material) const { const bool previous32BitTextureFlag = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_ALWAYS_32_BIT); SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); // read texture from disk // note that mipmaps might be disabled by Flags & 0x8 const bool doMipMaps = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); for (u32 i=0; iTextureName.size() && !material.Material.getTexture(i)) { if (!SceneManager->getParameters()->getAttributeAsBool(B3D_LOADER_IGNORE_MIPMAP_FLAG)) SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, (B3dTexture->Flags & 0x8) ? true:false); { video::ITexture* tex = 0; io::IFileSystem* fs = SceneManager->getFileSystem(); io::path texnameWithUserPath( SceneManager->getParameters()->getAttributeAsString(B3D_TEXTURE_PATH) ); if ( texnameWithUserPath.size() ) { texnameWithUserPath += '/'; texnameWithUserPath += B3dTexture->TextureName; } if (fs->existFile(texnameWithUserPath)) tex = SceneManager->getVideoDriver()->getTexture(texnameWithUserPath); else if (fs->existFile(B3dTexture->TextureName)) tex = SceneManager->getVideoDriver()->getTexture(B3dTexture->TextureName); else if (fs->existFile(fs->getFileDir(B3DFile->getFileName()) +"/"+ fs->getFileBasename(B3dTexture->TextureName))) tex = SceneManager->getVideoDriver()->getTexture(fs->getFileDir(B3DFile->getFileName()) +"/"+ fs->getFileBasename(B3dTexture->TextureName)); else tex = SceneManager->getVideoDriver()->getTexture(fs->getFileBasename(B3dTexture->TextureName)); material.Material.setTexture(i, tex); } if (material.Textures[i]->Flags & 0x10) // Clamp U material.Material.TextureLayer[i].TextureWrapU=video::ETC_CLAMP; if (material.Textures[i]->Flags & 0x20) // Clamp V material.Material.TextureLayer[i].TextureWrapV=video::ETC_CLAMP; } } SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, doMipMaps); SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, previous32BitTextureFlag); } void CB3DMeshFileLoader::readString(core::stringc& newstring) { newstring=""; while (B3DFile->getPos() <= B3DFile->getSize()) { c8 character; B3DFile->read(&character, sizeof(character)); if (character==0) return; newstring.append(character); } } void CB3DMeshFileLoader::readFloats(f32* vec, u32 count) { B3DFile->read(vec, count*sizeof(f32)); #ifdef __BIG_ENDIAN__ for (u32 n=0; n& value); //! Sets an attribute value as a wide string array. //! \param attributeName: Name for the attribute //! \param value: Value for the attribute. Set this to 0 to delete the attribute virtual void setAttribute(const c8* attributeName, const core::array& value); //! Gets an attribute as an array of wide strings. //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() //! or 0 if attribute is not set. virtual core::array getAttributeAsArray(const c8* attributeName); //! Returns attribute value as an array of wide strings by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::array getAttributeAsArray(s32 index); //! Sets an attribute as an array of wide strings virtual void setAttribute(s32 index, const core::array& value); /* Bool Attribute */ //! Adds an attribute as bool virtual void addBool(const c8* attributeName, bool value); //! Sets an attribute as boolean value virtual void setAttribute(const c8* attributeName, bool value); //! Gets an attribute as boolean value //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual bool getAttributeAsBool(const c8* attributeName); //! Gets an attribute as boolean value //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual bool getAttributeAsBool(s32 index); //! Sets an attribute as boolean value virtual void setAttribute(s32 index, bool value); /* Enumeration Attribute */ //! Adds an attribute as enum virtual void addEnum(const c8* attributeName, const c8* enumValue, const c8* const* enumerationLiterals); //! Adds an attribute as enum virtual void addEnum(const c8* attributeName, s32 enumValue, const c8* const* enumerationLiterals); //! Sets an attribute as enumeration virtual void setAttribute(const c8* attributeName, const c8* enumValue, const c8* const* enumerationLiterals); //! Gets an attribute as enumeration //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual const c8* getAttributeAsEnumeration(const c8* attributeName); //! Gets an attribute as enumeration //! \param attributeName: Name of the attribute to get. //! \param enumerationLiteralsToUse: Use these enumeration literals to get the index value instead of the set ones. //! This is useful when the attribute list maybe was read from an xml file, and only contains the enumeration string, but //! no information about its index. //! \return Returns value of the attribute previously set by setAttribute() virtual s32 getAttributeAsEnumeration(const c8* attributeName, const c8* const* enumerationLiteralsToUse); //! Gets an attribute as enumeration //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual s32 getAttributeAsEnumeration(s32 index, const c8* const* enumerationLiteralsToUse); //! Gets an attribute as enumeration //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual const c8* getAttributeAsEnumeration(s32 index); //! Gets the list of enumeration literals of an enumeration attribute //! \param attributeName: Name of the attribute to get. virtual void getAttributeEnumerationLiteralsOfEnumeration(const c8* attributeName, core::array& outLiterals); //! Gets the list of enumeration literals of an enumeration attribute //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual void getAttributeEnumerationLiteralsOfEnumeration(s32 index, core::array& outLiterals); //! Sets an attribute as enumeration virtual void setAttribute(s32 index, const c8* enumValue, const c8* const* enumerationLiterals); /* SColor Attribute */ //! Adds an attribute as color virtual void addColor(const c8* attributeName, video::SColor value); //! Sets a attribute as color virtual void setAttribute(const c8* attributeName, video::SColor color); //! Gets an attribute as color //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual video::SColor getAttributeAsColor(const c8* attributeName); //! Gets an attribute as color //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual video::SColor getAttributeAsColor(s32 index); //! Sets an attribute as color virtual void setAttribute(s32 index, video::SColor color); /* SColorf Attribute */ //! Adds an attribute as floating point color virtual void addColorf(const c8* attributeName, video::SColorf value); //! Sets a attribute as floating point color virtual void setAttribute(const c8* attributeName, video::SColorf color); //! Gets an attribute as floating point color //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual video::SColorf getAttributeAsColorf(const c8* attributeName); //! Gets an attribute as floating point color //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual video::SColorf getAttributeAsColorf(s32 index); //! Sets an attribute as floating point color virtual void setAttribute(s32 index, video::SColorf color); /* Vector3d Attribute */ //! Adds an attribute as 3d vector virtual void addVector3d(const c8* attributeName, core::vector3df value); //! Sets a attribute as 3d vector virtual void setAttribute(const c8* attributeName, core::vector3df v); //! Gets an attribute as 3d vector //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::vector3df getAttributeAsVector3d(const c8* attributeName); //! Gets an attribute as 3d vector //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::vector3df getAttributeAsVector3d(s32 index); //! Sets an attribute as vector virtual void setAttribute(s32 index, core::vector3df v); /* Vector2d Attribute */ //! Adds an attribute as 2d vector virtual void addVector2d(const c8* attributeName, core::vector2df value); //! Sets a attribute as 2d vector virtual void setAttribute(const c8* attributeName, core::vector2df v); //! Gets an attribute as 2d vector //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::vector2df getAttributeAsVector2d(const c8* attributeName); //! Gets an attribute as 3d vector //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::vector2df getAttributeAsVector2d(s32 index); //! Sets an attribute as vector virtual void setAttribute(s32 index, core::vector2df v); /* Position2d Attribute */ //! Adds an attribute as 2d position virtual void addPosition2d(const c8* attributeName, core::position2di value); //! Sets a attribute as 2d position virtual void setAttribute(const c8* attributeName, core::position2di v); //! Gets an attribute as position //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::position2di getAttributeAsPosition2d(const c8* attributeName); //! Gets an attribute as position //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::position2di getAttributeAsPosition2d(s32 index); //! Sets an attribute as 2d position virtual void setAttribute(s32 index, core::position2di v); /* Rectangle Attribute */ //! Adds an attribute as rectangle virtual void addRect(const c8* attributeName, core::rect value); //! Sets an attribute as rectangle virtual void setAttribute(const c8* attributeName, core::rect v); //! Gets an attribute as rectangle //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::rect getAttributeAsRect(const c8* attributeName); //! Gets an attribute as rectangle //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::rect getAttributeAsRect(s32 index); //! Sets an attribute as rectangle virtual void setAttribute(s32 index, core::rect v); /* Dimension2d Attribute */ //! Adds an attribute as dimension2d virtual void addDimension2d(const c8* attributeName, core::dimension2d value); //! Sets an attribute as dimension2d virtual void setAttribute(const c8* attributeName, core::dimension2d v); //! Gets an attribute as dimension2d //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::dimension2d getAttributeAsDimension2d(const c8* attributeName); //! Gets an attribute as dimension2d //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::dimension2d getAttributeAsDimension2d(s32 index); //! Sets an attribute as dimension2d virtual void setAttribute(s32 index, core::dimension2d v); /* matrix attribute */ //! Adds an attribute as matrix virtual void addMatrix(const c8* attributeName, const core::matrix4& v); //! Sets an attribute as matrix virtual void setAttribute(const c8* attributeName, const core::matrix4& v); //! Gets an attribute as a matrix4 //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::matrix4 getAttributeAsMatrix(const c8* attributeName); //! Gets an attribute as matrix //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::matrix4 getAttributeAsMatrix(s32 index); //! Sets an attribute as matrix virtual void setAttribute(s32 index, const core::matrix4& v); /* quaternion attribute */ //! Adds an attribute as quaternion virtual void addQuaternion(const c8* attributeName, core::quaternion v); //! Sets an attribute as quaternion virtual void setAttribute(const c8* attributeName, core::quaternion v); //! Gets an attribute as a quaternion //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::quaternion getAttributeAsQuaternion(const c8* attributeName); //! Gets an attribute as quaternion //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::quaternion getAttributeAsQuaternion(s32 index); //! Sets an attribute as quaternion virtual void setAttribute(s32 index, core::quaternion v); /* 3d bounding box */ //! Adds an attribute as axis aligned bounding box virtual void addBox3d(const c8* attributeName, core::aabbox3df v); //! Sets an attribute as axis aligned bounding box virtual void setAttribute(const c8* attributeName, core::aabbox3df v); //! Gets an attribute as a axis aligned bounding box //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::aabbox3df getAttributeAsBox3d(const c8* attributeName); //! Gets an attribute as axis aligned bounding box //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::aabbox3df getAttributeAsBox3d(s32 index); //! Sets an attribute as axis aligned bounding box virtual void setAttribute(s32 index, core::aabbox3df v); /* plane */ //! Adds an attribute as 3d plane virtual void addPlane3d(const c8* attributeName, core::plane3df v); //! Sets an attribute as 3d plane virtual void setAttribute(const c8* attributeName, core::plane3df v); //! Gets an attribute as a 3d plane //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::plane3df getAttributeAsPlane3d(const c8* attributeName); //! Gets an attribute as 3d plane //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::plane3df getAttributeAsPlane3d(s32 index); //! Sets an attribute as 3d plane virtual void setAttribute(s32 index, core::plane3df v); /* 3d triangle */ //! Adds an attribute as 3d triangle virtual void addTriangle3d(const c8* attributeName, core::triangle3df v); //! Sets an attribute as 3d trianle virtual void setAttribute(const c8* attributeName, core::triangle3df v); //! Gets an attribute as a 3d triangle //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::triangle3df getAttributeAsTriangle3d(const c8* attributeName); //! Gets an attribute as 3d triangle //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::triangle3df getAttributeAsTriangle3d(s32 index); //! Sets an attribute as 3d triangle virtual void setAttribute(s32 index, core::triangle3df v); /* line 2d */ //! Adds an attribute as a 2d line virtual void addLine2d(const c8* attributeName, core::line2df v); //! Sets an attribute as a 2d line virtual void setAttribute(const c8* attributeName, core::line2df v); //! Gets an attribute as a 2d line //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::line2df getAttributeAsLine2d(const c8* attributeName); //! Gets an attribute as a 2d line //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::line2df getAttributeAsLine2d(s32 index); //! Sets an attribute as a 2d line virtual void setAttribute(s32 index, core::line2df v); /* line 3d */ //! Adds an attribute as a 3d line virtual void addLine3d(const c8* attributeName, core::line3df v); //! Sets an attribute as a 3d line virtual void setAttribute(const c8* attributeName, core::line3df v); //! Gets an attribute as a 3d line //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::line3df getAttributeAsLine3d(const c8* attributeName); //! Gets an attribute as a 3d line //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::line3df getAttributeAsLine3d(s32 index); //! Sets an attribute as a 3d line virtual void setAttribute(s32 index, core::line3df v); /* Texture Attribute */ //! Adds an attribute as texture reference virtual void addTexture(const c8* attributeName, video::ITexture* texture, const io::path& filename = ""); //! Sets an attribute as texture reference virtual void setAttribute(const c8* attributeName, video::ITexture* texture, const io::path& filename = ""); //! Gets an attribute as texture reference //! \param attributeName: Name of the attribute to get. virtual video::ITexture* getAttributeAsTexture(const c8* attributeName); //! Gets an attribute as texture reference //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual video::ITexture* getAttributeAsTexture(s32 index); //! Sets an attribute as texture reference virtual void setAttribute(s32 index, video::ITexture* texture, const io::path& filename = ""); /* User Pointer Attribute */ //! Adds an attribute as user pointner virtual void addUserPointer(const c8* attributeName, void* userPointer); //! Sets an attribute as user pointer virtual void setAttribute(const c8* attributeName, void* userPointer); //! Gets an attribute as user pointer //! \param attributeName: Name of the attribute to get. virtual void* getAttributeAsUserPointer(const c8* attributeName); //! Gets an attribute as user pointer //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual void* getAttributeAsUserPointer(s32 index); //! Sets an attribute as user pointer virtual void setAttribute(s32 index, void* userPointer); protected: void readAttributeFromXML(io::IXMLReader* reader); core::array Attributes; IAttribute* getAttributeP(const c8* attributeName) const; video::IVideoDriver* Driver; }; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CAttributes.cpp0000644000000000000000000012744212574354552020104 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CAttributes.h" #include "CAttributeImpl.h" #include "ITexture.h" #include "IXMLWriter.h" #include "IVideoDriver.h" namespace irr { namespace io { CAttributes::CAttributes(video::IVideoDriver* driver) : Driver(driver) { #ifdef _DEBUG setDebugName("CAttributes"); #endif if (Driver) Driver->grab(); } CAttributes::~CAttributes() { clear(); if (Driver) Driver->drop(); } //! Removes all attributes void CAttributes::clear() { for (u32 i=0; idrop(); Attributes.clear(); } //! Sets a string attribute. //! \param attributeName: Name for the attribute //! \param value: Value for the attribute. Set this to 0 to delete the attribute void CAttributes::setAttribute(const c8* attributeName, const c8* value) { for (u32 i=0; iName == attributeName) { if (!value) { Attributes[i]->drop(); Attributes.erase(i); } else Attributes[i]->setString(value); return; } if (value) { Attributes.push_back(new CStringAttribute(attributeName, value)); } } //! Gets a string attribute. //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setStringAttribute() //! or 0 if attribute is not set. core::stringc CAttributes::getAttributeAsString(const c8* attributeName) { core::stringc str; IAttribute* att = getAttributeP(attributeName); if (att) return att->getString(); else return str; } //! Gets a string attribute. //! \param attributeName: Name of the attribute to get. //! \param target: Buffer where the string is copied to. void CAttributes::getAttributeAsString(const c8* attributeName, char* target) { IAttribute* att = getAttributeP(attributeName); if (att) { core::stringc str = att->getString(); strcpy(target,str.c_str()); } else target[0] = 0; } //! Returns string attribute value by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. core::stringc CAttributes::getAttributeAsString(s32 index) { core::stringc str; if ((u32)index < Attributes.size()) return Attributes[index]->getString(); return str; } //! Sets a string attribute. //! \param attributeName: Name for the attribute //! \param value: Value for the attribute. Set this to 0 to delete the attribute void CAttributes::setAttribute(const c8* attributeName, const wchar_t* value) { for (u32 i=0; iName == attributeName) { if (!value) { Attributes[i]->drop(); Attributes.erase(i); } else Attributes[i]->setString(value); return; } } if (value) { Attributes.push_back(new CStringAttribute(attributeName, value)); } } //! Gets a string attribute. //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setStringAttribute() //! or 0 if attribute is not set. core::stringw CAttributes::getAttributeAsStringW(const c8* attributeName) { core::stringw str; IAttribute* att = getAttributeP(attributeName); if (att) str = att->getStringW(); return str; } //! Gets a string attribute. //! \param attributeName: Name of the attribute to get. //! \param target: Buffer where the string is copied to. void CAttributes::getAttributeAsStringW(const c8* attributeName, wchar_t* target) { IAttribute* att = getAttributeP(attributeName); if (att) { core::stringw str = att->getStringW(); wcscpy(target,str.c_str()); } else target[0] = 0; } //! Returns string attribute value by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. core::stringw CAttributes::getAttributeAsStringW(s32 index) { if ((u32)index < Attributes.size()) return Attributes[index]->getStringW(); else return core::stringw(); } //! Adds an attribute as an array of wide strings void CAttributes::addArray(const c8* attributeName, const core::array& value) { Attributes.push_back(new CStringWArrayAttribute(attributeName, value)); } //! Sets an attribute value as an array of wide strings. void CAttributes::setAttribute(const c8* attributeName, const core::array& value) { IAttribute* att = getAttributeP(attributeName); if (att) att->setArray(value); else { Attributes.push_back(new CStringWArrayAttribute(attributeName, value)); } } //! Gets an attribute as an array of wide strings. core::array CAttributes::getAttributeAsArray(const c8* attributeName) { IAttribute* att = getAttributeP(attributeName); if (att) return att->getArray(); else return core::array(); } //! Returns attribute value as an array of wide strings by index. core::array CAttributes::getAttributeAsArray(s32 index) { core::array ret; if (index >= 0 && index < (s32)Attributes.size()) ret = Attributes[index]->getArray(); return ret; } //! Sets an attribute as an array of wide strings void CAttributes::setAttribute(s32 index, const core::array& value) { if (index >= 0 && index < (s32)Attributes.size() ) Attributes[index]->setArray(value); } //! Returns attribute index from name, -1 if not found s32 CAttributes::findAttribute(const c8* attributeName) const { for (u32 i=0; iName == attributeName) return i; return -1; } IAttribute* CAttributes::getAttributeP(const c8* attributeName) const { for (u32 i=0; iName == attributeName) return Attributes[i]; return 0; } //! Sets a attribute as boolean value void CAttributes::setAttribute(const c8* attributeName, bool value) { IAttribute* att = getAttributeP(attributeName); if (att) att->setBool(value); else { Attributes.push_back(new CBoolAttribute(attributeName, value)); } } //! Gets a attribute as boolean value //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() as bool //! or 0 if attribute is not set. bool CAttributes::getAttributeAsBool(const c8* attributeName) { bool ret = false; IAttribute* att = getAttributeP(attributeName); if (att) ret = att->getBool(); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! Sets a attribute as integer value void CAttributes::setAttribute(const c8* attributeName, s32 value) { IAttribute* att = getAttributeP(attributeName); if (att) att->setInt(value); else { Attributes.push_back(new CIntAttribute(attributeName, value)); } } //! Gets a attribute as integer value //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() as integer //! or 0 if attribute is not set. s32 CAttributes::getAttributeAsInt(const c8* attributeName) const { IAttribute* att = getAttributeP(attributeName); if (att) return att->getInt(); else return 0; } //! Sets a attribute as float value void CAttributes::setAttribute(const c8* attributeName, f32 value) { IAttribute* att = getAttributeP(attributeName); if (att) att->setFloat(value); else Attributes.push_back(new CFloatAttribute(attributeName, value)); } //! Gets a attribute as integer value //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() as float value //! or 0 if attribute is not set. f32 CAttributes::getAttributeAsFloat(const c8* attributeName) { IAttribute* att = getAttributeP(attributeName); if (att) return att->getFloat(); return 0.f; } //! Sets a attribute as color void CAttributes::setAttribute(const c8* attributeName, video::SColor value) { IAttribute* att = getAttributeP(attributeName); if (att) att->setColor(value); else Attributes.push_back(new CColorAttribute(attributeName, value)); } //! Gets an attribute as color //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() video::SColor CAttributes::getAttributeAsColor(const c8* attributeName) { video::SColor ret(0); IAttribute* att = getAttributeP(attributeName); if (att) ret = att->getColor(); return ret; } //! Sets a attribute as floating point color void CAttributes::setAttribute(const c8* attributeName, video::SColorf value) { IAttribute* att = getAttributeP(attributeName); if (att) att->setColor(value); else Attributes.push_back(new CColorfAttribute(attributeName, value)); } //! Gets an attribute as floating point color //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() video::SColorf CAttributes::getAttributeAsColorf(const c8* attributeName) { IAttribute* att = getAttributeP(attributeName); if (att) return att->getColorf(); else return video::SColorf(); } //! Sets a attribute as 2d position void CAttributes::setAttribute(const c8* attributeName, core::position2di value) { IAttribute* att = getAttributeP(attributeName); if (att) att->setPosition(value); else Attributes.push_back(new CPosition2DAttribute(attributeName, value)); } //! Gets an attribute as 2d position //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() core::position2di CAttributes::getAttributeAsPosition2d(const c8* attributeName) { IAttribute* att = getAttributeP(attributeName); if (att) return att->getPosition(); else return core::position2di(); } //! Sets a attribute as rectangle void CAttributes::setAttribute(const c8* attributeName, core::rect value) { IAttribute* att = getAttributeP(attributeName); if (att) att->setRect(value); else Attributes.push_back(new CRectAttribute(attributeName, value)); } //! Gets an attribute as rectangle //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() core::rect CAttributes::getAttributeAsRect(const c8* attributeName) { IAttribute* att = getAttributeP(attributeName); if (att) return att->getRect(); else return core::rect(); } //! Sets a attribute as dimension2d void CAttributes::setAttribute(const c8* attributeName, core::dimension2d value) { IAttribute* att = getAttributeP(attributeName); if (att) att->setDimension2d(value); else Attributes.push_back(new CDimension2dAttribute(attributeName, value)); } //! Gets an attribute as dimension2d //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() core::dimension2d CAttributes::getAttributeAsDimension2d(const c8* attributeName) { IAttribute* att = getAttributeP(attributeName); if (att) return att->getDimension2d(); else return core::dimension2d(); } //! Sets a attribute as vector void CAttributes::setAttribute(const c8* attributeName, core::vector3df value) { IAttribute* att = getAttributeP(attributeName); if (att) att->setVector(value); else Attributes.push_back(new CVector3DAttribute(attributeName, value)); } //! Sets a attribute as vector void CAttributes::setAttribute(const c8* attributeName, core::vector2df value) { IAttribute* att = getAttributeP(attributeName); if (att) att->setVector2d(value); else Attributes.push_back(new CVector2DAttribute(attributeName, value)); } //! Gets an attribute as vector //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() core::vector3df CAttributes::getAttributeAsVector3d(const c8* attributeName) { IAttribute* att = getAttributeP(attributeName); if (att) return att->getVector(); else return core::vector3df(); } //! Gets an attribute as vector core::vector2df CAttributes::getAttributeAsVector2d(const c8* attributeName) { IAttribute* att = getAttributeP(attributeName); if (att) return att->getVector2d(); else return core::vector2df(); } //! Sets an attribute as binary data void CAttributes::setAttribute(const c8* attributeName, void* data, s32 dataSizeInBytes ) { IAttribute* att = getAttributeP(attributeName); if (att) att->setBinary(data, dataSizeInBytes); else Attributes.push_back(new CBinaryAttribute(attributeName, data, dataSizeInBytes)); } //! Gets an attribute as binary data //! \param attributeName: Name of the attribute to get. void CAttributes::getAttributeAsBinaryData(const c8* attributeName, void* outData, s32 maxSizeInBytes) { IAttribute* att = getAttributeP(attributeName); if (att) att->getBinary(outData, maxSizeInBytes); } //! Sets an attribute as enumeration void CAttributes::setAttribute(const c8* attributeName, const char* enumValue, const char* const* enumerationLiterals) { IAttribute* att = getAttributeP(attributeName); if (att) att->setEnum(enumValue, enumerationLiterals); else Attributes.push_back(new CEnumAttribute(attributeName, enumValue, enumerationLiterals)); } //! Gets an attribute as enumeration //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() const char* CAttributes::getAttributeAsEnumeration(const c8* attributeName) { IAttribute* att = getAttributeP(attributeName); if (att) return att->getEnum(); else return 0; } //! Gets an attribute as enumeration s32 CAttributes::getAttributeAsEnumeration(const c8* attributeName, const char* const* enumerationLiteralsToUse) { IAttribute* att = getAttributeP(attributeName); if (enumerationLiteralsToUse && att) { const char* value = att->getEnum(); if (value) { for (s32 i=0; enumerationLiteralsToUse[i]; ++i) if (!strcmp(value, enumerationLiteralsToUse[i])) return i; } } return -1; } //! Gets the list of enumeration literals of an enumeration attribute //! \param attributeName: Name of the attribute to get. void CAttributes::getAttributeEnumerationLiteralsOfEnumeration(const c8* attributeName, core::array& outLiterals) { IAttribute* att = getAttributeP(attributeName); if (att && att->getType() == EAT_ENUM) outLiterals = ((CEnumAttribute*)att)->EnumLiterals; } //! Sets an attribute as texture reference void CAttributes::setAttribute(const c8* attributeName, video::ITexture* value, const io::path& filename) { IAttribute* att = getAttributeP(attributeName); if (att) att->setTexture(value, filename); else Attributes.push_back(new CTextureAttribute(attributeName, value, Driver, filename)); } //! Gets an attribute as texture reference //! \param attributeName: Name of the attribute to get. video::ITexture* CAttributes::getAttributeAsTexture(const c8* attributeName) { IAttribute* att = getAttributeP(attributeName); if (att) return att->getTexture(); else return 0; } //! Gets an attribute as texture reference //! \param index: Index value, must be between 0 and getAttributeCount()-1. video::ITexture* CAttributes::getAttributeAsTexture(s32 index) { if ((u32)index < Attributes.size()) return Attributes[index]->getTexture(); else return 0; } //! Returns amount of string attributes set in this scene manager. u32 CAttributes::getAttributeCount() const { return Attributes.size(); } //! Returns string attribute name by index. //! \param index: Index value, must be between 0 and getStringAttributeCount()-1. const c8* CAttributes::getAttributeName(s32 index) { if ((u32)index >= Attributes.size()) return 0; return Attributes[index]->Name.c_str(); } //! Returns the type of an attribute E_ATTRIBUTE_TYPE CAttributes::getAttributeType(const c8* attributeName) { E_ATTRIBUTE_TYPE ret = EAT_UNKNOWN; IAttribute* att = getAttributeP(attributeName); if (att) ret = att->getType(); return ret; } //! Returns attribute type by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. E_ATTRIBUTE_TYPE CAttributes::getAttributeType(s32 index) { if ((u32)index >= Attributes.size()) return EAT_UNKNOWN; return Attributes[index]->getType(); } //! Returns the type of an attribute const wchar_t* CAttributes::getAttributeTypeString(const c8* attributeName) { IAttribute* att = getAttributeP(attributeName); if (att) return att->getTypeString(); else return L"unknown"; } //! Returns attribute type string by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. const wchar_t* CAttributes::getAttributeTypeString(s32 index) { if ((u32)index >= Attributes.size()) return L"unknown"; return Attributes[index]->getTypeString(); } //! Gets an attribute as boolean value //! \param index: Index value, must be between 0 and getAttributeCount()-1. bool CAttributes::getAttributeAsBool(s32 index) { bool ret = false; if ((u32)index < Attributes.size()) ret = Attributes[index]->getBool(); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return ret; } //! Gets an attribute as integer value //! \param index: Index value, must be between 0 and getAttributeCount()-1. s32 CAttributes::getAttributeAsInt(s32 index) const { if ((u32)index < Attributes.size()) return Attributes[index]->getInt(); else return 0; } //! Gets an attribute as float value //! \param index: Index value, must be between 0 and getAttributeCount()-1. f32 CAttributes::getAttributeAsFloat(s32 index) { if ((u32)index < Attributes.size()) return Attributes[index]->getFloat(); else return 0.f; } //! Gets an attribute as color //! \param index: Index value, must be between 0 and getAttributeCount()-1. video::SColor CAttributes::getAttributeAsColor(s32 index) { video::SColor ret(0); if ((u32)index < Attributes.size()) ret = Attributes[index]->getColor(); return ret; } //! Gets an attribute as floating point color //! \param index: Index value, must be between 0 and getAttributeCount()-1. video::SColorf CAttributes::getAttributeAsColorf(s32 index) { if ((u32)index < Attributes.size()) return Attributes[index]->getColorf(); return video::SColorf(); } //! Gets an attribute as 3d vector //! \param index: Index value, must be between 0 and getAttributeCount()-1. core::vector3df CAttributes::getAttributeAsVector3d(s32 index) { if ((u32)index < Attributes.size()) return Attributes[index]->getVector(); else return core::vector3df(); } //! Gets an attribute as 2d vector core::vector2df CAttributes::getAttributeAsVector2d(s32 index) { if ((u32)index < Attributes.size()) return Attributes[index]->getVector2d(); else return core::vector2df(); } //! Gets an attribute as position2d //! \param index: Index value, must be between 0 and getAttributeCount()-1. core::position2di CAttributes::getAttributeAsPosition2d(s32 index) { if ((u32)index < Attributes.size()) return Attributes[index]->getPosition(); else return core::position2di(); } //! Gets an attribute as rectangle //! \param index: Index value, must be between 0 and getAttributeCount()-1. core::rect CAttributes::getAttributeAsRect(s32 index) { if ((u32)index < Attributes.size()) return Attributes[index]->getRect(); else return core::rect(); } //! Gets an attribute as dimension2d //! \param index: Index value, must be between 0 and getAttributeCount()-1. core::dimension2d CAttributes::getAttributeAsDimension2d(s32 index) { if ((u32)index < Attributes.size()) return Attributes[index]->getDimension2d(); else return core::dimension2d(); } //! Gets an attribute as binary data ///! \param index: Index value, must be between 0 and getAttributeCount()-1. void CAttributes::getAttributeAsBinaryData(s32 index, void* outData, s32 maxSizeInBytes) { if ((u32)index < Attributes.size()) Attributes[index]->getBinary(outData, maxSizeInBytes); } //! Gets an attribute as enumeration //! \param index: Index value, must be between 0 and getAttributeCount()-1. const char* CAttributes::getAttributeAsEnumeration(s32 index) { if ((u32)index < Attributes.size()) return Attributes[index]->getEnum(); else return 0; } //! Gets an attribute as enumeration //! \param index: Index value, must be between 0 and getAttributeCount()-1. s32 CAttributes::getAttributeAsEnumeration(s32 index, const char* const* enumerationLiteralsToUse) { if ((u32)index < Attributes.size()) { IAttribute* att = Attributes[index]; if (enumerationLiteralsToUse && att) { const char* value = att->getEnum(); if (value) { for (s32 i=0; enumerationLiteralsToUse[i]; ++i) if (!strcmp(value, enumerationLiteralsToUse[i])) return i; } } } return -1; } //! Gets the list of enumeration literals of an enumeration attribute //! \param index: Index value, must be between 0 and getAttributeCount()-1. void CAttributes::getAttributeEnumerationLiteralsOfEnumeration(s32 index, core::array& outLiterals) { if ((u32)index < Attributes.size() && Attributes[index]->getType() == EAT_ENUM) outLiterals = ((CEnumAttribute*)Attributes[index])->EnumLiterals; } //! Adds an attribute as integer void CAttributes::addInt(const c8* attributeName, s32 value) { Attributes.push_back(new CIntAttribute(attributeName, value)); } //! Adds an attribute as float void CAttributes::addFloat(const c8* attributeName, f32 value) { Attributes.push_back(new CFloatAttribute(attributeName, value)); } //! Adds an attribute as string void CAttributes::addString(const c8* attributeName, const char* value) { Attributes.push_back(new CStringAttribute(attributeName, value)); } //! Adds an attribute as wchar string void CAttributes::addString(const c8* attributeName, const wchar_t* value) { Attributes.push_back(new CStringAttribute(attributeName, value)); } //! Adds an attribute as bool void CAttributes::addBool(const c8* attributeName, bool value) { Attributes.push_back(new CBoolAttribute(attributeName, value)); } //! Adds an attribute as enum void CAttributes::addEnum(const c8* attributeName, const char* enumValue, const char* const* enumerationLiterals) { Attributes.push_back(new CEnumAttribute(attributeName, enumValue, enumerationLiterals)); } //! Adds an attribute as enum void CAttributes::addEnum(const c8* attributeName, s32 enumValue, const char* const* enumerationLiterals) { addEnum(attributeName, "", enumerationLiterals); Attributes.getLast()->setInt(enumValue); } //! Adds an attribute as color void CAttributes::addColor(const c8* attributeName, video::SColor value) { Attributes.push_back(new CColorAttribute(attributeName, value)); } //! Adds an attribute as floating point color void CAttributes::addColorf(const c8* attributeName, video::SColorf value) { Attributes.push_back(new CColorfAttribute(attributeName, value)); } //! Adds an attribute as 3d vector void CAttributes::addVector3d(const c8* attributeName, core::vector3df value) { Attributes.push_back(new CVector3DAttribute(attributeName, value)); } //! Adds an attribute as 2d vector void CAttributes::addVector2d(const c8* attributeName, core::vector2df value) { Attributes.push_back(new CVector2DAttribute(attributeName, value)); } //! Adds an attribute as 2d position void CAttributes::addPosition2d(const c8* attributeName, core::position2di value) { Attributes.push_back(new CPosition2DAttribute(attributeName, value)); } //! Adds an attribute as rectangle void CAttributes::addRect(const c8* attributeName, core::rect value) { Attributes.push_back(new CRectAttribute(attributeName, value)); } //! Adds an attribute as dimension2d void CAttributes::addDimension2d(const c8* attributeName, core::dimension2d value) { Attributes.push_back(new CDimension2dAttribute(attributeName, value)); } //! Adds an attribute as binary data void CAttributes::addBinary(const c8* attributeName, void* data, s32 dataSizeInBytes) { Attributes.push_back(new CBinaryAttribute(attributeName, data, dataSizeInBytes)); } //! Adds an attribute as texture reference void CAttributes::addTexture(const c8* attributeName, video::ITexture* texture, const io::path& filename) { Attributes.push_back(new CTextureAttribute(attributeName, texture, Driver, filename)); } //! Returns if an attribute with a name exists bool CAttributes::existsAttribute(const c8* attributeName) { return getAttributeP(attributeName) != 0; } //! Sets an attribute value as string. //! \param attributeName: Name for the attribute void CAttributes::setAttribute(s32 index, const c8* value) { if ((u32)index < Attributes.size()) Attributes[index]->setString(value); } //! Sets an attribute value as string. //! \param attributeName: Name for the attribute void CAttributes::setAttribute(s32 index, const wchar_t* value) { if ((u32)index < Attributes.size()) Attributes[index]->setString(value); } //! Sets an attribute as boolean value void CAttributes::setAttribute(s32 index, bool value) { if ((u32)index < Attributes.size()) Attributes[index]->setBool(value); } //! Sets an attribute as integer value void CAttributes::setAttribute(s32 index, s32 value) { if ((u32)index < Attributes.size()) Attributes[index]->setInt(value); } //! Sets a attribute as float value void CAttributes::setAttribute(s32 index, f32 value) { if ((u32)index < Attributes.size()) Attributes[index]->setFloat(value); } //! Sets a attribute as color void CAttributes::setAttribute(s32 index, video::SColor color) { if ((u32)index < Attributes.size()) Attributes[index]->setColor(color); } //! Sets a attribute as floating point color void CAttributes::setAttribute(s32 index, video::SColorf color) { if ((u32)index < Attributes.size()) Attributes[index]->setColor(color); } //! Sets a attribute as vector void CAttributes::setAttribute(s32 index, core::vector3df v) { if ((u32)index < Attributes.size()) Attributes[index]->setVector(v); } //! Sets a attribute as vector void CAttributes::setAttribute(s32 index, core::vector2df v) { if ((u32)index < Attributes.size()) Attributes[index]->setVector2d(v); } //! Sets a attribute as position void CAttributes::setAttribute(s32 index, core::position2di v) { if ((u32)index < Attributes.size()) Attributes[index]->setPosition(v); } //! Sets a attribute as rectangle void CAttributes::setAttribute(s32 index, core::rect v) { if ((u32)index < Attributes.size()) Attributes[index]->setRect(v); } //! Sets a attribute as dimension2d void CAttributes::setAttribute(s32 index, core::dimension2d v) { if ((u32)index < Attributes.size()) Attributes[index]->setDimension2d(v); } //! Sets an attribute as binary data void CAttributes::setAttribute(s32 index, void* data, s32 dataSizeInBytes ) { if ((u32)index < Attributes.size()) Attributes[index]->setBinary(data, dataSizeInBytes); } //! Sets an attribute as enumeration void CAttributes::setAttribute(s32 index, const char* enumValue, const char* const* enumerationLiterals) { if ((u32)index < Attributes.size()) Attributes[index]->setEnum(enumValue, enumerationLiterals); } //! Sets an attribute as texture reference void CAttributes::setAttribute(s32 index, video::ITexture* texture, const io::path& filename) { if ((u32)index < Attributes.size()) Attributes[index]->setTexture(texture, filename); } //! Adds an attribute as matrix void CAttributes::addMatrix(const c8* attributeName, const core::matrix4& v) { Attributes.push_back(new CMatrixAttribute(attributeName, v)); } //! Sets an attribute as matrix void CAttributes::setAttribute(const c8* attributeName, const core::matrix4& v) { IAttribute* att = getAttributeP(attributeName); if (att) att->setMatrix(v); else Attributes.push_back(new CMatrixAttribute(attributeName, v)); } //! Gets an attribute as a matrix4 core::matrix4 CAttributes::getAttributeAsMatrix(const c8* attributeName) { IAttribute* att = getAttributeP(attributeName); if (att) return att->getMatrix(); else return core::matrix4(); } //! Gets an attribute as matrix core::matrix4 CAttributes::getAttributeAsMatrix(s32 index) { if ((u32)index < Attributes.size()) return Attributes[index]->getMatrix(); else return core::matrix4(); } //! Sets an attribute as matrix void CAttributes::setAttribute(s32 index, const core::matrix4& v) { if ((u32)index < Attributes.size()) Attributes[index]->setMatrix(v); } //! Adds an attribute as quaternion void CAttributes::addQuaternion(const c8* attributeName, core::quaternion v) { Attributes.push_back(new CQuaternionAttribute(attributeName, v)); } //! Sets an attribute as quaternion void CAttributes::setAttribute(const c8* attributeName, core::quaternion v) { IAttribute* att = getAttributeP(attributeName); if (att) att->setQuaternion(v); else { Attributes.push_back(new CQuaternionAttribute(attributeName, v)); } } //! Gets an attribute as a quaternion core::quaternion CAttributes::getAttributeAsQuaternion(const c8* attributeName) { core::quaternion ret(0,1,0, 0); IAttribute* att = getAttributeP(attributeName); if (att) ret = att->getQuaternion(); return ret; } //! Gets an attribute as quaternion core::quaternion CAttributes::getAttributeAsQuaternion(s32 index) { core::quaternion ret(0,1,0, 0); if (index >= 0 && index < (s32)Attributes.size()) ret = Attributes[index]->getQuaternion(); return ret; } //! Sets an attribute as quaternion void CAttributes::setAttribute(s32 index, core::quaternion v) { if (index >= 0 && index < (s32)Attributes.size() ) Attributes[index]->setQuaternion(v); } //! Adds an attribute as axis aligned bounding box void CAttributes::addBox3d(const c8* attributeName, core::aabbox3df v) { Attributes.push_back(new CBBoxAttribute(attributeName, v)); } //! Sets an attribute as axis aligned bounding box void CAttributes::setAttribute(const c8* attributeName, core::aabbox3df v) { IAttribute* att = getAttributeP(attributeName); if (att) att->setBBox(v); else { Attributes.push_back(new CBBoxAttribute(attributeName, v)); } } //! Gets an attribute as a axis aligned bounding box core::aabbox3df CAttributes::getAttributeAsBox3d(const c8* attributeName) { core::aabbox3df ret(0,0,0, 0,0,0); IAttribute* att = getAttributeP(attributeName); if (att) ret = att->getBBox(); return ret; } //! Gets an attribute as axis aligned bounding box core::aabbox3df CAttributes::getAttributeAsBox3d(s32 index) { core::aabbox3df ret(0,0,0, 0,0,0); if (index >= 0 && index < (s32)Attributes.size()) ret = Attributes[index]->getBBox(); return ret; } //! Sets an attribute as axis aligned bounding box void CAttributes::setAttribute(s32 index, core::aabbox3df v) { if (index >= 0 && index < (s32)Attributes.size() ) Attributes[index]->setBBox(v); } //! Adds an attribute as 3d plane void CAttributes::addPlane3d(const c8* attributeName, core::plane3df v) { Attributes.push_back(new CPlaneAttribute(attributeName, v)); } //! Sets an attribute as 3d plane void CAttributes::setAttribute(const c8* attributeName, core::plane3df v) { IAttribute* att = getAttributeP(attributeName); if (att) att->setPlane(v); else { Attributes.push_back(new CPlaneAttribute(attributeName, v)); } } //! Gets an attribute as a 3d plane core::plane3df CAttributes::getAttributeAsPlane3d(const c8* attributeName) { core::plane3df ret(0,0,0, 0,1,0); IAttribute* att = getAttributeP(attributeName); if (att) ret = att->getPlane(); return ret; } //! Gets an attribute as 3d plane core::plane3df CAttributes::getAttributeAsPlane3d(s32 index) { core::plane3df ret(0,0,0, 0,1,0); if (index >= 0 && index < (s32)Attributes.size()) ret = Attributes[index]->getPlane(); return ret; } //! Sets an attribute as 3d plane void CAttributes::setAttribute(s32 index, core::plane3df v) { if (index >= 0 && index < (s32)Attributes.size() ) Attributes[index]->setPlane(v); } //! Adds an attribute as 3d triangle void CAttributes::addTriangle3d(const c8* attributeName, core::triangle3df v) { Attributes.push_back(new CTriangleAttribute(attributeName, v)); } //! Sets an attribute as 3d triangle void CAttributes::setAttribute(const c8* attributeName, core::triangle3df v) { IAttribute* att = getAttributeP(attributeName); if (att) att->setTriangle(v); else { Attributes.push_back(new CTriangleAttribute(attributeName, v)); } } //! Gets an attribute as a 3d triangle core::triangle3df CAttributes::getAttributeAsTriangle3d(const c8* attributeName) { core::triangle3df ret; ret.pointA = ret.pointB = ret.pointC = core::vector3df(0,0,0); IAttribute* att = getAttributeP(attributeName); if (att) ret = att->getTriangle(); return ret; } //! Gets an attribute as 3d triangle core::triangle3df CAttributes::getAttributeAsTriangle3d(s32 index) { core::triangle3df ret; ret.pointA = ret.pointB = ret.pointC = core::vector3df(0,0,0); if (index >= 0 && index < (s32)Attributes.size()) ret = Attributes[index]->getTriangle(); return ret; } //! Sets an attribute as 3d triangle void CAttributes::setAttribute(s32 index, core::triangle3df v) { if (index >= 0 && index < (s32)Attributes.size() ) Attributes[index]->setTriangle(v); } //! Adds an attribute as a 2d line void CAttributes::addLine2d(const c8* attributeName, core::line2df v) { Attributes.push_back(new CLine2dAttribute(attributeName, v)); } //! Sets an attribute as a 2d line void CAttributes::setAttribute(const c8* attributeName, core::line2df v) { IAttribute* att = getAttributeP(attributeName); if (att) att->setLine2d(v); else { Attributes.push_back(new CLine2dAttribute(attributeName, v)); } } //! Gets an attribute as a 2d line core::line2df CAttributes::getAttributeAsLine2d(const c8* attributeName) { core::line2df ret(0,0, 0,0); IAttribute* att = getAttributeP(attributeName); if (att) ret = att->getLine2d(); return ret; } //! Gets an attribute as a 2d line core::line2df CAttributes::getAttributeAsLine2d(s32 index) { core::line2df ret(0,0, 0,0); if (index >= 0 && index < (s32)Attributes.size()) ret = Attributes[index]->getLine2d(); return ret; } //! Sets an attribute as a 2d line void CAttributes::setAttribute(s32 index, core::line2df v) { if (index >= 0 && index < (s32)Attributes.size() ) Attributes[index]->setLine2d(v); } //! Adds an attribute as a 3d line void CAttributes::addLine3d(const c8* attributeName, core::line3df v) { Attributes.push_back(new CLine3dAttribute(attributeName, v)); } //! Sets an attribute as a 3d line void CAttributes::setAttribute(const c8* attributeName, core::line3df v) { IAttribute* att = getAttributeP(attributeName); if (att) att->setLine3d(v); else { Attributes.push_back(new CLine3dAttribute(attributeName, v)); } } //! Gets an attribute as a 3d line core::line3df CAttributes::getAttributeAsLine3d(const c8* attributeName) { core::line3df ret(0,0,0, 0,0,0); IAttribute* att = getAttributeP(attributeName); if (att) ret = att->getLine3d(); return ret; } //! Gets an attribute as a 3d line core::line3df CAttributes::getAttributeAsLine3d(s32 index) { core::line3df ret(0,0,0, 0,0,0); if (index >= 0 && index < (s32)Attributes.size()) ret = Attributes[index]->getLine3d(); return ret; } //! Sets an attribute as a 3d line void CAttributes::setAttribute(s32 index, core::line3df v) { if (index >= 0 && index < (s32)Attributes.size() ) Attributes[index]->setLine3d(v); } //! Adds an attribute as user pointner void CAttributes::addUserPointer(const c8* attributeName, void* userPointer) { Attributes.push_back(new CUserPointerAttribute(attributeName, userPointer)); } //! Sets an attribute as user pointer void CAttributes::setAttribute(const c8* attributeName, void* userPointer) { IAttribute* att = getAttributeP(attributeName); if (att) att->setUserPointer(userPointer); else { Attributes.push_back(new CUserPointerAttribute(attributeName, userPointer)); } } //! Gets an attribute as user pointer //! \param attributeName: Name of the attribute to get. void* CAttributes::getAttributeAsUserPointer(const c8* attributeName) { void* value = 0; IAttribute* att = getAttributeP(attributeName); if (att) value = att->getUserPointer(); return value; } //! Gets an attribute as user pointer //! \param index: Index value, must be between 0 and getAttributeCount()-1. void* CAttributes::getAttributeAsUserPointer(s32 index) { void* value = 0; if (index >= 0 && index < (s32)Attributes.size()) value = Attributes[index]->getUserPointer(); return value; } //! Sets an attribute as user pointer void CAttributes::setAttribute(s32 index, void* userPointer) { if (index >= 0 && index < (s32)Attributes.size() ) Attributes[index]->setUserPointer(userPointer); } //! Reads attributes from a xml file. //! \param readCurrentElementOnly: If set to true, reading only works if current element has the name 'attributes'. //! IF set to false, the first appearing list attributes are read. bool CAttributes::read(io::IXMLReader* reader, bool readCurrentElementOnly, const wchar_t* nonDefaultElementName) { if (!reader) return false; clear(); core::stringw elementName = L"attributes"; if (nonDefaultElementName) elementName = nonDefaultElementName; if (readCurrentElementOnly) { if (elementName != reader->getNodeName()) return false; } while(reader->read()) { switch(reader->getNodeType()) { case io::EXN_ELEMENT: readAttributeFromXML(reader); break; case io::EXN_ELEMENT_END: if (elementName == reader->getNodeName()) return true; break; default: break; } } return true; } void CAttributes::readAttributeFromXML(io::IXMLReader* reader) { core::stringw element = reader->getNodeName(); core::stringc name = reader->getAttributeValue(L"name"); if (element == L"enum") { addEnum(name.c_str(), 0, 0); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"binary") { addBinary(name.c_str(), 0, 0); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"color") { addColor(name.c_str(), video::SColor()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"colorf") { addColorf(name.c_str(), video::SColorf()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"float") { addFloat(name.c_str(), 0); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"int") { addInt(name.c_str(), 0); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"bool") { addBool(name.c_str(), 0); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"string") { addString(name.c_str(), L""); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"texture") { addTexture(name.c_str(), 0); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"vector3d") { addVector3d(name.c_str(), core::vector3df()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"vector2d") { addVector2d(name.c_str(), core::vector2df()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"position") { addPosition2d(name.c_str(), core::position2di()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"rect") { addRect(name.c_str(), core::rect()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"matrix") { addMatrix(name.c_str(), core::matrix4()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"quaternion") { addQuaternion(name.c_str(), core::quaternion()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"box3d") { addBox3d(name.c_str(), core::aabbox3df()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"plane") { addPlane3d(name.c_str(), core::plane3df()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"triangle") { addTriangle3d(name.c_str(), core::triangle3df()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"line2d") { addLine2d(name.c_str(), core::line2df()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"line3d") { addLine3d(name.c_str(), core::line3df()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } else if (element == L"stringwarray") { core::array tmpArray; s32 count = reader->getAttributeValueAsInt(L"count"); s32 n=0; const core::stringw tmpName(L"value"); for (; ngetAttributeValue((tmpName+core::stringw(n)).c_str())); } addArray(name.c_str(),tmpArray); } else if (element == L"userPointer") { // It's debatable if a pointer should be set or not, but it's more likely that adding it now would wreck user-applications. // Also it probably doesn't makes sense setting this to a value when it comes from file. } else if (element == L"dimension2d") { addDimension2d(name.c_str(), core::dimension2d()); Attributes.getLast()->setString(reader->getAttributeValue(L"value")); } } //! Write these attributes into a xml file bool CAttributes::write(io::IXMLWriter* writer, bool writeXMLHeader, const wchar_t* nonDefaultElementName) { if (!writer) return false; if (writeXMLHeader) writer->writeXMLHeader(); core::stringw elementName = L"attributes"; if (nonDefaultElementName) elementName = nonDefaultElementName; writer->writeElement(elementName.c_str(), false); writer->writeLineBreak(); s32 i=0; for (; i<(s32)Attributes.size(); ++i) { if ( Attributes[i]->getType() == EAT_STRINGWARRAY ) { core::array arraynames, arrayvalues; core::array arrayinput = Attributes[i]->getArray(); // build arrays // name arraynames.push_back(core::stringw(L"name")); arrayvalues.push_back(core::stringw(Attributes[i]->Name.c_str()) ); // count arraynames.push_back(core::stringw(L"count")); arrayvalues.push_back(core::stringw((s32)arrayinput.size())); // array... u32 n=0; const core::stringw tmpName(L"value"); for (; n < arrayinput.size(); ++n) { arraynames.push_back((tmpName+core::stringw(n)).c_str()); arrayvalues.push_back(arrayinput[n]); } // write them writer->writeElement( Attributes[i]->getTypeString(), true, arraynames, arrayvalues); } else { writer->writeElement( Attributes[i]->getTypeString(), true, L"name", core::stringw(Attributes[i]->Name.c_str()).c_str(), L"value", Attributes[i]->getStringW().c_str() ); } writer->writeLineBreak(); } writer->writeClosingTag(elementName.c_str()); writer->writeLineBreak(); return true; } } // end namespace io } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CAttributeImpl.h0000644000000000000000000012141112574354552020176 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CAttributes.h" #include "fast_atof.h" #include "ITexture.h" #include "IVideoDriver.h" namespace irr { namespace io { /* basic types */ // Attribute implemented for boolean values class CBoolAttribute : public IAttribute { public: CBoolAttribute(const char* name, bool value) { Name = name; setBool(value); } virtual s32 getInt() { return BoolValue ? 1 : 0; } virtual f32 getFloat() { return BoolValue ? 1.0f : 0.0f; } virtual bool getBool() { return BoolValue; } virtual core::stringw getStringW() { return core::stringw( BoolValue ? L"true" : L"false" ); } virtual void setInt(s32 intValue) { BoolValue = (intValue != 0); } virtual void setFloat(f32 floatValue) { BoolValue = (floatValue != 0); } virtual void setBool(bool boolValue) { BoolValue = boolValue; } virtual void setString(const char* string) { BoolValue = strcmp(string, "true") == 0; } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_BOOL; } virtual const wchar_t* getTypeString() const { return L"bool"; } bool BoolValue; }; // Attribute implemented for integers class CIntAttribute : public IAttribute { public: CIntAttribute(const char* name, s32 value) { Name = name; setInt(value); } virtual s32 getInt() { return Value; } virtual f32 getFloat() { return (f32)Value; } virtual bool getBool() { return (Value != 0); } virtual core::stringw getStringW() { return core::stringw(Value); } virtual void setInt(s32 intValue) { Value = intValue; } virtual void setFloat(f32 floatValue) { Value = (s32)floatValue; }; virtual void setString(const char* text) { Value = atoi(text); } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_INT; } virtual const wchar_t* getTypeString() const { return L"int"; } s32 Value; }; // Attribute implemented for floats class CFloatAttribute : public IAttribute { public: CFloatAttribute(const char* name, f32 value) { Name = name; setFloat(value); } virtual s32 getInt() { return (s32)Value; } virtual f32 getFloat() { return Value; } virtual bool getBool() { return (Value != 0); } virtual core::stringw getStringW() { return core::stringw((double)Value); } virtual void setInt(s32 intValue) { Value = (f32)intValue; } virtual void setFloat(f32 floatValue) { Value = floatValue; } virtual void setString(const char* text) { Value = core::fast_atof(text); } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_FLOAT; } virtual const wchar_t* getTypeString() const { return L"float"; } f32 Value; }; /* Types which can be represented as a list of numbers */ // Base class for all attributes which are a list of numbers- // vectors, colors, positions, triangles, etc class CNumbersAttribute : public IAttribute { public: CNumbersAttribute(const char* name, video::SColorf value) : ValueI(), ValueF(), Count(4), IsFloat(true) { Name = name; ValueF.push_back(value.r); ValueF.push_back(value.g); ValueF.push_back(value.b); ValueF.push_back(value.a); } CNumbersAttribute(const char* name, video::SColor value) : ValueI(), ValueF(), Count(4), IsFloat(false) { Name = name; ValueI.push_back(value.getRed()); ValueI.push_back(value.getGreen()); ValueI.push_back(value.getBlue()); ValueI.push_back(value.getAlpha()); } CNumbersAttribute(const char* name, core::vector3df value) : ValueI(), ValueF(), Count(3), IsFloat(true) { Name = name; ValueF.push_back(value.X); ValueF.push_back(value.Y); ValueF.push_back(value.Z); } CNumbersAttribute(const char* name, core::rect value) : ValueI(), ValueF(), Count(4), IsFloat(false) { Name = name; ValueI.push_back(value.UpperLeftCorner.X); ValueI.push_back(value.UpperLeftCorner.Y); ValueI.push_back(value.LowerRightCorner.X); ValueI.push_back(value.LowerRightCorner.Y); } CNumbersAttribute(const char* name, core::rect value) : ValueI(), ValueF(), Count(4), IsFloat(true) { Name = name; ValueF.push_back(value.UpperLeftCorner.X); ValueF.push_back(value.UpperLeftCorner.Y); ValueF.push_back(value.LowerRightCorner.X); ValueF.push_back(value.LowerRightCorner.Y); } CNumbersAttribute(const char* name, core::matrix4 value) : ValueI(), ValueF(), Count(16), IsFloat(true) { Name = name; for (s32 r=0; r<4; ++r) for (s32 c=0; c<4; ++c) ValueF.push_back(value(r,c)); } CNumbersAttribute(const char* name, core::quaternion value) : ValueI(), ValueF(), Count(4), IsFloat(true) { Name = name; ValueF.push_back(value.X); ValueF.push_back(value.Y); ValueF.push_back(value.Z); ValueF.push_back(value.W); } CNumbersAttribute(const char* name, core::aabbox3d value) : ValueI(), ValueF(), Count(6), IsFloat(true) { Name = name; ValueF.push_back(value.MinEdge.X); ValueF.push_back(value.MinEdge.Y); ValueF.push_back(value.MinEdge.Z); ValueF.push_back(value.MaxEdge.X); ValueF.push_back(value.MaxEdge.Y); ValueF.push_back(value.MaxEdge.Z); } CNumbersAttribute(const char* name, core::plane3df value) : ValueI(), ValueF(), Count(4), IsFloat(true) { Name = name; ValueF.push_back(value.Normal.X); ValueF.push_back(value.Normal.Y); ValueF.push_back(value.Normal.Z); ValueF.push_back(value.D); } CNumbersAttribute(const char* name, core::triangle3df value) : ValueI(), ValueF(), Count(9), IsFloat(true) { Name = name; ValueF.push_back(value.pointA.X); ValueF.push_back(value.pointA.Y); ValueF.push_back(value.pointA.Z); ValueF.push_back(value.pointB.X); ValueF.push_back(value.pointB.Y); ValueF.push_back(value.pointB.Z); ValueF.push_back(value.pointC.X); ValueF.push_back(value.pointC.Y); ValueF.push_back(value.pointC.Z); } CNumbersAttribute(const char* name, core::vector2df value) : ValueI(), ValueF(), Count(2), IsFloat(true) { Name = name; ValueF.push_back(value.X); ValueF.push_back(value.Y); } CNumbersAttribute(const char* name, core::vector2di value) : ValueI(), ValueF(), Count(2), IsFloat(false) { Name = name; ValueI.push_back(value.X); ValueI.push_back(value.Y); } CNumbersAttribute(const char* name, core::line2di value) : ValueI(), ValueF(), Count(4), IsFloat(false) { Name = name; ValueI.push_back(value.start.X); ValueI.push_back(value.start.Y); ValueI.push_back(value.end.X); ValueI.push_back(value.end.Y); } CNumbersAttribute(const char* name, core::line2df value) : ValueI(), ValueF(), Count(4), IsFloat(true) { Name = name; ValueF.push_back(value.start.X); ValueF.push_back(value.start.Y); ValueF.push_back(value.end.X); ValueF.push_back(value.end.Y); } CNumbersAttribute(const char* name, core::line3df value) : ValueI(), ValueF(), Count(6), IsFloat(true) { Name = name; ValueF.push_back(value.start.X); ValueF.push_back(value.start.Y); ValueF.push_back(value.start.Z); ValueF.push_back(value.end.X); ValueF.push_back(value.end.Y); ValueF.push_back(value.end.Z); } CNumbersAttribute(const char* name, core::dimension2du value) : ValueI(), ValueF(), Count(2), IsFloat(false) { Name = name; ValueI.push_back(value.Width); ValueI.push_back(value.Height); } CNumbersAttribute(const char* name, core::dimension2df value) : ValueI(), ValueF(), Count(2), IsFloat(true) { Name = name; ValueF.push_back(value.Width); ValueF.push_back(value.Height); } // getting values virtual s32 getInt() { if (Count==0) return 0; if (IsFloat) return (s32)ValueF[0]; else return ValueI[0]; } virtual f32 getFloat() { if (Count==0) return 0.0f; if (IsFloat) return ValueF[0]; else return (f32)ValueI[0]; } virtual bool getBool() { // return true if any number is nonzero bool ret=false; for (u32 i=0; i < Count; ++i) if ( IsFloat ? (ValueF[i] != 0) : (ValueI[i] != 0) ) { ret=true; break; } return ret; } virtual core::stringc getString() { core::stringc outstr; for (u32 i=0; i 0 ? ValueF[0] : 0); p.Y = (s32)(Count > 1 ? ValueF[1] : 0); } else { p.X = Count > 0 ? ValueI[0] : 0; p.Y = Count > 1 ? ValueI[1] : 0; } return p; } virtual core::vector3df getVector() { core::vector3df v; if (IsFloat) { v.X = Count > 0 ? ValueF[0] : 0; v.Y = Count > 1 ? ValueF[1] : 0; v.Z = Count > 2 ? ValueF[2] : 0; } else { v.X = (f32)(Count > 0 ? ValueI[0] : 0); v.Y = (f32)(Count > 1 ? ValueI[1] : 0); v.Z = (f32)(Count > 2 ? ValueI[2] : 0); } return v; } virtual core::vector2df getVector2d() { core::vector2df v; if (IsFloat) { v.X = Count > 0 ? ValueF[0] : 0; v.Y = Count > 1 ? ValueF[1] : 0; } else { v.X = (f32)(Count > 0 ? ValueI[0] : 0); v.Y = (f32)(Count > 1 ? ValueI[1] : 0); } return v; } virtual video::SColorf getColorf() { video::SColorf c; if (IsFloat) { c.setColorComponentValue(0, Count > 0 ? ValueF[0] : 0); c.setColorComponentValue(1, Count > 1 ? ValueF[1] : 0); c.setColorComponentValue(2, Count > 2 ? ValueF[2] : 0); c.setColorComponentValue(3, Count > 3 ? ValueF[3] : 0); } else { c.setColorComponentValue(0, Count > 0 ? (f32)(ValueI[0]) / 255.0f : 0); c.setColorComponentValue(1, Count > 1 ? (f32)(ValueI[1]) / 255.0f : 0); c.setColorComponentValue(2, Count > 2 ? (f32)(ValueI[2]) / 255.0f : 0); c.setColorComponentValue(3, Count > 3 ? (f32)(ValueI[3]) / 255.0f : 0); } return c; } virtual video::SColor getColor() { return getColorf().toSColor(); } virtual core::rect getRect() { core::rect r; if (IsFloat) { r.UpperLeftCorner.X = (s32)(Count > 0 ? ValueF[0] : 0); r.UpperLeftCorner.Y = (s32)(Count > 1 ? ValueF[1] : 0); r.LowerRightCorner.X = (s32)(Count > 2 ? ValueF[2] : r.UpperLeftCorner.X); r.LowerRightCorner.Y = (s32)(Count > 3 ? ValueF[3] : r.UpperLeftCorner.Y); } else { r.UpperLeftCorner.X = Count > 0 ? ValueI[0] : 0; r.UpperLeftCorner.Y = Count > 1 ? ValueI[1] : 0; r.LowerRightCorner.X = Count > 2 ? ValueI[2] : r.UpperLeftCorner.X; r.LowerRightCorner.Y = Count > 3 ? ValueI[3] : r.UpperLeftCorner.Y; } return r; } virtual core::dimension2du getDimension2d() { core::dimension2d dim; if (IsFloat) { dim.Width = (u32)(Count > 0 ? ValueF[0] : 0); dim.Height = (u32)(Count > 1 ? ValueF[1] : 0); } else { dim.Width = (u32)(Count > 0 ? ValueI[0] : 0); dim.Height = (u32)(Count > 1 ? ValueI[1] : 0); } return dim; } virtual core::matrix4 getMatrix() { core::matrix4 ret; if (IsFloat) { for (u32 r=0; r<4; ++r) for (u32 c=0; c<4; ++c) if (Count > c+r*4) ret(r,c) = ValueF[c+r*4]; } else { for (u32 r=0; r<4; ++r) for (u32 c=0; c<4; ++c) if (Count > c+r*4) ret(r,c) = (f32)ValueI[c+r*4]; } return ret; } virtual core::quaternion getQuaternion() { core::quaternion ret; if (IsFloat) { ret.X = Count > 0 ? ValueF[0] : 0.0f; ret.Y = Count > 1 ? ValueF[1] : 0.0f; ret.Z = Count > 2 ? ValueF[2] : 0.0f; ret.W = Count > 3 ? ValueF[3] : 0.0f; } else { ret.X = Count > 0 ? (f32)ValueI[0] : 0.0f; ret.Y = Count > 1 ? (f32)ValueI[1] : 0.0f; ret.Z = Count > 2 ? (f32)ValueI[2] : 0.0f; ret.W = Count > 3 ? (f32)ValueI[3] : 0.0f; } return ret; } virtual core::triangle3df getTriangle() { core::triangle3df ret; if (IsFloat) { ret.pointA.X = Count > 0 ? ValueF[0] : 0.0f; ret.pointA.Y = Count > 1 ? ValueF[1] : 0.0f; ret.pointA.Z = Count > 2 ? ValueF[2] : 0.0f; ret.pointB.X = Count > 3 ? ValueF[3] : 0.0f; ret.pointB.Y = Count > 4 ? ValueF[4] : 0.0f; ret.pointB.Z = Count > 5 ? ValueF[5] : 0.0f; ret.pointC.X = Count > 6 ? ValueF[6] : 0.0f; ret.pointC.Y = Count > 7 ? ValueF[7] : 0.0f; ret.pointC.Z = Count > 8 ? ValueF[8] : 0.0f; } else { ret.pointA.X = Count > 0 ? (f32)ValueI[0] : 0.0f; ret.pointA.Y = Count > 1 ? (f32)ValueI[1] : 0.0f; ret.pointA.Z = Count > 2 ? (f32)ValueI[2] : 0.0f; ret.pointB.X = Count > 3 ? (f32)ValueI[3] : 0.0f; ret.pointB.Y = Count > 4 ? (f32)ValueI[4] : 0.0f; ret.pointB.Z = Count > 5 ? (f32)ValueI[5] : 0.0f; ret.pointC.X = Count > 6 ? (f32)ValueI[6] : 0.0f; ret.pointC.Y = Count > 7 ? (f32)ValueI[7] : 0.0f; ret.pointC.Z = Count > 8 ? (f32)ValueI[8] : 0.0f; } return ret; } virtual core::plane3df getPlane() { core::plane3df ret; if (IsFloat) { ret.Normal.X = Count > 0 ? ValueF[0] : 0.0f; ret.Normal.Y = Count > 1 ? ValueF[1] : 0.0f; ret.Normal.Z = Count > 2 ? ValueF[2] : 0.0f; ret.D = Count > 3 ? ValueF[3] : 0.0f; } else { ret.Normal.X = Count > 0 ? (f32)ValueI[0] : 0.0f; ret.Normal.Y = Count > 1 ? (f32)ValueI[1] : 0.0f; ret.Normal.Z = Count > 2 ? (f32)ValueI[2] : 0.0f; ret.D = Count > 3 ? (f32)ValueI[3] : 0.0f; } return ret; } virtual core::aabbox3df getBBox() { core::aabbox3df ret; if (IsFloat) { ret.MinEdge.X = Count > 0 ? ValueF[0] : 0.0f; ret.MinEdge.Y = Count > 1 ? ValueF[1] : 0.0f; ret.MinEdge.Z = Count > 2 ? ValueF[2] : 0.0f; ret.MaxEdge.X = Count > 3 ? ValueF[3] : 0.0f; ret.MaxEdge.Y = Count > 4 ? ValueF[4] : 0.0f; ret.MaxEdge.Z = Count > 5 ? ValueF[5] : 0.0f; } else { ret.MinEdge.X = Count > 0 ? (f32)ValueI[0] : 0.0f; ret.MinEdge.Y = Count > 1 ? (f32)ValueI[1] : 0.0f; ret.MinEdge.Z = Count > 2 ? (f32)ValueI[2] : 0.0f; ret.MaxEdge.X = Count > 3 ? (f32)ValueI[3] : 0.0f; ret.MaxEdge.Y = Count > 4 ? (f32)ValueI[4] : 0.0f; ret.MaxEdge.Z = Count > 5 ? (f32)ValueI[5] : 0.0f; } return ret; } virtual core::line2df getLine2d() { core::line2df ret; if (IsFloat) { ret.start.X = Count > 0 ? ValueF[0] : 0.0f; ret.start.Y = Count > 1 ? ValueF[1] : 0.0f; ret.end.X = Count > 2 ? ValueF[2] : 0.0f; ret.end.Y = Count > 3 ? ValueF[3] : 0.0f; } else { ret.start.X = Count > 0 ? (f32)ValueI[0] : 0.0f; ret.start.Y = Count > 1 ? (f32)ValueI[1] : 0.0f; ret.end.X = Count > 2 ? (f32)ValueI[2] : 0.0f; ret.end.Y = Count > 3 ? (f32)ValueI[3] : 0.0f; } return ret; } virtual core::line3df getLine3d() { core::line3df ret; if (IsFloat) { ret.start.X = Count > 0 ? ValueF[0] : 0.0f; ret.start.Y = Count > 1 ? ValueF[1] : 0.0f; ret.start.Z = Count > 2 ? ValueF[2] : 0.0f; ret.end.X = Count > 3 ? ValueF[3] : 0.0f; ret.end.Y = Count > 4 ? ValueF[4] : 0.0f; ret.end.Z = Count > 5 ? ValueF[5] : 0.0f; } else { ret.start.X = Count > 0 ? (f32)ValueI[0] : 0.0f; ret.start.Y = Count > 1 ? (f32)ValueI[1] : 0.0f; ret.start.Z = Count > 2 ? (f32)ValueI[2] : 0.0f; ret.end.X = Count > 3 ? (f32)ValueI[3] : 0.0f; ret.end.Y = Count > 4 ? (f32)ValueI[4] : 0.0f; ret.end.Z = Count > 5 ? (f32)ValueI[5] : 0.0f; } return ret; } //! get float array virtual core::array getFloatArray() { if (!IsFloat) { ValueF.clear(); for (u32 i=0; i getIntArray() { if (IsFloat) { ValueI.clear(); for (u32 i=0; i '9') ) ) ++P; // set value if ( *P) { if (IsFloat) { f32 c = 0; P = core::fast_atof_move(P, c); ValueF[i] = c; } else { // todo: fix this to read ints properly f32 c = 0; P = core::fast_atof_move(P, c); ValueI[i] = (s32)c; } } } // todo: warning message //if (i < Count-1) //{ // //} } virtual void setPosition(core::position2di v) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = (f32)v.X; if (Count > 1) ValueF[1] = (f32)v.Y; } else { if (Count > 0) ValueI[0] = v.X; if (Count > 1) ValueI[1] = v.Y; } } virtual void setVector(core::vector3df v) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = v.X; if (Count > 1) ValueF[1] = v.Y; if (Count > 2) ValueF[2] = v.Z; } else { if (Count > 0) ValueI[0] = (s32)v.X; if (Count > 1) ValueI[1] = (s32)v.Y; if (Count > 2) ValueI[2] = (s32)v.Z; } } virtual void setColor(video::SColorf color) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = color.r; if (Count > 1) ValueF[1] = color.g; if (Count > 2) ValueF[2] = color.b; if (Count > 3) ValueF[3] = color.a; } else { if (Count > 0) ValueI[0] = (s32)(color.r * 255); if (Count > 1) ValueI[1] = (s32)(color.g * 255); if (Count > 2) ValueI[2] = (s32)(color.b * 255); if (Count > 3) ValueI[3] = (s32)(color.a * 255); } } virtual void setColor(video::SColor color) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = (f32)color.getRed() / 255.0f; if (Count > 1) ValueF[1] = (f32)color.getGreen() / 255.0f; if (Count > 2) ValueF[2] = (f32)color.getBlue() / 255.0f; if (Count > 3) ValueF[3] = (f32)color.getAlpha() / 255.0f; } else { if (Count > 0) ValueI[0] = color.getRed(); if (Count > 1) ValueI[1] = color.getGreen(); if (Count > 2) ValueI[2] = color.getBlue(); if (Count > 3) ValueI[3] = color.getAlpha(); } } virtual void setRect(core::rect value) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = (f32)value.UpperLeftCorner.X; if (Count > 1) ValueF[1] = (f32)value.UpperLeftCorner.Y; if (Count > 2) ValueF[2] = (f32)value.LowerRightCorner.X; if (Count > 3) ValueF[3] = (f32)value.LowerRightCorner.Y; } else { if (Count > 0) ValueI[0] = value.UpperLeftCorner.X; if (Count > 1) ValueI[1] = value.UpperLeftCorner.Y; if (Count > 2) ValueI[2] = value.LowerRightCorner.X; if (Count > 3) ValueI[3] = value.LowerRightCorner.Y; } } virtual void setMatrix(core::matrix4 value) { reset(); if (IsFloat) { for (u32 r=0; r<4; ++r) for (u32 c=0; c<4; ++c) if (Count > c+r*4) ValueF[c+r*4] = value(r,c); } else { for (u32 r=0; r<4; ++r) for (u32 c=0; c<4; ++c) if (Count > c+r*4) ValueI[c+r*4] = (s32)value(r,c); } } virtual void setQuaternion(core::quaternion value) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = value.X; if (Count > 1) ValueF[1] = value.Y; if (Count > 2) ValueF[2] = value.Z; if (Count > 3) ValueF[3] = value.W; } else { if (Count > 0) ValueI[0] = (s32)value.X; if (Count > 1) ValueI[1] = (s32)value.Y; if (Count > 2) ValueI[2] = (s32)value.Z; if (Count > 3) ValueI[3] = (s32)value.W; } } virtual void setBoundingBox(core::aabbox3d value) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = value.MinEdge.X; if (Count > 1) ValueF[1] = value.MinEdge.Y; if (Count > 2) ValueF[2] = value.MinEdge.Z; if (Count > 3) ValueF[3] = value.MaxEdge.X; if (Count > 4) ValueF[4] = value.MaxEdge.Y; if (Count > 5) ValueF[5] = value.MaxEdge.Z; } else { if (Count > 0) ValueI[0] = (s32)value.MinEdge.X; if (Count > 1) ValueI[1] = (s32)value.MinEdge.Y; if (Count > 2) ValueI[2] = (s32)value.MinEdge.Z; if (Count > 3) ValueI[3] = (s32)value.MaxEdge.X; if (Count > 4) ValueI[4] = (s32)value.MaxEdge.Y; if (Count > 5) ValueI[5] = (s32)value.MaxEdge.Z; } } virtual void setPlane(core::plane3df value) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = value.Normal.X; if (Count > 1) ValueF[1] = value.Normal.Y; if (Count > 2) ValueF[2] = value.Normal.Z; if (Count > 3) ValueF[3] = value.D; } else { if (Count > 0) ValueI[0] = (s32)value.Normal.X; if (Count > 1) ValueI[1] = (s32)value.Normal.Y; if (Count > 2) ValueI[2] = (s32)value.Normal.Z; if (Count > 3) ValueI[3] = (s32)value.D; } } virtual void setTriangle3d(core::triangle3df value) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = value.pointA.X; if (Count > 1) ValueF[1] = value.pointA.Y; if (Count > 2) ValueF[2] = value.pointA.Z; if (Count > 3) ValueF[3] = value.pointB.X; if (Count > 4) ValueF[4] = value.pointB.Y; if (Count > 5) ValueF[5] = value.pointB.Z; if (Count > 6) ValueF[6] = value.pointC.X; if (Count > 7) ValueF[7] = value.pointC.Y; if (Count > 8) ValueF[8] = value.pointC.Z; } else { if (Count > 0) ValueI[0] = (s32)value.pointA.X; if (Count > 1) ValueI[1] = (s32)value.pointA.Y; if (Count > 2) ValueI[2] = (s32)value.pointA.Z; if (Count > 3) ValueI[3] = (s32)value.pointB.X; if (Count > 4) ValueI[4] = (s32)value.pointB.Y; if (Count > 5) ValueI[5] = (s32)value.pointB.Z; if (Count > 6) ValueI[6] = (s32)value.pointC.X; if (Count > 7) ValueI[7] = (s32)value.pointC.Y; if (Count > 8) ValueI[8] = (s32)value.pointC.Z; } } virtual void setVector2d(core::vector2df v) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = v.X; if (Count > 1) ValueF[1] = v.Y; } else { if (Count > 0) ValueI[0] = (s32)v.X; if (Count > 1) ValueI[1] = (s32)v.Y; } } virtual void setVector2d(core::vector2di v) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = (f32)v.X; if (Count > 1) ValueF[1] = (f32)v.Y; } else { if (Count > 0) ValueI[0] = v.X; if (Count > 1) ValueI[1] = v.Y; } } virtual void setLine2d(core::line2di v) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = (f32)v.start.X; if (Count > 1) ValueF[1] = (f32)v.start.Y; if (Count > 2) ValueF[2] = (f32)v.end.X; if (Count > 3) ValueF[3] = (f32)v.end.Y; } else { if (Count > 0) ValueI[0] = v.start.X; if (Count > 1) ValueI[1] = v.start.Y; if (Count > 2) ValueI[2] = v.end.X; if (Count > 3) ValueI[3] = v.end.Y; } } virtual void setLine2d(core::line2df v) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = v.start.X; if (Count > 1) ValueF[1] = v.start.Y; if (Count > 2) ValueF[2] = v.end.X; if (Count > 3) ValueF[3] = v.end.Y; } else { if (Count > 0) ValueI[0] = (s32)v.start.X; if (Count > 1) ValueI[1] = (s32)v.start.Y; if (Count > 2) ValueI[2] = (s32)v.end.X; if (Count > 3) ValueI[3] = (s32)v.end.Y; } } virtual void setDimension2d(core::dimension2du v) { reset(); if (IsFloat) { if (Count > 0) ValueF[0] = (f32)v.Width; if (Count > 1) ValueF[1] = (f32)v.Height; } else { if (Count > 0) ValueI[0] = (s32)v.Width; if (Count > 1) ValueI[1] = (s32)v.Height; } } //! set float array virtual void setFloatArray(core::array &vals) { reset(); for (u32 i=0; i &vals) { reset(); for (u32 i=0; i ValueI; core::array ValueF; u32 Count; bool IsFloat; }; // Attribute implemented for floating point colors class CColorfAttribute : public CNumbersAttribute { public: CColorfAttribute(const char* name, video::SColorf value) : CNumbersAttribute(name, value) {} virtual s32 getInt() { return getColor().color; } virtual f32 getFloat() { return (f32)getColor().color; } virtual void setInt(s32 intValue) { video::SColorf c = video::SColor(intValue); ValueF[0] = c.r; ValueF[1] = c.g; ValueF[2] = c.b; ValueF[3] = c.a; } virtual void setFloat(f32 floatValue) { setInt((s32)floatValue); } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_COLORF; } virtual const wchar_t* getTypeString() const { return L"colorf"; } }; // Attribute implemented for colors class CColorAttribute : public CNumbersAttribute { public: CColorAttribute(const char* name, const video::SColorf& value) : CNumbersAttribute(name, value) {} CColorAttribute(const char* name, const video::SColor& value) : CNumbersAttribute(name, value) {} virtual s32 getInt() { return getColor().color; } virtual f32 getFloat() { return (f32)getColor().color; } virtual void setInt(s32 intValue) { video::SColorf c = video::SColor(intValue); ValueF[0] = c.r; ValueF[1] = c.g; ValueF[2] = c.b; ValueF[3] = c.a; } virtual void setFloat(f32 floatValue) { setInt((s32)floatValue); } virtual core::stringw getStringW() { char tmp[10]; const video::SColor c = getColor(); sprintf(tmp, "%02x%02x%02x%02x", c.getAlpha(), c.getRed(), c.getGreen(), c.getBlue()); return core::stringw(tmp); } virtual void setString(const char* text) { u32 c; if (sscanf(text, "%08x", &c)!=1) { CNumbersAttribute::setString(text); } else setColor(c); } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_COLOR; } virtual const wchar_t* getTypeString() const { return L"color"; } }; // Attribute implemented for 3d vectors class CVector3DAttribute : public CNumbersAttribute { public: CVector3DAttribute(const char* name, core::vector3df value) : CNumbersAttribute(name, value) {} virtual E_ATTRIBUTE_TYPE getType() const { return EAT_VECTOR3D; } virtual core::matrix4 getMatrix() { core::matrix4 ret; ret.makeIdentity(); ret.setTranslation( core::vector3df(ValueF[0],ValueF[1],ValueF[2]) ); return ret; } virtual const wchar_t* getTypeString() const { return L"vector3d"; } }; // Attribute implemented for 2d vectors class CVector2DAttribute : public CNumbersAttribute { public: CVector2DAttribute(const char* name, core::vector2df value) : CNumbersAttribute(name, value) {} virtual E_ATTRIBUTE_TYPE getType() const { return EAT_VECTOR2D; } virtual const wchar_t* getTypeString() const { return L"vector2d"; } }; // Attribute implemented for 2d vectors class CPosition2DAttribute : public CNumbersAttribute { public: CPosition2DAttribute(const char* name, core::position2di value) : CNumbersAttribute(name, value) {} virtual E_ATTRIBUTE_TYPE getType() const { return EAT_POSITION2D; } virtual const wchar_t* getTypeString() const { return L"position"; } }; // Attribute implemented for rectangles class CRectAttribute : public CNumbersAttribute { public: CRectAttribute(const char* name, core::rect value) : CNumbersAttribute(name, value) { } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_RECT; } virtual const wchar_t* getTypeString() const { return L"rect"; } }; // Attribute implemented for dimension class CDimension2dAttribute : public CNumbersAttribute { public: CDimension2dAttribute (const char* name, core::dimension2d value) : CNumbersAttribute(name, value) { } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_DIMENSION2D; } virtual const wchar_t* getTypeString() const { return L"dimension2d"; } }; // Attribute implemented for matrices class CMatrixAttribute : public CNumbersAttribute { public: CMatrixAttribute(const char* name, core::matrix4 value) : CNumbersAttribute(name, value) { } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_MATRIX; } virtual core::quaternion getQuaternion() { return core::quaternion(getMatrix()); } virtual const wchar_t* getTypeString() const { return L"matrix"; } }; // Attribute implemented for quaternions class CQuaternionAttribute : public CNumbersAttribute { public: CQuaternionAttribute(const char* name, core::quaternion value) : CNumbersAttribute(name, value) { } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_QUATERNION; } virtual core::matrix4 getMatrix() { return getQuaternion().getMatrix(); } virtual const wchar_t* getTypeString() const { return L"quaternion"; } }; // Attribute implemented for bounding boxes class CBBoxAttribute : public CNumbersAttribute { public: CBBoxAttribute(const char* name, core::aabbox3df value) : CNumbersAttribute(name, value) { } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_BBOX; } virtual const wchar_t* getTypeString() const { return L"box3d"; } }; // Attribute implemented for planes class CPlaneAttribute : public CNumbersAttribute { public: CPlaneAttribute(const char* name, core::plane3df value) : CNumbersAttribute(name, value) { } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_PLANE; } virtual const wchar_t* getTypeString() const { return L"plane"; } }; // Attribute implemented for triangles class CTriangleAttribute : public CNumbersAttribute { public: CTriangleAttribute(const char* name, core::triangle3df value) : CNumbersAttribute(name, value) { } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_TRIANGLE3D; } virtual core::plane3df getPlane() { return getTriangle().getPlane(); } virtual const wchar_t* getTypeString() const { return L"triangle"; } }; // Attribute implemented for 2d lines class CLine2dAttribute : public CNumbersAttribute { public: CLine2dAttribute(const char* name, core::line2df value) : CNumbersAttribute(name, value) { } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_LINE2D; } virtual const wchar_t* getTypeString() const { return L"line2d"; } }; // Attribute implemented for 3d lines class CLine3dAttribute : public CNumbersAttribute { public: CLine3dAttribute(const char* name, core::line3df value) : CNumbersAttribute(name, value) { } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_LINE3D; } virtual const wchar_t* getTypeString() const { return L"line3d"; } }; // vector2df // dimension2du /* Special attributes */ // Attribute implemented for enumeration literals class CEnumAttribute : public IAttribute { public: CEnumAttribute(const char* name, const char* value, const char* const* literals) { Name = name; setEnum(value, literals); } virtual void setEnum(const char* enumValue, const char* const* enumerationLiterals) { int literalCount = 0; if (enumerationLiterals) { s32 i; for (i=0; enumerationLiterals[i]; ++i) ++literalCount; EnumLiterals.reallocate(literalCount); for (i=0; enumerationLiterals[i]; ++i) EnumLiterals.push_back(enumerationLiterals[i]); } setString(enumValue); } virtual s32 getInt() { for (s32 i=0; EnumLiterals.size(); ++i) if (Value.equals_ignore_case(EnumLiterals[i])) { return i; } return -1; } virtual f32 getFloat() { return (f32)getInt(); } virtual bool getBool() { return (getInt() != 0); // does not make a lot of sense, I know } virtual core::stringc getString() { return Value; } virtual core::stringw getStringW() { return core::stringw(Value.c_str()); } virtual void setInt(s32 intValue) { if (intValue>=0 && intValue<(s32)EnumLiterals.size()) Value = EnumLiterals[intValue]; else Value = ""; } virtual void setFloat(f32 floatValue) { setInt((s32)floatValue); }; virtual void setString(const char* text) { Value = text; } virtual const char* getEnum() { return Value.c_str(); } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_ENUM; } virtual const wchar_t* getTypeString() const { return L"enum"; } core::stringc Value; core::array EnumLiterals; }; // Attribute implemented for strings class CStringAttribute : public IAttribute { public: CStringAttribute(const char* name, const char* value) { IsStringW=false; Name = name; setString(value); } CStringAttribute(const char* name, const wchar_t* value) { IsStringW = true; Name = name; setString(value); } CStringAttribute(const char* name, void* binaryData, s32 lenghtInBytes) { IsStringW=false; Name = name; setBinary(binaryData, lenghtInBytes); } virtual s32 getInt() { if (IsStringW) return atoi(core::stringc(ValueW.c_str()).c_str()); else return atoi(Value.c_str()); } virtual f32 getFloat() { if (IsStringW) return core::fast_atof(core::stringc(ValueW.c_str()).c_str()); else return core::fast_atof(Value.c_str()); } virtual bool getBool() { if (IsStringW) return ValueW.equals_ignore_case(L"true"); else return Value.equals_ignore_case("true"); } virtual core::stringc getString() { if (IsStringW) return core::stringc(ValueW.c_str()); else return Value; } virtual core::stringw getStringW() { if (IsStringW) return ValueW; else return core::stringw(Value.c_str()); } virtual void setInt(s32 intValue) { if (IsStringW) ValueW = core::stringw(intValue); else Value = core::stringc(intValue); } virtual void setFloat(f32 floatValue) { if (IsStringW) { ValueW = core::stringw((double)floatValue); } else { Value = core::stringc((double)floatValue); } }; virtual void setString(const char* text) { if (IsStringW) ValueW = core::stringw(text); else Value = text; } virtual void setString(const wchar_t* text) { if (IsStringW) ValueW = text; else Value = core::stringc(text); } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_STRING; } virtual const wchar_t* getTypeString() const { return L"string"; } virtual void getBinary(void* outdata, s32 maxLength) { s32 dataSize = maxLength; c8* datac8 = (c8*)(outdata); s32 p = 0; const c8* dataString = Value.c_str(); for (s32 i=0; i= '0' && h <='9') return h-'0'; if (h >= 'a' && h <='f') return h-'a' + 10; return 0; } static inline void getHexStrFromByte(c8 byte, c8* out) { s32 b = (byte & 0xf0) >> 4; for (s32 i=0; i<2; ++i) { if (b >=0 && b <= 9) out[i] = b+'0'; if (b >=10 && b <= 15) out[i] = (b-10)+'a'; b = byte & 0x0f; } } }; // Attribute implemented for binary data class CBinaryAttribute : public CStringAttribute { public: CBinaryAttribute(const char* name, void* binaryData, s32 lenghtInBytes) : CStringAttribute(name, binaryData, lenghtInBytes) { } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_BINARY; } virtual const wchar_t* getTypeString() const { return L"binary"; } }; // Attribute implemented for texture references class CTextureAttribute : public IAttribute { public: CTextureAttribute(const char* name, video::ITexture* value, video::IVideoDriver* driver, const io::path& filename) : Value(0), Driver(driver), OverrideName(filename) { if (Driver) Driver->grab(); Name = name; setTexture(value); } ~CTextureAttribute() { if (Driver) Driver->drop(); if (Value) Value->drop(); } virtual video::ITexture* getTexture() { return Value; } virtual bool getBool() { return (Value != 0); } virtual core::stringw getStringW() { // (note: don't try to put all this in some ?: operators, or c++ builder will choke) if ( OverrideName.size() ) return core::stringw(OverrideName); if ( Value ) return core::stringw(Value->getName().getPath().c_str()); return core::stringw(0); } virtual core::stringc getString() { // since texture names can be stringw we are careful with the types if ( OverrideName.size() ) return core::stringc(OverrideName); if ( Value ) return core::stringc(Value->getName().getPath().c_str()); return core::stringc(0); } virtual void setString(const char* text) { if (Driver) { if (text && *text) { setTexture(Driver->getTexture(text)); OverrideName=text; } else setTexture(0); } } virtual void setTexture(video::ITexture* value) { if ( value == Value ) return; if (Value) Value->drop(); Value = value; if (Value) Value->grab(); } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_TEXTURE; } virtual const wchar_t* getTypeString() const { return L"texture"; } video::ITexture* Value; video::IVideoDriver* Driver; io::path OverrideName; }; // Attribute implemented for array of stringw class CStringWArrayAttribute : public IAttribute { public: CStringWArrayAttribute(const char* name, const core::array& value) { Name = name; setArray(value); } virtual core::array getArray() { return Value; } virtual void setArray(const core::array& value) { Value = value; } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_STRINGWARRAY; } virtual const wchar_t* getTypeString() const { return L"stringwarray"; } core::array Value; }; // Attribute implemented for user pointers class CUserPointerAttribute : public IAttribute { public: CUserPointerAttribute(const char* name, void* value) { Name = name; Value = value; } virtual s32 getInt() { return *static_cast(Value); } virtual bool getBool() { return (Value != 0); } virtual core::stringw getStringW() { wchar_t buf[32]; swprintf(buf, 32, L"%p", Value); return core::stringw(buf); } virtual void setString(const char* text) { u32 tmp; sscanf(text, "0x%x", &tmp); Value = (void *) tmp; } virtual E_ATTRIBUTE_TYPE getType() const { return EAT_USER_POINTER; } virtual void setUserPointer(void* v) { Value = v; } virtual void* getUserPointer() { return Value; } virtual const wchar_t* getTypeString() const { return L"userPointer"; } void* Value; }; // todo: CGUIFontAttribute } // end namespace io } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CAnimatedMeshSceneNode.h0000644000000000000000000001755612574354552021552 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_ANIMATED_MESH_SCENE_NODE_H_INCLUDED__ #define __C_ANIMATED_MESH_SCENE_NODE_H_INCLUDED__ #include "IAnimatedMeshSceneNode.h" #include "IAnimatedMesh.h" #include "matrix4.h" namespace irr { namespace scene { class IDummyTransformationSceneNode; class CAnimatedMeshSceneNode : public IAnimatedMeshSceneNode { public: //! constructor CAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); //! destructor virtual ~CAnimatedMeshSceneNode(); //! sets the current frame. from now on the animation is played from this frame. virtual void setCurrentFrame(f32 frame); //! frame virtual void OnRegisterSceneNode(); //! OnAnimate() is called just before rendering the whole scene. virtual void OnAnimate(u32 timeMs); //! renders the node. virtual void render(); //! returns the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const; //! sets the frames between the animation is looped. //! the default is 0 - MaximalFrameCount of the mesh. virtual bool setFrameLoop(s32 begin, s32 end); //! Sets looping mode which is on by default. If set to false, //! animations will not be looped. virtual void setLoopMode(bool playAnimationLooped); //! returns the current loop mode virtual bool getLoopMode() const; //! Sets a callback interface which will be called if an animation //! playback has ended. Set this to 0 to disable the callback again. virtual void setAnimationEndCallback(IAnimationEndCallBack* callback=0); //! sets the speed with which the animation is played virtual void setAnimationSpeed(f32 framesPerSecond); //! gets the speed with which the animation is played virtual f32 getAnimationSpeed() const; //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. virtual video::SMaterial& getMaterial(u32 i); //! returns amount of materials used by this scene node. virtual u32 getMaterialCount() const; //! Creates shadow volume scene node as child of this node //! and returns a pointer to it. virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh, s32 id, bool zfailmethod=true, f32 infinity=1000.0f); //! Returns a pointer to a child node, which has the same transformation as //! the corrsesponding joint, if the mesh in this scene node is a skinned mesh. virtual IBoneSceneNode* getJointNode(const c8* jointName); //! same as getJointNode(const c8* jointName), but based on id virtual IBoneSceneNode* getJointNode(u32 jointID); //! Gets joint count. virtual u32 getJointCount() const; //! Deprecated command, please use getJointNode. virtual ISceneNode* getMS3DJointNode(const c8* jointName); //! Deprecated command, please use getJointNode. virtual ISceneNode* getXJointNode(const c8* jointName); //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. virtual bool removeChild(ISceneNode* child); //! Starts a MD2 animation. virtual bool setMD2Animation(EMD2_ANIMATION_TYPE anim); //! Starts a special MD2 animation. virtual bool setMD2Animation(const c8* animationName); //! Returns the current displayed frame number. virtual f32 getFrameNr() const; //! Returns the current start frame number. virtual s32 getStartFrame() const; //! Returns the current end frame number. virtual s32 getEndFrame() const; //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. /* In this way it is possible to change the materials a mesh causing all mesh scene nodes referencing this mesh to change too. */ virtual void setReadOnlyMaterials(bool readonly); //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style virtual bool isReadOnlyMaterials() const; //! Sets a new mesh virtual void setMesh(IAnimatedMesh* mesh); //! Returns the current mesh virtual IAnimatedMesh* getMesh(void) { return Mesh; } //! Writes attributes of the scene node. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const; //! Reads attributes of the scene node. virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_ANIMATED_MESH; } // returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, // or the absolutetransformation if it's a normal scenenode const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname); //! updates the absolute position based on the relative and the parents position virtual void updateAbsolutePosition(); //! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set) virtual void setJointMode(E_JOINT_UPDATE_ON_RENDER mode); //! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2) //! you must call animateJoints(), or the mesh will not animate virtual void setTransitionTime(f32 Time); //! updates the joint positions of this mesh virtual void animateJoints(bool CalculateAbsolutePositions=true); //! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected) virtual void setRenderFromIdentity( bool On ); //! Creates a clone of this scene node and its children. /** \param newParent An optional new parent. \param newManager An optional new scene manager. \return The newly created clone of this node. */ virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0); private: //! Get a static mesh for the current frame of this animated mesh IMesh* getMeshForCurrentFrame(); void buildFrameNr(u32 timeMs); void checkJoints(); void beginTransition(); core::array Materials; core::aabbox3d Box; IAnimatedMesh* Mesh; s32 StartFrame; s32 EndFrame; f32 FramesPerSecond; f32 CurrentFrameNr; u32 LastTimeMs; u32 TransitionTime; //Transition time in millisecs f32 Transiting; //is mesh transiting (plus cache of TransitionTime) f32 TransitingBlend; //0-1, calculated on buildFrameNr //0-unused, 1-get joints only, 2-set joints only, 3-move and set E_JOINT_UPDATE_ON_RENDER JointMode; bool JointsUsed; bool Looping; bool ReadOnlyMaterials; bool RenderFromIdentity; IAnimationEndCallBack* LoopCallBack; s32 PassCount; IShadowVolumeSceneNode* Shadow; core::array JointChildSceneNodes; core::array PretransitingSave; // Quake3 Model struct SMD3Special : public virtual IReferenceCounted { core::stringc Tagname; SMD3QuaternionTagList AbsoluteTagList; SMD3Special & operator = (const SMD3Special & copyMe) { Tagname = copyMe.Tagname; AbsoluteTagList = copyMe.AbsoluteTagList; return *this; } }; SMD3Special *MD3Special; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CAnimatedMeshSceneNode.cpp0000644000000000000000000007361312574354552022101 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CAnimatedMeshSceneNode.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "S3DVertex.h" #include "os.h" #include "CShadowVolumeSceneNode.h" #include "IAnimatedMeshMD3.h" #include "CSkinnedMesh.h" #include "IDummyTransformationSceneNode.h" #include "IBoneSceneNode.h" #include "IMaterialRenderer.h" #include "IMesh.h" #include "IMeshCache.h" #include "IAnimatedMesh.h" #include "quaternion.h" namespace irr { namespace scene { //! constructor CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) : IAnimatedMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), StartFrame(0), EndFrame(0), FramesPerSecond(0.025f), CurrentFrameNr(0.f), LastTimeMs(0), TransitionTime(0), Transiting(0.f), TransitingBlend(0.f), JointMode(EJUOR_NONE), JointsUsed(false), Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false), LoopCallBack(0), PassCount(0), Shadow(0), MD3Special(0) { #ifdef _DEBUG setDebugName("CAnimatedMeshSceneNode"); #endif setMesh(mesh); } //! destructor CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode() { if (MD3Special) MD3Special->drop(); if (Mesh) Mesh->drop(); if (Shadow) Shadow->drop(); if (LoopCallBack) LoopCallBack->drop(); } //! Sets the current frame. From now on the animation is played from this frame. void CAnimatedMeshSceneNode::setCurrentFrame(f32 frame) { // if you pass an out of range value, we just clamp it CurrentFrameNr = core::clamp ( frame, (f32)StartFrame, (f32)EndFrame ); beginTransition(); //transit to this frame if enabled } //! Returns the currently displayed frame number. f32 CAnimatedMeshSceneNode::getFrameNr() const { return CurrentFrameNr; } //! Get CurrentFrameNr and update transiting settings void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs) { if (Transiting!=0.f) { TransitingBlend += (f32)(timeMs) * Transiting; if (TransitingBlend > 1.f) { Transiting=0.f; TransitingBlend=0.f; } } if ((StartFrame==EndFrame)) { CurrentFrameNr = (f32)StartFrame; //Support for non animated meshes } else if (Looping) { // play animation looped CurrentFrameNr += timeMs * FramesPerSecond; // We have no interpolation between EndFrame and StartFrame, // the last frame must be identical to first one with our current solution. if (FramesPerSecond > 0.f) //forwards... { if (CurrentFrameNr > EndFrame) CurrentFrameNr = StartFrame + fmod(CurrentFrameNr - StartFrame, (f32)(EndFrame-StartFrame)); } else //backwards... { if (CurrentFrameNr < StartFrame) CurrentFrameNr = EndFrame - fmod(EndFrame - CurrentFrameNr, (f32)(EndFrame-StartFrame)); } } else { // play animation non looped CurrentFrameNr += timeMs * FramesPerSecond; if (FramesPerSecond > 0.f) //forwards... { if (CurrentFrameNr > (f32)EndFrame) { CurrentFrameNr = (f32)EndFrame; if (LoopCallBack) LoopCallBack->OnAnimationEnd(this); } } else //backwards... { if (CurrentFrameNr < (f32)StartFrame) { CurrentFrameNr = (f32)StartFrame; if (LoopCallBack) LoopCallBack->OnAnimationEnd(this); } } } } void CAnimatedMeshSceneNode::OnRegisterSceneNode() { if (IsVisible) { // because this node supports rendering of mixed mode meshes consisting of // transparent and solid material at the same time, we need to go through all // materials, check of what type they are and register this node for the right // render pass according to that. video::IVideoDriver* driver = SceneManager->getVideoDriver(); PassCount = 0; int transparentCount = 0; int solidCount = 0; // count transparent and solid materials in this scene node for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); if (rnd && rnd->isTransparent()) ++transparentCount; else ++solidCount; if (solidCount && transparentCount) break; } // register according to material types counted if (solidCount) SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); if (transparentCount) SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); ISceneNode::OnRegisterSceneNode(); } } IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame() { if(Mesh->getMeshType() != EAMT_SKINNED) { s32 frameNr = (s32) getFrameNr(); s32 frameBlend = (s32) (core::fract ( getFrameNr() ) * 1000.f); return Mesh->getMesh(frameNr, frameBlend, StartFrame, EndFrame); } else { #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ return 0; #else // As multiple scene nodes may be sharing the same skinned mesh, we have to // re-animate it every frame to ensure that this node gets the mesh that it needs. CSkinnedMesh* skinnedMesh = reinterpret_cast(Mesh); if (JointMode == EJUOR_CONTROL)//write to mesh skinnedMesh->transferJointsToMesh(JointChildSceneNodes); else skinnedMesh->animateMesh(getFrameNr(), 1.0f); // Update the skinned mesh for the current joint transforms. skinnedMesh->skinMesh(); if (JointMode == EJUOR_READ)//read from mesh { skinnedMesh->recoverJointsFromMesh(JointChildSceneNodes); //---slow--- for (u32 n=0;ngetParent()==this) { JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option } } if(JointMode == EJUOR_CONTROL) { // For meshes other than EJUOR_CONTROL, this is done by calling animateMesh() skinnedMesh->updateBoundingBox(); } return skinnedMesh; #endif } } //! OnAnimate() is called just before rendering the whole scene. void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs) { if (LastTimeMs==0) // first frame { LastTimeMs = timeMs; } // set CurrentFrameNr buildFrameNr(timeMs-LastTimeMs); // update bbox if (Mesh) { scene::IMesh * mesh = getMeshForCurrentFrame(); if (mesh) Box = mesh->getBoundingBox(); } LastTimeMs = timeMs; IAnimatedMeshSceneNode::OnAnimate(timeMs); } //! renders the node. void CAnimatedMeshSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); if (!Mesh || !driver) return; bool isTransparentPass = SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; ++PassCount; scene::IMesh* m = getMeshForCurrentFrame(); if(m) { Box = m->getBoundingBox(); } else { #ifdef _DEBUG os::Printer::log("Animated Mesh returned no mesh to render.", Mesh->getDebugName(), ELL_WARNING); #endif } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); if (Shadow && PassCount==1) Shadow->updateShadowVolumes(); // for debug purposes only: bool renderMeshes = true; video::SMaterial mat; if (DebugDataVisible && PassCount==1) { // overwrite half transparency if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY) { for (u32 i=0; igetMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = m->getMeshBuffer(i); mat = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; if (RenderFromIdentity) driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); else if (Mesh->getMeshType() == EAMT_SKINNED) driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); driver->setMaterial(mat); driver->drawMeshBuffer(mb); } renderMeshes = false; } } // render original meshes if (renderMeshes) { for (u32 i=0; igetMeshBufferCount(); ++i) { video::IMaterialRenderer* rnd = driver->getMaterialRenderer(Materials[i].MaterialType); bool transparent = (rnd && rnd->isTransparent()); // only render transparent buffer if this is the transparent render pass // and solid only in solid pass if (transparent == isTransparentPass) { scene::IMeshBuffer* mb = m->getMeshBuffer(i); const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; if (RenderFromIdentity) driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); else if (Mesh->getMeshType() == EAMT_SKINNED) driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); driver->setMaterial(material); driver->drawMeshBuffer(mb); } } } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); // for debug purposes only: if (DebugDataVisible && PassCount==1) { video::SMaterial debug_mat; debug_mat.Lighting = false; debug_mat.AntiAliasing=0; driver->setMaterial(debug_mat); // show normals if (DebugDataVisible & scene::EDS_NORMALS) { const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); const u32 count = m->getMeshBufferCount(); // draw normals for (u32 g=0; g < count; ++g) { driver->drawMeshBufferNormals(m->getMeshBuffer(g), debugNormalLength, debugNormalColor); } } debug_mat.ZBuffer = video::ECFN_NEVER; debug_mat.Lighting = false; driver->setMaterial(debug_mat); if (DebugDataVisible & scene::EDS_BBOX) driver->draw3DBox(Box, video::SColor(255,255,255,255)); // show bounding box if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) { for (u32 g=0; g< m->getMeshBufferCount(); ++g) { const IMeshBuffer* mb = m->getMeshBuffer(g); if (Mesh->getMeshType() == EAMT_SKINNED) driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); driver->draw3DBox(mb->getBoundingBox(), video::SColor(255,190,128,128)); } } // show skeleton if (DebugDataVisible & scene::EDS_SKELETON) { if (Mesh->getMeshType() == EAMT_SKINNED) { // draw skeleton for (u32 g=0; g < ((ISkinnedMesh*)Mesh)->getAllJoints().size(); ++g) { ISkinnedMesh::SJoint *joint=((ISkinnedMesh*)Mesh)->getAllJoints()[g]; for (u32 n=0;nChildren.size();++n) { driver->draw3DLine(joint->GlobalAnimatedMatrix.getTranslation(), joint->Children[n]->GlobalAnimatedMatrix.getTranslation(), video::SColor(255,51,66,255)); } } } // show tag for quake3 models if (Mesh->getMeshType() == EAMT_MD3) { IAnimatedMesh * arrow = SceneManager->addArrowMesh ( "__tag_show", 0xFF0000FF, 0xFF000088, 4, 8, 5.f, 4.f, 0.5f, 1.f); if (!arrow) { arrow = SceneManager->getMesh ( "__tag_show" ); } IMesh *arrowMesh = arrow->getMesh(0); core::matrix4 matr; SMD3QuaternionTagList *taglist = ((IAnimatedMeshMD3*)Mesh)->getTagList( (s32)getFrameNr(), 255, getStartFrame(), getEndFrame()); if (taglist) { for ( u32 ts = 0; ts != taglist->size(); ++ts ) { (*taglist)[ts].setto(matr); driver->setTransform(video::ETS_WORLD, matr ); for ( u32 a = 0; a != arrowMesh->getMeshBufferCount(); ++a ) driver->drawMeshBuffer(arrowMesh->getMeshBuffer(a)); } } } } // show mesh if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) { debug_mat.Lighting = false; debug_mat.Wireframe = true; debug_mat.ZBuffer = video::ECFN_NEVER; driver->setMaterial(debug_mat); for (u32 g=0; ggetMeshBufferCount(); ++g) { const IMeshBuffer* mb = m->getMeshBuffer(g); if (RenderFromIdentity) driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); else if (Mesh->getMeshType() == EAMT_SKINNED) driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); driver->drawMeshBuffer(mb); } } } } //! Returns the current start frame number. s32 CAnimatedMeshSceneNode::getStartFrame() const { return StartFrame; } //! Returns the current start frame number. s32 CAnimatedMeshSceneNode::getEndFrame() const { return EndFrame; } //! sets the frames between the animation is looped. //! the default is 0 - MaximalFrameCount of the mesh. bool CAnimatedMeshSceneNode::setFrameLoop(s32 begin, s32 end) { const s32 maxFrameCount = Mesh->getFrameCount() - 1; if (end < begin) { StartFrame = core::s32_clamp(end, 0, maxFrameCount); EndFrame = core::s32_clamp(begin, StartFrame, maxFrameCount); } else { StartFrame = core::s32_clamp(begin, 0, maxFrameCount); EndFrame = core::s32_clamp(end, StartFrame, maxFrameCount); } if (FramesPerSecond < 0) setCurrentFrame((f32)EndFrame); else setCurrentFrame((f32)StartFrame); return true; } //! sets the speed with witch the animation is played void CAnimatedMeshSceneNode::setAnimationSpeed(f32 framesPerSecond) { FramesPerSecond = framesPerSecond * 0.001f; } f32 CAnimatedMeshSceneNode::getAnimationSpeed() const { return FramesPerSecond * 1000.f; } //! returns the axis aligned bounding box of this node const core::aabbox3d& CAnimatedMeshSceneNode::getBoundingBox() const { return Box; } //! returns the material based on the zero based index i. To get the amount //! of materials used by this scene node, use getMaterialCount(). //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. video::SMaterial& CAnimatedMeshSceneNode::getMaterial(u32 i) { if (i >= Materials.size()) return ISceneNode::getMaterial(i); return Materials[i]; } //! returns amount of materials used by this scene node. u32 CAnimatedMeshSceneNode::getMaterialCount() const { return Materials.size(); } //! Creates shadow volume scene node as child of this node //! and returns a pointer to it. IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode( const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity) { if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) return 0; if (!shadowMesh) shadowMesh = Mesh; // if null is given, use the mesh of node if (Shadow) Shadow->drop(); Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity); return Shadow; } //! Returns a pointer to a child node, which has the same transformation as //! the corresponding joint, if the mesh in this scene node is a skinned mesh. IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(const c8* jointName) { #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ os::Printer::log("Compiled without _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_", ELL_WARNING); return 0; #else if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) { os::Printer::log("No mesh, or mesh not of skinned mesh type", ELL_WARNING); return 0; } checkJoints(); ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh; const s32 number = skinnedMesh->getJointNumber(jointName); if (number == -1) { os::Printer::log("Joint with specified name not found in skinned mesh", jointName, ELL_DEBUG); return 0; } if ((s32)JointChildSceneNodes.size() <= number) { os::Printer::log("Joint was found in mesh, but is not loaded into node", jointName, ELL_WARNING); return 0; } return JointChildSceneNodes[number]; #endif } //! Returns a pointer to a child node, which has the same transformation as //! the corresponding joint, if the mesh in this scene node is a skinned mesh. IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(u32 jointID) { #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ os::Printer::log("Compiled without _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_", ELL_WARNING); return 0; #else if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) { os::Printer::log("No mesh, or mesh not of skinned mesh type", ELL_WARNING); return 0; } checkJoints(); if (JointChildSceneNodes.size() <= jointID) { os::Printer::log("Joint not loaded into node", ELL_WARNING); return 0; } return JointChildSceneNodes[jointID]; #endif } //! Gets joint count. u32 CAnimatedMeshSceneNode::getJointCount() const { #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ return 0; #else if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) return 0; ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh; return skinnedMesh->getJointCount(); #endif } //! Returns a pointer to a child node, which has the same transformation as //! the corresponding joint, if the mesh in this scene node is a ms3d mesh. ISceneNode* CAnimatedMeshSceneNode::getMS3DJointNode(const c8* jointName) { return getJointNode(jointName); } //! Returns a pointer to a child node, which has the same transformation as //! the corresponding joint, if the mesh in this scene node is a .x mesh. ISceneNode* CAnimatedMeshSceneNode::getXJointNode(const c8* jointName) { return getJointNode(jointName); } //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, //! or to remove attached childs. bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child) { if (child && Shadow == child) { Shadow->drop(); Shadow = 0; } if (ISceneNode::removeChild(child)) { if (JointsUsed) //stop weird bugs caused while changing parents as the joints are being created { for (u32 i=0; igetMeshType() != EAMT_MD2) return false; IAnimatedMeshMD2* md = (IAnimatedMeshMD2*)Mesh; s32 begin, end, speed; md->getFrameLoop(anim, begin, end, speed); setAnimationSpeed( f32(speed) ); setFrameLoop(begin, end); return true; } //! Starts a special MD2 animation. bool CAnimatedMeshSceneNode::setMD2Animation(const c8* animationName) { if (!Mesh || Mesh->getMeshType() != EAMT_MD2) return false; IAnimatedMeshMD2* md = (IAnimatedMeshMD2*)Mesh; s32 begin, end, speed; if (!md->getFrameLoop(animationName, begin, end, speed)) return false; setAnimationSpeed( (f32)speed ); setFrameLoop(begin, end); return true; } //! Sets looping mode which is on by default. If set to false, //! animations will not be looped. void CAnimatedMeshSceneNode::setLoopMode(bool playAnimationLooped) { Looping = playAnimationLooped; } //! returns the current loop mode bool CAnimatedMeshSceneNode::getLoopMode() const { return Looping; } //! Sets a callback interface which will be called if an animation //! playback has ended. Set this to 0 to disable the callback again. void CAnimatedMeshSceneNode::setAnimationEndCallback(IAnimationEndCallBack* callback) { if (callback == LoopCallBack) return; if (LoopCallBack) LoopCallBack->drop(); LoopCallBack = callback; if (LoopCallBack) LoopCallBack->grab(); } //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. void CAnimatedMeshSceneNode::setReadOnlyMaterials(bool readonly) { ReadOnlyMaterials = readonly; } //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style bool CAnimatedMeshSceneNode::isReadOnlyMaterials() const { return ReadOnlyMaterials; } //! Writes attributes of the scene node. void CAnimatedMeshSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { IAnimatedMeshSceneNode::serializeAttributes(out, options); if (options && (options->Flags&io::EARWF_USE_RELATIVE_PATHS) && options->Filename) { const io::path path = SceneManager->getFileSystem()->getRelativeFilename( SceneManager->getFileSystem()->getAbsolutePath(SceneManager->getMeshCache()->getMeshName(Mesh).getPath()), options->Filename); out->addString("Mesh", path.c_str()); } else out->addString("Mesh", SceneManager->getMeshCache()->getMeshName(Mesh).getPath().c_str()); out->addBool("Looping", Looping); out->addBool("ReadOnlyMaterials", ReadOnlyMaterials); out->addFloat("FramesPerSecond", FramesPerSecond); out->addInt("StartFrame", StartFrame); out->addInt("EndFrame", EndFrame); } //! Reads attributes of the scene node. void CAnimatedMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { IAnimatedMeshSceneNode::deserializeAttributes(in, options); io::path oldMeshStr = SceneManager->getMeshCache()->getMeshName(Mesh); io::path newMeshStr = in->getAttributeAsString("Mesh"); Looping = in->getAttributeAsBool("Looping"); ReadOnlyMaterials = in->getAttributeAsBool("ReadOnlyMaterials"); FramesPerSecond = in->getAttributeAsFloat("FramesPerSecond"); StartFrame = in->getAttributeAsInt("StartFrame"); EndFrame = in->getAttributeAsInt("EndFrame"); if (newMeshStr != "" && oldMeshStr != newMeshStr) { IAnimatedMesh* newAnimatedMesh = SceneManager->getMesh(newMeshStr.c_str()); if (newAnimatedMesh) setMesh(newAnimatedMesh); } // TODO: read animation names instead of frame begin and ends } //! Sets a new mesh void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh) { if (!mesh) return; // won't set null mesh if (Mesh != mesh) { if (Mesh) Mesh->drop(); Mesh = mesh; // grab the mesh (it's non-null!) Mesh->grab(); } // get materials and bounding box Box = Mesh->getBoundingBox(); IMesh* m = Mesh->getMesh(0,0); if (m) { Materials.clear(); Materials.reallocate(m->getMeshBufferCount()); for (u32 i=0; igetMeshBufferCount(); ++i) { IMeshBuffer* mb = m->getMeshBuffer(i); if (mb) Materials.push_back(mb->getMaterial()); else Materials.push_back(video::SMaterial()); } } // clean up joint nodes if (JointsUsed) { JointsUsed=false; checkJoints(); } // get start and begin time // setAnimationSpeed(Mesh->getAnimationSpeed()); setFrameLoop(0, Mesh->getFrameCount()); } // returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, // or the absolutetransformation if it's a normal scenenode const SMD3QuaternionTag* CAnimatedMeshSceneNode::getMD3TagTransformation(const core::stringc& tagname) { return MD3Special ? MD3Special->AbsoluteTagList.get(tagname) : 0; } //! updates the absolute position based on the relative and the parents position void CAnimatedMeshSceneNode::updateAbsolutePosition() { IAnimatedMeshSceneNode::updateAbsolutePosition(); if (!Mesh || Mesh->getMeshType() != EAMT_MD3) return; SMD3QuaternionTagList *taglist; taglist = ( (IAnimatedMeshMD3*) Mesh )->getTagList ( (s32)getFrameNr(),255,getStartFrame (),getEndFrame () ); if (taglist) { if (!MD3Special) { MD3Special = new SMD3Special(); } SMD3QuaternionTag parent ( MD3Special->Tagname ); if (Parent && Parent->getType() == ESNT_ANIMATED_MESH) { const SMD3QuaternionTag * p = ((IAnimatedMeshSceneNode*) Parent)->getMD3TagTransformation ( MD3Special->Tagname ); if (p) parent = *p; } SMD3QuaternionTag relative( RelativeTranslation, RelativeRotation ); MD3Special->AbsoluteTagList.set_used ( taglist->size () ); for ( u32 i=0; i!= taglist->size (); ++i ) { MD3Special->AbsoluteTagList[i].position = parent.position + (*taglist)[i].position + relative.position; MD3Special->AbsoluteTagList[i].rotation = parent.rotation * (*taglist)[i].rotation * relative.rotation; } } } //! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set) void CAnimatedMeshSceneNode::setJointMode(E_JOINT_UPDATE_ON_RENDER mode) { checkJoints(); JointMode=mode; } //! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2) //! you must call animateJoints(), or the mesh will not animate void CAnimatedMeshSceneNode::setTransitionTime(f32 time) { const u32 ttime = (u32)core::floor32(time*1000.0f); if (TransitionTime==ttime) return; TransitionTime = ttime; if (ttime != 0) setJointMode(EJUOR_CONTROL); else setJointMode(EJUOR_NONE); } //! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected) void CAnimatedMeshSceneNode::setRenderFromIdentity(bool enable) { RenderFromIdentity=enable; } //! updates the joint positions of this mesh void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions) { #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ return; #else if (Mesh && Mesh->getMeshType() == EAMT_SKINNED ) { checkJoints(); const f32 frame = getFrameNr(); //old? CSkinnedMesh* skinnedMesh=reinterpret_cast(Mesh); skinnedMesh->transferOnlyJointsHintsToMesh( JointChildSceneNodes ); skinnedMesh->animateMesh(frame, 1.0f); skinnedMesh->recoverJointsFromMesh( JointChildSceneNodes); //----------------------------------------- // Transition //----------------------------------------- if (Transiting != 0.f) { // Init additional matrices if (PretransitingSave.size()setPosition( core::lerp( PretransitingSave[n].getTranslation(), JointChildSceneNodes[n]->getPosition(), TransitingBlend)); //------Rotation------ //Code is slow, needs to be fixed up const core::quaternion RotationStart(PretransitingSave[n].getRotationDegrees()*core::DEGTORAD); const core::quaternion RotationEnd(JointChildSceneNodes[n]->getRotation()*core::DEGTORAD); core::quaternion QRotation; QRotation.slerp(RotationStart, RotationEnd, TransitingBlend); core::vector3df tmpVector; QRotation.toEuler(tmpVector); tmpVector*=core::RADTODEG; //convert from radians back to degrees JointChildSceneNodes[n]->setRotation( tmpVector ); //------Scale------ //JointChildSceneNodes[n]->setScale( // core::lerp( // PretransitingSave[n].getScale(), // JointChildSceneNodes[n]->getScale(), // TransitingBlend)); } } if (CalculateAbsolutePositions) { //---slow--- for (u32 n=0;ngetParent()==this) { JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option } } } } #endif } /*! */ void CAnimatedMeshSceneNode::checkJoints() { #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ return; #else if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) return; if (!JointsUsed) { for (u32 i=0; iaddJoints(JointChildSceneNodes, this, SceneManager); ((CSkinnedMesh*)Mesh)->recoverJointsFromMesh(JointChildSceneNodes); JointsUsed=true; JointMode=EJUOR_READ; } #endif } /*! */ void CAnimatedMeshSceneNode::beginTransition() { if (!JointsUsed) return; if (TransitionTime != 0) { //Check the array is big enough if (PretransitingSave.size()getRelativeTransformation(); Transiting = core::reciprocal((f32)TransitionTime); } TransitingBlend = 0.f; } /*! */ ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; if (!newManager) newManager = SceneManager; CAnimatedMeshSceneNode* newNode = new CAnimatedMeshSceneNode(Mesh, NULL, newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale); if (newParent) { newNode->setParent(newParent); // not in constructor because virtual overload for updateAbsolutePosition won't be called newNode->drop(); } newNode->cloneMembers(this, newManager); newNode->Materials = Materials; newNode->Box = Box; newNode->Mesh = Mesh; newNode->StartFrame = StartFrame; newNode->EndFrame = EndFrame; newNode->FramesPerSecond = FramesPerSecond; newNode->CurrentFrameNr = CurrentFrameNr; newNode->JointMode = JointMode; newNode->JointsUsed = JointsUsed; newNode->TransitionTime = TransitionTime; newNode->Transiting = Transiting; newNode->TransitingBlend = TransitingBlend; newNode->Looping = Looping; newNode->ReadOnlyMaterials = ReadOnlyMaterials; newNode->LoopCallBack = LoopCallBack; if (newNode->LoopCallBack) newNode->LoopCallBack->grab(); newNode->PassCount = PassCount; newNode->Shadow = Shadow; if (newNode->Shadow) newNode->Shadow->grab(); newNode->JointChildSceneNodes = JointChildSceneNodes; newNode->PretransitingSave = PretransitingSave; newNode->RenderFromIdentity = RenderFromIdentity; newNode->MD3Special = MD3Special; return newNode; } } // end namespace scene } // end namespace irr irrlicht-1.8.3/source/Irrlicht/CAnimatedMeshMD3.h0000644000000000000000000000741412574354552020262 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_ANIMATED_MESH_MD3_H_INCLUDED__ #define __C_ANIMATED_MESH_MD3_H_INCLUDED__ #include "IAnimatedMeshMD3.h" #include "IReadFile.h" #include "IFileSystem.h" #include "irrArray.h" #include "irrString.h" #include "SMesh.h" #include "SMeshBuffer.h" #include "IQ3Shader.h" namespace irr { namespace scene { class CAnimatedMeshMD3 : public IAnimatedMeshMD3 { public: //! constructor CAnimatedMeshMD3(); //! destructor virtual ~CAnimatedMeshMD3(); //! loads a quake3 md3 file virtual bool loadModelFile(u32 modelIndex, io::IReadFile* file, io::IFileSystem* fs, video::IVideoDriver* driver); // IAnimatedMeshMD3 virtual void setInterpolationShift(u32 shift, u32 loopMode); virtual SMD3Mesh* getOriginalMesh(); virtual SMD3QuaternionTagList* getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop); //IAnimatedMesh virtual u32 getFrameCount() const; //! Gets the default animation speed of the animated mesh. /** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */ virtual f32 getAnimationSpeed() const { return FramesPerSecond; } //! Gets the frame count of the animated mesh. /** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated. The actual speed is set in the scene node the mesh is instantiated in.*/ virtual void setAnimationSpeed(f32 fps) { FramesPerSecond=fps; } virtual IMesh* getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop); virtual const core::aabbox3d& getBoundingBox() const; virtual E_ANIMATED_MESH_TYPE getMeshType() const; //! returns amount of mesh buffers. virtual u32 getMeshBufferCount() const; //! returns pointer to a mesh buffer virtual IMeshBuffer* getMeshBuffer(u32 nr) const; //! Returns pointer to a mesh buffer which fits a material virtual IMeshBuffer* getMeshBuffer(const video::SMaterial &material) const; virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue); //! set user axis aligned bounding box virtual void setBoundingBox(const core::aabbox3df& box); //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX); //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX); private: //! animates one frame inline void Animate(u32 frame); video::SMaterial Material; //! hold original compressed MD3 Info SMD3Mesh *Mesh; u32 IPolShift; u32 LoopMode; f32 Scaling; //! Cache Info struct SCacheInfo { SCacheInfo(s32 frame=-1, s32 start=-1, s32 end=-1 ) : Frame(frame), startFrameLoop(start), endFrameLoop(end) {} bool operator == ( const SCacheInfo &other ) const { return 0 == memcmp ( this, &other, sizeof ( SCacheInfo ) ); } s32 Frame; s32 startFrameLoop; s32 endFrameLoop; }; SCacheInfo Current; //! return a Mesh per frame SMesh* MeshIPol; SMD3QuaternionTagList TagListIPol; IMeshBuffer* createMeshBuffer(const SMD3MeshBuffer* source, io::IFileSystem* fs, video::IVideoDriver* driver); void buildVertexArray(u32 frameA, u32 frameB, f32 interpolate, const SMD3MeshBuffer* source, SMeshBufferLightMap* dest); void buildTagArray(u32 frameA, u32 frameB, f32 interpolate); f32 FramesPerSecond; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CAnimatedMeshMD3.cpp0000644000000000000000000003016112574354552020610 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Fabio Concas / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_MD3_LOADER_ #include "CAnimatedMeshMD3.h" #include "os.h" namespace irr { namespace scene { // byte-align structures #include "irrpack.h" //! General properties of a single animation frame. struct SMD3Frame { f32 mins[3]; // bounding box per frame f32 maxs[3]; f32 position[3]; // position of bounding box f32 radius; // radius of bounding sphere c8 creator[16]; // name of frame } PACK_STRUCT; //! An attachment point for another MD3 model. struct SMD3Tag { c8 Name[64]; //name of 'tag' as it's usually called in the md3 files try to see it as a sub-mesh/seperate mesh-part. f32 position[3]; //relative position of tag f32 rotationMatrix[9]; //3x3 rotation direction of tag } PACK_STRUCT; //!Shader struct SMD3Shader { c8 name[64]; // name of shader s32 shaderIndex; } PACK_STRUCT; // Default alignment #include "irrunpack.h" //! Constructor CAnimatedMeshMD3::CAnimatedMeshMD3() :Mesh(0), IPolShift(0), LoopMode(0), Scaling(1.f)//, FramesPerSecond(25.f) { #ifdef _DEBUG setDebugName("CAnimatedMeshMD3"); #endif Mesh = new SMD3Mesh(); MeshIPol = new SMesh(); setInterpolationShift(0, 0); } //! Destructor CAnimatedMeshMD3::~CAnimatedMeshMD3() { if (Mesh) Mesh->drop(); if (MeshIPol) MeshIPol->drop(); } //! Returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. u32 CAnimatedMeshMD3::getFrameCount() const { return Mesh->MD3Header.numFrames << IPolShift; } //! Rendering Hint void CAnimatedMeshMD3::setInterpolationShift(u32 shift, u32 loopMode) { IPolShift = shift; LoopMode = loopMode; } //! returns amount of mesh buffers. u32 CAnimatedMeshMD3::getMeshBufferCount() const { return MeshIPol->getMeshBufferCount(); } //! returns pointer to a mesh buffer IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(u32 nr) const { return MeshIPol->getMeshBuffer(nr); } //! Returns pointer to a mesh buffer which fits a material IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(const video::SMaterial &material) const { return MeshIPol->getMeshBuffer(material); } void CAnimatedMeshMD3::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) { MeshIPol->setMaterialFlag(flag, newvalue); } //! set the hardware mapping hint, for driver void CAnimatedMeshMD3::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer) { MeshIPol->setHardwareMappingHint(newMappingHint, buffer); } //! flags the meshbuffer as changed, reloads hardware buffers void CAnimatedMeshMD3::setDirty(E_BUFFER_TYPE buffer) { MeshIPol->setDirty(buffer); } //! set user axis aligned bounding box void CAnimatedMeshMD3::setBoundingBox(const core::aabbox3df& box) { MeshIPol->setBoundingBox(box); } //! Returns the animated tag list based on a detail level. 0 is the lowest, 255 the highest detail. SMD3QuaternionTagList *CAnimatedMeshMD3::getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) { if (0 == Mesh) return 0; getMesh(frame, detailLevel, startFrameLoop, endFrameLoop); return &TagListIPol; } //! Returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. IMesh* CAnimatedMeshMD3::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) { if (0 == Mesh) return 0; //! check if we have the mesh in our private cache SCacheInfo candidate(frame, startFrameLoop, endFrameLoop); if (candidate == Current) return MeshIPol; startFrameLoop = core::s32_max(0, startFrameLoop >> IPolShift); endFrameLoop = core::if_c_a_else_b(endFrameLoop < 0, Mesh->MD3Header.numFrames - 1, endFrameLoop >> IPolShift); const u32 mask = 1 << IPolShift; s32 frameA; s32 frameB; f32 iPol; if (LoopMode) { // correct frame to "pixel center" frame -= mask >> 1; // interpolation iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask)); // wrap anim frame >>= IPolShift; frameA = core::if_c_a_else_b(frame < startFrameLoop, endFrameLoop, frame); frameB = core::if_c_a_else_b(frameA + 1 > endFrameLoop, startFrameLoop, frameA + 1); } else { // correct frame to "pixel center" frame -= mask >> 1; iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask)); // clamp anim frame >>= IPolShift; frameA = core::s32_clamp(frame, startFrameLoop, endFrameLoop); frameB = core::s32_min(frameA + 1, endFrameLoop); } // build current vertex for (u32 i = 0; i!= Mesh->Buffer.size(); ++i) { buildVertexArray(frameA, frameB, iPol, Mesh->Buffer[i], (SMeshBufferLightMap*) MeshIPol->getMeshBuffer(i)); } MeshIPol->recalculateBoundingBox(); // build current tags buildTagArray(frameA, frameB, iPol); Current = candidate; return MeshIPol; } //! create a Irrlicht MeshBuffer for a MD3 MeshBuffer IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source, io::IFileSystem* fs, video::IVideoDriver * driver) { SMeshBufferLightMap * dest = new SMeshBufferLightMap(); dest->Vertices.set_used(source->MeshHeader.numVertices); dest->Indices.set_used(source->Indices.size()); u32 i; // fill in static face info for (i = 0; i < source->Indices.size(); i += 3) { dest->Indices[i + 0] = (u16) source->Indices[i + 0]; dest->Indices[i + 1] = (u16) source->Indices[i + 1]; dest->Indices[i + 2] = (u16) source->Indices[i + 2]; } // fill in static vertex info for (i = 0; i!= (u32)source->MeshHeader.numVertices; ++i) { video::S3DVertex2TCoords &v = dest->Vertices[i]; v.Color = 0xFFFFFFFF; v.TCoords.X = source->Tex[i].u; v.TCoords.Y = source->Tex[i].v; v.TCoords2.X = 0.f; v.TCoords2.Y = 0.f; } // load static texture u32 pos = 0; quake3::tTexArray textureArray; quake3::getTextures(textureArray, source->Shader, pos, fs, driver); dest->Material.MaterialType = video::EMT_SOLID; dest->Material.setTexture(0, textureArray[0]); dest->Material.Lighting = false; return dest; } //! build final mesh's vertices from frames frameA and frameB with linear interpolation. void CAnimatedMeshMD3::buildVertexArray(u32 frameA, u32 frameB, f32 interpolate, const SMD3MeshBuffer* source, SMeshBufferLightMap* dest) { const u32 frameOffsetA = frameA * source->MeshHeader.numVertices; const u32 frameOffsetB = frameB * source->MeshHeader.numVertices; const f32 scale = (1.f/ 64.f); for (s32 i = 0; i != source->MeshHeader.numVertices; ++i) { video::S3DVertex2TCoords &v = dest->Vertices [ i ]; const SMD3Vertex &vA = source->Vertices [ frameOffsetA + i ]; const SMD3Vertex &vB = source->Vertices [ frameOffsetB + i ]; // position v.Pos.X = scale * (vA.position[0] + interpolate * (vB.position[0] - vA.position[0])); v.Pos.Y = scale * (vA.position[2] + interpolate * (vB.position[2] - vA.position[2])); v.Pos.Z = scale * (vA.position[1] + interpolate * (vB.position[1] - vA.position[1])); // normal const core::vector3df nA(quake3::getMD3Normal(vA.normal[0], vA.normal[1])); const core::vector3df nB(quake3::getMD3Normal(vB.normal[0], vB.normal[1])); v.Normal.X = nA.X + interpolate * (nB.X - nA.X); v.Normal.Y = nA.Z + interpolate * (nB.Z - nA.Z); v.Normal.Z = nA.Y + interpolate * (nB.Y - nA.Y); } dest->recalculateBoundingBox(); } //! build final mesh's tag from frames frameA and frameB with linear interpolation. void CAnimatedMeshMD3::buildTagArray(u32 frameA, u32 frameB, f32 interpolate) { const u32 frameOffsetA = frameA * Mesh->MD3Header.numTags; const u32 frameOffsetB = frameB * Mesh->MD3Header.numTags; for (s32 i = 0; i != Mesh->MD3Header.numTags; ++i) { SMD3QuaternionTag &d = TagListIPol [ i ]; const SMD3QuaternionTag &qA = Mesh->TagList[ frameOffsetA + i]; const SMD3QuaternionTag &qB = Mesh->TagList[ frameOffsetB + i]; // rotation d.rotation.slerp(qA.rotation, qB.rotation, interpolate); // position d.position.X = qA.position.X + interpolate * (qB.position.X - qA.position.X); d.position.Y = qA.position.Y + interpolate * (qB.position.Y - qA.position.Y); d.position.Z = qA.position.Z + interpolate * (qB.position.Z - qA.position.Z); } } /*! loads a model */ bool CAnimatedMeshMD3::loadModelFile(u32 modelIndex, io::IReadFile* file, io::IFileSystem* fs, video::IVideoDriver* driver) { if (!file) return false; //! Check MD3Header { file->read(&Mesh->MD3Header, sizeof(SMD3Header)); if (strncmp("IDP3", Mesh->MD3Header.headerID, 4)) { os::Printer::log("MD3 Loader: invalid header"); return false; } } //! store model name Mesh->Name = file->getFileName(); u32 i; //! Frame Data (ignore) #if 0 SMD3Frame frameImport; file->seek(Mesh->MD3Header.frameStart); for (i = 0; i != Mesh->MD3Header.numFrames; ++i) { file->read(&frameImport, sizeof(frameImport)); } #endif //! Tag Data const u32 totalTags = Mesh->MD3Header.numTags * Mesh->MD3Header.numFrames; SMD3Tag import; file->seek(Mesh->MD3Header.tagStart); Mesh->TagList.set_used(totalTags); for (i = 0; i != totalTags; ++i) { file->read(&import, sizeof(import)); SMD3QuaternionTag &exp = Mesh->TagList[i]; //! tag name exp.Name = import.Name; //! position exp.position.X = import.position[0]; exp.position.Y = import.position[2]; exp.position.Z = import.position[1]; //! construct quaternion from a RH 3x3 Matrix exp.rotation.set(import.rotationMatrix[7], 0.f, -import.rotationMatrix[6], 1 + import.rotationMatrix[8]); exp.rotation.normalize(); } //! Meshes u32 offset = Mesh->MD3Header.tagEnd; for (i = 0; i != (u32)Mesh->MD3Header.numMeshes; ++i) { //! construct a new mesh buffer SMD3MeshBuffer * buf = new SMD3MeshBuffer(); // !read mesh header info SMD3MeshHeader &meshHeader = buf->MeshHeader; //! read mesh info file->seek(offset); file->read(&meshHeader, sizeof(SMD3MeshHeader)); //! prepare memory buf->Vertices.set_used(meshHeader.numVertices * Mesh->MD3Header.numFrames); buf->Indices.set_used(meshHeader.numTriangles * 3); buf->Tex.set_used(meshHeader.numVertices); //! read skins (shaders). should be 1 per meshbuffer SMD3Shader skin; file->seek(offset + buf->MeshHeader.offset_shaders); for (s32 g = 0; g != buf->MeshHeader.numShader; ++g) { file->read(&skin, sizeof(skin)); io::path name; cutFilenameExtension(name, skin.name); name.replace('\\', '/'); buf->Shader = name; } //! read texture coordinates file->seek(offset + buf->MeshHeader.offset_st); file->read(buf->Tex.pointer(), buf->MeshHeader.numVertices * sizeof(SMD3TexCoord)); //! read vertices file->seek(offset + meshHeader.vertexStart); file->read(buf->Vertices.pointer(), Mesh->MD3Header.numFrames * meshHeader.numVertices * sizeof(SMD3Vertex)); //! read indices file->seek(offset + meshHeader.offset_triangles); file->read(buf->Indices.pointer(), meshHeader.numTriangles * sizeof(SMD3Face)); //! store meshBuffer Mesh->Buffer.push_back(buf); offset += meshHeader.offset_end; } // Init Mesh Interpolation for (i = 0; i != Mesh->Buffer.size(); ++i) { IMeshBuffer * buffer = createMeshBuffer(Mesh->Buffer[i], fs, driver); MeshIPol->addMeshBuffer(buffer); buffer->drop(); } MeshIPol->recalculateBoundingBox(); // Init Tag Interpolation for (i = 0; i != (u32)Mesh->MD3Header.numTags; ++i) { TagListIPol.push_back(Mesh->TagList[i]); } return true; } SMD3Mesh * CAnimatedMeshMD3::getOriginalMesh() { return Mesh; } //! Returns an axis aligned bounding box const core::aabbox3d& CAnimatedMeshMD3::getBoundingBox() const { return MeshIPol->BoundingBox; } //! Returns the type of the animated mesh. E_ANIMATED_MESH_TYPE CAnimatedMeshMD3::getMeshType() const { return EAMT_MD3; } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_MD3_LOADER_ irrlicht-1.8.3/source/Irrlicht/CAnimatedMeshMD2.h0000644000000000000000000001057512574354552020263 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_ANIMATED_MESH_MD2_H_INCLUDED__ #define __C_ANIMATED_MESH_MD2_H_INCLUDED__ #include "IAnimatedMeshMD2.h" #include "IMesh.h" #include "CMeshBuffer.h" #include "IReadFile.h" #include "S3DVertex.h" #include "irrArray.h" #include "irrString.h" namespace irr { namespace scene { class CAnimatedMeshMD2 : public IAnimatedMeshMD2 { public: //! constructor CAnimatedMeshMD2(); //! destructor virtual ~CAnimatedMeshMD2(); //! returns the amount of frames. If the amount is 1, it is a static (=non animated) mesh. virtual u32 getFrameCount() const; //! Gets the default animation speed of the animated mesh. /** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */ virtual f32 getAnimationSpeed() const { return FramesPerSecond; } //! Gets the frame count of the animated mesh. /** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated. The actual speed is set in the scene node the mesh is instantiated in.*/ virtual void setAnimationSpeed(f32 fps) { FramesPerSecond=fps; } //! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level. virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1); //! returns amount of mesh buffers. virtual u32 getMeshBufferCount() const; //! returns pointer to a mesh buffer virtual IMeshBuffer* getMeshBuffer(u32 nr) const; //! Returns pointer to a mesh buffer which fits a material /** \param material: material to search for \return Returns the pointer to the mesh buffer or NULL if there is no such mesh buffer. */ virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const; //! returns an axis aligned bounding box virtual const core::aabbox3d& getBoundingBox() const; //! set user axis aligned bounding box virtual void setBoundingBox( const core::aabbox3df& box); //! sets a flag of all contained materials to a new value virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue); //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX); //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX); //! Returns the type of the animated mesh. virtual E_ANIMATED_MESH_TYPE getMeshType() const; //! Returns frame loop data for a special MD2 animation type. virtual void getFrameLoop(EMD2_ANIMATION_TYPE, s32& outBegin, s32& outEnd, s32& outFps) const; //! Returns frame loop data for a special MD2 animation type. virtual bool getFrameLoop(const c8* name, s32& outBegin, s32& outEnd, s32& outFps) const; //! Returns amount of md2 animations in this file. virtual s32 getAnimationCount() const; //! Returns name of md2 animation. //! \param nr: Zero based index of animation. virtual const c8* getAnimationName(s32 nr) const; // // exposed for loader // //! the buffer that contains the most recent animation SMeshBuffer* InterpolationBuffer; //! named animations struct SAnimationData { core::stringc name; s32 begin; s32 end; s32 fps; }; //! scale and translations for keyframes struct SKeyFrameTransform { core::vector3df scale; core::vector3df translate; }; //! md2 vertex data struct SMD2Vert { core::vector3d Pos; u8 NormalIdx; }; //! keyframe transformations core::array FrameTransforms; //! keyframe vertex data core::array *FrameList; //! bounding boxes for each keyframe core::array > BoxList; //! named animations core::array< SAnimationData > AnimationData; u32 FrameCount; private: //! updates the interpolation buffer void updateInterpolationBuffer(s32 frame, s32 startFrame, s32 endFrame); f32 FramesPerSecond; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CAnimatedMeshMD2.cpp0000644000000000000000000003443112574354552020613 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_MD2_LOADER_ #include "CAnimatedMeshMD2.h" #include "SColor.h" #include "irrMath.h" namespace irr { namespace scene { const s32 MD2_FRAME_SHIFT = 2; const f32 MD2_FRAME_SHIFT_RECIPROCAL = 1.f / (1 << MD2_FRAME_SHIFT); const s32 Q2_VERTEX_NORMAL_TABLE_SIZE = 162; static const f32 Q2_VERTEX_NORMAL_TABLE[Q2_VERTEX_NORMAL_TABLE_SIZE][3] = { {-0.525731f, 0.000000f, 0.850651f}, {-0.442863f, 0.238856f, 0.864188f}, {-0.295242f, 0.000000f, 0.955423f}, {-0.309017f, 0.500000f, 0.809017f}, {-0.162460f, 0.262866f, 0.951056f}, {0.000000f, 0.000000f, 1.000000f}, {0.000000f, 0.850651f, 0.525731f}, {-0.147621f, 0.716567f, 0.681718f}, {0.147621f, 0.716567f, 0.681718f}, {0.000000f, 0.525731f, 0.850651f}, {0.309017f, 0.500000f, 0.809017f}, {0.525731f, 0.000000f, 0.850651f}, {0.295242f, 0.000000f, 0.955423f}, {0.442863f, 0.238856f, 0.864188f}, {0.162460f, 0.262866f, 0.951056f}, {-0.681718f, 0.147621f, 0.716567f}, {-0.809017f, 0.309017f, 0.500000f}, {-0.587785f, 0.425325f, 0.688191f}, {-0.850651f, 0.525731f, 0.000000f}, {-0.864188f, 0.442863f, 0.238856f}, {-0.716567f, 0.681718f, 0.147621f}, {-0.688191f, 0.587785f, 0.425325f}, {-0.500000f, 0.809017f, 0.309017f}, {-0.238856f, 0.864188f, 0.442863f}, {-0.425325f, 0.688191f, 0.587785f}, {-0.716567f, 0.681718f, -0.147621f}, {-0.500000f, 0.809017f, -0.309017f}, {-0.525731f, 0.850651f, 0.000000f}, {0.000000f, 0.850651f, -0.525731f}, {-0.238856f, 0.864188f, -0.442863f}, {0.000000f, 0.955423f, -0.295242f}, {-0.262866f, 0.951056f, -0.162460f}, {0.000000f, 1.000000f, 0.000000f}, {0.000000f, 0.955423f, 0.295242f}, {-0.262866f, 0.951056f, 0.162460f}, {0.238856f, 0.864188f, 0.442863f}, {0.262866f, 0.951056f, 0.162460f}, {0.500000f, 0.809017f, 0.309017f}, {0.238856f, 0.864188f, -0.442863f}, {0.262866f, 0.951056f, -0.162460f}, {0.500000f, 0.809017f, -0.309017f}, {0.850651f, 0.525731f, 0.000000f}, {0.716567f, 0.681718f, 0.147621f}, {0.716567f, 0.681718f, -0.147621f}, {0.525731f, 0.850651f, 0.000000f}, {0.425325f, 0.688191f, 0.587785f}, {0.864188f, 0.442863f, 0.238856f}, {0.688191f, 0.587785f, 0.425325f}, {0.809017f, 0.309017f, 0.500000f}, {0.681718f, 0.147621f, 0.716567f}, {0.587785f, 0.425325f, 0.688191f}, {0.955423f, 0.295242f, 0.000000f}, {1.000000f, 0.000000f, 0.000000f}, {0.951056f, 0.162460f, 0.262866f}, {0.850651f, -0.525731f, 0.000000f}, {0.955423f, -0.295242f, 0.000000f}, {0.864188f, -0.442863f, 0.238856f}, {0.951056f, -0.162460f, 0.262866f}, {0.809017f, -0.309017f, 0.500000f}, {0.681718f, -0.147621f, 0.716567f}, {0.850651f, 0.000000f, 0.525731f}, {0.864188f, 0.442863f, -0.238856f}, {0.809017f, 0.309017f, -0.500000f}, {0.951056f, 0.162460f, -0.262866f}, {0.525731f, 0.000000f, -0.850651f}, {0.681718f, 0.147621f, -0.716567f}, {0.681718f, -0.147621f, -0.716567f}, {0.850651f, 0.000000f, -0.525731f}, {0.809017f, -0.309017f, -0.500000f}, {0.864188f, -0.442863f, -0.238856f}, {0.951056f, -0.162460f, -0.262866f}, {0.147621f, 0.716567f, -0.681718f}, {0.309017f, 0.500000f, -0.809017f}, {0.425325f, 0.688191f, -0.587785f}, {0.442863f, 0.238856f, -0.864188f}, {0.587785f, 0.425325f, -0.688191f}, {0.688191f, 0.587785f, -0.425325f}, {-0.147621f, 0.716567f, -0.681718f}, {-0.309017f, 0.500000f, -0.809017f}, {0.000000f, 0.525731f, -0.850651f}, {-0.525731f, 0.000000f, -0.850651f}, {-0.442863f, 0.238856f, -0.864188f}, {-0.295242f, 0.000000f, -0.955423f}, {-0.162460f, 0.262866f, -0.951056f}, {0.000000f, 0.000000f, -1.000000f}, {0.295242f, 0.000000f, -0.955423f}, {0.162460f, 0.262866f, -0.951056f}, {-0.442863f, -0.238856f, -0.864188f}, {-0.309017f, -0.500000f, -0.809017f}, {-0.162460f, -0.262866f, -0.951056f}, {0.000000f, -0.850651f, -0.525731f}, {-0.147621f, -0.716567f, -0.681718f}, {0.147621f, -0.716567f, -0.681718f}, {0.000000f, -0.525731f, -0.850651f}, {0.309017f, -0.500000f, -0.809017f}, {0.442863f, -0.238856f, -0.864188f}, {0.162460f, -0.262866f, -0.951056f}, {0.238856f, -0.864188f, -0.442863f}, {0.500000f, -0.809017f, -0.309017f}, {0.425325f, -0.688191f, -0.587785f}, {0.716567f, -0.681718f, -0.147621f}, {0.688191f, -0.587785f, -0.425325f}, {0.587785f, -0.425325f, -0.688191f}, {0.000000f, -0.955423f, -0.295242f}, {0.000000f, -1.000000f, 0.000000f}, {0.262866f, -0.951056f, -0.162460f}, {0.000000f, -0.850651f, 0.525731f}, {0.000000f, -0.955423f, 0.295242f}, {0.238856f, -0.864188f, 0.442863f}, {0.262866f, -0.951056f, 0.162460f}, {0.500000f, -0.809017f, 0.309017f}, {0.716567f, -0.681718f, 0.147621f}, {0.525731f, -0.850651f, 0.000000f}, {-0.238856f, -0.864188f, -0.442863f}, {-0.500000f, -0.809017f, -0.309017f}, {-0.262866f, -0.951056f, -0.162460f}, {-0.850651f, -0.525731f, 0.000000f}, {-0.716567f, -0.681718f, -0.147621f}, {-0.716567f, -0.681718f, 0.147621f}, {-0.525731f, -0.850651f, 0.000000f}, {-0.500000f, -0.809017f, 0.309017f}, {-0.238856f, -0.864188f, 0.442863f}, {-0.262866f, -0.951056f, 0.162460f}, {-0.864188f, -0.442863f, 0.238856f}, {-0.809017f, -0.309017f, 0.500000f}, {-0.688191f, -0.587785f, 0.425325f}, {-0.681718f, -0.147621f, 0.716567f}, {-0.442863f, -0.238856f, 0.864188f}, {-0.587785f, -0.425325f, 0.688191f}, {-0.309017f, -0.500000f, 0.809017f}, {-0.147621f, -0.716567f, 0.681718f}, {-0.425325f, -0.688191f, 0.587785f}, {-0.162460f, -0.262866f, 0.951056f}, {0.442863f, -0.238856f, 0.864188f}, {0.162460f, -0.262866f, 0.951056f}, {0.309017f, -0.500000f, 0.809017f}, {0.147621f, -0.716567f, 0.681718f}, {0.000000f, -0.525731f, 0.850651f}, {0.425325f, -0.688191f, 0.587785f}, {0.587785f, -0.425325f, 0.688191f}, {0.688191f, -0.587785f, 0.425325f}, {-0.955423f, 0.295242f, 0.000000f}, {-0.951056f, 0.162460f, 0.262866f}, {-1.000000f, 0.000000f, 0.000000f}, {-0.850651f, 0.000000f, 0.525731f}, {-0.955423f, -0.295242f, 0.000000f}, {-0.951056f, -0.162460f, 0.262866f}, {-0.864188f, 0.442863f, -0.238856f}, {-0.951056f, 0.162460f, -0.262866f}, {-0.809017f, 0.309017f, -0.500000f}, {-0.864188f, -0.442863f, -0.238856f}, {-0.951056f, -0.162460f, -0.262866f}, {-0.809017f, -0.309017f, -0.500000f}, {-0.681718f, 0.147621f, -0.716567f}, {-0.681718f, -0.147621f, -0.716567f}, {-0.850651f, 0.000000f, -0.525731f}, {-0.688191f, 0.587785f, -0.425325f}, {-0.587785f, 0.425325f, -0.688191f}, {-0.425325f, 0.688191f, -0.587785f}, {-0.425325f, -0.688191f, -0.587785f}, {-0.587785f, -0.425325f, -0.688191f}, {-0.688191f, -0.587785f, -0.425325f}, }; struct SMD2AnimationType { s32 begin; s32 end; s32 fps; }; static const SMD2AnimationType MD2AnimationTypeList[21] = { { 0, 39, 9}, // STAND { 40, 45, 10}, // RUN { 46, 53, 10}, // ATTACK { 54, 57, 7}, // PAIN_A { 58, 61, 7}, // PAIN_B { 62, 65, 7}, // PAIN_C { 66, 71, 7}, // JUMP { 72, 83, 7}, // FLIP { 84, 94, 7}, // SALUTE { 95, 111, 10}, // FALLBACK {112, 122, 7}, // WAVE {123, 134, 6}, // POINT {135, 153, 10}, // CROUCH_STAND {154, 159, 7}, // CROUCH_WALK {160, 168, 10}, // CROUCH_ATTACK {169, 172, 7}, // CROUCH_PAIN {173, 177, 5}, // CROUCH_DEATH {178, 183, 7}, // DEATH_FALLBACK {184, 189, 7}, // DEATH_FALLFORWARD {190, 197, 7}, // DEATH_FALLBACKSLOW {198, 198, 5}, // BOOM }; //! constructor CAnimatedMeshMD2::CAnimatedMeshMD2() : InterpolationBuffer(0), FrameList(0), FrameCount(0), FramesPerSecond((f32)(MD2AnimationTypeList[0].fps << MD2_FRAME_SHIFT)) { #ifdef _DEBUG IAnimatedMesh::setDebugName("CAnimatedMeshMD2 IAnimatedMesh"); IMesh::setDebugName("CAnimatedMeshMD2 IMesh"); #endif InterpolationBuffer = new SMeshBuffer; } //! destructor CAnimatedMeshMD2::~CAnimatedMeshMD2() { delete [] FrameList; if (InterpolationBuffer) InterpolationBuffer->drop(); } //! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. u32 CAnimatedMeshMD2::getFrameCount() const { return FrameCount< getFrameCount()) frame = (frame % getFrameCount()); if (startFrameLoop == -1 && endFrameLoop == -1) { startFrameLoop = 0; endFrameLoop = getFrameCount(); } updateInterpolationBuffer(frame, startFrameLoop, endFrameLoop); return this; } //! returns amount of mesh buffers. MD2 meshes only have one buffer u32 CAnimatedMeshMD2::getMeshBufferCount() const { return 1; } //! returns pointer to a mesh buffer IMeshBuffer* CAnimatedMeshMD2::getMeshBuffer(u32 nr) const { if (nr == 0) return InterpolationBuffer; else return 0; } //! Returns pointer to a mesh buffer which fits a material IMeshBuffer* CAnimatedMeshMD2::getMeshBuffer(const video::SMaterial &material) const { if (InterpolationBuffer->Material == material) return InterpolationBuffer; else return 0; } // updates the interpolation buffer void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop, s32 endFrameLoop) { u32 firstFrame, secondFrame; f32 div; // TA: resolve missing ipol in loop between end-start if (endFrameLoop - startFrameLoop == 0) { firstFrame = frame>>MD2_FRAME_SHIFT; secondFrame = frame>>MD2_FRAME_SHIFT; div = 1.0f; } else { // key frames u32 s = startFrameLoop >> MD2_FRAME_SHIFT; u32 e = endFrameLoop >> MD2_FRAME_SHIFT; firstFrame = frame >> MD2_FRAME_SHIFT; secondFrame = core::if_c_a_else_b(firstFrame + 1 > e, s, firstFrame + 1); firstFrame = core::s32_min(FrameCount - 1, firstFrame); secondFrame = core::s32_min(FrameCount - 1, secondFrame); //div = (frame % (1<(InterpolationBuffer->getVertices()); SMD2Vert* first = FrameList[firstFrame].pointer(); SMD2Vert* second = FrameList[secondFrame].pointer(); // interpolate both frames const u32 count = FrameList[firstFrame].size(); for (u32 i=0; iPos.X) * FrameTransforms[firstFrame].scale.X + FrameTransforms[firstFrame].translate.X, f32(first->Pos.Y) * FrameTransforms[firstFrame].scale.Y + FrameTransforms[firstFrame].translate.Y, f32(first->Pos.Z) * FrameTransforms[firstFrame].scale.Z + FrameTransforms[firstFrame].translate.Z); const core::vector3df two = core::vector3df(f32(second->Pos.X) * FrameTransforms[secondFrame].scale.X + FrameTransforms[secondFrame].translate.X, f32(second->Pos.Y) * FrameTransforms[secondFrame].scale.Y + FrameTransforms[secondFrame].translate.Y, f32(second->Pos.Z) * FrameTransforms[secondFrame].scale.Z + FrameTransforms[secondFrame].translate.Z); target->Pos = two.getInterpolated(one, div); const core::vector3df n1( Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][0], Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][2], Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][1]); const core::vector3df n2( Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][0], Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][2], Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][1]); target->Normal = n2.getInterpolated(n1, div); ++target; ++first; ++second; } //update bounding box InterpolationBuffer->setBoundingBox(BoxList[secondFrame].getInterpolated(BoxList[firstFrame], div)); InterpolationBuffer->setDirty(); } //! sets a flag of all contained materials to a new value void CAnimatedMeshMD2::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) { InterpolationBuffer->Material.setFlag(flag, newvalue); } //! set the hardware mapping hint, for driver void CAnimatedMeshMD2::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer) { InterpolationBuffer->setHardwareMappingHint(newMappingHint, buffer); } //! flags the meshbuffer as changed, reloads hardware buffers void CAnimatedMeshMD2::setDirty(E_BUFFER_TYPE buffer) { InterpolationBuffer->setDirty(buffer); } //! returns an axis aligned bounding box const core::aabbox3d& CAnimatedMeshMD2::getBoundingBox() const { return InterpolationBuffer->BoundingBox; } //! set user axis aligned bounding box void CAnimatedMeshMD2::setBoundingBox(const core::aabbox3df& box) { InterpolationBuffer->BoundingBox = box; } //! Returns the type of the animated mesh. E_ANIMATED_MESH_TYPE CAnimatedMeshMD2::getMeshType() const { return EAMT_MD2; } //! Returns frame loop data for a special MD2 animation type. void CAnimatedMeshMD2::getFrameLoop(EMD2_ANIMATION_TYPE l, s32& outBegin, s32& outEnd, s32& outFPS) const { if (l < 0 || l >= EMAT_COUNT) return; outBegin = MD2AnimationTypeList[l].begin << MD2_FRAME_SHIFT; outEnd = MD2AnimationTypeList[l].end << MD2_FRAME_SHIFT; // correct to anim between last->first frame outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1; outFPS = MD2AnimationTypeList[l].fps << MD2_FRAME_SHIFT; } //! Returns frame loop data for a special MD2 animation type. bool CAnimatedMeshMD2::getFrameLoop(const c8* name, s32& outBegin, s32&outEnd, s32& outFPS) const { for (u32 i=0; i < AnimationData.size(); ++i) { if (AnimationData[i].name == name) { outBegin = AnimationData[i].begin << MD2_FRAME_SHIFT; outEnd = AnimationData[i].end << MD2_FRAME_SHIFT; outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1; outFPS = AnimationData[i].fps << MD2_FRAME_SHIFT; return true; } } return false; } //! Returns amount of md2 animations in this file. s32 CAnimatedMeshMD2::getAnimationCount() const { return AnimationData.size(); } //! Returns name of md2 animation. const c8* CAnimatedMeshMD2::getAnimationName(s32 nr) const { if ((u32)nr >= AnimationData.size()) return 0; return AnimationData[nr].name.c_str(); } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_MD2_LOADER_ irrlicht-1.8.3/source/Irrlicht/CAnimatedMeshHalfLife.h0000644000000000000000000003743612574354552021360 0ustar rootroot// Copyright (C) 2002-2012 Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_ANIMATED_MESH_HALFLIFE_H_INCLUDED__ #define __C_ANIMATED_MESH_HALFLIFE_H_INCLUDED__ #include "IAnimatedMesh.h" #include "ISceneManager.h" #include "irrArray.h" #include "irrString.h" #include "IMeshLoader.h" #include "SMesh.h" #include "IReadFile.h" namespace irr { namespace scene { // STUDIO MODELS, Copyright (c) 1998, Valve LLC. All rights reserved. #define MAXSTUDIOTRIANGLES 20000 // TODO: tune this #define MAXSTUDIOVERTS 2048 // TODO: tune this #define MAXSTUDIOSEQUENCES 256 // total animation sequences #define MAXSTUDIOSKINS 100 // total textures #define MAXSTUDIOSRCBONES 512 // bones allowed at source movement #define MAXSTUDIOBONES 128 // total bones actually used #define MAXSTUDIOMODELS 32 // sub-models per model #define MAXSTUDIOBODYPARTS 32 #define MAXSTUDIOGROUPS 4 #define MAXSTUDIOANIMATIONS 512 // per sequence #define MAXSTUDIOMESHES 256 #define MAXSTUDIOEVENTS 1024 #define MAXSTUDIOPIVOTS 256 #define MAXSTUDIOCONTROLLERS 8 typedef f32 vec3_hl[3]; // x,y,z typedef f32 vec4_hl[4]; // x,y,z,w // byte-align structures #include "irrpack.h" struct SHalflifeHeader { c8 id[4]; s32 version; c8 name[64]; s32 length; vec3_hl eyeposition; // ideal eye position vec3_hl min; // ideal movement hull size vec3_hl max; vec3_hl bbmin; // clipping bounding box vec3_hl bbmax; s32 flags; u32 numbones; // bones u32 boneindex; u32 numbonecontrollers; // bone controllers u32 bonecontrollerindex; u32 numhitboxes; // complex bounding boxes u32 hitboxindex; u32 numseq; // animation sequences u32 seqindex; u32 numseqgroups; // demand loaded sequences u32 seqgroupindex; u32 numtextures; // raw textures u32 textureindex; u32 texturedataindex; u32 numskinref; // replaceable textures u32 numskinfamilies; u32 skinindex; u32 numbodyparts; u32 bodypartindex; u32 numattachments; // queryable attachable points u32 attachmentindex; s32 soundtable; s32 soundindex; s32 soundgroups; s32 soundgroupindex; s32 numtransitions; // animation node to animation node transition graph s32 transitionindex; } PACK_STRUCT; // header for demand loaded sequence group data struct studioseqhdr_t { s32 id; s32 version; c8 name[64]; s32 length; } PACK_STRUCT; // bones struct SHalflifeBone { c8 name[32]; // bone name for symbolic links s32 parent; // parent bone s32 flags; // ?? s32 bonecontroller[6]; // bone controller index, -1 == none f32 value[6]; // default DoF values f32 scale[6]; // scale for delta DoF values } PACK_STRUCT; // bone controllers struct SHalflifeBoneController { s32 bone; // -1 == 0 s32 type; // X, Y, Z, XR, YR, ZR, M f32 start; f32 end; s32 rest; // byte index value at rest s32 index; // 0-3 user set controller, 4 mouth } PACK_STRUCT; // intersection boxes struct SHalflifeBBox { s32 bone; s32 group; // intersection group vec3_hl bbmin; // bounding box vec3_hl bbmax; } PACK_STRUCT; #ifndef ZONE_H // NOTE: this was a void*, but that crashes on 64bit. // I have found no mdl format desc, so not sure what it's meant to be, but s32 at least works. typedef s32 cache_user_t; #endif // demand loaded sequence groups struct SHalflifeSequenceGroup { c8 label[32]; // textual name c8 name[64]; // file name cache_user_t cache; // cache index pointer s32 data; // hack for group 0 } PACK_STRUCT; // sequence descriptions struct SHalflifeSequence { c8 label[32]; // sequence label f32 fps; // frames per second s32 flags; // looping/non-looping flags s32 activity; s32 actweight; s32 numevents; s32 eventindex; s32 numframes; // number of frames per sequence u32 numpivots; // number of foot pivots u32 pivotindex; s32 motiontype; s32 motionbone; vec3_hl linearmovement; s32 automoveposindex; s32 automoveangleindex; vec3_hl bbmin; // per sequence bounding box vec3_hl bbmax; s32 numblends; s32 animindex; // SHalflifeAnimOffset pointer relative to start of sequence group data // [blend][bone][X, Y, Z, XR, YR, ZR] s32 blendtype[2]; // X, Y, Z, XR, YR, ZR f32 blendstart[2]; // starting value f32 blendend[2]; // ending value s32 blendparent; s32 seqgroup; // sequence group for demand loading s32 entrynode; // transition node at entry s32 exitnode; // transition node at exit s32 nodeflags; // transition rules s32 nextseq; // auto advancing sequences } PACK_STRUCT; // events struct mstudioevent_t { s32 frame; s32 event; s32 type; c8 options[64]; } PACK_STRUCT; // pivots struct mstudiopivot_t { vec3_hl org; // pivot point s32 start; s32 end; } PACK_STRUCT; // attachment struct SHalflifeAttachment { c8 name[32]; s32 type; s32 bone; vec3_hl org; // attachment point vec3_hl vectors[3]; } PACK_STRUCT; struct SHalflifeAnimOffset { u16 offset[6]; } PACK_STRUCT; // animation frames union SHalflifeAnimationFrame { struct { u8 valid; u8 total; } PACK_STRUCT num; s16 value; } PACK_STRUCT; // body part index struct SHalflifeBody { c8 name[64]; u32 nummodels; u32 base; u32 modelindex; // index into models array } PACK_STRUCT; // skin info struct SHalflifeTexture { c8 name[64]; s32 flags; s32 width; s32 height; s32 index; } PACK_STRUCT; // skin families // short index[skinfamilies][skinref] // studio models struct SHalflifeModel { c8 name[64]; s32 type; f32 boundingradius; u32 nummesh; u32 meshindex; u32 numverts; // number of unique vertices u32 vertinfoindex; // vertex bone info u32 vertindex; // vertex vec3_hl u32 numnorms; // number of unique surface normals u32 norminfoindex; // normal bone info u32 normindex; // normal vec3_hl u32 numgroups; // deformation groups u32 groupindex; } PACK_STRUCT; // meshes struct SHalflifeMesh { u32 numtris; u32 triindex; u32 skinref; u32 numnorms; // per mesh normals u32 normindex; // normal vec3_hl } PACK_STRUCT; // Default alignment #include "irrunpack.h" // lighting options #define STUDIO_NF_FLATSHADE 0x0001 #define STUDIO_NF_CHROME 0x0002 #define STUDIO_NF_FULLBRIGHT 0x0004 // motion flags #define STUDIO_X 0x0001 #define STUDIO_Y 0x0002 #define STUDIO_Z 0x0004 #define STUDIO_XR 0x0008 #define STUDIO_YR 0x0010 #define STUDIO_ZR 0x0020 #define STUDIO_LX 0x0040 #define STUDIO_LY 0x0080 #define STUDIO_LZ 0x0100 #define STUDIO_AX 0x0200 #define STUDIO_AY 0x0400 #define STUDIO_AZ 0x0800 #define STUDIO_AXR 0x1000 #define STUDIO_AYR 0x2000 #define STUDIO_AZR 0x4000 #define STUDIO_TYPES 0x7FFF #define STUDIO_RLOOP 0x8000 // controller that wraps shortest distance // sequence flags #define STUDIO_LOOPING 0x0001 // bone flags #define STUDIO_HAS_NORMALS 0x0001 #define STUDIO_HAS_VERTICES 0x0002 #define STUDIO_HAS_BBOX 0x0004 #define STUDIO_HAS_CHROME 0x0008 // if any of the textures have chrome on them #define RAD_TO_STUDIO (32768.0/M_PI) #define STUDIO_TO_RAD (M_PI/32768.0) /*! Textureatlas Combine Source Images with arbitrary size and bithdepth to an Image with 2^n size borders from the source images are copied around for allowing filtering ( bilinear, mipmap ) */ struct STextureAtlas { STextureAtlas () { release(); } virtual ~STextureAtlas () { release (); } void release (); void addSource ( const c8 * name, video::IImage * image ); void create ( u32 pixelborder, video::E_TEXTURE_CLAMP texmode ); void getScale ( core::vector2df &scale ); void getTranslation ( const c8 * name, core::vector2di &pos ); struct TextureAtlasEntry { io::path name; u32 width; u32 height; core::vector2di pos; video::IImage * image; bool operator < ( const TextureAtlasEntry & other ) { return height > other.height; } }; core::array < TextureAtlasEntry > atlas; video::IImage * Master; }; //! Possible types of Animation Type enum E_ANIMATION_TYPE { //! No Animation EAMT_STILL, //! From Start to End, then Stop ( Limited Line ) EAMT_WAYPOINT, //! Linear Cycling Animation ( Sawtooth ) EAMT_LOOPING, //! Linear bobbing ( Triangle ) EAMT_PINGPONG }; //! Names for Animation Type const c8* const MeshAnimationTypeNames[] = { "still", "waypoint", "looping", "pingpong", 0 }; //! Data for holding named Animation Info struct KeyFrameInterpolation { core::stringc Name; // Name of the current Animation/Bone E_ANIMATION_TYPE AnimationType; // Type of Animation ( looping, usw..) f32 CurrentFrame; // Current Frame s32 NextFrame; // Frame which will be used next. For blending s32 StartFrame; // Absolute Frame where the current animation start s32 Frames; // Relative Frames how much Frames this animation have s32 LoopingFrames; // How much of Frames sould be looped s32 EndFrame; // Absolute Frame where the current animation ends End = start + frames - 1 f32 FramesPerSecond; // Speed in Frames/Seconds the animation is played f32 RelativeSpeed; // Factor Original fps is modified u32 BeginTime; // Animation started at this thime u32 EndTime; // Animation end at this time u32 LastTime; // Last Keyframe was done at this time KeyFrameInterpolation ( const c8 * name = "", s32 start = 0, s32 frames = 0, s32 loopingframes = 0, f32 fps = 0.f, f32 relativefps = 1.f ) : Name ( name ), AnimationType ( loopingframes ? EAMT_LOOPING : EAMT_WAYPOINT), CurrentFrame ( (f32) start ), NextFrame ( start ), StartFrame ( start ), Frames ( frames ), LoopingFrames ( loopingframes ), EndFrame ( start + frames - 1 ), FramesPerSecond ( fps ), RelativeSpeed ( relativefps ), BeginTime ( 0 ), EndTime ( 0 ), LastTime ( 0 ) { } // linear search bool operator == ( const KeyFrameInterpolation & other ) const { return Name.equals_ignore_case ( other.Name ); } }; //! a List holding named Animations typedef core::array < KeyFrameInterpolation > IAnimationList; //! a List holding named Skins typedef core::array < core::stringc > ISkinList; // Current Model per Body struct SubModel { core::stringc name; u32 startBuffer; u32 endBuffer; u32 state; }; struct BodyPart { core::stringc name; u32 defaultModel; core::array < SubModel > model; }; //! a List holding named Models and SubModels typedef core::array < BodyPart > IBodyList; class CAnimatedMeshHalfLife : public IAnimatedMesh { public: //! constructor CAnimatedMeshHalfLife(); //! destructor virtual ~CAnimatedMeshHalfLife(); //! loads a Halflife mdl file virtual bool loadModelFile( io::IReadFile* file, ISceneManager * smgr ); //IAnimatedMesh virtual u32 getFrameCount() const; virtual IMesh* getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop); virtual const core::aabbox3d& getBoundingBox() const; virtual E_ANIMATED_MESH_TYPE getMeshType() const; virtual void renderModel ( u32 param, video::IVideoDriver * driver, const core::matrix4 &absoluteTransformation); //! returns amount of mesh buffers. virtual u32 getMeshBufferCount() const; //! returns pointer to a mesh buffer virtual IMeshBuffer* getMeshBuffer(u32 nr) const; //! Returns pointer to a mesh buffer which fits a material virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const; virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue); //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX); //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX); //! set user axis aligned bounding box virtual void setBoundingBox(const core::aabbox3df& box); //! Gets the default animation speed of the animated mesh. /** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */ virtual f32 getAnimationSpeed() const { return FramesPerSecond; } //! Gets the frame count of the animated mesh. /** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated. The actual speed is set in the scene node the mesh is instantiated in.*/ virtual void setAnimationSpeed(f32 fps) { FramesPerSecond=fps; } //! Get the Animation List virtual IAnimationList* getAnimList () { return &AnimList; } //! Return the named Body List of this Animated Mesh virtual IBodyList *getBodyList() { return &BodyList; } private: // KeyFrame Animation List IAnimationList AnimList; // Sum of all sequences u32 FrameCount; // Named meshes of the Body IBodyList BodyList; //! return a Mesh per frame SMesh* MeshIPol; ISceneManager *SceneManager; SHalflifeHeader *Header; SHalflifeHeader *TextureHeader; bool OwnTexModel; // do we have a modelT.mdl ? SHalflifeHeader *AnimationHeader[32]; // sequences named model01.mdl, model02.mdl void initData (); SHalflifeHeader * loadModel( io::IReadFile* file, const io::path &filename ); bool postLoadModel( const io::path &filename ); u32 SequenceIndex; // sequence index f32 CurrentFrame; // Current Frame f32 FramesPerSecond; #define MOUTH_CONTROLLER 4 u8 BoneController[4 + 1 ]; // bone controllers + mouth position u8 Blending[2]; // animation blending vec4_hl BoneAdj; f32 SetController( s32 controllerIndex, f32 value ); u32 SkinGroupSelection; // skin group selection u32 SetSkin( u32 value ); void initModel(); void dumpModelInfo(u32 level) const; void ExtractBbox(s32 sequence, core::aabbox3df &box) const; void setUpBones (); SHalflifeAnimOffset * getAnim( SHalflifeSequence *seq ); void slerpBones( vec4_hl q1[], vec3_hl pos1[], vec4_hl q2[], vec3_hl pos2[], f32 s ); void calcRotations ( vec3_hl *pos, vec4_hl *q, SHalflifeSequence *seq, SHalflifeAnimOffset *anim, f32 f ); void calcBoneAdj(); void calcBoneQuaternion(const s32 frame, const SHalflifeBone *bone, SHalflifeAnimOffset *anim, const u32 j, f32& angle1, f32& angle2) const; void calcBonePosition(const s32 frame, f32 s, const SHalflifeBone *bone, SHalflifeAnimOffset *anim, f32 *pos ) const; void buildVertices (); io::path TextureBaseName; #define HL_TEXTURE_ATLAS #ifdef HL_TEXTURE_ATLAS STextureAtlas TextureAtlas; video::ITexture *TextureMaster; #endif }; //! Meshloader capable of loading HalfLife Model files class CHalflifeMDLMeshFileLoader : public IMeshLoader { public: //! Constructor CHalflifeMDLMeshFileLoader( scene::ISceneManager* smgr ); //! returns true if the file maybe is able to be loaded by this class /** based on the file extension (e.g. ".bsp") */ virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. /** \return Pointer to the created mesh. Returns 0 if loading failed. If you no longer need the mesh, you should call IAnimatedMesh::drop(). See IReferenceCounted::drop() for more information. */ virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: scene::ISceneManager* SceneManager; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/CAnimatedMeshHalfLife.cpp0000644000000000000000000013151612574354552021705 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt / Fabio Concas / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_ #include "CAnimatedMeshHalfLife.h" #include "os.h" #include "CColorConverter.h" #include "CImage.h" #include "coreutil.h" #include "SMeshBuffer.h" #include "IVideoDriver.h" #include "IFileSystem.h" namespace irr { namespace scene { using namespace video; void AngleQuaternion(const core::vector3df& angles, vec4_hl quaternion) { f32 angle; f32 sr, sp, sy, cr, cp, cy; // FIXME: rescale the inputs to 1/2 angle angle = angles.Z * 0.5f; sy = sin(angle); cy = cos(angle); angle = angles.Y * 0.5f; sp = sin(angle); cp = cos(angle); angle = angles.X * 0.5f; sr = sin(angle); cr = cos(angle); quaternion[0] = sr*cp*cy-cr*sp*sy; // X quaternion[1] = cr*sp*cy+sr*cp*sy; // Y quaternion[2] = cr*cp*sy-sr*sp*cy; // Z quaternion[3] = cr*cp*cy+sr*sp*sy; // W } void QuaternionMatrix( const vec4_hl quaternion, f32 (*matrix)[4] ) { matrix[0][0] = 1.f - 2.f * quaternion[1] * quaternion[1] - 2.f * quaternion[2] * quaternion[2]; matrix[1][0] = 2.f * quaternion[0] * quaternion[1] + 2.f * quaternion[3] * quaternion[2]; matrix[2][0] = 2.f * quaternion[0] * quaternion[2] - 2.f * quaternion[3] * quaternion[1]; matrix[0][1] = 2.f * quaternion[0] * quaternion[1] - 2.f * quaternion[3] * quaternion[2]; matrix[1][1] = 1.f - 2.f * quaternion[0] * quaternion[0] - 2.f * quaternion[2] * quaternion[2]; matrix[2][1] = 2.f * quaternion[1] * quaternion[2] + 2.f * quaternion[3] * quaternion[0]; matrix[0][2] = 2.f * quaternion[0] * quaternion[2] + 2.f * quaternion[3] * quaternion[1]; matrix[1][2] = 2.f * quaternion[1] * quaternion[2] - 2.f * quaternion[3] * quaternion[0]; matrix[2][2] = 1.f - 2.f * quaternion[0] * quaternion[0] - 2.f * quaternion[1] * quaternion[1]; } void QuaternionSlerp( const vec4_hl p, vec4_hl q, f32 t, vec4_hl qt ) { s32 i; f32 omega, cosom, sinom, sclp, sclq; // decide if one of the quaternions is backwards f32 a = 0; f32 b = 0; for (i = 0; i < 4; i++) { a += (p[i]-q[i])*(p[i]-q[i]); b += (p[i]+q[i])*(p[i]+q[i]); } if (a > b) { for (i = 0; i < 4; i++) { q[i] = -q[i]; } } cosom = p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3]; if ((1.f + cosom) > 0.00000001) { if ((1.f - cosom) > 0.00000001) { omega = acos( cosom ); sinom = sin( omega ); sclp = sin( (1.f - t)*omega) / sinom; sclq = sin( t*omega ) / sinom; } else { sclp = 1.f - t; sclq = t; } for (i = 0; i < 4; i++) { qt[i] = sclp * p[i] + sclq * q[i]; } } else { qt[0] = -p[1]; qt[1] = p[0]; qt[2] = -p[3]; qt[3] = p[2]; sclp = sin( (1.f - t) * 0.5f * core::PI); sclq = sin( t * 0.5f * core::PI); for (i = 0; i < 3; i++) { qt[i] = sclp * p[i] + sclq * qt[i]; } } } void R_ConcatTransforms (const f32 in1[3][4], const f32 in2[3][4], f32 out[3][4]) { out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0]; out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1]; out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2]; out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3]; out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0]; out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1]; out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2]; out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3]; out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0]; out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1]; out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2]; out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3]; } #define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]) inline void VectorTransform(const vec3_hl in1, const f32 in2[3][4], core::vector3df& out) { out.X = DotProduct(in1, in2[0]) + in2[0][3]; out.Z = DotProduct(in1, in2[1]) + in2[1][3]; out.Y = DotProduct(in1, in2[2]) + in2[2][3]; } static f32 BoneTransform[MAXSTUDIOBONES][3][4]; // bone transformation matrix void getBoneVector ( core::vector3df &out, u32 index ) { out.X = BoneTransform[index][0][3]; out.Z = BoneTransform[index][1][3]; out.Y = BoneTransform[index][2][3]; } void getBoneBox ( core::aabbox3df &box, u32 index, f32 size = 0.5f ) { box.MinEdge.X = BoneTransform[index][0][3] - size; box.MinEdge.Z = BoneTransform[index][1][3] - size; box.MinEdge.Y = BoneTransform[index][2][3] - size; size *= 2.f; box.MaxEdge.X = box.MinEdge.X + size; box.MaxEdge.Y = box.MinEdge.Y + size; box.MaxEdge.Z = box.MinEdge.Z + size; } void getTransformedBoneVector ( core::vector3df &out, u32 index, const vec3_hl in) { out.X = DotProduct(in, BoneTransform[index][0]) + BoneTransform[index][0][3]; out.Z = DotProduct(in, BoneTransform[index][1]) + BoneTransform[index][1][3]; out.Y = DotProduct(in, BoneTransform[index][2]) + BoneTransform[index][2][3]; } //! Constructor CHalflifeMDLMeshFileLoader::CHalflifeMDLMeshFileLoader( scene::ISceneManager* smgr) : SceneManager(smgr) { #ifdef _DEBUG setDebugName("CHalflifeMDLMeshFileLoader"); #endif } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool CHalflifeMDLMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension(filename, "mdl"); } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* CHalflifeMDLMeshFileLoader::createMesh(io::IReadFile* file) { CAnimatedMeshHalfLife* msh = new CAnimatedMeshHalfLife(); if (msh) { if (msh->loadModelFile(file, SceneManager)) return msh; msh->drop(); } return 0; } //! Constructor CAnimatedMeshHalfLife::CAnimatedMeshHalfLife() : FrameCount(0), MeshIPol(0), SceneManager(0), Header(0), TextureHeader(0), OwnTexModel(false), SequenceIndex(0), CurrentFrame(0), FramesPerSecond(25.f), SkinGroupSelection(0) #ifdef HL_TEXTURE_ATLAS , TextureMaster(0) #endif { #ifdef _DEBUG setDebugName("CAnimatedMeshHalfLife"); #endif initData(); } /*! loads a complete model */ bool CAnimatedMeshHalfLife::loadModelFile(io::IReadFile* file, ISceneManager* smgr) { if (!file) return false; SceneManager = smgr; if ( loadModel(file, file->getFileName()) ) { if ( postLoadModel ( file->getFileName() ) ) { initModel (); //dumpModelInfo ( 1 ); return true; } } return false; } //! Destructor CAnimatedMeshHalfLife::~CAnimatedMeshHalfLife() { delete [] (u8*) Header; if (OwnTexModel) delete [] (u8*) TextureHeader; for (u32 i = 0; i < 32; ++i) delete [] (u8*) AnimationHeader[i]; if (MeshIPol) MeshIPol->drop(); } //! Returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. u32 CAnimatedMeshHalfLife::getFrameCount() const { return FrameCount; } //! set the hardware mapping hint, for driver void CAnimatedMeshHalfLife::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,E_BUFFER_TYPE buffer) { } //! flags the meshbuffer as changed, reloads hardware buffers void CAnimatedMeshHalfLife::setDirty(E_BUFFER_TYPE buffer) { } static core::vector3df TransformedVerts[MAXSTUDIOVERTS]; // transformed vertices //static core::vector3df TransformedNormals[MAXSTUDIOVERTS]; // light surface normals /*! */ void CAnimatedMeshHalfLife::initModel() { // init Sequences to Animation KeyFrameInterpolation ipol; ipol.Name.reserve ( 64 ); u32 i; AnimList.clear(); FrameCount = 0; SHalflifeSequence *seq = (SHalflifeSequence*) ((u8*) Header + Header->seqindex); for ( i = 0; i < Header->numseq; i++) { ipol.Name = seq[i].label; ipol.StartFrame = FrameCount; ipol.Frames = core::max_ ( 1, seq[i].numframes - 1 ); ipol.EndFrame = ipol.StartFrame + ipol.Frames - 1; ipol.FramesPerSecond = seq[i].fps; ipol.AnimationType = seq[i].flags & STUDIO_LOOPING ? EAMT_LOOPING : EAMT_WAYPOINT; AnimList.push_back ( ipol ); FrameCount += ipol.Frames; } // initBoneControllers /* SHalflifeBoneController *bonecontroller = (SHalflifeBoneController *)((u8*) Header + Header->bonecontrollerindex); for ( i = 0; i < Header->numbonecontrollers; i++) { printf ( "BoneController%d index:%d%s range:%f - %f\n", i, bonecontroller[i].index, bonecontroller[i].index == MOUTH_CONTROLLER ? " (Mouth)": "", bonecontroller[i].start,bonecontroller[i].end ); } // initSkins for (i = 0; i < TextureHeader->numskinfamilies; i++) { printf ( "Skin%d\n", i + 1); } */ // initBodyparts u32 meshBuffer = 0; BodyList.clear(); SHalflifeBody *body = (SHalflifeBody *) ((u8*) Header + Header->bodypartindex); for (i=0; i < Header->numbodyparts; ++i) { BodyPart part; part.name = body[i].name; part.defaultModel = core::max_ ( 0, (s32) body[i].base - 1 ); SHalflifeModel * model = (SHalflifeModel *)((u8*) Header + body[i].modelindex); for ( u32 g = 0; g < body[i].nummodels; ++g) { SubModel sub; sub.name = model[g].name; sub.startBuffer = meshBuffer; sub.endBuffer = sub.startBuffer + model[g].nummesh; sub.state = g == part.defaultModel; part.model.push_back ( sub ); meshBuffer += model[g].nummesh; } BodyList.push_back ( part ); } SequenceIndex = 0; CurrentFrame = 0.f; SetController(0, 0.f); SetController(1, 0.f); SetController(2, 0.f); SetController(3, 0.f); SetController(MOUTH_CONTROLLER, 0.f); SetSkin (0); // init Meshbuffers const SHalflifeTexture *tex = (SHalflifeTexture *) ((u8*) TextureHeader + TextureHeader->textureindex); const u16 *skinref = (u16 *)((u8*)TextureHeader + TextureHeader->skinindex); if ((SkinGroupSelection != 0) && (SkinGroupSelection < TextureHeader->numskinfamilies)) skinref += (SkinGroupSelection * TextureHeader->numskinref); core::vector2df tex_scale; core::vector2di tex_trans ( 0, 0 ); #ifdef HL_TEXTURE_ATLAS TextureAtlas.getScale(tex_scale); #endif for (u32 bodypart=0 ; bodypart < Header->numbodyparts ; ++bodypart) { const SHalflifeBody *body = (SHalflifeBody *)((u8*) Header + Header->bodypartindex) + bodypart; for (u32 modelnr = 0; modelnr < body->nummodels; ++modelnr) { const SHalflifeModel *model = (SHalflifeModel *)((u8*) Header + body->modelindex) + modelnr; #if 0 const vec3_hl *studioverts = (vec3_hl *)((u8*)Header + model->vertindex); const vec3_hl *studionorms = (vec3_hl *)((u8*)Header + model->normindex); #endif for (i = 0; i < model->nummesh; ++i) { const SHalflifeMesh *mesh = (SHalflifeMesh *)((u8*)Header + model->meshindex) + i; const SHalflifeTexture *currentex = &tex[skinref[mesh->skinref]]; #ifdef HL_TEXTURE_ATLAS TextureAtlas.getTranslation ( currentex->name, tex_trans ); #else tex_scale.X = 1.f/(f32)currentex->width; tex_scale.Y = 1.f/(f32)currentex->height; #endif SMeshBuffer * buffer = new SMeshBuffer(); // count index vertex size indexcount = mesh->numtris * 3 u32 indexCount = 0; u32 vertexCount = 0; const s16 *tricmd = (s16*)((u8*)Header + mesh->triindex); s32 c; while ( (c = *(tricmd++)) ) { if (c < 0) c = -c; indexCount += ( c - 2 ) * 3; vertexCount += c; tricmd += ( 4 * c ); } // indices buffer->Indices.set_used ( indexCount ); buffer->Vertices.set_used ( vertexCount ); // fill in static indices and vertex u16 *index = buffer->Indices.pointer(); video::S3DVertex * v = buffer->Vertices.pointer(); // blow up gl_triangle_fan/gl_triangle_strip to indexed triangle list E_PRIMITIVE_TYPE type; vertexCount = 0; indexCount = 0; tricmd = (s16*)((u8*)Header + mesh->triindex); while ( (c = *(tricmd++)) ) { if (c < 0) { // triangle fan c = -c; type = EPT_TRIANGLE_FAN; } else { type = EPT_TRIANGLE_STRIP; } for ( s32 g = 0; g < c; ++g, v += 1, tricmd += 4 ) { // fill vertex #if 0 const f32 *av = studioverts[tricmd[0]]; v->Pos.X = av[0]; v->Pos.Z = av[1]; v->Pos.Y = av[2]; av = studionorms[tricmd[1]]; v->Normal.X = av[0]; v->Normal.Z = av[1]; v->Normal.Y = av[2]; #endif v->Normal.X = 0.f; v->Normal.Z = 0.f; v->Normal.Y = 1.f; v->TCoords.X = (tex_trans.X + tricmd[2])*tex_scale.X; v->TCoords.Y = (tex_trans.Y + tricmd[3])*tex_scale.Y; v->Color.color = 0xFFFFFFFF; // fill index if ( g < c - 2 ) { if ( type == EPT_TRIANGLE_FAN ) { index[indexCount+0] = vertexCount; index[indexCount+1] = vertexCount+g+1; index[indexCount+2] = vertexCount+g+2; } else { if ( g & 1 ) { index[indexCount+0] = vertexCount+g+1; index[indexCount+1] = vertexCount+g+0; index[indexCount+2] = vertexCount+g+2; } else { index[indexCount+0] = vertexCount+g+0; index[indexCount+1] = vertexCount+g+1; index[indexCount+2] = vertexCount+g+2; } } indexCount += 3; } } vertexCount += c; } // material video::SMaterial &m = buffer->getMaterial(); m.MaterialType = video::EMT_SOLID; m.BackfaceCulling = true; if ( currentex->flags & STUDIO_NF_CHROME ) { // don't know what to do with chrome here } #ifdef HL_TEXTURE_ATLAS io::path store = TextureBaseName + "atlas"; #else io::path fname; io::path ext; core::splitFilename ( currentex->name, 0, &fname, &ext ); io::path store = TextureBaseName + fname; #endif m.TextureLayer[0].Texture = SceneManager->getVideoDriver()->getTexture ( store ); m.Lighting = false; MeshIPol->addMeshBuffer(buffer); buffer->recalculateBoundingBox(); buffer->drop(); } // mesh MeshIPol->recalculateBoundingBox(); } // model } // body part } /*! */ void CAnimatedMeshHalfLife::buildVertices() { /* const u16 *skinref = (u16 *)((u8*)TextureHeader + TextureHeader->skinindex); if (SkinGroupSelection != 0 && SkinGroupSelection < TextureHeader->numskinfamilies) skinref += (SkinGroupSelection * TextureHeader->numskinref); */ u32 i; s32 c,g; const s16 *tricmd; u32 meshBufferNr = 0; for ( u32 bodypart = 0 ; bodypart < Header->numbodyparts; ++bodypart) { const SHalflifeBody *body = (SHalflifeBody *)((u8*) Header + Header->bodypartindex) + bodypart; for ( u32 modelnr = 0; modelnr < body->nummodels; ++modelnr ) { const SHalflifeModel *model = (SHalflifeModel *)((u8*) Header + body->modelindex) + modelnr; const u8 *vertbone = ((u8*)Header + model->vertinfoindex); const vec3_hl *studioverts = (vec3_hl *)((u8*)Header + model->vertindex); for ( i = 0; i < model->numverts; i++) { VectorTransform ( studioverts[i], BoneTransform[vertbone[i]], TransformedVerts[i] ); } /* const u8 *normbone = ((u8*)Header + model->norminfoindex); const vec3_hl *studionorms = (vec3_hl *)((u8*)Header + model->normindex); for ( i = 0; i < model->numnorms; i++) { VectorTransform ( studionorms[i], BoneTransform[normbone[i]], TransformedNormals[i] ); } */ for (i = 0; i < model->nummesh; i++) { const SHalflifeMesh *mesh = (SHalflifeMesh *)((u8*)Header + model->meshindex) + i; IMeshBuffer * buffer = MeshIPol->getMeshBuffer ( meshBufferNr++ ); video::S3DVertex* v = (video::S3DVertex* ) buffer->getVertices(); tricmd = (s16*)((u8*)Header + mesh->triindex); while ( (c = *(tricmd++)) ) { if (c < 0) c = -c; for ( g = 0; g < c; ++g, v += 1, tricmd += 4 ) { // fill vertex const core::vector3df& av = TransformedVerts[tricmd[0]]; v->Pos = av; /* const core::vector3df& an = TransformedNormals[tricmd[1]]; v->Normal = an; //v->Normal.normalize(); */ } } // tricmd } // nummesh } // model } // bodypart } /*! render Bones */ void CAnimatedMeshHalfLife::renderModel(u32 param, IVideoDriver * driver, const core::matrix4 &absoluteTransformation) { SHalflifeBone *bone = (SHalflifeBone *) ((u8 *) Header + Header->boneindex); video::SColor blue(0xFF000080); video::SColor red(0xFF800000); video::SColor yellow(0xFF808000); video::SColor cyan(0xFF008080); core::aabbox3df box; u32 i; for ( i = 0; i < Header->numbones; i++) { if (bone[i].parent >= 0) { getBoneVector ( box.MinEdge, bone[i].parent ); getBoneVector ( box.MaxEdge, i ); driver->draw3DLine ( box.MinEdge, box.MaxEdge, blue ); // draw parent bone node if (bone[bone[i].parent].parent >=0 ) { getBoneBox ( box, bone[i].parent ); driver->draw3DBox ( box, blue ); } getBoneBox ( box, i ); driver->draw3DBox ( box, blue ); } else { // draw parent bone node getBoneBox ( box, i, 1.f ); driver->draw3DBox ( box , red ); } } // attachements SHalflifeAttachment *attach = (SHalflifeAttachment *) ((u8*) Header + Header->attachmentindex); core::vector3df v[8]; for ( i = 0; i < Header->numattachments; i++) { getTransformedBoneVector ( v[0],attach[i].bone,attach[i].org ); getTransformedBoneVector ( v[1],attach[i].bone,attach[i].vectors[0] ); getTransformedBoneVector ( v[2],attach[i].bone,attach[i].vectors[1] ); getTransformedBoneVector ( v[3],attach[i].bone,attach[i].vectors[2] ); driver->draw3DLine ( v[0], v[1], cyan ); driver->draw3DLine ( v[0], v[2], cyan ); driver->draw3DLine ( v[0], v[3], cyan ); } // hit boxes SHalflifeBBox *hitbox = (SHalflifeBBox *) ((u8*) Header + Header->hitboxindex); f32 *bbmin,*bbmax; vec3_hl v2[8]; for (i = 0; i < Header->numhitboxes; i++) { bbmin = hitbox[i].bbmin; bbmax = hitbox[i].bbmax; v2[0][0] = bbmin[0]; v2[0][1] = bbmax[1]; v2[0][2] = bbmin[2]; v2[1][0] = bbmin[0]; v2[1][1] = bbmin[1]; v2[1][2] = bbmin[2]; v2[2][0] = bbmax[0]; v2[2][1] = bbmax[1]; v2[2][2] = bbmin[2]; v2[3][0] = bbmax[0]; v2[3][1] = bbmin[1]; v2[3][2] = bbmin[2]; v2[4][0] = bbmax[0]; v2[4][1] = bbmax[1]; v2[4][2] = bbmax[2]; v2[5][0] = bbmax[0]; v2[5][1] = bbmin[1]; v2[5][2] = bbmax[2]; v2[6][0] = bbmin[0]; v2[6][1] = bbmax[1]; v2[6][2] = bbmax[2]; v2[7][0] = bbmin[0]; v2[7][1] = bbmin[1]; v2[7][2] = bbmax[2]; for ( u32 g = 0; g < 8; ++g ) getTransformedBoneVector ( v[g],hitbox[i].bone,v2[g] ); driver->draw3DLine(v[0], v[1], yellow); driver->draw3DLine(v[1], v[3], yellow); driver->draw3DLine(v[3], v[2], yellow); driver->draw3DLine(v[2], v[0], yellow); driver->draw3DLine(v[4], v[5], yellow); driver->draw3DLine(v[5], v[7], yellow); driver->draw3DLine(v[7], v[6], yellow); driver->draw3DLine(v[6], v[4], yellow); driver->draw3DLine(v[0], v[6], yellow); driver->draw3DLine(v[1], v[7], yellow); driver->draw3DLine(v[3], v[5], yellow); driver->draw3DLine(v[2], v[4], yellow); } } //! Returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. IMesh* CAnimatedMeshHalfLife::getMesh(s32 frameInt, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) { f32 frame = frameInt + (detailLevel * 0.001f); u32 frameA = core::floor32 ( frame ); // f32 blend = core::fract ( frame ); SHalflifeSequence *seq = (SHalflifeSequence*) ((u8*) Header + Header->seqindex); // find SequenceIndex from summed list u32 frameCount = 0; for (u32 i = 0; i < Header->numseq; ++i) { u32 val = core::max_ ( 1, seq[i].numframes - 1 ); if ( frameCount + val > frameA ) { SequenceIndex = i; CurrentFrame = frame - frameCount; break; } frameCount += val; } seq += SequenceIndex; //SetBodyPart ( 1, 1 ); setUpBones (); buildVertices(); MeshIPol->BoundingBox.MinEdge.X = seq->bbmin[0]; MeshIPol->BoundingBox.MinEdge.Z = seq->bbmin[1]; MeshIPol->BoundingBox.MinEdge.Y = seq->bbmin[2]; MeshIPol->BoundingBox.MaxEdge.X = seq->bbmax[0]; MeshIPol->BoundingBox.MaxEdge.Z = seq->bbmax[1]; MeshIPol->BoundingBox.MaxEdge.Y = seq->bbmax[2]; return MeshIPol; } /*! */ void CAnimatedMeshHalfLife::initData () { u32 i; Header = 0; TextureHeader = 0; OwnTexModel = false; for ( i = 0; i < 32; ++i ) AnimationHeader[i] = 0; SequenceIndex = 0; CurrentFrame = 0.f; for ( i = 0; i < 5; ++i ) BoneController[i] = 0; for ( i = 0; i < 2; ++i ) Blending[i] = 0; SkinGroupSelection = 0; AnimList.clear(); FrameCount = 0; if (!MeshIPol) MeshIPol = new SMesh(); MeshIPol->clear(); #ifdef HL_TEXTURE_ATLAS TextureAtlas.release(); #endif } /*! */ void STextureAtlas::release() { for (u32 i = 0; i < atlas.size(); i++) { if ( atlas[i].image ) { atlas[i].image->drop(); atlas[i].image = 0; } } Master = 0; } /*! */ void STextureAtlas::addSource ( const c8 * name, video::IImage * image ) { TextureAtlasEntry entry; entry.name = name; entry.image = image; entry.width = image->getDimension().Width; entry.height = image->getDimension().Height; entry.pos.X = 0; entry.pos.Y = 0; atlas.push_back ( entry ); } /*! */ void STextureAtlas::getScale(core::vector2df& scale) { for (s32 i = static_cast(atlas.size()) - 1; i >= 0; --i) { if ( atlas[i].name == "_merged_" ) { scale.X = 1.f / atlas[i].width; scale.Y = 1.f / atlas[i].height; return; } } scale.X = 1.f; scale.Y = 1.f; } /*! */ void STextureAtlas::getTranslation(const c8* name, core::vector2di& pos) { for ( u32 i = 0; i < atlas.size(); ++i) { if ( atlas[i].name == name ) { pos = atlas[i].pos; return; } } } /*! */ void STextureAtlas::create(u32 border, E_TEXTURE_CLAMP texmode) { u32 i = 0; u32 w = 0; u32 w2; u32 h2; u32 h; u32 wsum; u32 hsum = 0; ECOLOR_FORMAT format = ECF_R8G8B8; const s32 frame = core::s32_max ( 0, (border - 1 ) / 2 ); // sort for biggest coming first atlas.sort(); // split size wsum = frame; for (i = 0; i < atlas.size(); i++) { // make space w2 = atlas[i].width + border; // align w2 = (w2 + 1) & ~1; wsum += w2; } u32 splitsize = 256; if ( wsum > 512 ) splitsize = 512; wsum = frame; hsum = frame; w = frame; h = 0; for (i = 0; i < atlas.size(); i++) { if ( atlas[i].image->getColorFormat() == ECF_A8R8G8B8 ) { format = ECF_A8R8G8B8; } // make space w2 = atlas[i].width + border; h2 = atlas[i].height + border; // align w2 = (w2 + 1) & ~1; h2 = (h2 + 1) & ~1; h = core::s32_max ( h, h2 ); if ( w + w2 >= splitsize ) { hsum += h; wsum = core::s32_max ( wsum, w ); h = h2; w = frame; } atlas[i].pos.X = w; atlas[i].pos.Y = hsum; w += w2; } hsum += h; wsum = core::s32_max ( wsum, w ); // build image core::dimension2d dim = core::dimension2d( wsum, hsum ).getOptimalSize(); IImage* master = new CImage(format, dim); master->fill(0); video::SColor col[2]; static const u8 wrap[][4] = { {1, 0}, // ETC_REPEAT {0, 1}, // ETC_CLAMP {0, 1}, // ETC_CLAMP_TO_EDGE {0, 1} // ETC_MIRROR }; s32 a,b; for (i = 0; i < atlas.size(); i++) { atlas[i].image->copyTo ( master, atlas[i].pos ); // clamp/wrap ( copy edges, filtering needs it ) for ( b = 0; b < frame; ++b ) { for ( a = 0 - b; a <= (s32) atlas[i].width + b; ++a ) { col[0] = atlas[i].image->getPixel ( core::s32_clamp ( a, 0, atlas[i].width - 1 ), 0 ); col[1] = atlas[i].image->getPixel ( core::s32_clamp ( a, 0, atlas[i].width - 1 ), atlas[i].height - 1 ); master->setPixel ( atlas[i].pos.X + a, atlas[i].pos.Y + ( b + 1 ) * -1, col[wrap[texmode][0]] ); master->setPixel ( atlas[i].pos.X + a, atlas[i].pos.Y + atlas[i].height - 1 + ( b + 1 ) * 1, col[wrap[texmode][1]] ); } for ( a = -1 - b; a <= (s32) atlas[i].height + b; ++a ) { col[0] = atlas[i].image->getPixel ( 0, core::s32_clamp ( a, 0, atlas[i].height - 1 ) ); col[1] = atlas[i].image->getPixel ( atlas[i].width - 1, core::s32_clamp ( a, 0, atlas[i].height - 1 ) ); master->setPixel ( atlas[i].pos.X + ( b + 1 ) * -1, atlas[i].pos.Y + a, col[wrap[texmode][0]] ); master->setPixel ( atlas[i].pos.X + atlas[i].width + b, atlas[i].pos.Y + a, col[wrap[texmode][1]] ); } } } addSource ( "_merged_", master ); Master = master; } /*! */ SHalflifeHeader* CAnimatedMeshHalfLife::loadModel(io::IReadFile* file, const io::path& filename) { bool closefile = false; // if secondary files are needed, open here and mark for closing if ( 0 == file ) { file = SceneManager->getFileSystem()->createAndOpenFile(filename); closefile = true; } if ( 0 == file ) return 0; // read into memory u8* pin = new u8[file->getSize()]; file->read(pin, file->getSize()); SHalflifeHeader* header = (SHalflifeHeader*) pin; const bool idst = (0 == strncmp(header->id, "IDST", 4)); const bool idsq = (0 == strncmp(header->id, "IDSQ", 4)); if ( (!idst && !idsq) || (idsq && !Header) ) { os::Printer::log("MDL Halflife Loader: Wrong file header", file->getFileName(), ELL_WARNING); if ( closefile ) { file->drop(); file = 0; } delete [] pin; return 0; } // don't know the real header.. idsg might be different if (header->textureindex && idst ) { io::path path; io::path fname; io::path ext; core::splitFilename(file->getFileName(), &path, &fname, &ext); TextureBaseName = path + fname + "_"; SHalflifeTexture *tex = (SHalflifeTexture *)(pin + header->textureindex); u32 *palette = new u32[256]; for (u32 i = 0; i < header->numtextures; ++i) { const u8 *src = pin + tex[i].index; // convert rgb to argb palette { const u8 *pal = src + tex[i].width * tex[i].height; for( u32 g=0; g<256; ++g ) { palette[g] = 0xFF000000 | pal[0] << 16 | pal[1] << 8 | pal[2]; pal += 3; } } IImage* image = SceneManager->getVideoDriver()->createImage(ECF_R8G8B8, core::dimension2d(tex[i].width, tex[i].height)); CColorConverter::convert8BitTo24Bit(src, (u8*)image->lock(), tex[i].width, tex[i].height, (u8*) palette, 0, false); image->unlock(); #ifdef HL_TEXTURE_ATLAS TextureAtlas.addSource ( tex[i].name, image ); #else core::splitFilename ( tex[i].name, 0, &fname, &ext ); SceneManager->getVideoDriver()->addTexture ( TextureBaseName + fname, image ); image->drop(); #endif } delete [] palette; #ifdef HL_TEXTURE_ATLAS TextureAtlas.create ( 2 * 2 + 1, ETC_CLAMP ); SceneManager->getVideoDriver()->addTexture ( TextureBaseName + "atlas", TextureAtlas.Master ); TextureAtlas.release(); #endif } if (!Header) Header = header; if ( closefile ) { file->drop(); file = 0; } return header; } /*! */ f32 CAnimatedMeshHalfLife::SetController( s32 controllerIndex, f32 value ) { if (!Header) return 0.f; SHalflifeBoneController *bonecontroller = (SHalflifeBoneController *)((u8*) Header + Header->bonecontrollerindex); // find first controller that matches the index u32 i; for (i = 0; i < Header->numbonecontrollers; i++, bonecontroller++) { if (bonecontroller->index == controllerIndex) break; } if (i >= Header->numbonecontrollers) return value; // wrap 0..360 if it's a rotational controller if (bonecontroller->type & (STUDIO_XR | STUDIO_YR | STUDIO_ZR)) { // ugly hack, invert value if end < start if (bonecontroller->end < bonecontroller->start) value = -value; // does the controller not wrap? if (bonecontroller->start + 359.f >= bonecontroller->end) { if (value > ((bonecontroller->start + bonecontroller->end) / 2.f) + 180.f) value = value - 360.f; if (value < ((bonecontroller->start + bonecontroller->end) / 2.f) - 180.f) value = value + 360.f; } else { if (value > 360.f) value = value - (s32)(value / 360.f) * 360.f; else if (value < 0.f) value = value + (s32)((value / -360.f) + 1) * 360.f; } } s32 range = controllerIndex == MOUTH_CONTROLLER ? 64 : 255; s32 setting = (s32) ( (f32) range * (value - bonecontroller->start) / (bonecontroller->end - bonecontroller->start)); if (setting < 0) setting = 0; if (setting > range) setting = range; BoneController[controllerIndex] = setting; return setting * (1.f / (f32) range ) * (bonecontroller->end - bonecontroller->start) + bonecontroller->start; } /*! */ u32 CAnimatedMeshHalfLife::SetSkin( u32 value ) { if (value < Header->numskinfamilies) SkinGroupSelection = value; return SkinGroupSelection; } /*! */ bool CAnimatedMeshHalfLife::postLoadModel( const io::path &filename ) { io::path path; io::path texname; io::path submodel; core::splitFilename ( filename ,&path, &texname, 0 ); // preload textures // if no textures are stored in main file, use texfile if (Header->numtextures == 0) { submodel = path + texname + "T.mdl"; TextureHeader = loadModel(0, submodel); if (!TextureHeader) return false; OwnTexModel = true; } else { TextureHeader = Header; OwnTexModel = false; } // preload animations if (Header->numseqgroups > 1) { c8 seq[8]; for (u32 i = 1; i < Header->numseqgroups; i++) { snprintf( seq, 8, "%02d.mdl", i ); submodel = path + texname + seq; AnimationHeader[i] = loadModel(0, submodel); if (!AnimationHeader[i]) return false; } } return true; } /*! */ void CAnimatedMeshHalfLife::dumpModelInfo(u32 level) const { const u8 *phdr = (const u8*) Header; const SHalflifeHeader * hdr = Header; u32 i; if (level == 0) { printf ( "Bones: %d\n" "Bone Controllers: %d\n" "Hit Boxes: %d\n" "Sequences: %d\n" "Sequence Groups: %d\n", hdr->numbones, hdr->numbonecontrollers, hdr->numhitboxes, hdr->numseq, hdr->numseqgroups ); printf ( "Textures: %d\n" "Skin Families: %d\n" "Bodyparts: %d\n" "Attachments: %d\n" "Transitions: %d\n", hdr->numtextures, hdr->numskinfamilies, hdr->numbodyparts, hdr->numattachments, hdr->numtransitions); return; } printf("id: %c%c%c%c\n", phdr[0], phdr[1], phdr[2], phdr[3]); printf("version: %d\n", hdr->version); printf("name: \"%s\"\n", hdr->name); printf("length: %d\n\n", hdr->length); printf("eyeposition: %f %f %f\n", hdr->eyeposition[0], hdr->eyeposition[1], hdr->eyeposition[2]); printf("min: %f %f %f\n", hdr->min[0], hdr->min[1], hdr->min[2]); printf("max: %f %f %f\n", hdr->max[0], hdr->max[1], hdr->max[2]); printf("bbmin: %f %f %f\n", hdr->bbmin[0], hdr->bbmin[1], hdr->bbmin[2]); printf("bbmax: %f %f %f\n", hdr->bbmax[0], hdr->bbmax[1], hdr->bbmax[2]); printf("flags: %d\n\n", hdr->flags); printf("numbones: %d\n", hdr->numbones); for (i = 0; i < hdr->numbones; i++) { const SHalflifeBone *bone = (const SHalflifeBone *) (phdr + hdr->boneindex); printf("bone %d.name: \"%s\"\n", i + 1, bone[i].name); printf("bone %d.parent: %d\n", i + 1, bone[i].parent); printf("bone %d.flags: %d\n", i + 1, bone[i].flags); printf("bone %d.bonecontroller: %d %d %d %d %d %d\n", i + 1, bone[i].bonecontroller[0], bone[i].bonecontroller[1], bone[i].bonecontroller[2], bone[i].bonecontroller[3], bone[i].bonecontroller[4], bone[i].bonecontroller[5]); printf("bone %d.value: %f %f %f %f %f %f\n", i + 1, bone[i].value[0], bone[i].value[1], bone[i].value[2], bone[i].value[3], bone[i].value[4], bone[i].value[5]); printf("bone %d.scale: %f %f %f %f %f %f\n", i + 1, bone[i].scale[0], bone[i].scale[1], bone[i].scale[2], bone[i].scale[3], bone[i].scale[4], bone[i].scale[5]); } printf("\nnumbonecontrollers: %d\n", hdr->numbonecontrollers); const SHalflifeBoneController *bonecontrollers = (const SHalflifeBoneController *) (phdr + hdr->bonecontrollerindex); for (i = 0; i < hdr->numbonecontrollers; i++) { printf("bonecontroller %d.bone: %d\n", i + 1, bonecontrollers[i].bone); printf("bonecontroller %d.type: %d\n", i + 1, bonecontrollers[i].type); printf("bonecontroller %d.start: %f\n", i + 1, bonecontrollers[i].start); printf("bonecontroller %d.end: %f\n", i + 1, bonecontrollers[i].end); printf("bonecontroller %d.rest: %d\n", i + 1, bonecontrollers[i].rest); printf("bonecontroller %d.index: %d\n", i + 1, bonecontrollers[i].index); } printf("\nnumhitboxes: %d\n", hdr->numhitboxes); const SHalflifeBBox *box = (const SHalflifeBBox *) (phdr + hdr->hitboxindex); for (i = 0; i < hdr->numhitboxes; i++) { printf("hitbox %d.bone: %d\n", i + 1, box[i].bone); printf("hitbox %d.group: %d\n", i + 1, box[i].group); printf("hitbox %d.bbmin: %f %f %f\n", i + 1, box[i].bbmin[0], box[i].bbmin[1], box[i].bbmin[2]); printf("hitbox %d.bbmax: %f %f %f\n", i + 1, box[i].bbmax[0], box[i].bbmax[1], box[i].bbmax[2]); } printf("\nnumseq: %d\n", hdr->numseq); const SHalflifeSequence *seq = (const SHalflifeSequence *) (phdr + hdr->seqindex); for (i = 0; i < hdr->numseq; i++) { printf("seqdesc %d.label: \"%s\"\n", i + 1, seq[i].label); printf("seqdesc %d.fps: %f\n", i + 1, seq[i].fps); printf("seqdesc %d.flags: %d\n", i + 1, seq[i].flags); printf("<...>\n"); } printf("\nnumseqgroups: %d\n", hdr->numseqgroups); for (i = 0; i < hdr->numseqgroups; i++) { const SHalflifeSequenceGroup *group = (const SHalflifeSequenceGroup *) (phdr + hdr->seqgroupindex); printf("\nseqgroup %d.label: \"%s\"\n", i + 1, group[i].label); printf("\nseqgroup %d.namel: \"%s\"\n", i + 1, group[i].name); printf("\nseqgroup %d.data: %d\n", i + 1, group[i].data); } printf("\nnumskinref: %d\n", hdr->numskinref); printf("numskinfamilies: %d\n", hdr->numskinfamilies); printf("\nnumbodyparts: %d\n", hdr->numbodyparts); const SHalflifeBody *pbodyparts = (const SHalflifeBody*) ((const u8*) hdr + hdr->bodypartindex); for (i = 0; i < hdr->numbodyparts; i++) { printf("bodypart %d.name: \"%s\"\n", i + 1, pbodyparts[i].name); printf("bodypart %d.nummodels: %d\n", i + 1, pbodyparts[i].nummodels); printf("bodypart %d.base: %d\n", i + 1, pbodyparts[i].base); printf("bodypart %d.modelindex: %d\n", i + 1, pbodyparts[i].modelindex); } printf("\nnumattachments: %d\n", hdr->numattachments); for (i = 0; i < hdr->numattachments; i++) { const SHalflifeAttachment *attach = (const SHalflifeAttachment *) ((const u8*) hdr + hdr->attachmentindex); printf("attachment %d.name: \"%s\"\n", i + 1, attach[i].name); } hdr = TextureHeader; printf("\nnumtextures: %d\n", hdr->numtextures); printf("textureindex: %d\n", hdr->textureindex); printf("texturedataindex: %d\n", hdr->texturedataindex); const SHalflifeTexture *ptextures = (const SHalflifeTexture *) ((const u8*) hdr + hdr->textureindex); for (i = 0; i < hdr->numtextures; i++) { printf("texture %d.name: \"%s\"\n", i + 1, ptextures[i].name); printf("texture %d.flags: %d\n", i + 1, ptextures[i].flags); printf("texture %d.width: %d\n", i + 1, ptextures[i].width); printf("texture %d.height: %d\n", i + 1, ptextures[i].height); printf("texture %d.index: %d\n", i + 1, ptextures[i].index); } } /*! */ void CAnimatedMeshHalfLife::ExtractBbox(s32 sequence, core::aabbox3df &box) const { const SHalflifeSequence *seq = (const SHalflifeSequence *)((const u8*)Header + Header->seqindex) + sequence; box.MinEdge.X = seq[0].bbmin[0]; box.MinEdge.Y = seq[0].bbmin[1]; box.MinEdge.Z = seq[0].bbmin[2]; box.MaxEdge.X = seq[0].bbmax[0]; box.MaxEdge.Y = seq[0].bbmax[1]; box.MaxEdge.Z = seq[0].bbmax[2]; } /*! */ void CAnimatedMeshHalfLife::calcBoneAdj() { const SHalflifeBoneController *bonecontroller = (const SHalflifeBoneController *)((const u8*) Header + Header->bonecontrollerindex); for (u32 j = 0; j < Header->numbonecontrollers; j++) { const s32 i = bonecontroller[j].index; // check for 360% wrapping f32 value; if (bonecontroller[j].type & STUDIO_RLOOP) { value = BoneController[i] * (360.f/256.f) + bonecontroller[j].start; } else { const f32 range = i <= 3 ? 255.f : 64.f; value = core::clamp(BoneController[i] / range,0.f,1.f); value = (1.f - value) * bonecontroller[j].start + value * bonecontroller[j].end; } switch(bonecontroller[j].type & STUDIO_TYPES) { case STUDIO_XR: case STUDIO_YR: case STUDIO_ZR: BoneAdj[j] = value * core::DEGTORAD; break; case STUDIO_X: case STUDIO_Y: case STUDIO_Z: BoneAdj[j] = value; break; } } } /*! */ void CAnimatedMeshHalfLife::calcBoneQuaternion(const s32 frame, const SHalflifeBone * const bone, SHalflifeAnimOffset *anim, const u32 j, f32& angle1, f32& angle2) const { // three vector components if (anim->offset[j+3] == 0) { angle2 = angle1 = bone->value[j+3]; // default } else { SHalflifeAnimationFrame *animvalue = (SHalflifeAnimationFrame *)((u8*)anim + anim->offset[j+3]); s32 k = frame; while (animvalue->num.total <= k) { k -= animvalue->num.total; animvalue += animvalue->num.valid + 1; } // Bah, missing blend! if (animvalue->num.valid > k) { angle1 = animvalue[k+1].value; if (animvalue->num.valid > k + 1) { angle2 = animvalue[k+2].value; } else { if (animvalue->num.total > k + 1) angle2 = angle1; else angle2 = animvalue[animvalue->num.valid+2].value; } } else { angle1 = animvalue[animvalue->num.valid].value; if (animvalue->num.total > k + 1) { angle2 = angle1; } else { angle2 = animvalue[animvalue->num.valid + 2].value; } } angle1 = bone->value[j+3] + angle1 * bone->scale[j+3]; angle2 = bone->value[j+3] + angle2 * bone->scale[j+3]; } if (bone->bonecontroller[j+3] != -1) { angle1 += BoneAdj[bone->bonecontroller[j+3]]; angle2 += BoneAdj[bone->bonecontroller[j+3]]; } } /*! */ void CAnimatedMeshHalfLife::calcBonePosition(const s32 frame, f32 s, const SHalflifeBone * const bone, SHalflifeAnimOffset *anim, f32 *pos) const { for (s32 j = 0; j < 3; ++j) { pos[j] = bone->value[j]; // default; if (anim->offset[j] != 0) { SHalflifeAnimationFrame *animvalue = (SHalflifeAnimationFrame *)((u8*)anim + anim->offset[j]); s32 k = frame; // find span of values that includes the frame we want while (animvalue->num.total <= k) { k -= animvalue->num.total; animvalue += animvalue->num.valid + 1; } // if we're inside the span if (animvalue->num.valid > k) { // and there's more data in the span if (animvalue->num.valid > k + 1) { pos[j] += (animvalue[k+1].value * (1.f - s) + s * animvalue[k+2].value) * bone->scale[j]; } else { pos[j] += animvalue[k+1].value * bone->scale[j]; } } else { // are we at the end of the repeating values section and there's another section with data? if (animvalue->num.total <= k + 1) { pos[j] += (animvalue[animvalue->num.valid].value * (1.f - s) + s * animvalue[animvalue->num.valid + 2].value) * bone->scale[j]; } else { pos[j] += animvalue[animvalue->num.valid].value * bone->scale[j]; } } } if (bone->bonecontroller[j] != -1) { pos[j] += BoneAdj[bone->bonecontroller[j]]; } } } /*! */ void CAnimatedMeshHalfLife::calcRotations(vec3_hl *pos, vec4_hl *q, SHalflifeSequence *seq, SHalflifeAnimOffset *anim, f32 f) { s32 frame = (s32)f; f32 s = (f - frame); // add in programatic controllers calcBoneAdj(); SHalflifeBone *bone = (SHalflifeBone *)((u8 *)Header + Header->boneindex); for ( u32 i = 0; i < Header->numbones; i++, bone++, anim++) { core::vector3df angle1, angle2; calcBoneQuaternion(frame, bone, anim, 0, angle1.X, angle2.X); calcBoneQuaternion(frame, bone, anim, 1, angle1.Y, angle2.Y); calcBoneQuaternion(frame, bone, anim, 2, angle1.Z, angle2.Z); if (!angle1.equals(angle2)) { vec4_hl q1, q2; AngleQuaternion( angle1, q1 ); AngleQuaternion( angle2, q2 ); QuaternionSlerp( q1, q2, s, q[i] ); } else { AngleQuaternion( angle1, q[i] ); } calcBonePosition(frame, s, bone, anim, pos[i]); } if (seq->motiontype & STUDIO_X) pos[seq->motionbone][0] = 0.f; if (seq->motiontype & STUDIO_Y) pos[seq->motionbone][1] = 0.f; if (seq->motiontype & STUDIO_Z) pos[seq->motionbone][2] = 0.f; } /*! */ SHalflifeAnimOffset * CAnimatedMeshHalfLife::getAnim( SHalflifeSequence *seq ) { SHalflifeSequenceGroup *seqgroup = (SHalflifeSequenceGroup *)((u8*)Header + Header->seqgroupindex) + seq->seqgroup; if (seq->seqgroup == 0) { return (SHalflifeAnimOffset *)((u8*)Header + seqgroup->data + seq->animindex); } return (SHalflifeAnimOffset *)((u8*)AnimationHeader[seq->seqgroup] + seq->animindex); } /*! */ void CAnimatedMeshHalfLife::slerpBones(vec4_hl q1[], vec3_hl pos1[], vec4_hl q2[], vec3_hl pos2[], f32 s) { if (s < 0) s = 0; else if (s > 1.f) s = 1.f; f32 s1 = 1.f - s; for ( u32 i = 0; i < Header->numbones; i++) { vec4_hl q3; QuaternionSlerp( q1[i], q2[i], s, q3 ); q1[i][0] = q3[0]; q1[i][1] = q3[1]; q1[i][2] = q3[2]; q1[i][3] = q3[3]; pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s; pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s; pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s; } } /*! */ void CAnimatedMeshHalfLife::setUpBones() { static vec3_hl pos[MAXSTUDIOBONES]; f32 bonematrix[3][4]; static vec4_hl q[MAXSTUDIOBONES]; static vec3_hl pos2[MAXSTUDIOBONES]; static vec4_hl q2[MAXSTUDIOBONES]; static vec3_hl pos3[MAXSTUDIOBONES]; static vec4_hl q3[MAXSTUDIOBONES]; static vec3_hl pos4[MAXSTUDIOBONES]; static vec4_hl q4[MAXSTUDIOBONES]; if (SequenceIndex >= Header->numseq) SequenceIndex = 0; SHalflifeSequence *seq = (SHalflifeSequence *)((u8*) Header + Header->seqindex) + SequenceIndex; SHalflifeAnimOffset *anim = getAnim(seq); calcRotations(pos, q, seq, anim, CurrentFrame); if (seq->numblends > 1) { anim += Header->numbones; calcRotations( pos2, q2, seq, anim, CurrentFrame ); f32 s = Blending[0] / 255.f; slerpBones( q, pos, q2, pos2, s ); if (seq->numblends == 4) { anim += Header->numbones; calcRotations( pos3, q3, seq, anim, CurrentFrame ); anim += Header->numbones; calcRotations( pos4, q4, seq, anim, CurrentFrame ); s = Blending[0] / 255.f; slerpBones( q3, pos3, q4, pos4, s ); s = Blending[1] / 255.f; slerpBones( q, pos, q3, pos3, s ); } } SHalflifeBone *bone = (SHalflifeBone *)((u8*) Header + Header->boneindex); for (u32 i = 0; i < Header->numbones; i++) { QuaternionMatrix( q[i], bonematrix ); bonematrix[0][3] = pos[i][0]; bonematrix[1][3] = pos[i][1]; bonematrix[2][3] = pos[i][2]; if (bone[i].parent == -1) { memcpy(BoneTransform[i], bonematrix, sizeof(f32) * 12); } else { R_ConcatTransforms (BoneTransform[bone[i].parent], bonematrix, BoneTransform[i]); } } } //! Returns an axis aligned bounding box const core::aabbox3d& CAnimatedMeshHalfLife::getBoundingBox() const { return MeshIPol->BoundingBox; } //! Returns the type of the animated mesh. E_ANIMATED_MESH_TYPE CAnimatedMeshHalfLife::getMeshType() const { return EAMT_MDL_HALFLIFE; } //! returns amount of mesh buffers. u32 CAnimatedMeshHalfLife::getMeshBufferCount() const { return MeshIPol->getMeshBufferCount(); } //! returns pointer to a mesh buffer IMeshBuffer* CAnimatedMeshHalfLife::getMeshBuffer(u32 nr) const { return MeshIPol->getMeshBuffer(nr); } //! Returns pointer to a mesh buffer which fits a material /** \param material: material to search for \return Returns the pointer to the mesh buffer or NULL if there is no such mesh buffer. */ IMeshBuffer* CAnimatedMeshHalfLife::getMeshBuffer(const video::SMaterial &material) const { return MeshIPol->getMeshBuffer(material); } void CAnimatedMeshHalfLife::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) { MeshIPol->setMaterialFlag ( flag, newvalue ); } //! set user axis aligned bounding box void CAnimatedMeshHalfLife::setBoundingBox(const core::aabbox3df& box) { MeshIPol->setBoundingBox(box); } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_MD3_LOADER_ irrlicht-1.8.3/source/Irrlicht/C3DSMeshFileLoader.h0000644000000000000000000000775212574354552020561 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_3DS_MESH_FILE_LOADER_H_INCLUDED__ #define __C_3DS_MESH_FILE_LOADER_H_INCLUDED__ #include "IMeshLoader.h" #include "IFileSystem.h" #include "ISceneManager.h" #include "irrString.h" #include "SMesh.h" #include "matrix4.h" namespace irr { namespace scene { //! Meshloader capable of loading 3ds meshes. class C3DSMeshFileLoader : public IMeshLoader { public: //! Constructor C3DSMeshFileLoader(ISceneManager* smgr, io::IFileSystem* fs); //! destructor virtual ~C3DSMeshFileLoader(); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") virtual bool isALoadableFileExtension(const io::path& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. virtual IAnimatedMesh* createMesh(io::IReadFile* file); private: // byte-align structures #include "irrpack.h" struct ChunkHeader { u16 id; s32 length; } PACK_STRUCT; // Default alignment #include "irrunpack.h" struct ChunkData { ChunkData() : read(0) {} ChunkHeader header; s32 read; }; struct SCurrentMaterial { void clear() { Material=video::SMaterial(); Name=""; Filename[0]=""; Filename[1]=""; Filename[2]=""; Filename[3]=""; Filename[4]=""; Strength[0]=0.f; Strength[1]=0.f; Strength[2]=0.f; Strength[3]=0.f; Strength[4]=0.f; } video::SMaterial Material; core::stringc Name; core::stringc Filename[5]; f32 Strength[5]; }; struct SMaterialGroup { SMaterialGroup() : faceCount(0), faces(0) {}; SMaterialGroup(const SMaterialGroup& o) { *this = o; } ~SMaterialGroup() { clear(); } void clear() { delete [] faces; faces = 0; faceCount = 0; } void operator =(const SMaterialGroup& o) { MaterialName = o.MaterialName; faceCount = o.faceCount; faces = new u16[faceCount]; for (u16 i=0; i TempIndices; f32* TCoords; u16 CountVertices; u16 CountFaces; // = CountIndices/4 u16 CountTCoords; core::array MaterialGroups; SCurrentMaterial CurrentMaterial; core::array Materials; core::array MeshBufferNames; core::matrix4 TransformationMatrix; SMesh* Mesh; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/source/Irrlicht/C3DSMeshFileLoader.cpp0000644000000000000000000010445512574354552021112 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_3DS_LOADER_ #include "C3DSMeshFileLoader.h" #include "os.h" #include "SMeshBuffer.h" #include "SAnimatedMesh.h" #include "IReadFile.h" #include "IVideoDriver.h" #include "IMeshManipulator.h" #ifdef _DEBUG #define _IRR_DEBUG_3DS_LOADER_ #endif namespace irr { namespace scene { namespace { enum e3DSChunk { // Primary chunk C3DS_MAIN3DS = 0x4D4D, // Main Chunks C3DS_EDIT3DS = 0x3D3D, C3DS_KEYF3DS = 0xB000, C3DS_VERSION = 0x0002, C3DS_MESHVERSION = 0x3D3E, // sub chunks of C3DS_EDIT3DS C3DS_EDIT_MATERIAL = 0xAFFF, C3DS_EDIT_OBJECT = 0x4000, // sub chunks of C3DS_EDIT_MATERIAL C3DS_MATNAME = 0xA000, C3DS_MATAMBIENT = 0xA010, C3DS_MATDIFFUSE = 0xA020, C3DS_MATSPECULAR = 0xA030, C3DS_MATSHININESS = 0xA040, C3DS_MATSHIN2PCT = 0xA041, C3DS_TRANSPARENCY = 0xA050, C3DS_TRANSPARENCY_FALLOFF = 0xA052, C3DS_REFL_BLUR = 0xA053, C3DS_TWO_SIDE = 0xA081, C3DS_WIRE = 0xA085, C3DS_SHADING = 0xA100, C3DS_MATTEXMAP = 0xA200, C3DS_MATSPECMAP = 0xA204, C3DS_MATOPACMAP = 0xA210, C3DS_MATREFLMAP = 0xA220, C3DS_MATBUMPMAP = 0xA230, C3DS_MATMAPFILE = 0xA300, C3DS_MAT_TEXTILING = 0xA351, C3DS_MAT_USCALE = 0xA354, C3DS_MAT_VSCALE = 0xA356, C3DS_MAT_UOFFSET = 0xA358, C3DS_MAT_VOFFSET = 0xA35A, // subs of C3DS_EDIT_OBJECT C3DS_OBJTRIMESH = 0x4100, // subs of C3DS_OBJTRIMESH C3DS_TRIVERT = 0x4110, C3DS_POINTFLAGARRAY= 0x4111, C3DS_TRIFACE = 0x4120, C3DS_TRIFACEMAT = 0x4130, C3DS_TRIUV = 0x4140, C3DS_TRISMOOTH = 0x4150, C3DS_TRIMATRIX = 0x4160, C3DS_MESHCOLOR = 0x4165, C3DS_DIRECT_LIGHT = 0x4600, C3DS_DL_INNER_RANGE= 0x4659, C3DS_DL_OUTER_RANGE= 0x465A, C3DS_DL_MULTIPLIER = 0x465B, C3DS_CAMERA = 0x4700, C3DS_CAM_SEE_CONE = 0x4710, C3DS_CAM_RANGES = 0x4720, // subs of C3DS_KEYF3DS C3DS_KF_HDR = 0xB00A, C3DS_AMBIENT_TAG = 0xB001, C3DS_OBJECT_TAG = 0xB002, C3DS_CAMERA_TAG = 0xB003, C3DS_TARGET_TAG = 0xB004, C3DS_LIGHTNODE_TAG = 0xB005, C3DS_KF_SEG = 0xB008, C3DS_KF_CURTIME = 0xB009, C3DS_KF_NODE_HDR = 0xB010, C3DS_PIVOTPOINT = 0xB013, C3DS_BOUNDBOX = 0xB014, C3DS_MORPH_SMOOTH = 0xB015, C3DS_POS_TRACK_TAG = 0xB020, C3DS_ROT_TRACK_TAG = 0xB021, C3DS_SCL_TRACK_TAG = 0xB022, C3DS_NODE_ID = 0xB030, // Viewport definitions C3DS_VIEWPORT_LAYOUT = 0x7001, C3DS_VIEWPORT_DATA = 0x7011, C3DS_VIEWPORT_DATA_3 = 0x7012, C3DS_VIEWPORT_SIZE = 0x7020, // different color chunk types C3DS_COL_RGB = 0x0010, C3DS_COL_TRU = 0x0011, C3DS_COL_LIN_24 = 0x0012, C3DS_COL_LIN_F = 0x0013, // percentage chunk types C3DS_PERCENTAGE_I = 0x0030, C3DS_PERCENTAGE_F = 0x0031, C3DS_CHUNK_MAX = 0xFFFF }; } //! Constructor C3DSMeshFileLoader::C3DSMeshFileLoader(ISceneManager* smgr, io::IFileSystem* fs) : SceneManager(smgr), FileSystem(fs), Vertices(0), Indices(0), SmoothingGroups(0), TCoords(0), CountVertices(0), CountFaces(0), CountTCoords(0), Mesh(0) { #ifdef _DEBUG setDebugName("C3DSMeshFileLoader"); #endif if (FileSystem) FileSystem->grab(); } //! destructor C3DSMeshFileLoader::~C3DSMeshFileLoader() { cleanUp(); if (FileSystem) FileSystem->drop(); if (Mesh) Mesh->drop(); } //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") bool C3DSMeshFileLoader::isALoadableFileExtension(const io::path& filename) const { return core::hasFileExtension ( filename, "3ds" ); } //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). //! See IReferenceCounted::drop() for more information. IAnimatedMesh* C3DSMeshFileLoader::createMesh(io::IReadFile* file) { ChunkData data; readChunkData(file, data); if (data.header.id != C3DS_MAIN3DS ) return 0; CurrentMaterial.clear(); Materials.clear(); MeshBufferNames.clear(); cleanUp(); if (Mesh) Mesh->drop(); Mesh = new SMesh(); if (readChunk(file, &data)) { // success for (u32 i=0; igetMeshBufferCount(); ++i) { SMeshBuffer* mb = ((SMeshBuffer*)Mesh->getMeshBuffer(i)); // drop empty buffers if (mb->getIndexCount() == 0 || mb->getVertexCount() == 0) { Mesh->MeshBuffers.erase(i--); mb->drop(); } else { if (mb->Material.MaterialType == video::EMT_PARALLAX_MAP_SOLID) { SMesh tmp; tmp.addMeshBuffer(mb); mb->drop(); IMesh* tangentMesh = SceneManager->getMeshManipulator()->createMeshWithTangents(&tmp); Mesh->MeshBuffers[i]=tangentMesh->getMeshBuffer(0); // we need to grab because we replace the buffer manually. Mesh->MeshBuffers[i]->grab(); // clean up intermediate mesh struct tangentMesh->drop(); } Mesh->MeshBuffers[i]->recalculateBoundingBox(); } } Mesh->recalculateBoundingBox(); SAnimatedMesh* am = new SAnimatedMesh(); am->Type = EAMT_3DS; am->addMesh(Mesh); am->recalculateBoundingBox(); Mesh->drop(); Mesh = 0; return am; } Mesh->drop(); Mesh = 0; return 0; } bool C3DSMeshFileLoader::readPercentageChunk(io::IReadFile* file, ChunkData* chunk, f32& percentage) { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load percentage chunk.", ELL_DEBUG); #endif ChunkData data; readChunkData(file, data); short intpercentage; float fpercentage; switch(data.header.id) { case C3DS_PERCENTAGE_I: { // read short file->read(&intpercentage, 2); #ifdef __BIG_ENDIAN__ intpercentage = os::Byteswap::byteswap(intpercentage); #endif percentage=intpercentage/100.0f; data.read += 2; } break; case C3DS_PERCENTAGE_F: { // read float file->read(&fpercentage, sizeof(float)); data.read += sizeof(float); #ifdef __BIG_ENDIAN__ percentage = os::Byteswap::byteswap(fpercentage); #else percentage = (f32)fpercentage; #endif } break; default: { // unknown percentage chunk os::Printer::log("Unknown percentage chunk in 3Ds file.", ELL_WARNING); file->seek(data.header.length - data.read, true); data.read += data.header.length - data.read; } } chunk->read += data.read; return true; } bool C3DSMeshFileLoader::readColorChunk(io::IReadFile* file, ChunkData* chunk, video::SColor& out) { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load color chunk.", ELL_DEBUG); #endif ChunkData data; readChunkData(file, data); u8 c[3]; f32 cf[3]; switch(data.header.id) { case C3DS_COL_TRU: case C3DS_COL_LIN_24: { // read 8 bit data file->read(c, sizeof(c)); out.set(255, c[0], c[1], c[2]); data.read += sizeof(c); } break; case C3DS_COL_RGB: case C3DS_COL_LIN_F: { // read float data file->read(cf, sizeof(cf)); #ifdef __BIG_ENDIAN__ cf[0] = os::Byteswap::byteswap(cf[0]); cf[1] = os::Byteswap::byteswap(cf[1]); cf[2] = os::Byteswap::byteswap(cf[2]); #endif out.set(255, (s32)(cf[0]*255.0f), (s32)(cf[1]*255.0f), (s32)(cf[2]*255.0f)); data.read += sizeof(cf); } break; default: { // unknown color chunk size os::Printer::log("Unknown size of color chunk in 3Ds file.", ELL_WARNING); file->seek(data.header.length - data.read, true); data.read += data.header.length - data.read; } } chunk->read += data.read; return true; } bool C3DSMeshFileLoader::readMaterialChunk(io::IReadFile* file, ChunkData* parent) { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load material chunk.", ELL_DEBUG); #endif u16 matSection=0; while(parent->read < parent->header.length) { ChunkData data; readChunkData(file, data); switch(data.header.id) { case C3DS_MATNAME: { c8* c = new c8[data.header.length - data.read]; file->read(c, data.header.length - data.read); if (strlen(c)) CurrentMaterial.Name = c; data.read += data.header.length - data.read; delete [] c; } break; case C3DS_MATAMBIENT: readColorChunk(file, &data, CurrentMaterial.Material.AmbientColor); break; case C3DS_MATDIFFUSE: readColorChunk(file, &data, CurrentMaterial.Material.DiffuseColor); break; case C3DS_MATSPECULAR: readColorChunk(file, &data, CurrentMaterial.Material.SpecularColor); break; case C3DS_MATSHININESS: readPercentageChunk(file, &data, CurrentMaterial.Material.Shininess); CurrentMaterial.Material.Shininess = (1.f-CurrentMaterial.Material.Shininess)*128.f; break; case C3DS_TRANSPARENCY: { f32 percentage; readPercentageChunk(file, &data, percentage); if (percentage>0.0f) { CurrentMaterial.Material.MaterialTypeParam=percentage; CurrentMaterial.Material.MaterialType=video::EMT_TRANSPARENT_VERTEX_ALPHA; } else { CurrentMaterial.Material.MaterialType=video::EMT_SOLID; } } break; case C3DS_WIRE: CurrentMaterial.Material.Wireframe=true; break; case C3DS_TWO_SIDE: CurrentMaterial.Material.BackfaceCulling=false; break; case C3DS_SHADING: { s16 flags; file->read(&flags, 2); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif switch (flags) { case 0: CurrentMaterial.Material.Wireframe=true; break; case 1: CurrentMaterial.Material.Wireframe=false; CurrentMaterial.Material.GouraudShading=false; break; case 2: CurrentMaterial.Material.Wireframe=false; CurrentMaterial.Material.GouraudShading=true; break; default: // phong and metal missing break; } data.read += data.header.length - data.read; } break; case C3DS_MATTEXMAP: case C3DS_MATSPECMAP: case C3DS_MATOPACMAP: case C3DS_MATREFLMAP: case C3DS_MATBUMPMAP: { matSection=data.header.id; // Should contain a percentage chunk, but does // not always have it s16 testval; const long pos = file->getPos(); file->read(&testval, 2); #ifdef __BIG_ENDIAN__ testval = os::Byteswap::byteswap(testval); #endif file->seek(pos, false); if ((testval == C3DS_PERCENTAGE_I) || (testval == C3DS_PERCENTAGE_F)) switch (matSection) { case C3DS_MATTEXMAP: readPercentageChunk(file, &data, CurrentMaterial.Strength[0]); break; case C3DS_MATSPECMAP: readPercentageChunk(file, &data, CurrentMaterial.Strength[1]); break; case C3DS_MATOPACMAP: readPercentageChunk(file, &data, CurrentMaterial.Strength[2]); break; case C3DS_MATBUMPMAP: readPercentageChunk(file, &data, CurrentMaterial.Strength[4]); break; } } break; case C3DS_MATMAPFILE: { // read texture file name c8* c = new c8[data.header.length - data.read]; file->read(c, data.header.length - data.read); switch (matSection) { case C3DS_MATTEXMAP: CurrentMaterial.Filename[0] = c; break; case C3DS_MATSPECMAP: CurrentMaterial.Filename[1] = c; break; case C3DS_MATOPACMAP: CurrentMaterial.Filename[2] = c; break; case C3DS_MATREFLMAP: CurrentMaterial.Filename[3] = c; break; case C3DS_MATBUMPMAP: CurrentMaterial.Filename[4] = c; break; } data.read += data.header.length - data.read; delete [] c; } break; case C3DS_MAT_TEXTILING: { s16 flags; file->read(&flags, 2); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif data.read += 2; } break; case C3DS_MAT_USCALE: case C3DS_MAT_VSCALE: case C3DS_MAT_UOFFSET: case C3DS_MAT_VOFFSET: { f32 value; file->read(&value, 4); #ifdef __BIG_ENDIAN__ value = os::Byteswap::byteswap(value); #endif u32 i=0; if (matSection != C3DS_MATTEXMAP) i=1; u32 j=0,k=0; if (data.header.id == C3DS_MAT_VSCALE) { j=1; k=1; } else if (data.header.id == C3DS_MAT_UOFFSET) { j=2; k=0; } else if (data.header.id == C3DS_MAT_VOFFSET) { j=2; k=1; } CurrentMaterial.Material.getTextureMatrix(i)(j,k)=value; data.read += 4; } break; default: // ignore chunk file->seek(data.header.length - data.read, true); data.read += data.header.length - data.read; } parent->read += data.read; } Materials.push_back(CurrentMaterial); CurrentMaterial.clear(); return true; } bool C3DSMeshFileLoader::readTrackChunk(io::IReadFile* file, ChunkData& data, IMeshBuffer* mb, const core::vector3df& pivot) { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load track chunk.", ELL_DEBUG); #endif u16 flags; u32 flags2; // Track flags file->read(&flags, 2); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif file->read(&flags2, 4); #ifdef __BIG_ENDIAN__ flags2 = os::Byteswap::byteswap(flags2); #endif file->read(&flags2, 4); #ifdef __BIG_ENDIAN__ flags2 = os::Byteswap::byteswap(flags2); #endif // Num keys file->read(&flags2, 4); #ifdef __BIG_ENDIAN__ flags2 = os::Byteswap::byteswap(flags2); #endif file->read(&flags2, 4); #ifdef __BIG_ENDIAN__ flags2 = os::Byteswap::byteswap(flags2); #endif // TCB flags file->read(&flags, 2); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif data.read += 20; f32 angle=0.0f; if (data.header.id== C3DS_ROT_TRACK_TAG) { // Angle file->read(&angle, sizeof(f32)); #ifdef __BIG_ENDIAN__ angle = os::Byteswap::byteswap(angle); #endif data.read += sizeof(f32); } core::vector3df vec; file->read(&vec.X, sizeof(f32)); file->read(&vec.Y, sizeof(f32)); file->read(&vec.Z, sizeof(f32)); #ifdef __BIG_ENDIAN__ vec.X = os::Byteswap::byteswap(vec.X); vec.Y = os::Byteswap::byteswap(vec.Y); vec.Z = os::Byteswap::byteswap(vec.Z); #endif data.read += 12; vec-=pivot; // apply transformation to mesh buffer if (false)//mb) { video::S3DVertex *vertices=(video::S3DVertex*)mb->getVertices(); if (data.header.id==C3DS_POS_TRACK_TAG) { for (u32 i=0; igetVertexCount(); ++i) vertices[i].Pos+=vec; } else if (data.header.id==C3DS_ROT_TRACK_TAG) { //TODO } else if (data.header.id==C3DS_SCL_TRACK_TAG) { //TODO } } // skip further frames file->seek(data.header.length - data.read, true); data.read += data.header.length - data.read; return true; } bool C3DSMeshFileLoader::readFrameChunk(io::IReadFile* file, ChunkData* parent) { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load frame chunk.", ELL_DEBUG); #endif ChunkData data; //KF_HDR is always at the beginning readChunkData(file, data); if (data.header.id != C3DS_KF_HDR) return false; else { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load keyframe header.", ELL_DEBUG); #endif u16 version; file->read(&version, 2); #ifdef __BIG_ENDIAN__ version = os::Byteswap::byteswap(version); #endif core::stringc name; readString(file, data, name); u32 flags; file->read(&flags, 4); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif data.read += 4; parent->read += data.read; } data.read=0; IMeshBuffer* mb=0; core::vector3df pivot,bboxCenter; while(parent->read < parent->header.length) { readChunkData(file, data); switch(data.header.id) { case C3DS_OBJECT_TAG: { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load object tag.", ELL_DEBUG); #endif mb=0; pivot.set(0.0f, 0.0f, 0.0f); } break; case C3DS_KF_SEG: { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load keyframe segment.", ELL_DEBUG); #endif u32 flags; file->read(&flags, 4); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif file->read(&flags, 4); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif data.read += 8; } break; case C3DS_KF_NODE_HDR: { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load keyframe node header.", ELL_DEBUG); #endif s16 flags; c8* c = new c8[data.header.length - data.read-6]; file->read(c, data.header.length - data.read-6); // search mesh buffer to apply these transformations to for (u32 i=0; igetMeshBuffer(i); break; } } file->read(&flags, 2); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif file->read(&flags, 2); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif file->read(&flags, 2); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif data.read += data.header.length - data.read; delete [] c; } break; case C3DS_KF_CURTIME: { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load keyframe current time.", ELL_DEBUG); #endif u32 flags; file->read(&flags, 4); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif data.read += 4; } break; case C3DS_NODE_ID: { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load node ID.", ELL_DEBUG); #endif u16 flags; file->read(&flags, 2); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif data.read += 2; } break; case C3DS_PIVOTPOINT: { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load pivot point.", ELL_DEBUG); #endif file->read(&pivot.X, sizeof(f32)); file->read(&pivot.Y, sizeof(f32)); file->read(&pivot.Z, sizeof(f32)); #ifdef __BIG_ENDIAN__ pivot.X = os::Byteswap::byteswap(pivot.X); pivot.Y = os::Byteswap::byteswap(pivot.Y); pivot.Z = os::Byteswap::byteswap(pivot.Z); #endif data.read += 12; } break; case C3DS_BOUNDBOX: { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load bounding box.", ELL_DEBUG); #endif core::aabbox3df bbox; // abuse bboxCenter as temporary variable file->read(&bboxCenter.X, sizeof(f32)); file->read(&bboxCenter.Y, sizeof(f32)); file->read(&bboxCenter.Z, sizeof(f32)); #ifdef __BIG_ENDIAN__ bboxCenter.X = os::Byteswap::byteswap(bboxCenter.X); bboxCenter.Y = os::Byteswap::byteswap(bboxCenter.Y); bboxCenter.Z = os::Byteswap::byteswap(bboxCenter.Z); #endif bbox.reset(bboxCenter); file->read(&bboxCenter.X, sizeof(f32)); file->read(&bboxCenter.Y, sizeof(f32)); file->read(&bboxCenter.Z, sizeof(f32)); #ifdef __BIG_ENDIAN__ bboxCenter.X = os::Byteswap::byteswap(bboxCenter.X); bboxCenter.Y = os::Byteswap::byteswap(bboxCenter.Y); bboxCenter.Z = os::Byteswap::byteswap(bboxCenter.Z); #endif bbox.addInternalPoint(bboxCenter); bboxCenter=bbox.getCenter(); data.read += 24; } break; case C3DS_MORPH_SMOOTH: { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load morph smooth.", ELL_DEBUG); #endif f32 flag; file->read(&flag, 4); #ifdef __BIG_ENDIAN__ flag = os::Byteswap::byteswap(flag); #endif data.read += 4; } break; case C3DS_POS_TRACK_TAG: case C3DS_ROT_TRACK_TAG: case C3DS_SCL_TRACK_TAG: readTrackChunk(file, data, mb, bboxCenter-pivot); break; default: // ignore chunk file->seek(data.header.length - data.read, true); data.read += data.header.length - data.read; } parent->read += data.read; data.read=0; } return true; } bool C3DSMeshFileLoader::readChunk(io::IReadFile* file, ChunkData* parent) { while(parent->read < parent->header.length) { ChunkData data; readChunkData(file, data); switch(data.header.id) { case C3DS_VERSION: { u16 version; file->read(&version, sizeof(u16)); #ifdef __BIG_ENDIAN__ version = os::Byteswap::byteswap(version); #endif file->seek(data.header.length - data.read - 2, true); data.read += data.header.length - data.read; if (version != 0x03) os::Printer::log("3ds file version is other than 3.", ELL_ERROR); } break; case C3DS_EDIT_MATERIAL: readMaterialChunk(file, &data); break; case C3DS_KEYF3DS: readFrameChunk(file, &data); break; case C3DS_EDIT3DS: break; case C3DS_MESHVERSION: case 0x01: { u32 version; file->read(&version, sizeof(u32)); #ifdef __BIG_ENDIAN__ version = os::Byteswap::byteswap(version); #endif data.read += sizeof(u32); } break; case C3DS_EDIT_OBJECT: { core::stringc name; readString(file, data, name); readObjectChunk(file, &data); composeObject(file, name); } break; default: // ignore chunk file->seek(data.header.length - data.read, true); data.read += data.header.length - data.read; } parent->read += data.read; } return true; } bool C3DSMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData* parent) { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load object chunk.", ELL_DEBUG); #endif while(parent->read < parent->header.length) { ChunkData data; readChunkData(file, data); switch(data.header.id) { case C3DS_OBJTRIMESH: readObjectChunk(file, &data); break; case C3DS_TRIVERT: readVertices(file, data); break; case C3DS_POINTFLAGARRAY: { u16 numVertex, flags; file->read(&numVertex, sizeof(u16)); #ifdef __BIG_ENDIAN__ numVertex= os::Byteswap::byteswap(numVertex); #endif for (u16 i=0; iread(&flags, sizeof(u16)); #ifdef __BIG_ENDIAN__ flags = os::Byteswap::byteswap(flags); #endif } data.read += (numVertex+1)*sizeof(u16); } break; case C3DS_TRIFACE: readIndices(file, data); readObjectChunk(file, &data); // read smooth and material groups break; case C3DS_TRIFACEMAT: readMaterialGroup(file, data); break; case C3DS_TRIUV: // getting texture coordinates readTextureCoords(file, data); break; case C3DS_TRIMATRIX: { f32 mat[4][3]; file->read(&mat, 12*sizeof(f32)); TransformationMatrix.makeIdentity(); for (int i=0; i<4; ++i) { for (int j=0; j<3; ++j) { #ifdef __BIG_ENDIAN__ TransformationMatrix(i,j)=os::Byteswap::byteswap(mat[i][j]); #else TransformationMatrix(i,j)=mat[i][j]; #endif } } data.read += 12*sizeof(f32); } break; case C3DS_MESHCOLOR: { u8 flag; file->read(&flag, sizeof(u8)); ++data.read; } break; case C3DS_TRISMOOTH: // TODO { SmoothingGroups = new u32[CountFaces]; file->read(SmoothingGroups, CountFaces*sizeof(u32)); #ifdef __BIG_ENDIAN__ for (u16 i=0; iseek(data.header.length - data.read, true); data.read += data.header.length - data.read; } parent->read += data.read; } return true; } void C3DSMeshFileLoader::composeObject(io::IReadFile* file, const core::stringc& name) { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Compose object.", ELL_DEBUG); #endif if (Mesh->getMeshBufferCount() != Materials.size()) loadMaterials(file); if (MaterialGroups.empty()) { // no material group, so add all SMaterialGroup group; group.faceCount = CountFaces; group.faces = new u16[group.faceCount]; for (u16 i=0; iaddMeshBuffer(mb); mb->getMaterial() = Materials[0].Material; mb->drop(); // add an empty mesh buffer name MeshBufferNames.push_back(""); } } for (u32 i=0; igetVideoDriver()->getMaximalPrimitiveCount(), (u32)((1<<16)-1))-3; // currently hardcoded s16 max value for index pointers // find mesh buffer for this group for (mbPos=0; mbPosgetMeshBuffer(mbPos); mat=&Materials[mbPos].Material; MeshBufferNames[mbPos]=name; break; } } if (mb != 0) { // add geometry to the buffer. video::S3DVertex vtx; core::vector3df vec; vtx.Color=mat->DiffuseColor; if (mat->MaterialType==video::EMT_TRANSPARENT_VERTEX_ALPHA) { vtx.Color.setAlpha((int)(255.0f*mat->MaterialTypeParam)); } vtx.Normal.set(0,0,0); for (s32 f=0; fVertices.size(); if (vtxCount>maxPrimitives) { IMeshBuffer* tmp = mb; mb = new SMeshBuffer(); Mesh->addMeshBuffer(mb); mb->drop(); Mesh->MeshBuffers[mbPos] = Mesh->MeshBuffers.getLast(); Mesh->MeshBuffers[Mesh->MeshBuffers.size()-1] = tmp; mb->getMaterial() = tmp->getMaterial(); vtxCount=0; } for (s32 v=0; v<3; ++v) { s32 idx = Indices[MaterialGroups[i].faces[f]*4 +v]; if (CountVertices > idx) { vtx.Pos.X = Vertices[idx*3 + 0]; vtx.Pos.Z = Vertices[idx*3 + 1]; vtx.Pos.Y = Vertices[idx*3 + 2]; // TransformationMatrix.transformVect(vtx.Pos); } if (CountTCoords > idx) { vtx.TCoords.X = TCoords[idx*2 + 0]; vtx.TCoords.Y = 1.0f -TCoords[idx*2 + 1]; } mb->Vertices.push_back(vtx); } // compute normal core::plane3d pl(mb->Vertices[vtxCount].Pos, mb->Vertices[vtxCount+2].Pos, mb->Vertices[vtxCount+1].Pos); mb->Vertices[vtxCount].Normal = pl.Normal; mb->Vertices[vtxCount+1].Normal = pl.Normal; mb->Vertices[vtxCount+2].Normal = pl.Normal; // add indices mb->Indices.push_back(vtxCount); mb->Indices.push_back(vtxCount+2); mb->Indices.push_back(vtxCount+1); } } else os::Printer::log("Found no matching material for Group in 3ds file.", ELL_WARNING); } cleanUp(); } void C3DSMeshFileLoader::loadMaterials(io::IReadFile* file) { // create a mesh buffer for every material core::stringc modelFilename = file->getFileName(); if (Materials.empty()) os::Printer::log("No materials found in 3ds file.", ELL_INFORMATION); MeshBufferNames.reallocate(Materials.size()); for (u32 i=0; iaddMeshBuffer(m); m->getMaterial() = Materials[i].Material; if (Materials[i].Filename[0].size()) { video::ITexture* texture = 0; if (FileSystem->existFile(Materials[i].Filename[0])) texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[0]); if (!texture) { const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[0]); if (FileSystem->existFile(fname)) texture = SceneManager->getVideoDriver()->getTexture(fname); } if (!texture) os::Printer::log("Could not load a texture for entry in 3ds file", Materials[i].Filename[0].c_str(), ELL_WARNING); else m->getMaterial().setTexture(0, texture); } if (Materials[i].Filename[2].size()) { video::ITexture* texture = 0; if (FileSystem->existFile(Materials[i].Filename[2])) texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[2]); if (!texture) { const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[2]); if (FileSystem->existFile(fname)) texture = SceneManager->getVideoDriver()->getTexture(fname); } if (!texture) { os::Printer::log("Could not load a texture for entry in 3ds file", Materials[i].Filename[2].c_str(), ELL_WARNING); } else { m->getMaterial().setTexture(0, texture); m->getMaterial().MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; } } if (Materials[i].Filename[3].size()) { video::ITexture* texture = 0; if (FileSystem->existFile(Materials[i].Filename[3])) texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[3]); if (!texture) { const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[3]); if (FileSystem->existFile(fname)) texture = SceneManager->getVideoDriver()->getTexture(fname); } if (!texture) { os::Printer::log("Could not load a texture for entry in 3ds file", Materials[i].Filename[3].c_str(), ELL_WARNING); } else { m->getMaterial().setTexture(1, m->getMaterial().getTexture(0)); m->getMaterial().setTexture(0, texture); m->getMaterial().MaterialType = video::EMT_REFLECTION_2_LAYER; } } if (Materials[i].Filename[4].size()) { video::ITexture* texture = 0; if (FileSystem->existFile(Materials[i].Filename[4])) texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[4]); if (!texture) { const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[4]); if (FileSystem->existFile(fname)) texture = SceneManager->getVideoDriver()->getTexture(fname); } if (!texture) os::Printer::log("Could not load a texture for entry in 3ds file", Materials[i].Filename[4].c_str(), ELL_WARNING); else { m->getMaterial().setTexture(1, texture); SceneManager->getVideoDriver()->makeNormalMapTexture(texture, Materials[i].Strength[4]*10.f); m->getMaterial().MaterialType=video::EMT_PARALLAX_MAP_SOLID; m->getMaterial().MaterialTypeParam=.035f; } } m->drop(); } } void C3DSMeshFileLoader::cleanUp() { delete [] Vertices; CountVertices = 0; Vertices = 0; delete [] Indices; Indices = 0; CountFaces = 0; delete [] SmoothingGroups; SmoothingGroups = 0; delete [] TCoords; TCoords = 0; CountTCoords = 0; MaterialGroups.clear(); } void C3DSMeshFileLoader::readTextureCoords(io::IReadFile* file, ChunkData& data) { #ifdef _IRR_DEBUG_3DS_LOADER_ os::Printer::log("Load texture coords.", ELL_DEBUG); #endif file->read(&CountTCoords, sizeof(CountTCoords)); #ifdef __BIG_ENDIAN__ CountTCoords = os::Byteswap::byteswap(CountTCoords); #endif data.read += sizeof(CountTCoords); s32 tcoordsBufferByteSize = CountTCoords * sizeof(f32) * 2; if (data.header.length - data.read != tcoordsBufferByteSize) { os::Printer::log("Invalid size of tcoords found in 3ds file.", ELL_WARNING); return; } TCoords = new f32[CountTCoords * 3]; file->read(TCoords, tcoordsBufferByteSize); #ifdef __BIG_ENDIAN__ for (int i=0;iread(&group.faceCount, sizeof(group.faceCount)); #ifdef __BIG_ENDIAN__ group.faceCount = os::Byteswap::byteswap(group.faceCount); #endif data.read += sizeof(group.faceCount); // read faces group.faces = new u16[group.faceCount]; file->read(group.faces, sizeof(u16) * group.faceCount); #ifdef __BIG_ENDIAN__ for (u32 i=0;iread(&CountFaces, sizeof(CountFaces)); #ifdef __BIG_ENDIAN__ CountFaces = os::Byteswap::byteswap(CountFaces); #endif data.read += sizeof(CountFaces); s32 indexBufferByteSize = CountFaces * sizeof(u16) * 4; // Indices are u16s. // After every 3 Indices in the array, there follows an edge flag. Indices = new u16[CountFaces * 4]; file->read(Indices, indexBufferByteSize); #ifdef __BIG_ENDIAN__ for (int i=0;iread(&CountVertices, sizeof(CountVertices)); #ifdef __BIG_ENDIAN__ CountVertices = os::Byteswap::byteswap(CountVertices); #endif data.read += sizeof(CountVertices); const s32 vertexBufferByteSize = CountVertices * sizeof(f32) * 3; if (data.header.length - data.read != vertexBufferByteSize) { os::Printer::log("Invalid size of vertices found in 3ds file", core::stringc(CountVertices), ELL_ERROR); return; } Vertices = new f32[CountVertices * 3]; file->read(Vertices, vertexBufferByteSize); #ifdef __BIG_ENDIAN__ for (int i=0;iread(&data.header, sizeof(ChunkHeader)); #ifdef __BIG_ENDIAN__ data.header.id = os::Byteswap::byteswap(data.header.id); data.header.length = os::Byteswap::byteswap(data.header.length); #endif data.read += sizeof(ChunkHeader); } void C3DSMeshFileLoader::readString(io::IReadFile* file, ChunkData& data, core::stringc& out) { c8 c = 1; out = ""; while (c) { file->read(&c, sizeof(c8)); if (c) out.append(c); } data.read+=out.size()+1; } } // end namespace scene } // end namespace irr #endif // _IRR_COMPILE_WITH_3DS_LOADER_ irrlicht-1.8.3/source/Irrlicht/BuiltInFont.h0000644000000000000000000015060112574354552017506 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __BUILD_IN_FONT_H_INCLUDED__ #define __BUILD_IN_FONT_H_INCLUDED__ #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_GUI_ // header file generated by Bin2H, copyright 2002 by N.Gebhardt. // Bin2H is Freeware. Download it freely from www.code3d.com. // for the source bitmap, see builtInFont.bmp namespace irr { namespace gui { #ifdef _IRR_COMPILE_WITH_BMP_LOADER_ u8 BuiltInFontData[] = { 0x42, 0x4d, 0x4a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x63, 0x0b, 0x00, 0x00, 0x63, 0x0b, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x18, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x04, 0x44, 0x44, 0x02, 0x04, 0x44, 0x44, 0x40, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x04, 0x44, 0x44, 0x02, 0x04, 0x44, 0x44, 0x40, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x04, 0x44, 0x44, 0x02, 0x04, 0x44, 0x44, 0x40, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x44, 0x22, 0x44, 0x42, 0x04, 0x44, 0x44, 0x02, 0x04, 0x44, 0x44, 0x40, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x04, 0x40, 0x00, 0x02, 0x00, 0x44, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x04, 0x40, 0x40, 0x22, 0x20, 0x00, 0x02, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x04, 0x40, 0x02, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x24, 0x22, 0x22, 0x24, 0x42, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x24, 0x42, 0x22, 0x24, 0x42, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x42, 0x44, 0x22, 0x44, 0x42, 0x22, 0x22, 0x44, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x44, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x42, 0x44, 0x22, 0x22, 0x44, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x42, 0x24, 0x42, 0x44, 0x22, 0x44, 0x22, 0x22, 0x44, 0x42, 0x24, 0x42, 0x44, 0x22, 0x22, 0x24, 0x42, 0x24, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x24, 0x44, 0x22, 0x24, 0x44, 0x42, 0x22, 0x22, 0x22, 0x22, 0x24, 0x44, 0x44, 0x44, 0x22, 0x24, 0x44, 0x22, 0x22, 0x44, 0x42, 0x44, 0x42, 0x24, 0x44, 0x44, 0x22, 0x24, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x42, 0x22, 0x44, 0x22, 0x44, 0x22, 0x24, 0x42, 0x24, 0x42, 0x22, 0x24, 0x22, 0x24, 0x22, 0x24, 0x22, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x24, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x42, 0x22, 0x44, 0x44, 0x42, 0x24, 0x44, 0x42, 0x44, 0x44, 0x24, 0x42, 0x44, 0x42, 0x22, 0x22, 0x22, 0x22, 0x44, 0x42, 0x22, 0x42, 0x22, 0x44, 0x44, 0x24, 0x42, 0x24, 0x42, 0x22, 0x22, 0x44, 0x22, 0x44, 0x24, 0x22, 0x24, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x24, 0x22, 0x24, 0x44, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x44, 0x22, 0x24, 0x44, 0x44, 0x44, 0x22, 0x44, 0x42, 0x44, 0x42, 0x24, 0x22, 0x24, 0x44, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x24, 0x44, 0x22, 0x44, 0x44, 0x22, 0x44, 0x22, 0x44, 0x22, 0x24, 0x42, 0x24, 0x42, 0x24, 0x42, 0x44, 0x22, 0x44, 0x42, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x44, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x42, 0x44, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x44, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x42, 0x22, 0x24, 0x42, 0x24, 0x42, 0x44, 0x22, 0x44, 0x22, 0x22, 0x44, 0x42, 0x24, 0x42, 0x44, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x24, 0x42, 0x22, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x42, 0x22, 0x22, 0x22, 0x22, 0x24, 0x24, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x12, 0x22, 0x12, 0x22, 0x12, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x12, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x44, 0x22, 0x24, 0x42, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x42, 0x22, 0x42, 0x42, 0x22, 0x44, 0x22, 0x22, 0x44, 0x22, 0x22, 0x44, 0x22, 0x22, 0x44, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x44, 0x42, 0x22, 0x24, 0x42, 0x22, 0x44, 0x22, 0x24, 0x42, 0x22, 0x44, 0x22, 0x24, 0x22, 0x24, 0x42, 0x22, 0x24, 0x22, 0x24, 0x24, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x42, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x44, 0x24, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x42, 0x22, 0x42, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x44, 0x22, 0x42, 0x44, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x44, 0x22, 0x22, 0x44, 0x22, 0x22, 0x44, 0x22, 0x22, 0x44, 0x22, 0x22, 0x44, 0x22, 0x22, 0x44, 0x22, 0x22, 0x42, 0x22, 0x24, 0x44, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x42, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x24, 0x24, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x22, 0x42, 0x24, 0x24, 0x24, 0x24, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x42, 0x42, 0x22, 0x44, 0x22, 0x24, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x42, 0x42, 0x24, 0x24, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x42, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x32, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x32, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x42, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x22, 0x22, 0x44, 0x42, 0x22, 0x24, 0x44, 0x22, 0x22, 0x44, 0x42, 0x22, 0x24, 0x44, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x42, 0x42, 0x22, 0x24, 0x42, 0x22, 0x44, 0x22, 0x24, 0x42, 0x22, 0x44, 0x22, 0x24, 0x42, 0x22, 0x44, 0x22, 0x44, 0x44, 0x42, 0x22, 0x44, 0x22, 0x24, 0x42, 0x22, 0x44, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x24, 0x22, 0x44, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x44, 0x42, 0x22, 0x42, 0x24, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x44, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x42, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x42, 0x42, 0x24, 0x22, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x42, 0x24, 0x22, 0x44, 0x42, 0x22, 0x44, 0x22, 0x24, 0x42, 0x22, 0x44, 0x22, 0x24, 0x42, 0x22, 0x44, 0x22, 0x24, 0x42, 0x22, 0x44, 0x24, 0x42, 0x22, 0x44, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x24, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x42, 0x22, 0x44, 0x42, 0x22, 0x42, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x42, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x22, 0x24, 0x44, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x42, 0x42, 0x24, 0x42, 0x22, 0x42, 0x42, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x42, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x32, 0x24, 0x24, 0x23, 0x24, 0x24, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x42, 0x22, 0x23, 0x22, 0x24, 0x22, 0x32, 0x24, 0x22, 0x23, 0x24, 0x24, 0x22, 0x32, 0x22, 0x42, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x12, 0x22, 0x12, 0x22, 0x12, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x24, 0x44, 0x42, 0x22, 0x44, 0x22, 0x24, 0x44, 0x42, 0x24, 0x44, 0x42, 0x24, 0x44, 0x42, 0x24, 0x44, 0x42, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x44, 0x44, 0x22, 0x24, 0x22, 0x24, 0x22, 0x24, 0x44, 0x22, 0x22, 0x44, 0x42, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x24, 0x44, 0x44, 0x22, 0x44, 0x44, 0x42, 0x24, 0x44, 0x44, 0x22, 0x44, 0x44, 0x42, 0x24, 0x44, 0x44, 0x22, 0x44, 0x44, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x42, 0x22, 0x24, 0x24, 0x22, 0x22, 0x42, 0x42, 0x22, 0x24, 0x24, 0x22, 0x22, 0x42, 0x42, 0x22, 0x24, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x44, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x42, 0x22, 0x24, 0x24, 0x22, 0x22, 0x42, 0x42, 0x22, 0x24, 0x24, 0x22, 0x22, 0x42, 0x42, 0x22, 0x22, 0x44, 0x44, 0x42, 0x24, 0x22, 0x22, 0x24, 0x44, 0x42, 0x24, 0x44, 0x42, 0x24, 0x44, 0x42, 0x24, 0x44, 0x42, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x24, 0x44, 0x22, 0x42, 0x24, 0x24, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x44, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x24, 0x42, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x24, 0x44, 0x42, 0x22, 0x44, 0x22, 0x24, 0x44, 0x42, 0x24, 0x44, 0x42, 0x24, 0x44, 0x42, 0x24, 0x44, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x22, 0x24, 0x22, 0x24, 0x22, 0x24, 0x44, 0x22, 0x22, 0x44, 0x42, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x24, 0x22, 0x22, 0x42, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x42, 0x42, 0x22, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x42, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x24, 0x22, 0x22, 0x22, 0x32, 0x22, 0x42, 0x23, 0x22, 0x42, 0x22, 0x32, 0x24, 0x24, 0x23, 0x24, 0x24, 0x22, 0x32, 0x24, 0x22, 0x23, 0x22, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x42, 0x22, 0x32, 0x24, 0x22, 0x32, 0x24, 0x22, 0x34, 0x22, 0x42, 0x32, 0x23, 0x24, 0x23, 0x42, 0x23, 0x24, 0x23, 0x22, 0x22, 0x22, 0x32, 0x24, 0x24, 0x23, 0x24, 0x22, 0x22, 0x32, 0x22, 0x42, 0x23, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x12, 0x21, 0x22, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x12, 0x21, 0x22, 0x21, 0x22, 0x12, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x24, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x42, 0x42, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x42, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x44, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x22, 0x42, 0x22, 0x42, 0x22, 0x44, 0x22, 0x22, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x24, 0x24, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x24, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x24, 0x22, 0x24, 0x24, 0x42, 0x22, 0x42, 0x44, 0x22, 0x24, 0x24, 0x42, 0x22, 0x42, 0x22, 0x44, 0x44, 0x42, 0x24, 0x24, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x24, 0x42, 0x22, 0x42, 0x42, 0x24, 0x44, 0x42, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x24, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x42, 0x42, 0x22, 0x22, 0x42, 0x42, 0x22, 0x24, 0x22, 0x22, 0x22, 0x42, 0x42, 0x22, 0x42, 0x22, 0x24, 0x24, 0x22, 0x24, 0x42, 0x22, 0x22, 0x22, 0x42, 0x42, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x42, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x22, 0x24, 0x24, 0x22, 0x24, 0x44, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x24, 0x24, 0x22, 0x24, 0x24, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x24, 0x24, 0x22, 0x22, 0x22, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x44, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x22, 0x42, 0x24, 0x24, 0x22, 0x24, 0x44, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x32, 0x22, 0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x32, 0x22, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x32, 0x22, 0x32, 0x23, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x23, 0x24, 0x22, 0x22, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x12, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x44, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x22, 0x42, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x24, 0x44, 0x22, 0x42, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x22, 0x42, 0x24, 0x22, 0x22, 0x44, 0x42, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x24, 0x22, 0x22, 0x42, 0x42, 0x24, 0x44, 0x22, 0x42, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x24, 0x24, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x23, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x12, 0x21, 0x22, 0x22, 0x12, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x12, 0x21, 0x22, 0x21, 0x22, 0x22, 0x12, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x42, 0x22, 0x24, 0x44, 0x22, 0x42, 0x42, 0x24, 0x22, 0x42, 0x24, 0x24, 0x22, 0x42, 0x24, 0x24, 0x24, 0x22, 0x42, 0x42, 0x22, 0x44, 0x22, 0x24, 0x44, 0x22, 0x22, 0x44, 0x42, 0x24, 0x22, 0x24, 0x42, 0x22, 0x24, 0x22, 0x24, 0x42, 0x22, 0x42, 0x22, 0x24, 0x24, 0x22, 0x24, 0x24, 0x22, 0x24, 0x22, 0x24, 0x44, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x22, 0x22, 0x42, 0x24, 0x22, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x42, 0x42, 0x24, 0x22, 0x42, 0x24, 0x24, 0x22, 0x42, 0x24, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x42, 0x22, 0x42, 0x22, 0x24, 0x24, 0x22, 0x22, 0x42, 0x22, 0x42, 0x42, 0x24, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x22, 0x22, 0x42, 0x24, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x42, 0x42, 0x24, 0x22, 0x42, 0x24, 0x42, 0x22, 0x42, 0x24, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x42, 0x22, 0x42, 0x22, 0x42, 0x42, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x22, 0x44, 0x22, 0x24, 0x44, 0x22, 0x44, 0x22, 0x24, 0x22, 0x42, 0x24, 0x24, 0x22, 0x42, 0x24, 0x44, 0x42, 0x22, 0x44, 0x22, 0x22, 0x44, 0x22, 0x24, 0x44, 0x22, 0x22, 0x44, 0x42, 0x24, 0x42, 0x22, 0x44, 0x22, 0x44, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x42, 0x24, 0x24, 0x22, 0x42, 0x42, 0x24, 0x44, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x24, 0x24, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x32, 0x23, 0x22, 0x32, 0x22, 0x23, 0x22, 0x32, 0x22, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x32, 0x22, 0x23, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x23, 0x22, 0x32, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x12, 0x22, 0x12, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x44, 0x22, 0x22, 0x22, 0x44, 0x44, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x44, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x44, 0x22, 0x22, 0x42, 0x22, 0x22, 0x44, 0x42, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x24, 0x22, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x44, 0x44, 0x22, 0x42, 0x22, 0x24, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x44, 0x42, 0x22, 0x24, 0x42, 0x22, 0x44, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x24, 0x22, 0x22, 0x24, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x24, 0x22, 0x42, 0x22, 0x22, 0x24, 0x44, 0x22, 0x24, 0x24, 0x24, 0x22, 0x44, 0x44, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x24, 0x22, 0x24, 0x24, 0x22, 0x22, 0x42, 0x42, 0x42, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x24, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x24, 0x22, 0x24, 0x24, 0x22, 0x22, 0x42, 0x42, 0x42, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x42, 0x22, 0x44, 0x42, 0x22, 0x24, 0x42, 0x22, 0x44, 0x42, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x22, 0x24, 0x22, 0x24, 0x24, 0x22, 0x22, 0x42, 0x42, 0x22, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x22, 0x42, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x44, 0x22, 0x22, 0x44, 0x42, 0x22, 0x44, 0x44, 0x22, 0x22, 0x44, 0x22, 0x44, 0x44, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x44, 0x44, 0x22, 0x44, 0x22, 0x42, 0x22, 0x44, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x24, 0x44, 0x42, 0x22, 0x24, 0x44, 0x22, 0x24, 0x44, 0x42, 0x22, 0x44, 0x44, 0x22, 0x42, 0x22, 0x22, 0x24, 0x44, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x44, 0x22, 0x24, 0x22, 0x42, 0x24, 0x44, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x44, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x24, 0x22, 0x24, 0x44, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x44, 0x42, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x42, 0x24, 0x24, 0x22, 0x24, 0x22, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x44, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x22, 0x24, 0x24, 0x24, 0x24, 0x22, 0x24, 0x44, 0x22, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x22, 0x42, 0x24, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x42, 0x24, 0x42, 0x22, 0x24, 0x22, 0x22, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x24, 0x44, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x24, 0x24, 0x22, 0x24, 0x44, 0x42, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x24, 0x22, 0x44, 0x42, 0x22, 0x44, 0x42, 0x22, 0x42, 0x22, 0x22, 0x24, 0x44, 0x42, 0x24, 0x22, 0x22, 0x42, 0x24, 0x42, 0x22, 0x24, 0x22, 0x22, 0x42, 0x42, 0x42, 0x42, 0x24, 0x24, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x42, 0x24, 0x24, 0x22, 0x24, 0x22, 0x22, 0x44, 0x22, 0x24, 0x42, 0x24, 0x42, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x22, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x42, 0x22, 0x24, 0x44, 0x42, 0x22, 0x24, 0x44, 0x22, 0x24, 0x44, 0x42, 0x22, 0x44, 0x44, 0x22, 0x44, 0x44, 0x22, 0x24, 0x44, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x44, 0x22, 0x24, 0x42, 0x24, 0x42, 0x24, 0x22, 0x24, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x32, 0x23, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x23, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x22, 0x22, 0x32, 0x22, 0x22, 0x23, 0x22, 0x22, 0x22, 0x22, 0x12, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x21, 0x22, 0x21, 0x22, 0x21, 0x22, 0x21, 0x22, 0x22, 0x12, 0x21, 0x22, 0x21, 0x22, 0x12, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x21, 0x22, 0x22, 0x21, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x22, 0x22, 0x12, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x24, 0x24, 0x22, 0x24, 0x44, 0x22, 0x22, 0x44, 0x22, 0x24, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x22, 0x42, 0x22, 0x24, 0x42, 0x22, 0x24, 0x22, 0x44, 0x44, 0x22, 0x24, 0x42, 0x22, 0x22, 0x42, 0x22, 0x44, 0x22, 0x22, 0x44, 0x22, 0x22, 0x42, 0x22, 0x24, 0x42, 0x22, 0x24, 0x42, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x42, 0x22, 0x44, 0x22, 0x42, 0x44, 0x22, 0x42, 0x42, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x42, 0x22, 0x22, 0x42, 0x24, 0x22, 0x44, 0x44, 0x22, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x24, 0x24, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x42, 0x44, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x24, 0x44, 0x22, 0x22, 0x24, 0x42, 0x22, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x24, 0x42, 0x22, 0x22, 0x24, 0x22, 0x42, 0x42, 0x22, 0x22, 0x42, 0x24, 0x22, 0x42, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x24, 0x24, 0x22, 0x24, 0x42, 0x22, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x24, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x24, 0x42, 0x22, 0x44, 0x22, 0x24, 0x44, 0x22, 0x22, 0x42, 0x22, 0x24, 0x42, 0x22, 0x24, 0x44, 0x22, 0x42, 0x22, 0x22, 0x42, 0x24, 0x24, 0x22, 0x44, 0x44, 0x42, 0x24, 0x44, 0x22, 0x44, 0x24, 0x22, 0x42, 0x42, 0x22, 0x42, 0x24, 0x22, 0x22, 0x42, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x44, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x24, 0x42, 0x22, 0x42, 0x22, 0x24, 0x22, 0x22, 0x22, 0x24, 0x22, 0x42, 0x24, 0x22, 0x42, 0x24, 0x22, 0x22, 0x22, 0x22, 0x42, 0x24, 0x24, 0x22, 0x24, 0x24, 0x22, 0x22, 0x42, 0x22, 0x44, 0x22, 0x22, 0x24, 0x22, 0x22, 0x42, 0x22, 0x42, 0x24, 0x22, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x22, 0x24, 0x42, 0x22, 0x24, 0x22, 0x24, 0x42, 0x22, 0x24, 0x42, 0x22, 0x22, 0x42, 0x22, 0x44, 0x42, 0x22, 0x44, 0x22, 0x24, 0x44, 0x22, 0x24, 0x42, 0x22, 0x24, 0x42, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x31, 0x23, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x32, 0x22, 0x32, 0x22, 0x32, 0x22, 0x32, 0x22, 0x23, 0x22, 0x32, 0x22, 0x32, 0x23, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x32, 0x22, 0x22, 0x32, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22, 0x22, 0x23, 0x22 }; u32 BuiltInFontDataSize = sizeof(BuiltInFontData); #else // !defined(_IRR_COMPILE_WITH_BMP_LOADER_) // built-in font cannot be loaded if there is no BMP loader u8* BuiltInFontData=0; u32 BuiltInFontDataSize = 0; #endif } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_ #endif irrlicht-1.8.3/source/Irrlicht/builtInFont.bmp0000644000000000000000000002011212574354552020066 0ustar rootrootBMJ J(€€ c c ÿÿÿÿÿÿÿ"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""!"""!"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""DDDD@""""""""""""""""""""""""""""""""""""""""""""""""""""""""DDDD@""""""""""""""""""""""""""""""""""""""""""""""""""""B"""DDDD@"""""""""""""""""""""""""""""""""""""""""""""""""""$D"DBDDDD@""""""""""""""""""""""""""""""""""""""""""""""""""""B"""@D""""""""""""""""""""""""""""""""""""""""""""""""""""""""@@" """""""""""""""""""""""""""""""""""""""""""""""""""""""""@""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2"#""2"""2"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""!""""""""""!""""""""!"""""""!"""""""""""""""DDD""""""DDD"""""""""""""""""""""""""""""""""""""$"$"$""$B$B""""B"$"$B"$BDDD""""""""""BB""$""""""""""""""""""""""$BD"DB""D"D""""B"$""D"D""""""""""B""$BD""DB"""""""""""""$B$BD"D""DB$BD""$B$""""B"$D"$DB""""$DDD"$D""DBDB$DD"$DD""""""$B"D"D"$B$B"$"$"$"""D"""""DDD$""D""""""DDB"DDB$DBDD$BDB""""DB"B"DD$B$B""D"D$"$"$""""$B""""DDD$"$DB"""""$D"$DDD"DBDB$"$D"$""$"$D"DD"D"D"$B$B$BD"DB""""D"""""B"$"D"D""""""B""""""$BD""""D"DB""""""$B"$B$BD"D""DB$BD""""$"""""DDD$B"$B"""""""""""""BB""""$$DD""""""""""""""""""$"$"$""""""""""DDD""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2"""#""""2""#"""#"""#""2"#"""#""#""2"#""#""""2"""#""#""#"""""""""""!"""""""!""!""!""!""!""!"""""!"""!"""!"""!"""""""""""""""""""""""""""""""""""""""""""""""""""""""B"$""B""$DDDD"""""""""""""""""""""""""""""""""""""""""""""""""""$"$""$""$"""$"""D"$B$"B"B"B"$B"BB"D""D""D""D""D""""DB"$B"D"$B"D"$"$B"$"$$"""$""$""B"$"B"B"B"B$"BB$"B$"B$"B$"B$"B"B"D$"BB$$"BB$$"BB$$"BB$$"""$""$$"BB$"B"B"B"$B"BB$"B$"B$"B$"B$"B$D"BD"BB$$"BB$$"BB$$"BB$$"""$"""B"$"$"B"B"B""B"D""D""D""D""D""D""B"$D"BB$$"BB$$"BB$B"BB$$"""$"""""""""""""""$B""""""""""""""""""""""""""""""""""""$""""$$"""$""$$"BB$"B$$$$""""D""$""B""BB"D"$"B"""""""B"B"BB$$"$""""BB$$DDDD"""B"""B"$"B""""""$B"B""$""$""$B"""""""""$""$"$"""""B""""""$DDDD""2"#""2#"#"#"#""#""2""2""2""2""2""2"#""#""2"#""2"#""2"#""2#"""""""""""!""""!"""""!"""""!""""""""!"""!"""!""""!"""!"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""D"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$""""""""DB"$D""""DD""DB"$D""DB"$D""$""B""BB"$B"D"$B"D"$B"D"DDB"D"$B"D""$"$"B"B$$"D"B$"$"B"B$"$"B"B"$""DB"B$"BB$$"BB$$"BB$$"BD"$""B"$"""$"$"B"B"B"BBB$"$"B"B$"$"B"B"$""B$"B$""B"$""B"$""B"$""BB$""BB$$""$"$"B"B$$"BBB$"$"B"B$"$"B"B"$""B$"DB"D"$B"D"$B"D"$B"D$B"D"$""B""$"$"B"B"""B$B$"$"B"B$"$"B"B"BB"DB"BB"""""""""""""""""""""""""""""DB"$D""""$DB$"$"B"B$"$"B"B$"$"B""$""$""B"BB$B"BB$B""""""""B"B"""BB"""""""""""$"""B""BB"""""$""""""""B""$"$""D"""$B"""""""$""$""2$$#$$"2"#"""2B"#"$"2$"#$$"2"B#""#""#""2"#""2"#""2"#"""2"#""2""""""""!"""""!""""""!""!""!""!""!""!""""""!"""""!"""""!"""""""""""""""""""""""""D"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$""""""""""""""""""""""""""""""""""""""""$"$"B"B$"$"B"B$"$"B$DB"D"$DB$DB$DB$DB$"B"B"B"DD"$"$"$D""DB"$D"""$DD"DDB$DD"DDB$DD"DD""$"B$""$""$""$""$"B"B"B"B"B$"$"B"B$"$"B"B"""BB"$$""BB"$$""BB"$$""$""$""$""$""$""$"B"B"B"B"B$"D"B"B$"$"B"B"""BB"$$""BB"$$""BB""DDB$""$DB$DB$DB$DB$"B"B"B$D"B$$$"B"B$"$"B"B"""$"""B""$"""B""$"""D""$"B$""$""$""$""$"B"B"B"B"B$B$"B"B$"$"B"B"""$"""B""$"""B""$"""$DB"D"$DB$DB$DB$DB""""""""DD"$"$"$D""DB"$D""""$""$$""BB"""""BB"""""""""$""B""BB"""$"B$$"""""""BB""B""$""$$"""2"B#"B"2$$#$$"2$"#""""2""2B"2$"2$"4"B2#$#B#$#"""2$$#$""2"B#"B""""""""!"!""!""!"""!""!""!"!""!""!"!""""""!"""""!""""!""""""""""""""""""""""""""""""""$""""""$B""""""""""""""""""""""""B""""""""""""""""""""""""""""""$"""D"""B""""""""""""""""""D""""$$"""""""""BB""""""""""""$D"""""$BB"D""""""""BB"B"B$"D"B"B$""B"B"D"""$D"""$$"""B""$D""""""B"""""$$""D""""""""$$"$$B"BD"$$B"B"DDB$$"""B"B$B"BB$DB$"B"B""""$D"""""$$"$D""""""D"BB""BB"$"""BB"B"$$"$B"""BBB""""""""""BBB"""""B"B$""$$"$D"B""$"""""""$"""B""$""""$$"$$"""B"B$B""""""""B"B"""""""B$$""""$D""""$"D""""$"B"B$"D"B"B""B""B$$"$D""B""""""""$D""""B"""B$"B""""D""""$"D""""$"""B""D""""""B""""""""""""""""""""""DD"""""""""""""""""""""""""""""""""""""""B"2"#"#"""2"2""2""2#"""2"#"2"#"2#"2""2"#"2"2#"#""#"""2""#"""2"#$"""!"!"!"!"!"!"!"!"!"!"!"!"!"!"!"!"!"""""!""!"""""""""""""""""""""""""""""""""""""""""""""""""""B"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""B"B"""""""""B"$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B""B"D"$D""""B"B"$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B""B$""$""""$D"B"$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B""B$""DB""""B"""$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B""""D"$""BB$D"B"$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B""B"$"$$"$""B"B"$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B$"B"""""""B"BB$$"B"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2#"2#"2#"2#"2#"2#"2#"2#"2#"2#"2#"2#"2#"2#"2#"2#"2#"2"#""#""2"#""""""""!"!""!""""!""!""!""!"!""""!""""!"""!"""!"!""!"""""$B"""""B"""""""""""""$""""B""""""""""""""""""B"""""""""""""""""""$"""""B"""""""""""""$""""B""""""""""""""""""$""""$"B$""""""D"B"$D"BB$"B$$"B$$$"BB"D"$D""DB$"$B"$"$B"B"$$"$$"$"$D"$"B$""""B$""B"B$"BB$"B$$"B$$$"BB$"B$"B$"B$""$"B"BB"B"$$""B"BB$""$"B$""""B$$"B"B$"BB$"B$B"B$$$"BB$"B$"B$"B$"$""B"BB$$"BBB"B"BB"$"B"B"B"""B"B"D"$D"D"$"B$$"B$DB"D""D"$D""DB$B"D"D"BB$$"BBB$$"BB$D"$"B$""""B"""B""""B""""$""B""""""""""""""""""""B"""""""""""""""""$"B$"BB"B"""$""""B"$"B$""B""""""""""""""""""""""""""""""""""""""$"B$"$$"B""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2"#"#""#""2#"2"#"2""#""2""2""2""2"2"#"#""2"#"""2"#""2"#"#"2"2"#"""!"""""!""!""!"""""!""""""!"""""""""!""!"!"""""!""!""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""D"""D"""DDB"""""""""""""""$"""D$"B"B"D""B""DB""B""$$""B"B"$""DD"B"$"$"""""""""D"DB"$B"DB""$""$"B"B"B$"B"B"$"$""B""$$""$$""$""B""B"$"$""""""""$$"B$"B"$"B""$D"$$$"DD""$""B"$"$"$$""BBB""B""$""$""B"$"$"""""""""$"B$"B"$"B""$"B$"$"B"B"B""B"$"$"$$""BBB""B""$"""B"B"B"$""""""""$B"DB"$B"DB""$"B$"$"B"B$"B"B"$"$"B"B$""$"$$""BB""$"B"B"$"BB""""""""B""""""B""$D""DB"DD""D"DDB$"$"B"B$""$"B"B$"$"DD"D"B"D"$"""""B"""B""""""B"""""""""""""""""""""""""""""""""""""""""""""""""""$""""""""""""""2""2""#"""2""2""2""#"""2"""#"""2""#""#"#"#"#""2""2"2"#""#""2""""""!"""!""!""""""!"""""!"""""""""!""!""!""!"""""!"""""!""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$""""""""""""$D"""""""""""""""""""""""""""""""""""""""""""""""""$""B"""B""B""B"""B"B$DB"$D"$DB"DD"B""$DB$"B$"D"$"B$D"B$"B$"D"$D"""$"$D"$""""$"DB"B"B$"$"B"B$"$"B""B""B"B$"B$"BB$$"$""B$"B$"D"B"B""B"""""B"B"$$$$"$D"$"$"B""$"$"B""B""B$B$"B$""B$B"$""BBBB$$$"B"B$"$"$D"$""$"$"B$"$$"$DB"B""$"$"DB"DB"B""$DB$""B$B"$""BBBB$$$"B"B"""B"""B"$"B"B"B""B"$"$"B"B$"$"B""B""B"B$"B$""B$$"$""D"$B$B$"B"B""""""""""D""$D"""B"$DB"$D"$DB"DD"DD"$D"$"B$""B$"B$""D"$B$B$"$D"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2#""2"#""2""2"""#"""2""#"""2""#""#""#"""2""2#""2""2"#""""2""#""""!""""!""""""!"!"!"!""!"!""""""""""""!""!""""""!""""""""""""""""""""B$""""""""""""""""""""""""""""""""""""""""""""""""""""B""""""""$""B"""""B"""""""""""""""""""""""""""""""""""""B"""$$"$D""D"$$""$""B"""""B""$"B"$B"$"DD"$B""B"D""D""B"$B"$B"B""""""DDB"D"BD"BB""$""B"""B""""""B"B$"$"B""B$"DD""B$"B"B"B$"B$""""B"""$$""B"$""BD""$""B""$D""$B""B"B$"$"$B""$"BB""B$"B"B"B$""$""""B"""$$"$B""B"$"""$""B"""B""""""$"B$"$""$""B"$B"D"$D""B"$B"$D"B""B$$"DDB$D"D$"BB"B$""B$B""""""""$"B$"D"B$"B$"$B"B"$"""$"B$"B$""""B$$"$$""B"D""$""B"B$"$B""""""""$"$B"$"$B"$B""B"DB"D"$D"$B"$B""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""1#"2"#"""2"#""#""#"2"2"2"2"#"2"2#"#""#"#""#""#""#""2""2"#""#""#"irrlicht-1.8.3/source/Irrlicht/aesGladman/0000755000000000000000000000000012574354552017171 5ustar rootrootirrlicht-1.8.3/source/Irrlicht/aesGladman/sha2.h0000644000000000000000000001161412574354552020202 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 */ #ifndef _SHA2_H #define _SHA2_H #include "irrMath.h" /* Defines for suffixes to 32 and 64 bit unsigned numeric values */ #define sfx_lo(x,y) x##y #define sfx_hi(x,y) sfx_lo(x,y) #define n_u32(p) sfx_hi(0x##p,s_u32) #define n_u64(p) sfx_hi(0x##p,s_u64) /* define an unsigned 32-bit type */ #if UINT_MAX == 0xffffffff typedef unsigned int sha2_32t; #define s_u32 u #elif ULONG_MAX == 0xffffffff typedef unsigned long sha2_32t; #define s_u32 ul #else #error Please define sha2_32t as an unsigned 32 bit type in sha2.h #endif /* define an unsigned 64-bit type */ #if defined(_MSC_VER) || defined(__BORLANDC__) #if (_MSC_VER < 1300) || (__BORLANDC__ < 0x582) typedef unsigned __int64 sha2_64t; #define s_u64 ui64 #elif ULONG_MAX == 0xffffffffffffffff typedef unsigned long sha2_64t; #define s_u64 ul #elif ULONG_MAX == 0xffffffff typedef unsigned long long sha2_64t; /* a somewhat dangerous guess */ #define s_u64 ull #else #error Please define sha2_64t as an unsigned 64 bit type in sha2.h #endif #else #ifdef _IRR_SOLARIS_PLATFORM_ #include #else #include #endif typedef int64_t sha2_64t; #if __WORDSIZE==64 #define s_u64 ul #else #define s_u64 ull #endif #endif #define SHA256_DIGEST_SIZE 32 #define SHA384_DIGEST_SIZE 48 #define SHA512_DIGEST_SIZE 64 #define SHA256_BLOCK_SIZE 64 #define SHA384_BLOCK_SIZE 128 #define SHA512_BLOCK_SIZE 128 #define SHA2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE #define SHA2_GOOD 0 #define SHA2_BAD 1 /* type to hold the SHA256 context */ typedef struct { sha2_32t count[2]; sha2_32t hash[8]; sha2_32t wbuf[16]; } sha256_ctx; /* type to hold the SHA384/512 context */ typedef struct { sha2_64t count[2]; sha2_64t hash[8]; sha2_64t wbuf[16]; } sha512_ctx; typedef sha512_ctx sha384_ctx; /* type to hold a SHA2 context (256/384/512) */ typedef struct { union { sha256_ctx ctx256[1]; sha512_ctx ctx512[1]; } uu[1]; sha2_32t sha2_len; } sha2_ctx; #ifndef SHA2_DLL /* implement normal or DLL functions */ #define sha2_void void #define sha2_int int #else #define sha2_void void __declspec(dllexport) _stdcall #define sha2_int int __declspec(dllexport) _stdcall #endif sha2_void sha256_compile(sha256_ctx ctx[1]); sha2_void sha512_compile(sha512_ctx ctx[1]); sha2_void sha256_begin(sha256_ctx ctx[1]); sha2_void sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]); sha2_void sha256_end(unsigned char hval[], sha256_ctx ctx[1]); sha2_void sha256(unsigned char hval[], const unsigned char data[], unsigned long len); sha2_void sha384_begin(sha384_ctx ctx[1]); #define sha384_hash sha512_hash sha2_void sha384_end(unsigned char hval[], sha384_ctx ctx[1]); sha2_void sha384(unsigned char hval[], const unsigned char data[], unsigned long len); sha2_void sha512_begin(sha512_ctx ctx[1]); sha2_void sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]); sha2_void sha512_end(unsigned char hval[], sha512_ctx ctx[1]); sha2_void sha512(unsigned char hval[], const unsigned char data[], unsigned long len); sha2_int sha2_begin(unsigned long size, sha2_ctx ctx[1]); sha2_void sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]); sha2_void sha2_end(unsigned char hval[], sha2_ctx ctx[1]); sha2_int sha2(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len); #endif irrlicht-1.8.3/source/Irrlicht/aesGladman/sha2.cpp0000644000000000000000000005632012574354552020540 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 This is a byte oriented version of SHA2 that operates on arrays of bytes stored in memory. This code implements sha256, sha384 and sha512 but the latter two functions rely on efficient 64-bit integer operations that may not be very efficient on 32-bit machines The sha256 functions use a type 'sha256_ctx' to hold details of the current hash state and uses the following three calls: void sha256_begin(sha256_ctx ctx[1]) void sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]) void sha256_end(unsigned char hval[], sha256_ctx ctx[1]) The first subroutine initialises a hash computation by setting up the context in the sha256_ctx context. The second subroutine hashes 8-bit bytes from array data[] into the hash state withinh sha256_ctx context, the number of bytes to be hashed being given by the the unsigned long integer len. The third subroutine completes the hash calculation and places the resulting digest value in the array of 8-bit bytes hval[]. The sha384 and sha512 functions are similar and use the interfaces: void sha384_begin(sha384_ctx ctx[1]); void sha384_hash(const unsigned char data[], unsigned long len, sha384_ctx ctx[1]); void sha384_end(unsigned char hval[], sha384_ctx ctx[1]); void sha512_begin(sha512_ctx ctx[1]); void sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]); void sha512_end(unsigned char hval[], sha512_ctx ctx[1]); In addition there is a function sha2 that can be used to call all these functions using a call with a hash length parameter as follows: int sha2_begin(unsigned long len, sha2_ctx ctx[1]); void sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]); void sha2_end(unsigned char hval[], sha2_ctx ctx[1]); My thanks to Erik Andersen for testing this code on big-endian systems and for his assistance with corrections */ /* define the hash functions that you need */ #define SHA_2 /* for dynamic hash length */ #define SHA_256 #define SHA_384 #define SHA_512 #include /* for memcpy() etc. */ #include /* for _lrotr with VC++ */ #include "sha2.h" #include "../os.h" /* BYTE ORDER IN 32-BIT WORDS To obtain the highest speed on processors with 32-bit words, this code needs to determine the byte order of the target machine. The following block of code is an attempt to capture the most obvious ways in which various environemnts define byte order. It may well fail, in which case the definitions will need to be set by editing at the points marked **** EDIT HERE IF NECESSARY **** below. My thanks to Peter Gutmann for some of these defines (from cryptlib). */ #define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ #define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ #ifdef __BIG_ENDIAN__ #define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN #else #define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN #endif #ifdef _MSC_VER #pragma intrinsic(memcpy) #endif #define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) #if !defined(bswap_32) #define bswap_32(x) irr::os::Byteswap::byteswap(x) #endif #if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) #define SWAP_BYTES #else #undef SWAP_BYTES #endif #if defined(SHA_2) || defined(SHA_256) #define SHA256_MASK (SHA256_BLOCK_SIZE - 1) #if defined(SWAP_BYTES) #define bsw_32(p,n) { int _i = (n); while(_i--) p[_i] = bswap_32(p[_i]); } #else #define bsw_32(p,n) #endif /* SHA256 mixing function definitions */ #if 0 #define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) #define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) #else /* Thanks to Rich Schroeppel and Colin Plumb for the following */ #define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) #define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) #endif #define s256_0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22)) #define s256_1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25)) #define g256_0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3)) #define g256_1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10)) /* rotated SHA256 round definition. Rather than swapping variables as in */ /* FIPS-180, different variables are 'rotated' on each round, returning */ /* to their starting positions every eight rounds */ #define h2(i) p[i & 15] += \ g256_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g256_0(p[(i + 1) & 15]) #define h2_cycle(i,j) \ v[(7 - i) & 7] += (j ? h2(i) : p[i & 15]) + k256[i + j] \ + s256_1(v[(4 - i) & 7]) + ch(v[(4 - i) & 7], v[(5 - i) & 7], v[(6 - i) & 7]); \ v[(3 - i) & 7] += v[(7 - i) & 7]; \ v[(7 - i) & 7] += s256_0(v[(0 - i) & 7]) + maj(v[(0 - i) & 7], v[(1 - i) & 7], v[(2 - i) & 7]) /* SHA256 mixing data */ const sha2_32t k256[64] = { n_u32(428a2f98), n_u32(71374491), n_u32(b5c0fbcf), n_u32(e9b5dba5), n_u32(3956c25b), n_u32(59f111f1), n_u32(923f82a4), n_u32(ab1c5ed5), n_u32(d807aa98), n_u32(12835b01), n_u32(243185be), n_u32(550c7dc3), n_u32(72be5d74), n_u32(80deb1fe), n_u32(9bdc06a7), n_u32(c19bf174), n_u32(e49b69c1), n_u32(efbe4786), n_u32(0fc19dc6), n_u32(240ca1cc), n_u32(2de92c6f), n_u32(4a7484aa), n_u32(5cb0a9dc), n_u32(76f988da), n_u32(983e5152), n_u32(a831c66d), n_u32(b00327c8), n_u32(bf597fc7), n_u32(c6e00bf3), n_u32(d5a79147), n_u32(06ca6351), n_u32(14292967), n_u32(27b70a85), n_u32(2e1b2138), n_u32(4d2c6dfc), n_u32(53380d13), n_u32(650a7354), n_u32(766a0abb), n_u32(81c2c92e), n_u32(92722c85), n_u32(a2bfe8a1), n_u32(a81a664b), n_u32(c24b8b70), n_u32(c76c51a3), n_u32(d192e819), n_u32(d6990624), n_u32(f40e3585), n_u32(106aa070), n_u32(19a4c116), n_u32(1e376c08), n_u32(2748774c), n_u32(34b0bcb5), n_u32(391c0cb3), n_u32(4ed8aa4a), n_u32(5b9cca4f), n_u32(682e6ff3), n_u32(748f82ee), n_u32(78a5636f), n_u32(84c87814), n_u32(8cc70208), n_u32(90befffa), n_u32(a4506ceb), n_u32(bef9a3f7), n_u32(c67178f2), }; /* SHA256 initialisation data */ const sha2_32t i256[8] = { n_u32(6a09e667), n_u32(bb67ae85), n_u32(3c6ef372), n_u32(a54ff53a), n_u32(510e527f), n_u32(9b05688c), n_u32(1f83d9ab), n_u32(5be0cd19) }; sha2_void sha256_begin(sha256_ctx ctx[1]) { ctx->count[0] = ctx->count[1] = 0; memcpy(ctx->hash, i256, 8 * sizeof(sha2_32t)); } /* Compile 64 bytes of hash data into SHA256 digest value */ /* NOTE: this routine assumes that the byte order in the */ /* ctx->wbuf[] at this point is in such an order that low */ /* address bytes in the ORIGINAL byte stream placed in this */ /* buffer will now go to the high end of words on BOTH big */ /* and little endian systems */ sha2_void sha256_compile(sha256_ctx ctx[1]) { sha2_32t v[8], j, *p = ctx->wbuf; memcpy(v, ctx->hash, 8 * sizeof(sha2_32t)); for(j = 0; j < 64; j += 16) { h2_cycle( 0, j); h2_cycle( 1, j); h2_cycle( 2, j); h2_cycle( 3, j); h2_cycle( 4, j); h2_cycle( 5, j); h2_cycle( 6, j); h2_cycle( 7, j); h2_cycle( 8, j); h2_cycle( 9, j); h2_cycle(10, j); h2_cycle(11, j); h2_cycle(12, j); h2_cycle(13, j); h2_cycle(14, j); h2_cycle(15, j); } ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; ctx->hash[4] += v[4]; ctx->hash[5] += v[5]; ctx->hash[6] += v[6]; ctx->hash[7] += v[7]; } /* SHA256 hash data in an array of bytes into hash buffer */ /* and call the hash_compile function as required. */ sha2_void sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]) { sha2_32t pos = (sha2_32t)(ctx->count[0] & SHA256_MASK), space = SHA256_BLOCK_SIZE - pos; const unsigned char *sp = data; if((ctx->count[0] += len) < len) ++(ctx->count[1]); while(len >= space) /* tranfer whole blocks while possible */ { memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); sp += space; len -= space; space = SHA256_BLOCK_SIZE; pos = 0; bsw_32(ctx->wbuf, SHA256_BLOCK_SIZE >> 2) sha256_compile(ctx); } memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); } /* SHA256 Final padding and digest calculation */ static sha2_32t m1[4] = { n_u32(00000000), n_u32(ff000000), n_u32(ffff0000), n_u32(ffffff00) }; static sha2_32t b1[4] = { n_u32(80000000), n_u32(00800000), n_u32(00008000), n_u32(00000080) }; sha2_void sha256_end(unsigned char hval[], sha256_ctx ctx[1]) { sha2_32t i = (sha2_32t)(ctx->count[0] & SHA256_MASK); bsw_32(ctx->wbuf, (i + 3) >> 2) /* bytes in the buffer are now in an order in which references */ /* to 32-bit words will put bytes with lower addresses into the */ /* top of 32 bit words on BOTH big and little endian machines */ /* we now need to mask valid bytes and add the padding which is */ /* a single 1 bit and as many zero bits as necessary. */ ctx->wbuf[i >> 2] = (ctx->wbuf[i >> 2] & m1[i & 3]) | b1[i & 3]; /* we need 9 or more empty positions, one for the padding byte */ /* (above) and eight for the length count. If there is not */ /* enough space pad and empty the buffer */ if(i > SHA256_BLOCK_SIZE - 9) { if(i < 60) ctx->wbuf[15] = 0; sha256_compile(ctx); i = 0; } else /* compute a word index for the empty buffer positions */ i = (i >> 2) + 1; while(i < 14) /* and zero pad all but last two positions */ ctx->wbuf[i++] = 0; /* the following 32-bit length fields are assembled in the */ /* wrong byte order on little endian machines but this is */ /* corrected later since they are only ever used as 32-bit */ /* word values. */ ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29); ctx->wbuf[15] = ctx->count[0] << 3; sha256_compile(ctx); /* extract the hash value as bytes in case the hash buffer is */ /* mislaigned for 32-bit words */ for(i = 0; i < SHA256_DIGEST_SIZE; ++i) hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3))); } sha2_void sha256(unsigned char hval[], const unsigned char data[], unsigned long len) { sha256_ctx cx[1]; sha256_begin(cx); sha256_hash(data, len, cx); sha256_end(hval, cx); } #endif #if defined(SHA_2) || defined(SHA_384) || defined(SHA_512) #define SHA512_MASK (SHA512_BLOCK_SIZE - 1) #define rotr64(x,n) (((x) >> n) | ((x) << (64 - n))) #if !defined(bswap_64) #define bswap_64(x) ((((sha2_64t)(bswap_32((sha2_32t)(x)))) << 32) | (bswap_32((sha2_32t)((x) >> 32)))) #endif #if defined(SWAP_BYTES) #define bsw_64(p,n) { int _i = (n); while(_i--) p[_i] = bswap_64(p[_i]); } #else #define bsw_64(p,n) #endif /* SHA512 mixing function definitions */ #define s512_0(x) (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39)) #define s512_1(x) (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41)) #define g512_0(x) (rotr64((x), 1) ^ rotr64((x), 8) ^ ((x) >> 7)) #define g512_1(x) (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6)) /* rotated SHA512 round definition. Rather than swapping variables as in */ /* FIPS-180, different variables are 'rotated' on each round, returning */ /* to their starting positions every eight rounds */ #define h5(i) ctx->wbuf[i & 15] += \ g512_1(ctx->wbuf[(i + 14) & 15]) + ctx->wbuf[(i + 9) & 15] + g512_0(ctx->wbuf[(i + 1) & 15]) #define h5_cycle(i,j) \ v[(7 - i) & 7] += (j ? h5(i) : ctx->wbuf[i & 15]) + k512[i + j] \ + s512_1(v[(4 - i) & 7]) + ch(v[(4 - i) & 7], v[(5 - i) & 7], v[(6 - i) & 7]); \ v[(3 - i) & 7] += v[(7 - i) & 7]; \ v[(7 - i) & 7] += s512_0(v[(0 - i) & 7]) + maj(v[(0 - i) & 7], v[(1 - i) & 7], v[(2 - i) & 7]) /* SHA384/SHA512 mixing data */ const sha2_64t k512[80] = { n_u64(428a2f98d728ae22), n_u64(7137449123ef65cd), n_u64(b5c0fbcfec4d3b2f), n_u64(e9b5dba58189dbbc), n_u64(3956c25bf348b538), n_u64(59f111f1b605d019), n_u64(923f82a4af194f9b), n_u64(ab1c5ed5da6d8118), n_u64(d807aa98a3030242), n_u64(12835b0145706fbe), n_u64(243185be4ee4b28c), n_u64(550c7dc3d5ffb4e2), n_u64(72be5d74f27b896f), n_u64(80deb1fe3b1696b1), n_u64(9bdc06a725c71235), n_u64(c19bf174cf692694), n_u64(e49b69c19ef14ad2), n_u64(efbe4786384f25e3), n_u64(0fc19dc68b8cd5b5), n_u64(240ca1cc77ac9c65), n_u64(2de92c6f592b0275), n_u64(4a7484aa6ea6e483), n_u64(5cb0a9dcbd41fbd4), n_u64(76f988da831153b5), n_u64(983e5152ee66dfab), n_u64(a831c66d2db43210), n_u64(b00327c898fb213f), n_u64(bf597fc7beef0ee4), n_u64(c6e00bf33da88fc2), n_u64(d5a79147930aa725), n_u64(06ca6351e003826f), n_u64(142929670a0e6e70), n_u64(27b70a8546d22ffc), n_u64(2e1b21385c26c926), n_u64(4d2c6dfc5ac42aed), n_u64(53380d139d95b3df), n_u64(650a73548baf63de), n_u64(766a0abb3c77b2a8), n_u64(81c2c92e47edaee6), n_u64(92722c851482353b), n_u64(a2bfe8a14cf10364), n_u64(a81a664bbc423001), n_u64(c24b8b70d0f89791), n_u64(c76c51a30654be30), n_u64(d192e819d6ef5218), n_u64(d69906245565a910), n_u64(f40e35855771202a), n_u64(106aa07032bbd1b8), n_u64(19a4c116b8d2d0c8), n_u64(1e376c085141ab53), n_u64(2748774cdf8eeb99), n_u64(34b0bcb5e19b48a8), n_u64(391c0cb3c5c95a63), n_u64(4ed8aa4ae3418acb), n_u64(5b9cca4f7763e373), n_u64(682e6ff3d6b2b8a3), n_u64(748f82ee5defb2fc), n_u64(78a5636f43172f60), n_u64(84c87814a1f0ab72), n_u64(8cc702081a6439ec), n_u64(90befffa23631e28), n_u64(a4506cebde82bde9), n_u64(bef9a3f7b2c67915), n_u64(c67178f2e372532b), n_u64(ca273eceea26619c), n_u64(d186b8c721c0c207), n_u64(eada7dd6cde0eb1e), n_u64(f57d4f7fee6ed178), n_u64(06f067aa72176fba), n_u64(0a637dc5a2c898a6), n_u64(113f9804bef90dae), n_u64(1b710b35131c471b), n_u64(28db77f523047d84), n_u64(32caab7b40c72493), n_u64(3c9ebe0a15c9bebc), n_u64(431d67c49c100d4c), n_u64(4cc5d4becb3e42b6), n_u64(597f299cfc657e2a), n_u64(5fcb6fab3ad6faec), n_u64(6c44198c4a475817) }; /* Compile 64 bytes of hash data into SHA384/SHA512 digest value */ sha2_void sha512_compile(sha512_ctx ctx[1]) { sha2_64t v[8]; sha2_32t j; memcpy(v, ctx->hash, 8 * sizeof(sha2_64t)); for(j = 0; j < 80; j += 16) { h5_cycle( 0, j); h5_cycle( 1, j); h5_cycle( 2, j); h5_cycle( 3, j); h5_cycle( 4, j); h5_cycle( 5, j); h5_cycle( 6, j); h5_cycle( 7, j); h5_cycle( 8, j); h5_cycle( 9, j); h5_cycle(10, j); h5_cycle(11, j); h5_cycle(12, j); h5_cycle(13, j); h5_cycle(14, j); h5_cycle(15, j); } ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; ctx->hash[4] += v[4]; ctx->hash[5] += v[5]; ctx->hash[6] += v[6]; ctx->hash[7] += v[7]; } /* Compile 128 bytes of hash data into SHA256 digest value */ /* NOTE: this routine assumes that the byte order in the */ /* ctx->wbuf[] at this point is in such an order that low */ /* address bytes in the ORIGINAL byte stream placed in this */ /* buffer will now go to the high end of words on BOTH big */ /* and little endian systems */ sha2_void sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]) { sha2_32t pos = (sha2_32t)(ctx->count[0] & SHA512_MASK), space = SHA512_BLOCK_SIZE - pos; const unsigned char *sp = data; if((ctx->count[0] += len) < len) ++(ctx->count[1]); while(len >= space) /* tranfer whole blocks while possible */ { memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); sp += space; len -= space; space = SHA512_BLOCK_SIZE; pos = 0; bsw_64(ctx->wbuf, SHA512_BLOCK_SIZE >> 3); sha512_compile(ctx); } memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); } /* SHA384/512 Final padding and digest calculation */ static sha2_64t m2[8] = { n_u64(0000000000000000), n_u64(ff00000000000000), n_u64(ffff000000000000), n_u64(ffffff0000000000), n_u64(ffffffff00000000), n_u64(ffffffffff000000), n_u64(ffffffffffff0000), n_u64(ffffffffffffff00) }; static sha2_64t b2[8] = { n_u64(8000000000000000), n_u64(0080000000000000), n_u64(0000800000000000), n_u64(0000008000000000), n_u64(0000000080000000), n_u64(0000000000800000), n_u64(0000000000008000), n_u64(0000000000000080) }; static void sha_end(unsigned char hval[], sha512_ctx ctx[1], const unsigned int hlen) { sha2_32t i = (sha2_32t)(ctx->count[0] & SHA512_MASK); bsw_64(ctx->wbuf, (i + 7) >> 3); /* bytes in the buffer are now in an order in which references */ /* to 64-bit words will put bytes with lower addresses into the */ /* top of 64 bit words on BOTH big and little endian machines */ /* we now need to mask valid bytes and add the padding which is */ /* a single 1 bit and as many zero bits as necessary. */ ctx->wbuf[i >> 3] = (ctx->wbuf[i >> 3] & m2[i & 7]) | b2[i & 7]; /* we need 17 or more empty byte positions, one for the padding */ /* byte (above) and sixteen for the length count. If there is */ /* not enough space pad and empty the buffer */ if(i > SHA512_BLOCK_SIZE - 17) { if(i < 120) ctx->wbuf[15] = 0; sha512_compile(ctx); i = 0; } else i = (i >> 3) + 1; while(i < 14) ctx->wbuf[i++] = 0; /* the following 64-bit length fields are assembled in the */ /* wrong byte order on little endian machines but this is */ /* corrected later since they are only ever used as 64-bit */ /* word values. */ ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 61); ctx->wbuf[15] = ctx->count[0] << 3; sha512_compile(ctx); /* extract the hash value as bytes in case the hash buffer is */ /* misaligned for 32-bit words */ for(i = 0; i < hlen; ++i) hval[i] = (unsigned char)(ctx->hash[i >> 3] >> (8 * (~i & 7))); } #endif #if defined(SHA_2) || defined(SHA_384) /* SHA384 initialisation data */ const sha2_64t i384[80] = { n_u64(cbbb9d5dc1059ed8), n_u64(629a292a367cd507), n_u64(9159015a3070dd17), n_u64(152fecd8f70e5939), n_u64(67332667ffc00b31), n_u64(8eb44a8768581511), n_u64(db0c2e0d64f98fa7), n_u64(47b5481dbefa4fa4) }; sha2_void sha384_begin(sha384_ctx ctx[1]) { ctx->count[0] = ctx->count[1] = 0; memcpy(ctx->hash, i384, 8 * sizeof(sha2_64t)); } sha2_void sha384_end(unsigned char hval[], sha384_ctx ctx[1]) { sha_end(hval, ctx, SHA384_DIGEST_SIZE); } sha2_void sha384(unsigned char hval[], const unsigned char data[], unsigned long len) { sha384_ctx cx[1]; sha384_begin(cx); sha384_hash(data, len, cx); sha384_end(hval, cx); } #endif #if defined(SHA_2) || defined(SHA_512) /* SHA512 initialisation data */ const sha2_64t i512[80] = { n_u64(6a09e667f3bcc908), n_u64(bb67ae8584caa73b), n_u64(3c6ef372fe94f82b), n_u64(a54ff53a5f1d36f1), n_u64(510e527fade682d1), n_u64(9b05688c2b3e6c1f), n_u64(1f83d9abfb41bd6b), n_u64(5be0cd19137e2179) }; sha2_void sha512_begin(sha512_ctx ctx[1]) { ctx->count[0] = ctx->count[1] = 0; memcpy(ctx->hash, i512, 8 * sizeof(sha2_64t)); } sha2_void sha512_end(unsigned char hval[], sha512_ctx ctx[1]) { sha_end(hval, ctx, SHA512_DIGEST_SIZE); } sha2_void sha512(unsigned char hval[], const unsigned char data[], unsigned long len) { sha512_ctx cx[1]; sha512_begin(cx); sha512_hash(data, len, cx); sha512_end(hval, cx); } #endif #if defined(SHA_2) #define CTX_256(x) ((x)->uu->ctx256) #define CTX_384(x) ((x)->uu->ctx512) #define CTX_512(x) ((x)->uu->ctx512) /* SHA2 initialisation */ sha2_int sha2_begin(unsigned long len, sha2_ctx ctx[1]) { unsigned long l = len; switch(len) { case 256: l = len >> 3; case 32: CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0; memcpy(CTX_256(ctx)->hash, i256, 32); break; case 384: l = len >> 3; case 48: CTX_384(ctx)->count[0] = CTX_384(ctx)->count[1] = 0; memcpy(CTX_384(ctx)->hash, i384, 64); break; case 512: l = len >> 3; case 64: CTX_512(ctx)->count[0] = CTX_512(ctx)->count[1] = 0; memcpy(CTX_512(ctx)->hash, i512, 64); break; default: return SHA2_BAD; } ctx->sha2_len = l; return SHA2_GOOD; } sha2_void sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]) { switch(ctx->sha2_len) { case 32: sha256_hash(data, len, CTX_256(ctx)); return; case 48: sha384_hash(data, len, CTX_384(ctx)); return; case 64: sha512_hash(data, len, CTX_512(ctx)); return; } } sha2_void sha2_end(unsigned char hval[], sha2_ctx ctx[1]) { switch(ctx->sha2_len) { case 32: sha256_end(hval, CTX_256(ctx)); return; case 48: sha_end(hval, CTX_384(ctx), SHA384_DIGEST_SIZE); return; case 64: sha_end(hval, CTX_512(ctx), SHA512_DIGEST_SIZE); return; } } sha2_int sha2(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len) { sha2_ctx cx[1]; if(sha2_begin(size, cx) == SHA2_GOOD) { sha2_hash(data, len, cx); sha2_end(hval, cx); return SHA2_GOOD; } else return SHA2_BAD; } #endif irrlicht-1.8.3/source/Irrlicht/aesGladman/sha1.h0000644000000000000000000000421312574354552020176 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 */ #ifndef _SHA1_H #define _SHA1_H #include #define SHA1_BLOCK_SIZE 64 #define SHA1_DIGEST_SIZE 20 /* define an unsigned 32-bit type */ #if UINT_MAX == 0xffffffff typedef unsigned int sha1_32t; #elif ULONG_MAX == 0xffffffff typedef unsigned long sha1_32t; #else #error Please define sha1_32t as an unsigned 32 bit type in sha2.h #endif /* type to hold the SHA256 context */ typedef struct { sha1_32t count[2]; sha1_32t hash[5]; sha1_32t wbuf[16]; } sha1_ctx; void sha1_compile(sha1_ctx ctx[1]); void sha1_begin(sha1_ctx ctx[1]); void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]); void sha1_end(unsigned char hval[], sha1_ctx ctx[1]); void sha1(unsigned char hval[], const unsigned char data[], unsigned long len); #endif irrlicht-1.8.3/source/Irrlicht/aesGladman/sha1.cpp0000644000000000000000000002007212574354552020532 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 This is a byte oriented version of SHA1 that operates on arrays of bytes stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor */ #include /* for memcpy() etc. */ #include /* for _lrotl with VC++ */ #include "sha1.h" #include "../os.h" /* To obtain the highest speed on processors with 32-bit words, this code needs to determine the order in which bytes are packed into such words. The following block of code is an attempt to capture the most obvious ways in which various environemnts specify their endian definitions. It may well fail, in which case the definitions will need to be set by editing at the points marked **** EDIT HERE IF NECESSARY **** below. */ /* BYTE ORDER IN 32-BIT WORDS To obtain the highest speed on processors with 32-bit words, this code needs to determine the byte order of the target machine. The following block of code is an attempt to capture the most obvious ways in which various environemnts define byte order. It may well fail, in which case the definitions will need to be set by editing at the points marked **** EDIT HERE IF NECESSARY **** below. My thanks to Peter Gutmann for some of these defines (from cryptlib). */ #define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ #define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ #ifdef __BIG_ENDIAN__ #define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN #else #define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN #endif #define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) #if (PLATFORM_BYTE_ORDER == BRG_BIG_ENDIAN) #define swap_b32(x) (x) #else #define swap_b32(x) irr::os::Byteswap::byteswap(x) #endif #define SHA1_MASK (SHA1_BLOCK_SIZE - 1) #if 1 #define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) #define parity(x,y,z) ((x) ^ (y) ^ (z)) #define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) #else /* Discovered Rich Schroeppel and Colin Plumb */ #define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) #define parity(x,y,z) ((x) ^ (y) ^ (z)) #define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) #endif /* A normal version as set out in the FIPS */ #define rnd(f,k) \ t = a; a = rotl32(a,5) + f(b,c,d) + e + k + w[i]; \ e = d; d = c; c = rotl32(b, 30); b = t void sha1_compile(sha1_ctx ctx[1]) { sha1_32t w[80], i, a, b, c, d, e, t; /* note that words are compiled from the buffer into 32-bit */ /* words in big-endian order so an order reversal is needed */ /* here on little endian machines */ for(i = 0; i < SHA1_BLOCK_SIZE / 4; ++i) w[i] = swap_b32(ctx->wbuf[i]); for(i = SHA1_BLOCK_SIZE / 4; i < 80; ++i) w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1); a = ctx->hash[0]; b = ctx->hash[1]; c = ctx->hash[2]; d = ctx->hash[3]; e = ctx->hash[4]; for(i = 0; i < 20; ++i) { rnd(ch, 0x5a827999); } for(i = 20; i < 40; ++i) { rnd(parity, 0x6ed9eba1); } for(i = 40; i < 60; ++i) { rnd(maj, 0x8f1bbcdc); } for(i = 60; i < 80; ++i) { rnd(parity, 0xca62c1d6); } ctx->hash[0] += a; ctx->hash[1] += b; ctx->hash[2] += c; ctx->hash[3] += d; ctx->hash[4] += e; } void sha1_begin(sha1_ctx ctx[1]) { ctx->count[0] = ctx->count[1] = 0; ctx->hash[0] = 0x67452301; ctx->hash[1] = 0xefcdab89; ctx->hash[2] = 0x98badcfe; ctx->hash[3] = 0x10325476; ctx->hash[4] = 0xc3d2e1f0; } /* SHA1 hash data in an array of bytes into hash buffer and */ /* call the hash_compile function as required. */ void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]) { sha1_32t pos = (sha1_32t)(ctx->count[0] & SHA1_MASK), space = SHA1_BLOCK_SIZE - pos; const unsigned char *sp = data; if((ctx->count[0] += len) < len) ++(ctx->count[1]); while(len >= space) /* tranfer whole blocks if possible */ { memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0; sha1_compile(ctx); } /*lint -e{803} conceivable data overrun */ memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); } /* SHA1 final padding and digest calculation */ #if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) static sha1_32t mask[4] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff }; static sha1_32t bits[4] = { 0x00000080, 0x00008000, 0x00800000, 0x80000000 }; #else static sha1_32t mask[4] = { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 }; static sha1_32t bits[4] = { 0x80000000, 0x00800000, 0x00008000, 0x00000080 }; #endif void sha1_end(unsigned char hval[], sha1_ctx ctx[1]) { sha1_32t i = (sha1_32t)(ctx->count[0] & SHA1_MASK); /* mask out the rest of any partial 32-bit word and then set */ /* the next byte to 0x80. On big-endian machines any bytes in */ /* the buffer will be at the top end of 32 bit words, on little */ /* endian machines they will be at the bottom. Hence the AND */ /* and OR masks above are reversed for little endian systems */ /* Note that we can always add the first padding byte at this */ /* point because the buffer always has at least one empty slot */ ctx->wbuf[i >> 2] = (ctx->wbuf[i >> 2] & mask[i & 3]) | bits[i & 3]; /* we need 9 or more empty positions, one for the padding byte */ /* (above) and eight for the length count. If there is not */ /* enough space pad and empty the buffer */ if(i > SHA1_BLOCK_SIZE - 9) { if(i < 60) ctx->wbuf[15] = 0; sha1_compile(ctx); i = 0; } else /* compute a word index for the empty buffer positions */ i = (i >> 2) + 1; while(i < 14) /* and zero pad all but last two positions */ ctx->wbuf[i++] = 0; /* assemble the eight byte counter in in big-endian format */ ctx->wbuf[14] = swap_b32((ctx->count[1] << 3) | (ctx->count[0] >> 29)); ctx->wbuf[15] = swap_b32(ctx->count[0] << 3); sha1_compile(ctx); /* extract the hash value as bytes in case the hash buffer is */ /* misaligned for 32-bit words */ for(i = 0; i < SHA1_DIGEST_SIZE; ++i) hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3))); } void sha1(unsigned char hval[], const unsigned char data[], unsigned long len) { sha1_ctx cx[1]; sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx); } irrlicht-1.8.3/source/Irrlicht/aesGladman/Readme.txt0000644000000000000000000000170512574354552021132 0ustar rootrootA File Encryption Utility - VC++ 7.1 project Instructions 1. Unzip the enclosed files into a suitable VC++ project directory. 2. Obtain the bzip2 source code from http://sources.redhat.com/bzip2/ and unzip the files into the bzip2 sub-directory. 3. Compile the bzip2 project to give a static library 4. Compile the encfile project. 5. The executable encfile.exe is now ready for use: enfile password filename If the filename does not have the extension 'enc', it is assumed to be a normal file that will then be encrypted to a file with the same name but with an added extension 'enc'. If the filename has the extension 'enc' its is assumed to be an encrypted file that will be decrypted to a file with the same name but without the 'enc' extension. The default HASH function is SHA1, which is set up by defining USE_SHA1 in compiling the project. If USE_SHA256 is defined instead then SHA256 is used. Brian Gladman irrlicht-1.8.3/source/Irrlicht/aesGladman/pwd2key.h0000644000000000000000000000370112574354552020730 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 This is an implementation of RFC2898, which specifies key derivation from a password and a salt value. */ #ifndef PWD2KEY_H #define PWD2KEY_H void derive_key( const unsigned char pwd[], /* the PASSWORD, and */ unsigned int pwd_len, /* its length */ const unsigned char salt[], /* the SALT and its */ unsigned int salt_len, /* length */ unsigned int iter, /* the number of iterations */ unsigned char key[], /* space for the output key */ unsigned int key_len); /* and its required length */ #endif irrlicht-1.8.3/source/Irrlicht/aesGladman/pwd2key.cpp0000644000000000000000000001402512574354552021264 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 This is an implementation of RFC2898, which specifies key derivation from a password and a salt value. */ #include #include "hmac.h" void derive_key(const unsigned char pwd[], /* the PASSWORD */ unsigned int pwd_len, /* and its length */ const unsigned char salt[], /* the SALT and its */ unsigned int salt_len, /* length */ unsigned int iter, /* the number of iterations */ unsigned char key[], /* space for the output key */ unsigned int key_len)/* and its required length */ { unsigned int i, j, k, n_blk; unsigned char uu[HMAC_HASH_OUTPUT_SIZE], ux[HMAC_HASH_OUTPUT_SIZE]; hmac_ctx c1[1], c2[1], c3[1]; /* set HMAC context (c1) for password */ hmac_sha_begin(c1); hmac_sha_key(pwd, pwd_len, c1); /* set HMAC context (c2) for password and salt */ memcpy(c2, c1, sizeof(hmac_ctx)); hmac_sha_data(salt, salt_len, c2); /* find the number of SHA blocks in the key */ n_blk = 1 + (key_len - 1) / HMAC_HASH_OUTPUT_SIZE; for(i = 0; i < n_blk; ++i) /* for each block in key */ { /* ux[] holds the running xor value */ memset(ux, 0, HMAC_HASH_OUTPUT_SIZE); /* set HMAC context (c3) for password and salt */ memcpy(c3, c2, sizeof(hmac_ctx)); /* enter additional data for 1st block into uu */ uu[0] = (unsigned char)((i + 1) >> 24); uu[1] = (unsigned char)((i + 1) >> 16); uu[2] = (unsigned char)((i + 1) >> 8); uu[3] = (unsigned char)(i + 1); /* this is the key mixing iteration */ for(j = 0, k = 4; j < iter; ++j) { /* add previous round data to HMAC */ hmac_sha_data(uu, k, c3); /* obtain HMAC for uu[] */ hmac_sha_end(uu, HMAC_HASH_OUTPUT_SIZE, c3); /* xor into the running xor block */ for(k = 0; k < HMAC_HASH_OUTPUT_SIZE; ++k) ux[k] ^= uu[k]; /* set HMAC context (c3) for password */ memcpy(c3, c1, sizeof(hmac_ctx)); } /* compile key blocks into the key output */ j = 0; k = i * HMAC_HASH_OUTPUT_SIZE; while(j < HMAC_HASH_OUTPUT_SIZE && k < key_len) key[k++] = ux[j++]; } } #ifdef TEST #include struct { unsigned int pwd_len; unsigned int salt_len; unsigned int it_count; unsigned char *pwd; unsigned char salt[32]; unsigned char key[32]; } tests[] = { { 8, 4, 5, (unsigned char*)"password", { 0x12, 0x34, 0x56, 0x78 }, { 0x5c, 0x75, 0xce, 0xf0, 0x1a, 0x96, 0x0d, 0xf7, 0x4c, 0xb6, 0xb4, 0x9b, 0x9e, 0x38, 0xe6, 0xb5 } }, { 8, 8, 5, (unsigned char*)"password", { 0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12 }, { 0xd1, 0xda, 0xa7, 0x86, 0x15, 0xf2, 0x87, 0xe6, 0xa1, 0xc8, 0xb1, 0x20, 0xd7, 0x06, 0x2a, 0x49 } }, { 8, 21, 1, (unsigned char*)"password", { "ATHENA.MIT.EDUraeburn" }, { 0xcd, 0xed, 0xb5, 0x28, 0x1b, 0xb2, 0xf8, 0x01, 0x56, 0x5a, 0x11, 0x22, 0xb2, 0x56, 0x35, 0x15 } }, { 8, 21, 2, (unsigned char*)"password", { "ATHENA.MIT.EDUraeburn" }, { 0x01, 0xdb, 0xee, 0x7f, 0x4a, 0x9e, 0x24, 0x3e, 0x98, 0x8b, 0x62, 0xc7, 0x3c, 0xda, 0x93, 0x5d } }, { 8, 21, 1200, (unsigned char*)"password", { "ATHENA.MIT.EDUraeburn" }, { 0x5c, 0x08, 0xeb, 0x61, 0xfd, 0xf7, 0x1e, 0x4e, 0x4e, 0xc3, 0xcf, 0x6b, 0xa1, 0xf5, 0x51, 0x2b } } }; int main() { unsigned int i, j, key_len = 256; unsigned char key[256]; printf("\nTest of RFC2898 Password Based Key Derivation"); for(i = 0; i < 5; ++i) { derive_key(tests[i].pwd, tests[i].pwd_len, tests[i].salt, tests[i].salt_len, tests[i].it_count, key, key_len); printf("\ntest %i: ", i + 1); printf("key %s", memcmp(tests[i].key, key, 16) ? "is bad" : "is good"); for(j = 0; j < key_len && j < 64; j += 4) { if(j % 16 == 0) printf("\n"); printf("0x%02x%02x%02x%02x ", key[j], key[j + 1], key[j + 2], key[j + 3]); } printf(j < key_len ? " ... \n" : "\n"); } printf("\n"); return 0; } #endif irrlicht-1.8.3/source/Irrlicht/aesGladman/prng.h0000644000000000000000000000570212574354552020314 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 24/01/2003 This is the header file for an implementation of a random data pool based on the use of an external entropy function (inspired by Peter Gutmann's work). */ #ifndef _PRNG_H #define _PRNG_H #include "sha1.h" #define PRNG_POOL_LEN 256 /* minimum random pool size */ #define PRNG_MIN_MIX 20 /* min initial pool mixing iterations */ /* ensure that pool length is a multiple of the SHA1 digest size */ #define PRNG_POOL_SIZE (SHA1_DIGEST_SIZE * (1 + (PRNG_POOL_LEN - 1) / SHA1_DIGEST_SIZE)) /* A function for providing entropy is a parameter in the prng_init() */ /* call. This function has the following form and returns a maximum */ /* of 'len' bytes of pseudo random data in the buffer 'buf'. It can */ /* return less than 'len' bytes but will be repeatedly called for more */ /* data in this case. */ typedef int (*prng_entropy_fn)(unsigned char buf[], unsigned int len); typedef struct { unsigned char rbuf[PRNG_POOL_SIZE]; /* the random pool */ unsigned char obuf[PRNG_POOL_SIZE]; /* pool output buffer */ unsigned int pos; /* output buffer position */ prng_entropy_fn entropy; /* entropy function pointer */ } prng_ctx; /* initialise the random stream generator */ void prng_init(prng_entropy_fn fun, prng_ctx ctx[1]); /* obtain random bytes from the generator */ void prng_rand(unsigned char data[], unsigned int data_len, prng_ctx ctx[1]); /* close the random stream generator */ void prng_end(prng_ctx ctx[1]); #endif irrlicht-1.8.3/source/Irrlicht/aesGladman/prng.cpp0000644000000000000000000001220212574354552020640 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 24/01/2003 This file implements a random data pool based on the use of an external entropy function. It is based on the ideas advocated by Peter Gutmann in his work on pseudo random sequence generators. It is not a 'paranoid' random sequence generator and no attempt is made to protect the pool from prying eyes either by memory locking or by techniques to obscure its location in memory. */ #include #include "prng.h" /* mix a random data pool using the SHA1 compression function (as */ /* suggested by Peter Gutmann in his paper on random pools) */ static void prng_mix(unsigned char buf[]) { unsigned int i, len; sha1_ctx ctx[1]; /*lint -e{663} unusual array to pointer conversion */ for(i = 0; i < PRNG_POOL_SIZE; i += SHA1_DIGEST_SIZE) { /* copy digest size pool block into SHA1 hash block */ memcpy(ctx->hash, buf + (i ? i : PRNG_POOL_SIZE) - SHA1_DIGEST_SIZE, SHA1_DIGEST_SIZE); /* copy data from pool into the SHA1 data buffer */ len = PRNG_POOL_SIZE - i; memcpy(ctx->wbuf, buf + i, (len > SHA1_BLOCK_SIZE ? SHA1_BLOCK_SIZE : len)); if(len < SHA1_BLOCK_SIZE) memcpy(((char*)ctx->wbuf) + len, buf, SHA1_BLOCK_SIZE - len); /* compress using the SHA1 compression function */ sha1_compile(ctx); /* put digest size block back into the random pool */ memcpy(buf + i, ctx->hash, SHA1_DIGEST_SIZE); } } /* refresh the output buffer and update the random pool by adding */ /* entropy and remixing */ static void update_pool(prng_ctx ctx[1]) { unsigned int i = 0; /* transfer random pool data to the output buffer */ memcpy(ctx->obuf, ctx->rbuf, PRNG_POOL_SIZE); /* enter entropy data into the pool */ while(i < PRNG_POOL_SIZE) i += ctx->entropy(ctx->rbuf + i, PRNG_POOL_SIZE - i); /* invert and xor the original pool data into the pool */ for(i = 0; i < PRNG_POOL_SIZE; ++i) ctx->rbuf[i] ^= ~ctx->obuf[i]; /* mix the pool and the output buffer */ prng_mix(ctx->rbuf); prng_mix(ctx->obuf); } void prng_init(prng_entropy_fn fun, prng_ctx ctx[1]) { int i; /* clear the buffers and the counter in the context */ memset(ctx, 0, sizeof(prng_ctx)); /* set the pointer to the entropy collection function */ ctx->entropy = fun; /* initialise the random data pool */ update_pool(ctx); /* mix the pool a minimum number of times */ for(i = 0; i < PRNG_MIN_MIX; ++i) prng_mix(ctx->rbuf); /* update the pool to prime the pool output buffer */ update_pool(ctx); } /* provide random bytes from the random data pool */ void prng_rand(unsigned char data[], unsigned int data_len, prng_ctx ctx[1]) { unsigned char *rp = data; unsigned int len, pos = ctx->pos; while(data_len) { /* transfer 'data_len' bytes (or the number of bytes remaining */ /* the pool output buffer if less) into the output */ len = (data_len < PRNG_POOL_SIZE - pos ? data_len : PRNG_POOL_SIZE - pos); memcpy(rp, ctx->obuf + pos, len); rp += len; /* update ouput buffer position pointer */ pos += len; /* update pool output buffer pointer */ data_len -= len; /* update the remaining data count */ /* refresh the random pool if necessary */ if(pos == PRNG_POOL_SIZE) { update_pool(ctx); pos = 0; } } ctx->pos = pos; } void prng_end(prng_ctx ctx[1]) { /* ensure the data in the context is destroyed */ memset(ctx, 0, sizeof(prng_ctx)); } irrlicht-1.8.3/source/Irrlicht/aesGladman/hmac.h0000644000000000000000000000606512574354552020261 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 Includes a bugfix from Dr Brian Gladman made on 16/04/2012 for compiling on 64-bit This is an implementation of HMAC, the FIPS standard keyed hash function */ #ifndef _HMAC_H #define _HMAC_H #include #define USE_SHA1 // Irrlicht only cares about SHA1 for now #if !defined(USE_SHA1) && !defined(USE_SHA256) #error define USE_SHA1 or USE_SHA256 to set the HMAC hash algorithm #endif #ifdef USE_SHA1 #include "sha1.h" #define HMAC_HASH_INPUT_SIZE SHA1_BLOCK_SIZE #define HMAC_HASH_OUTPUT_SIZE SHA1_DIGEST_SIZE #define sha_ctx sha1_ctx #define sha_begin sha1_begin #define sha_hash sha1_hash #define sha_end sha1_end #endif #ifdef USE_SHA256 #include "sha2.h" #define HMAC_HASH_INPUT_SIZE SHA256_BLOCK_SIZE #define HMAC_HASH_OUTPUT_SIZE SHA256_DIGEST_SIZE #define sha_ctx sha256_ctx #define sha_begin sha256_begin #define sha_hash sha256_hash #define sha_end sha256_end #endif #define HMAC_OK 0 #define HMAC_BAD_MODE -1 #define HMAC_IN_DATA 0xffffffff typedef struct { unsigned char key[HMAC_HASH_INPUT_SIZE]; sha_ctx ctx[1]; unsigned long klen; } hmac_ctx; void hmac_sha_begin(hmac_ctx cx[1]); int hmac_sha_key(const unsigned char key[], unsigned long key_len, hmac_ctx cx[1]); void hmac_sha_data(const unsigned char data[], unsigned long data_len, hmac_ctx cx[1]); void hmac_sha_end(unsigned char mac[], unsigned long mac_len, hmac_ctx cx[1]); void hmac_sha(const unsigned char key[], unsigned long key_len, const unsigned char data[], unsigned long data_len, unsigned char mac[], unsigned long mac_len); #endif irrlicht-1.8.3/source/Irrlicht/aesGladman/hmac.cpp0000644000000000000000000001251312574354552020607 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 Includes a bugfix from Dr Brian Gladman made on 16/04/2012 for compiling on 64-bit This is an implementation of HMAC, the FIPS standard keyed hash function */ #include "hmac.h" #define HMAC_IPAD (0x36 * (((unsigned long)-1) / 0xff)) #define HMAC_OPAD (0x5c * (((unsigned long)-1) / 0xff)) /* initialise the HMAC context to zero */ void hmac_sha_begin(hmac_ctx cx[1]) { memset(cx, 0, sizeof(hmac_ctx)); } /* input the HMAC key (can be called multiple times) */ int hmac_sha_key(const unsigned char key[], unsigned long key_len, hmac_ctx cx[1]) { if(cx->klen == HMAC_IN_DATA) /* error if further key input */ return HMAC_BAD_MODE; /* is attempted in data mode */ if(cx->klen + key_len > HMAC_HASH_INPUT_SIZE) /* if the key has to be hashed */ { if(cx->klen <= HMAC_HASH_INPUT_SIZE) /* if the hash has not yet been */ { /* started, initialise it and */ sha_begin(cx->ctx); /* hash stored key characters */ sha_hash(cx->key, cx->klen, cx->ctx); } sha_hash(key, key_len, cx->ctx); /* hash long key data into hash */ } else /* otherwise store key data */ memcpy(cx->key + cx->klen, key, key_len); cx->klen += key_len; /* update the key length count */ return HMAC_OK; } /* input the HMAC data (can be called multiple times) - */ /* note that this call terminates the key input phase */ void hmac_sha_data(const unsigned char data[], unsigned long data_len, hmac_ctx cx[1]) { unsigned int i; if(cx->klen != HMAC_IN_DATA) /* if not yet in data phase */ { if(cx->klen > HMAC_HASH_INPUT_SIZE) /* if key is being hashed */ { /* complete the hash and */ sha_end(cx->key, cx->ctx); /* store the result as the */ cx->klen = HMAC_HASH_OUTPUT_SIZE; /* key and set new length */ } /* pad the key if necessary */ memset(cx->key + cx->klen, 0, HMAC_HASH_INPUT_SIZE - cx->klen); /* xor ipad into key value */ for(i = 0; i < HMAC_HASH_INPUT_SIZE / sizeof(unsigned long); ++i) ((unsigned long*)cx->key)[i] ^= HMAC_IPAD; /* and start hash operation */ sha_begin(cx->ctx); sha_hash(cx->key, HMAC_HASH_INPUT_SIZE, cx->ctx); /* mark as now in data mode */ cx->klen = HMAC_IN_DATA; } /* hash the data (if any) */ if(data_len) sha_hash(data, data_len, cx->ctx); } /* compute and output the MAC value */ void hmac_sha_end(unsigned char mac[], unsigned long mac_len, hmac_ctx cx[1]) { unsigned char dig[HMAC_HASH_OUTPUT_SIZE]; unsigned int i; /* if no data has been entered perform a null data phase */ if(cx->klen != HMAC_IN_DATA) hmac_sha_data((const unsigned char*)0, 0, cx); sha_end(dig, cx->ctx); /* complete the inner hash */ /* set outer key value using opad and removing ipad */ for(i = 0; i < HMAC_HASH_INPUT_SIZE / sizeof(unsigned long); ++i) ((unsigned long*)cx->key)[i] ^= HMAC_OPAD ^ HMAC_IPAD; /* perform the outer hash operation */ sha_begin(cx->ctx); sha_hash(cx->key, HMAC_HASH_INPUT_SIZE, cx->ctx); sha_hash(dig, HMAC_HASH_OUTPUT_SIZE, cx->ctx); sha_end(dig, cx->ctx); /* output the hash value */ for(i = 0; i < mac_len; ++i) mac[i] = dig[i]; } /* 'do it all in one go' subroutine */ void hmac_sha(const unsigned char key[], unsigned long key_len, const unsigned char data[], unsigned long data_len, unsigned char mac[], unsigned long mac_len) { hmac_ctx cx[1]; hmac_sha_begin(cx); hmac_sha_key(key, key_len, cx); hmac_sha_data(data, data_len, cx); hmac_sha_end(mac, mac_len, cx); } irrlicht-1.8.3/source/Irrlicht/aesGladman/fileenc.h0000644000000000000000000001032012574354552020743 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 24/01/2003 This file contains the header file for fileenc.c, which implements password based file encryption and authentication using AES in CTR mode, HMAC-SHA1 authentication and RFC2898 password based key derivation. */ #ifndef _FENC_H #define _FENC_H #include "aes.h" #include "hmac.h" #include "pwd2key.h" #define BLOCK_SIZE AES_BLOCK_SIZE #define PASSWORD_VERIFIER #define MAX_KEY_LENGTH 32 #define MAX_PWD_LENGTH 128 #define MAX_SALT_LENGTH 16 #define KEYING_ITERATIONS 1000 #ifdef PASSWORD_VERIFIER #define PWD_VER_LENGTH 2 #else #define PWD_VER_LENGTH 0 #endif #define GOOD_RETURN 0 #define PASSWORD_TOO_LONG -100 #define BAD_MODE -101 /* Field lengths (in bytes) versus File Encryption Mode (0 < mode < 4) Mode Key Salt MAC Overhead 1 16 8 10 18 2 24 12 10 22 3 32 16 10 26 The following macros assume that the mode value is correct. */ #define KEY_LENGTH(mode) (8 * (mode & 3) + 8) #define SALT_LENGTH(mode) (4 * (mode & 3) + 4) #define MAC_LENGTH(mode) (10) /* the context for file encryption */ typedef struct { unsigned char nonce[BLOCK_SIZE]; /* the CTR nonce */ unsigned char encr_bfr[BLOCK_SIZE]; /* encrypt buffer */ aes_encrypt_ctx encr_ctx[1]; /* encryption context */ hmac_ctx auth_ctx[1]; /* authentication context */ unsigned int encr_pos; /* block position (enc) */ unsigned int pwd_len; /* password length */ unsigned int mode; /* File encryption mode */ } fcrypt_ctx; /* initialise file encryption or decryption */ int fcrypt_init( int mode, /* the mode to be used (input) */ const unsigned char pwd[], /* the user specified password (input) */ unsigned int pwd_len, /* the length of the password (input) */ const unsigned char salt[], /* the salt (input) */ #ifdef PASSWORD_VERIFIER unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */ #endif fcrypt_ctx cx[1]); /* the file encryption context (output) */ /* perform 'in place' encryption or decryption and authentication */ void fcrypt_encrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]); void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]); /* close encryption/decryption and return the MAC value */ /* the return value is the length of the MAC */ int fcrypt_end(unsigned char mac[], /* the MAC value (output) */ fcrypt_ctx cx[1]); /* the context (input) */ #endif irrlicht-1.8.3/source/Irrlicht/aesGladman/fileenc.cpp0000644000000000000000000001166212574354552021310 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. ------------------------------------------------------------------------- Issue Date: 26/08/2003 This file implements password based file encryption and authentication using AES in CTR mode, HMAC-SHA1 authentication and RFC2898 password based key derivation. */ #include #include "fileenc.h" /* subroutine for data encryption/decryption */ /* this could be speeded up a lot by aligning */ /* buffers and using 32 bit operations */ static void encr_data(unsigned char data[], unsigned long d_len, fcrypt_ctx cx[1]) { unsigned long i = 0, pos = cx->encr_pos; while(i < d_len) { if(pos == BLOCK_SIZE) { unsigned int j = 0; /* increment encryption nonce */ while(j < 8 && !++cx->nonce[j]) ++j; /* encrypt the nonce to form next xor buffer */ aes_encrypt(cx->nonce, cx->encr_bfr, cx->encr_ctx); pos = 0; } data[i++] ^= cx->encr_bfr[pos++]; } cx->encr_pos = pos; } int fcrypt_init( int mode, /* the mode to be used (input) */ const unsigned char pwd[], /* the user specified password (input) */ unsigned int pwd_len, /* the length of the password (input) */ const unsigned char salt[], /* the salt (input) */ #ifdef PASSWORD_VERIFIER unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */ #endif fcrypt_ctx cx[1]) /* the file encryption context (output) */ { unsigned char kbuf[2 * MAX_KEY_LENGTH + PWD_VER_LENGTH]; if(pwd_len > MAX_PWD_LENGTH) return PASSWORD_TOO_LONG; if(mode < 1 || mode > 3) return BAD_MODE; cx->mode = mode; cx->pwd_len = pwd_len; /* initialise the encryption nonce and buffer pos */ cx->encr_pos = BLOCK_SIZE; /* if we need a random component in the encryption */ /* nonce, this is where it would have to be set */ memset(cx->nonce, 0, BLOCK_SIZE * sizeof(unsigned char)); /* initialise for authentication */ hmac_sha_begin(cx->auth_ctx); /* derive the encryption and authetication keys and the password verifier */ derive_key(pwd, pwd_len, salt, SALT_LENGTH(mode), KEYING_ITERATIONS, kbuf, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH); /* set the encryption key */ aes_encrypt_key(kbuf, KEY_LENGTH(mode), cx->encr_ctx); /* set the authentication key */ hmac_sha_key(kbuf + KEY_LENGTH(mode), KEY_LENGTH(mode), cx->auth_ctx); #ifdef PASSWORD_VERIFIER memcpy(pwd_ver, kbuf + 2 * KEY_LENGTH(mode), PWD_VER_LENGTH); #endif /* clear the buffer holding the derived key values */ memset(kbuf, 0, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH); return GOOD_RETURN; } /* perform 'in place' encryption and authentication */ void fcrypt_encrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]) { encr_data(data, data_len, cx); hmac_sha_data(data, data_len, cx->auth_ctx); } /* perform 'in place' authentication and decryption */ void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]) { hmac_sha_data(data, data_len, cx->auth_ctx); encr_data(data, data_len, cx); } /* close encryption/decryption and return the MAC value */ int fcrypt_end(unsigned char mac[], fcrypt_ctx cx[1]) { unsigned int res = cx->mode; hmac_sha_end(mac, MAC_LENGTH(cx->mode), cx->auth_ctx); memset(cx, 0, sizeof(fcrypt_ctx)); /* clear the encryption context */ return MAC_LENGTH(res); /* return MAC length in bytes */ } irrlicht-1.8.3/source/Irrlicht/aesGladman/aestab.cpp0000644000000000000000000001374612574354552021147 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2003, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 */ #define DO_TABLES #include "aesopt.h" #if defined(FIXED_TABLES) /* implemented in case of wrong call for fixed tables */ void gen_tabs(void) { } #else /* dynamic table generation */ #if !defined(FF_TABLES) /* Generate the tables for the dynamic table option It will generally be sensible to use tables to compute finite field multiplies and inverses but where memory is scarse this code might sometimes be better. But it only has effect during initialisation so its pretty unimportant in overall terms. */ /* return 2 ^ (n - 1) where n is the bit number of the highest bit set in x with x in the range 1 < x < 0x00000200. This form is used so that locals within fi can be bytes rather than words */ static aes_08t hibit(const aes_32t x) { aes_08t r = (aes_08t)((x >> 1) | (x >> 2)); r |= (r >> 2); r |= (r >> 4); return (r + 1) >> 1; } /* return the inverse of the finite field element x */ static aes_08t fi(const aes_08t x) { aes_08t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; if(x < 2) return x; for(;;) { if(!n1) return v1; while(n2 >= n1) { n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2); } if(!n2) return v2; while(n1 >= n2) { n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); } } } #endif /* The forward and inverse affine transformations used in the S-box */ #define fwd_affine(x) \ (w = (aes_32t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(aes_08t)(w^(w>>8))) #define inv_affine(x) \ (w = (aes_32t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(aes_08t)(w^(w>>8))) static int init = 0; void gen_tabs(void) { aes_32t i, w; #if defined(FF_TABLES) aes_08t pow[512], log[256]; if(init) return; /* log and power tables for GF(2^8) finite field with WPOLY as modular polynomial - the simplest primitive root is 0x03, used here to generate the tables */ i = 0; w = 1; do { pow[i] = (aes_08t)w; pow[i + 255] = (aes_08t)w; log[w] = (aes_08t)i++; w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); } while (w != 1); #else if(init) return; #endif for(i = 0, w = 1; i < RC_LENGTH; ++i) { t_set(r,c)[i] = bytes2word(w, 0, 0, 0); w = f2(w); } for(i = 0; i < 256; ++i) { aes_08t b; b = fwd_affine(fi((aes_08t)i)); w = bytes2word(f2(b), b, b, f3(b)); #ifdef SBX_SET t_set(s,box)[i] = b; #endif #ifdef FT1_SET /* tables for a normal encryption round */ t_set(f,n)[i] = w; #endif #ifdef FT4_SET t_set(f,n)[0][i] = w; t_set(f,n)[1][i] = upr(w,1); t_set(f,n)[2][i] = upr(w,2); t_set(f,n)[3][i] = upr(w,3); #endif w = bytes2word(b, 0, 0, 0); #ifdef FL1_SET /* tables for last encryption round (may also */ t_set(f,l)[i] = w; /* be used in the key schedule) */ #endif #ifdef FL4_SET t_set(f,l)[0][i] = w; t_set(f,l)[1][i] = upr(w,1); t_set(f,l)[2][i] = upr(w,2); t_set(f,l)[3][i] = upr(w,3); #endif #ifdef LS1_SET /* table for key schedule if t_set(f,l) above is */ t_set(l,s)[i] = w; /* not of the required form */ #endif #ifdef LS4_SET t_set(l,s)[0][i] = w; t_set(l,s)[1][i] = upr(w,1); t_set(l,s)[2][i] = upr(w,2); t_set(l,s)[3][i] = upr(w,3); #endif b = fi(inv_affine((aes_08t)i)); w = bytes2word(fe(b), f9(b), fd(b), fb(b)); #ifdef IM1_SET /* tables for the inverse mix column operation */ t_set(i,m)[b] = w; #endif #ifdef IM4_SET t_set(i,m)[0][b] = w; t_set(i,m)[1][b] = upr(w,1); t_set(i,m)[2][b] = upr(w,2); t_set(i,m)[3][b] = upr(w,3); #endif #ifdef ISB_SET t_set(i,box)[i] = b; #endif #ifdef IT1_SET /* tables for a normal decryption round */ t_set(i,n)[i] = w; #endif #ifdef IT4_SET t_set(i,n)[0][i] = w; t_set(i,n)[1][i] = upr(w,1); t_set(i,n)[2][i] = upr(w,2); t_set(i,n)[3][i] = upr(w,3); #endif w = bytes2word(b, 0, 0, 0); #ifdef IL1_SET /* tables for last decryption round */ t_set(i,l)[i] = w; #endif #ifdef IL4_SET t_set(i,l)[0][i] = w; t_set(i,l)[1][i] = upr(w,1); t_set(i,l)[2][i] = upr(w,2); t_set(i,l)[3][i] = upr(w,3); #endif } init = 1; } #endif irrlicht-1.8.3/source/Irrlicht/aesGladman/aesopt.h0000644000000000000000000011056112574354552020641 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2003, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 My thanks go to Dag Arne Osvik for devising the schemes used here for key length derivation from the form of the key schedule This file contains the compilation options for AES (Rijndael) and code that is common across encryption, key scheduling and table generation. OPERATION These source code files implement the AES algorithm Rijndael designed by Joan Daemen and Vincent Rijmen. This version is designed for the standard block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24 and 32 bytes). This version is designed for flexibility and speed using operations on 32-bit words rather than operations on bytes. It can be compiled with either big or little endian internal byte order but is faster when the native byte order for the processor is used. THE CIPHER INTERFACE The cipher interface is implemented as an array of bytes in which lower AES bit sequence indexes map to higher numeric significance within bytes. aes_08t (an unsigned 8-bit type) aes_32t (an unsigned 32-bit type) struct aes_encrypt_ctx (structure for the cipher encryption context) struct aes_decrypt_ctx (structure for the cipher decryption context) aes_rval the function return type C subroutine calls: aes_rval aes_encrypt_key128(const void *in_key, aes_encrypt_ctx cx[1]); aes_rval aes_encrypt_key192(const void *in_key, aes_encrypt_ctx cx[1]); aes_rval aes_encrypt_key256(const void *in_key, aes_encrypt_ctx cx[1]); aes_rval aes_encrypt(const void *in_blk, void *out_blk, const aes_encrypt_ctx cx[1]); aes_rval aes_decrypt_key128(const void *in_key, aes_decrypt_ctx cx[1]); aes_rval aes_decrypt_key192(const void *in_key, aes_decrypt_ctx cx[1]); aes_rval aes_decrypt_key256(const void *in_key, aes_decrypt_ctx cx[1]); aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx[1]); IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that you call genTabs() before AES is used so that the tables are initialised. C++ aes class subroutines: Class AESencrypt for encryption Construtors: AESencrypt(void) AESencrypt(const void *in_key) - 128 bit key Members: void key128(const void *in_key) void key192(const void *in_key) void key256(const void *in_key) void encrypt(const void *in_blk, void *out_blk) const Class AESdecrypt for encryption Construtors: AESdecrypt(void) AESdecrypt(const void *in_key) - 128 bit key Members: void key128(const void *in_key) void key192(const void *in_key) void key256(const void *in_key) void decrypt(const void *in_blk, void *out_blk) const COMPILATION The files used to provide AES (Rijndael) are a. aes.h for the definitions needed for use in C. b. aescpp.h for the definitions needed for use in C++. c. aesopt.h for setting compilation options (also includes common code). d. aescrypt.c for encryption and decrytpion, or e. aeskey.c for key scheduling. f. aestab.c for table loading or generation. g. aescrypt.asm for encryption and decryption using assembler code. h. aescrypt.mmx.asm for encryption and decryption using MMX assembler. To compile AES (Rijndael) for use in C code use aes.h and set the defines here for the facilities you need (key lengths, encryption and/or decryption). Do not define AES_DLL or AES_CPP. Set the options for optimisations and table sizes here. To compile AES (Rijndael) for use in in C++ code use aescpp.h but do not define AES_DLL To compile AES (Rijndael) in C as a Dynamic Link Library DLL) use aes.h and include the AES_DLL define. CONFIGURATION OPTIONS (here and in aes.h) a. set AES_DLL in aes.h if AES (Rijndael) is to be compiled as a DLL b. You may need to set PLATFORM_BYTE_ORDER to define the byte order. c. If you want the code to run in a specific internal byte order, then ALGORITHM_BYTE_ORDER must be set accordingly. d. set other configuration options decribed below. */ #ifndef _AESOPT_H #define _AESOPT_H #include "aes.h" /* CONFIGURATION - USE OF DEFINES Later in this section there are a number of defines that control the operation of the code. In each section, the purpose of each define is explained so that the relevant form can be included or excluded by setting either 1's or 0's respectively on the branches of the related #if clauses. */ /* BYTE ORDER IN 32-BIT WORDS To obtain the highest speed on processors with 32-bit words, this code needs to determine the byte order of the target machine. The following block of code is an attempt to capture the most obvious ways in which various environemnts define byte order. It may well fail, in which case the definitions will need to be set by editing at the points marked **** EDIT HERE IF NECESSARY **** below. My thanks to Peter Gutmann for some of these defines (from cryptlib). */ #define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ #define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ #ifdef __BIG_ENDIAN__ #define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN #else #define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN #endif /* SOME LOCAL DEFINITIONS */ #define NO_TABLES 0 #define ONE_TABLE 1 #define FOUR_TABLES 4 #define NONE 0 #define PARTIAL 1 #define FULL 2 #define aes_sw32 Byteswap::byteswap /* 1. FUNCTIONS REQUIRED This implementation provides subroutines for encryption, decryption and for setting the three key lengths (separately) for encryption and decryption. When the assembler code is not being used the following definition blocks allow the selection of the routines that are to be included in the compilation. */ #ifdef AES_ENCRYPT #define ENCRYPTION #define ENCRYPTION_KEY_SCHEDULE #endif #ifdef AES_DECRYPT #define DECRYPTION #define DECRYPTION_KEY_SCHEDULE #endif /* 2. ASSEMBLER SUPPORT This define (which can be on the command line) enables the use of the assembler code routines for encryption and decryption with the C code only providing key scheduling */ #if 0 #define AES_ASM #endif /* 3. BYTE ORDER WITHIN 32 BIT WORDS The fundamental data processing units in Rijndael are 8-bit bytes. The input, output and key input are all enumerated arrays of bytes in which bytes are numbered starting at zero and increasing to one less than the number of bytes in the array in question. This enumeration is only used for naming bytes and does not imply any adjacency or order relationship from one byte to another. When these inputs and outputs are considered as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. In this implementation bits are numbered from 0 to 7 starting at the numerically least significant end of each byte (bit n represents 2^n). However, Rijndael can be implemented more efficiently using 32-bit words by packing bytes into words so that bytes 4*n to 4*n+3 are placed into word[n]. While in principle these bytes can be assembled into words in any positions, this implementation only supports the two formats in which bytes in adjacent positions within words also have adjacent byte numbers. This order is called big-endian if the lowest numbered bytes in words have the highest numeric significance and little-endian if the opposite applies. This code can work in either order irrespective of the order used by the machine on which it runs. Normally the internal byte order will be set to the order of the processor on which the code is to be run but this define can be used to reverse this in special situations NOTE: Assembler code versions rely on PLATFORM_BYTE_ORDER being set */ #if 1 || defined(AES_ASM) #define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER #elif 0 #define ALGORITHM_BYTE_ORDER BRG_LITTLE_ENDIAN #elif 0 #define ALGORITHM_BYTE_ORDER BRG_BIG_ENDIAN #else #error The algorithm byte order is not defined #endif /* 4. FAST INPUT/OUTPUT OPERATIONS. On some machines it is possible to improve speed by transferring the bytes in the input and output arrays to and from the internal 32-bit variables by addressing these arrays as if they are arrays of 32-bit words. On some machines this will always be possible but there may be a large performance penalty if the byte arrays are not aligned on the normal word boundaries. On other machines this technique will lead to memory access errors when such 32-bit word accesses are not properly aligned. The option SAFE_IO avoids such problems but will often be slower on those machines that support misaligned access (especially so if care is taken to align the input and output byte arrays on 32-bit word boundaries). If SAFE_IO is not defined it is assumed that access to byte arrays as if they are arrays of 32-bit words will not cause problems when such accesses are misaligned. */ #if 1 && !defined(_MSC_VER) #define SAFE_IO #endif /* 5. LOOP UNROLLING The code for encryption and decrytpion cycles through a number of rounds that can be implemented either in a loop or by expanding the code into a long sequence of instructions, the latter producing a larger program but one that will often be much faster. The latter is called loop unrolling. There are also potential speed advantages in expanding two iterations in a loop with half the number of iterations, which is called partial loop unrolling. The following options allow partial or full loop unrolling to be set independently for encryption and decryption */ #if 1 #define ENC_UNROLL FULL #elif 0 #define ENC_UNROLL PARTIAL #else #define ENC_UNROLL NONE #endif #if 1 #define DEC_UNROLL FULL #elif 0 #define DEC_UNROLL PARTIAL #else #define DEC_UNROLL NONE #endif /* 6. FAST FINITE FIELD OPERATIONS If this section is included, tables are used to provide faster finite field arithmetic (this has no effect if FIXED_TABLES is defined). */ #if 0 #define FF_TABLES #endif /* 7. INTERNAL STATE VARIABLE FORMAT The internal state of Rijndael is stored in a number of local 32-bit word varaibles which can be defined either as an array or as individual names variables. Include this section if you want to store these local varaibles in arrays. Otherwise individual local variables will be used. */ #if 1 #define ARRAYS #endif /* In this implementation the columns of the state array are each held in 32-bit words. The state array can be held in various ways: in an array of words, in a number of individual word variables or in a number of processor registers. The following define maps a variable name x and a column number c to the way the state array variable is to be held. The first define below maps the state into an array x[c] whereas the second form maps the state into a number of individual variables x0, x1, etc. Another form could map individual state colums to machine register names. */ #if defined(ARRAYS) #define s(x,c) x[c] #else #define s(x,c) x##c #endif /* 8. FIXED OR DYNAMIC TABLES When this section is included the tables used by the code are compiled statically into the binary file. Otherwise the subroutine gen_tabs() must be called to compute them before the code is first used. */ #if 1 #define FIXED_TABLES #define DO_TABLES #endif /* 9. TABLE ALIGNMENT On some systems speed will be improved by aligning the AES large lookup tables on particular boundaries. This define should be set to a power of two giving the desired alignment. It can be left undefined if alignment is not needed. This option is specific to the Microsft VC++ compiler - it seems to sometimes cause trouble for the VC++ version 6 compiler. */ #if 0 && defined(_MSC_VER) && (_MSC_VER >= 1300) #define TABLE_ALIGN 64 #endif /* 10. INTERNAL TABLE CONFIGURATION This cipher proceeds by repeating in a number of cycles known as 'rounds' which are implemented by a round function which can optionally be speeded up using tables. The basic tables are each 256 32-bit words, with either one or four tables being required for each round function depending on how much speed is required. The encryption and decryption round functions are different and the last encryption and decrytpion round functions are different again making four different round functions in all. This means that: 1. Normal encryption and decryption rounds can each use either 0, 1 or 4 tables and table spaces of 0, 1024 or 4096 bytes each. 2. The last encryption and decryption rounds can also use either 0, 1 or 4 tables and table spaces of 0, 1024 or 4096 bytes each. Include or exclude the appropriate definitions below to set the number of tables used by this implementation. */ #if 1 /* set tables for the normal encryption round */ #define ENC_ROUND FOUR_TABLES #elif 0 #define ENC_ROUND ONE_TABLE #else #define ENC_ROUND NO_TABLES #endif #if 1 /* set tables for the last encryption round */ #define LAST_ENC_ROUND FOUR_TABLES #elif 0 #define LAST_ENC_ROUND ONE_TABLE #else #define LAST_ENC_ROUND NO_TABLES #endif #if 1 /* set tables for the normal decryption round */ #define DEC_ROUND FOUR_TABLES #elif 0 #define DEC_ROUND ONE_TABLE #else #define DEC_ROUND NO_TABLES #endif #if 1 /* set tables for the last decryption round */ #define LAST_DEC_ROUND FOUR_TABLES #elif 0 #define LAST_DEC_ROUND ONE_TABLE #else #define LAST_DEC_ROUND NO_TABLES #endif /* The decryption key schedule can be speeded up with tables in the same way that the round functions can. Include or exclude the following defines to set this requirement. */ #if 1 #define KEY_SCHED FOUR_TABLES #elif 0 #define KEY_SCHED ONE_TABLE #else #define KEY_SCHED NO_TABLES #endif /* END OF CONFIGURATION OPTIONS */ #define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2)) /* Disable or report errors on some combinations of options */ #if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES #undef LAST_ENC_ROUND #define LAST_ENC_ROUND NO_TABLES #elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES #undef LAST_ENC_ROUND #define LAST_ENC_ROUND ONE_TABLE #endif #if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE #undef ENC_UNROLL #define ENC_UNROLL NONE #endif #if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES #undef LAST_DEC_ROUND #define LAST_DEC_ROUND NO_TABLES #elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES #undef LAST_DEC_ROUND #define LAST_DEC_ROUND ONE_TABLE #endif #if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE #undef DEC_UNROLL #define DEC_UNROLL NONE #endif /* upr(x,n): rotates bytes within words by n positions, moving bytes to higher index positions with wrap around into low positions ups(x,n): moves bytes by n positions to higher index positions in words but without wrap around bval(x,n): extracts a byte from a word NOTE: The definitions given here are intended only for use with unsigned variables and with shift counts that are compile time constants */ #if (ALGORITHM_BYTE_ORDER == BRG_LITTLE_ENDIAN) #define upr(x,n) (((aes_32t)(x) << (8 * (n))) | ((aes_32t)(x) >> (32 - 8 * (n)))) #define ups(x,n) ((aes_32t) (x) << (8 * (n))) #define bval(x,n) ((aes_08t)((x) >> (8 * (n)))) #define bytes2word(b0, b1, b2, b3) \ (((aes_32t)(b3) << 24) | ((aes_32t)(b2) << 16) | ((aes_32t)(b1) << 8) | (b0)) #endif #if (ALGORITHM_BYTE_ORDER == BRG_BIG_ENDIAN) #define upr(x,n) (((aes_32t)(x) >> (8 * (n))) | ((aes_32t)(x) << (32 - 8 * (n)))) #define ups(x,n) ((aes_32t) (x) >> (8 * (n)))) #define bval(x,n) ((aes_08t)((x) >> (24 - 8 * (n)))) #define bytes2word(b0, b1, b2, b3) \ (((aes_32t)(b0) << 24) | ((aes_32t)(b1) << 16) | ((aes_32t)(b2) << 8) | (b3)) #endif #if defined(SAFE_IO) #define word_in(x,c) bytes2word(((aes_08t*)(x)+4*c)[0], ((aes_08t*)(x)+4*c)[1], \ ((aes_08t*)(x)+4*c)[2], ((aes_08t*)(x)+4*c)[3]) #define word_out(x,c,v) { ((aes_08t*)(x)+4*c)[0] = bval(v,0); ((aes_08t*)(x)+4*c)[1] = bval(v,1); \ ((aes_08t*)(x)+4*c)[2] = bval(v,2); ((aes_08t*)(x)+4*c)[3] = bval(v,3); } #elif (ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER) #define word_in(x,c) (*((aes_32t*)(x)+(c))) #define word_out(x,c,v) (*((aes_32t*)(x)+(c)) = (v)) #else #define word_in(x,c) aes_sw32(*((aes_32t*)(x)+(c))) #define word_out(x,c,v) (*((aes_32t*)(x)+(c)) = aes_sw32(v)) #endif /* the finite field modular polynomial and elements */ #define WPOLY 0x011b #define BPOLY 0x1b /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ #define m1 0x80808080 #define m2 0x7f7f7f7f #define gf_mulx(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY)) /* The following defines provide alternative definitions of gf_mulx that might give improved performance if a fast 32-bit multiply is not available. Note that a temporary variable u needs to be defined where gf_mulx is used. #define gf_mulx(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) #define m4 (0x01010101 * BPOLY) #define gf_mulx(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) */ /* Work out which tables are needed for the different options */ #ifdef AES_ASM #ifdef ENC_ROUND #undef ENC_ROUND #endif #define ENC_ROUND FOUR_TABLES #ifdef LAST_ENC_ROUND #undef LAST_ENC_ROUND #endif #define LAST_ENC_ROUND FOUR_TABLES #ifdef DEC_ROUND #undef DEC_ROUND #endif #define DEC_ROUND FOUR_TABLES #ifdef LAST_DEC_ROUND #undef LAST_DEC_ROUND #endif #define LAST_DEC_ROUND FOUR_TABLES #ifdef KEY_SCHED #undef KEY_SCHED #define KEY_SCHED FOUR_TABLES #endif #endif #if defined(ENCRYPTION) || defined(AES_ASM) #if ENC_ROUND == ONE_TABLE #define FT1_SET #elif ENC_ROUND == FOUR_TABLES #define FT4_SET #else #define SBX_SET #endif #if LAST_ENC_ROUND == ONE_TABLE #define FL1_SET #elif LAST_ENC_ROUND == FOUR_TABLES #define FL4_SET #elif !defined(SBX_SET) #define SBX_SET #endif #endif #if defined(DECRYPTION) || defined(AES_ASM) #if DEC_ROUND == ONE_TABLE #define IT1_SET #elif DEC_ROUND == FOUR_TABLES #define IT4_SET #else #define ISB_SET #endif #if LAST_DEC_ROUND == ONE_TABLE #define IL1_SET #elif LAST_DEC_ROUND == FOUR_TABLES #define IL4_SET #elif !defined(ISB_SET) #define ISB_SET #endif #endif #if defined(ENCRYPTION_KEY_SCHEDULE) || defined(DECRYPTION_KEY_SCHEDULE) #if KEY_SCHED == ONE_TABLE #define LS1_SET #define IM1_SET #elif KEY_SCHED == FOUR_TABLES #define LS4_SET #define IM4_SET #elif !defined(SBX_SET) #define SBX_SET #endif #endif /* generic definitions of Rijndael macros that use tables */ #define no_table(x,box,vf,rf,c) bytes2word( \ box[bval(vf(x,0,c),rf(0,c))], \ box[bval(vf(x,1,c),rf(1,c))], \ box[bval(vf(x,2,c),rf(2,c))], \ box[bval(vf(x,3,c),rf(3,c))]) #define one_table(x,op,tab,vf,rf,c) \ ( tab[bval(vf(x,0,c),rf(0,c))] \ ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) #define four_tables(x,tab,vf,rf,c) \ ( tab[0][bval(vf(x,0,c),rf(0,c))] \ ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ ^ tab[3][bval(vf(x,3,c),rf(3,c))]) #define vf1(x,r,c) (x) #define rf1(r,c) (r) #define rf2(r,c) ((8+r-c)&3) /* perform forward and inverse column mix operation on four bytes in long word x in */ /* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */ #if defined(FM4_SET) /* not currently used */ #define fwd_mcol(x) four_tables(x,t_use(f,m),vf1,rf1,0) #elif defined(FM1_SET) /* not currently used */ #define fwd_mcol(x) one_table(x,upr,t_use(f,m),vf1,rf1,0) #else #define dec_fmvars aes_32t g2 #define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1)) #endif #if defined(IM4_SET) #define inv_mcol(x) four_tables(x,t_use(i,m),vf1,rf1,0) #elif defined(IM1_SET) #define inv_mcol(x) one_table(x,upr,t_use(i,m),vf1,rf1,0) #else #define dec_imvars aes_32t g2, g4, g9 #define inv_mcol(x) (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \ (x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1)) #endif #if defined(FL4_SET) #define ls_box(x,c) four_tables(x,t_use(f,l),vf1,rf2,c) #elif defined(LS4_SET) #define ls_box(x,c) four_tables(x,t_use(l,s),vf1,rf2,c) #elif defined(FL1_SET) #define ls_box(x,c) one_table(x,upr,t_use(f,l),vf1,rf2,c) #elif defined(LS1_SET) #define ls_box(x,c) one_table(x,upr,t_use(l,s),vf1,rf2,c) #else #define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c) #endif /* If there are no global variables, the definitions here can be used to put the AES tables in a structure so that a pointer can then be added to the AES context to pass them to the AES routines that need them. If this facility is used, the calling program has to ensure that this pointer is managed appropriately. In particular, the value of the t_dec(in,it) item in the table structure must be set to zero in order to ensure that the tables are initialised. In practice the three code sequences in aeskey.c that control the calls to gen_tabs() and the gen_tabs() routine itself will have to be changed for a specific implementation. If global variables are available it will generally be preferable to use them with the precomputed FIXED_TABLES option that uses static global tables. The following defines can be used to control the way the tables are defined, initialised and used in embedded environments that require special features for these purposes the 't_dec' construction is used to declare fixed table arrays the 't_set' construction is used to set fixed table values the 't_use' construction is used to access fixed table values 256 byte tables: t_xxx(s,box) => forward S box t_xxx(i,box) => inverse S box 256 32-bit word OR 4 x 256 32-bit word tables: t_xxx(f,n) => forward normal round t_xxx(f,l) => forward last round t_xxx(i,n) => inverse normal round t_xxx(i,l) => inverse last round t_xxx(l,s) => key schedule table t_xxx(i,m) => key schedule table Other variables and tables: t_xxx(r,c) => the rcon table */ #define t_dec(m,n) t_##m##n #define t_set(m,n) t_##m##n #define t_use(m,n) t_##m##n #if defined(DO_TABLES) /* declare and instantiate tables */ /* finite field arithmetic operations for table generation */ #if defined(FIXED_TABLES) || !defined(FF_TABLES) #define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) #define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) #define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ ^ (((x>>5) & 4) * WPOLY)) #define f3(x) (f2(x) ^ x) #define f9(x) (f8(x) ^ x) #define fb(x) (f8(x) ^ f2(x) ^ x) #define fd(x) (f8(x) ^ f4(x) ^ x) #define fe(x) (f8(x) ^ f4(x) ^ f2(x)) #else #define f2(x) ((x) ? pow[log[x] + 0x19] : 0) #define f3(x) ((x) ? pow[log[x] + 0x01] : 0) #define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) #define fb(x) ((x) ? pow[log[x] + 0x68] : 0) #define fd(x) ((x) ? pow[log[x] + 0xee] : 0) #define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) #define fi(x) ((x) ? pow[ 255 - log[x]] : 0) #endif #if defined(FIXED_TABLES) /* declare and set values for static tables */ #define sb_data(w) \ w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) #define isb_data(w) \ w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d), #define mm_data(w) \ w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) #define h0(x) (x) /* These defines are used to ensure tables are generated in the right format depending on the internal byte order required */ #define w0(p) bytes2word(p, 0, 0, 0) #define w1(p) bytes2word(0, p, 0, 0) #define w2(p) bytes2word(0, 0, p, 0) #define w3(p) bytes2word(0, 0, 0, p) #define u0(p) bytes2word(f2(p), p, p, f3(p)) #define u1(p) bytes2word(f3(p), f2(p), p, p) #define u2(p) bytes2word(p, f3(p), f2(p), p) #define u3(p) bytes2word(p, p, f3(p), f2(p)) #define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) #define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) #define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) #define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) const aes_32t t_dec(r,c)[RC_LENGTH] = { w0(0x01), w0(0x02), w0(0x04), w0(0x08), w0(0x10), w0(0x20), w0(0x40), w0(0x80), w0(0x1b), w0(0x36) }; #if defined(__BORLANDC__) #define concat(s1, s2) s1##s2 #define d_1(t,n,b,v) const t n[256] = { b(concat(v,0)) } #define d_4(t,n,b,v) const t n[4][256] = { { b(concat(v,0)) }, { b(concat(v,1)) }, { b(concat(v,2)) }, { b(concat(v,3)) } } #else #define d_1(t,n,b,v) const t n[256] = { b(v##0) } #define d_4(t,n,b,v) const t n[4][256] = { { b(v##0) }, { b(v##1) }, { b(v##2) }, { b(v##3) } } #endif #else /* declare and instantiate tables for dynamic value generation in in tab.c */ aes_32t t_dec(r,c)[RC_LENGTH]; #define d_1(t,n,b,v) t n[256] #define d_4(t,n,b,v) t n[4][256] #endif #else /* declare tables without instantiation */ #if defined(FIXED_TABLES) extern const aes_32t t_dec(r,c)[RC_LENGTH]; #if defined(_MSC_VER) && defined(TABLE_ALIGN) #define d_1(t,n,b,v) extern __declspec(align(TABLE_ALIGN)) const t n[256] #define d_4(t,n,b,v) extern __declspec(align(TABLE_ALIGN)) const t n[4][256] #else #define d_1(t,n,b,v) extern const t n[256] #define d_4(t,n,b,v) extern const t n[4][256] #endif #else extern aes_32t t_dec(r,c)[RC_LENGTH]; #if defined(_MSC_VER) && defined(TABLE_ALIGN) #define d_1(t,n,b,v) extern __declspec(align(TABLE_ALIGN)) t n[256] #define d_4(t,n,b,v) extern __declspec(align(TABLE_ALIGN)) t n[4][256] #else #define d_1(t,n,b,v) extern t n[256] #define d_4(t,n,b,v) extern t n[4][256] #endif #endif #endif #ifdef SBX_SET d_1(aes_08t, t_dec(s,box), sb_data, h); #endif #ifdef ISB_SET d_1(aes_08t, t_dec(i,box), isb_data, h); #endif #ifdef FT1_SET d_1(aes_32t, t_dec(f,n), sb_data, u); #endif #ifdef FT4_SET d_4(aes_32t, t_dec(f,n), sb_data, u); #endif #ifdef FL1_SET d_1(aes_32t, t_dec(f,l), sb_data, w); #endif #ifdef FL4_SET d_4(aes_32t, t_dec(f,l), sb_data, w); #endif #ifdef IT1_SET d_1(aes_32t, t_dec(i,n), isb_data, v); #endif #ifdef IT4_SET d_4(aes_32t, t_dec(i,n), isb_data, v); #endif #ifdef IL1_SET d_1(aes_32t, t_dec(i,l), isb_data, w); #endif #ifdef IL4_SET d_4(aes_32t, t_dec(i,l), isb_data, w); #endif #ifdef LS1_SET #ifdef FL1_SET #undef LS1_SET #else d_1(aes_32t, t_dec(l,s), sb_data, w); #endif #endif #ifdef LS4_SET #ifdef FL4_SET #undef LS4_SET #else d_4(aes_32t, t_dec(l,s), sb_data, w); #endif #endif #ifdef IM1_SET d_1(aes_32t, t_dec(i,m), mm_data, v); #endif #ifdef IM4_SET d_4(aes_32t, t_dec(i,m), mm_data, v); #endif #endif irrlicht-1.8.3/source/Irrlicht/aesGladman/aeskey.cpp0000644000000000000000000003553112574354552021165 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2003, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 This file contains the code for implementing the key schedule for AES (Rijndael) for block and key sizes of 16, 24, and 32 bytes. See aesopt.h for further details including optimisation. */ #include "aesopt.h" /* Initialise the key schedule from the user supplied key. The key length can be specified in bytes, with legal values of 16, 24 and 32, or in bits, with legal values of 128, 192 and 256. These values correspond with Nk values of 4, 6 and 8 respectively. The following macros implement a single cycle in the key schedule generation process. The number of cycles needed for each cx->n_col and nk value is: nk = 4 5 6 7 8 ------------------------------ cx->n_col = 4 10 9 8 7 7 cx->n_col = 5 14 11 10 9 9 cx->n_col = 6 19 15 12 11 11 cx->n_col = 7 21 19 16 13 14 cx->n_col = 8 29 23 19 17 14 */ #define ke4(k,i) \ { k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \ k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \ } #define kel4(k,i) \ { k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \ k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \ } #define ke6(k,i) \ { k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \ k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \ k[6*(i)+10] = ss[4] ^= ss[3]; k[6*(i)+11] = ss[5] ^= ss[4]; \ } #define kel6(k,i) \ { k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \ k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \ } #define ke8(k,i) \ { k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \ k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \ k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); k[8*(i)+13] = ss[5] ^= ss[4]; \ k[8*(i)+14] = ss[6] ^= ss[5]; k[8*(i)+15] = ss[7] ^= ss[6]; \ } #define kel8(k,i) \ { k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \ k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \ } #if defined(ENCRYPTION_KEY_SCHEDULE) #if defined(AES_128) || defined(AES_VAR) aes_rval aes_encrypt_key128(const void *in_key, aes_encrypt_ctx cx[1]) { aes_32t ss[4]; cx->ks[0] = ss[0] = word_in(in_key, 0); cx->ks[1] = ss[1] = word_in(in_key, 1); cx->ks[2] = ss[2] = word_in(in_key, 2); cx->ks[3] = ss[3] = word_in(in_key, 3); #if ENC_UNROLL == NONE { aes_32t i; for(i = 0; i < ((11 * N_COLS - 1) / 4); ++i) ke4(cx->ks, i); } #else ke4(cx->ks, 0); ke4(cx->ks, 1); ke4(cx->ks, 2); ke4(cx->ks, 3); ke4(cx->ks, 4); ke4(cx->ks, 5); ke4(cx->ks, 6); ke4(cx->ks, 7); ke4(cx->ks, 8); kel4(cx->ks, 9); #endif /* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */ /* key and must be non-zero for 128 and 192 bits keys */ cx->ks[53] = cx->ks[45] = 0; cx->ks[52] = 10; #ifdef AES_ERR_CHK return aes_good; #endif } #endif #if defined(AES_192) || defined(AES_VAR) aes_rval aes_encrypt_key192(const void *in_key, aes_encrypt_ctx cx[1]) { aes_32t ss[6]; cx->ks[0] = ss[0] = word_in(in_key, 0); cx->ks[1] = ss[1] = word_in(in_key, 1); cx->ks[2] = ss[2] = word_in(in_key, 2); cx->ks[3] = ss[3] = word_in(in_key, 3); cx->ks[4] = ss[4] = word_in(in_key, 4); cx->ks[5] = ss[5] = word_in(in_key, 5); #if ENC_UNROLL == NONE { aes_32t i; for(i = 0; i < (13 * N_COLS - 1) / 6; ++i) ke6(cx->ks, i); } #else ke6(cx->ks, 0); ke6(cx->ks, 1); ke6(cx->ks, 2); ke6(cx->ks, 3); ke6(cx->ks, 4); ke6(cx->ks, 5); ke6(cx->ks, 6); kel6(cx->ks, 7); #endif /* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */ /* key and must be non-zero for 128 and 192 bits keys */ cx->ks[53] = cx->ks[45]; cx->ks[52] = 12; #ifdef AES_ERR_CHK return aes_good; #endif } #endif #if defined(AES_256) || defined(AES_VAR) aes_rval aes_encrypt_key256(const void *in_key, aes_encrypt_ctx cx[1]) { aes_32t ss[8]; cx->ks[0] = ss[0] = word_in(in_key, 0); cx->ks[1] = ss[1] = word_in(in_key, 1); cx->ks[2] = ss[2] = word_in(in_key, 2); cx->ks[3] = ss[3] = word_in(in_key, 3); cx->ks[4] = ss[4] = word_in(in_key, 4); cx->ks[5] = ss[5] = word_in(in_key, 5); cx->ks[6] = ss[6] = word_in(in_key, 6); cx->ks[7] = ss[7] = word_in(in_key, 7); #if ENC_UNROLL == NONE { aes_32t i; for(i = 0; i < (15 * N_COLS - 1) / 8; ++i) ke8(cx->ks, i); } #else ke8(cx->ks, 0); ke8(cx->ks, 1); ke8(cx->ks, 2); ke8(cx->ks, 3); ke8(cx->ks, 4); ke8(cx->ks, 5); kel8(cx->ks, 6); #endif #ifdef AES_ERR_CHK return aes_good; #endif } #endif #if defined(AES_VAR) aes_rval aes_encrypt_key(const void *in_key, int key_len, aes_encrypt_ctx cx[1]) { switch(key_len) { #ifdef AES_ERR_CHK case 16: case 128: return aes_encrypt_key128(in_key, cx); case 24: case 192: return aes_encrypt_key192(in_key, cx); case 32: case 256: return aes_encrypt_key256(in_key, cx); default: return aes_error; #else case 16: case 128: aes_encrypt_key128(in_key, cx); return; case 24: case 192: aes_encrypt_key192(in_key, cx); return; case 32: case 256: aes_encrypt_key256(in_key, cx); return; #endif } } #endif #endif #if defined(DECRYPTION_KEY_SCHEDULE) #if DEC_ROUND == NO_TABLES #define ff(x) (x) #else #define ff(x) inv_mcol(x) #ifdef dec_imvars #define d_vars dec_imvars #endif #endif #if 1 #define kdf4(k,i) \ { ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; ss[1] = ss[1] ^ ss[3]; ss[2] = ss[2] ^ ss[3]; ss[3] = ss[3]; \ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \ ss[4] ^= k[4*(i)]; k[4*(i)+4] = ff(ss[4]); ss[4] ^= k[4*(i)+1]; k[4*(i)+5] = ff(ss[4]); \ ss[4] ^= k[4*(i)+2]; k[4*(i)+6] = ff(ss[4]); ss[4] ^= k[4*(i)+3]; k[4*(i)+7] = ff(ss[4]); \ } #define kd4(k,i) \ { ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ k[4*(i)+4] = ss[4] ^= k[4*(i)]; k[4*(i)+5] = ss[4] ^= k[4*(i)+1]; \ k[4*(i)+6] = ss[4] ^= k[4*(i)+2]; k[4*(i)+7] = ss[4] ^= k[4*(i)+3]; \ } #define kdl4(k,i) \ { ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \ k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; k[4*(i)+5] = ss[1] ^ ss[3]; \ k[4*(i)+6] = ss[0]; k[4*(i)+7] = ss[1]; \ } #else #define kdf4(k,i) \ { ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+ 4] = ff(ss[0]); ss[1] ^= ss[0]; k[4*(i)+ 5] = ff(ss[1]); \ ss[2] ^= ss[1]; k[4*(i)+ 6] = ff(ss[2]); ss[3] ^= ss[2]; k[4*(i)+ 7] = ff(ss[3]); \ } #define kd4(k,i) \ { ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \ ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[4*(i)+ 4] = ss[4] ^= k[4*(i)]; \ ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[4] ^= k[4*(i)+ 1]; \ ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[4] ^= k[4*(i)+ 2]; \ ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[4] ^= k[4*(i)+ 3]; \ } #define kdl4(k,i) \ { ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+ 4] = ss[0]; ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[1]; \ ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[2]; ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[3]; \ } #endif #define kdf6(k,i) \ { ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 6] = ff(ss[0]); ss[1] ^= ss[0]; k[6*(i)+ 7] = ff(ss[1]); \ ss[2] ^= ss[1]; k[6*(i)+ 8] = ff(ss[2]); ss[3] ^= ss[2]; k[6*(i)+ 9] = ff(ss[3]); \ ss[4] ^= ss[3]; k[6*(i)+10] = ff(ss[4]); ss[5] ^= ss[4]; k[6*(i)+11] = ff(ss[5]); \ } #define kd6(k,i) \ { ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \ ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[6*(i)+ 6] = ss[6] ^= k[6*(i)]; \ ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1]; \ ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2]; \ ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3]; \ ss[4] ^= ss[3]; k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4]; \ ss[5] ^= ss[4]; k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5]; \ } #define kdl6(k,i) \ { ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 6] = ss[0]; ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[1]; \ ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[2]; ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[3]; \ } #define kdf8(k,i) \ { ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 8] = ff(ss[0]); ss[1] ^= ss[0]; k[8*(i)+ 9] = ff(ss[1]); \ ss[2] ^= ss[1]; k[8*(i)+10] = ff(ss[2]); ss[3] ^= ss[2]; k[8*(i)+11] = ff(ss[3]); \ ss[4] ^= ls_box(ss[3],0); k[8*(i)+12] = ff(ss[4]); ss[5] ^= ss[4]; k[8*(i)+13] = ff(ss[5]); \ ss[6] ^= ss[5]; k[8*(i)+14] = ff(ss[6]); ss[7] ^= ss[6]; k[8*(i)+15] = ff(ss[7]); \ } #define kd8(k,i) \ { aes_32t g = ls_box(ss[7],3) ^ t_use(r,c)[i]; \ ss[0] ^= g; g = ff(g); k[8*(i)+ 8] = g ^= k[8*(i)]; \ ss[1] ^= ss[0]; k[8*(i)+ 9] = g ^= k[8*(i)+ 1]; \ ss[2] ^= ss[1]; k[8*(i)+10] = g ^= k[8*(i)+ 2]; \ ss[3] ^= ss[2]; k[8*(i)+11] = g ^= k[8*(i)+ 3]; \ g = ls_box(ss[3],0); \ ss[4] ^= g; g = ff(g); k[8*(i)+12] = g ^= k[8*(i)+ 4]; \ ss[5] ^= ss[4]; k[8*(i)+13] = g ^= k[8*(i)+ 5]; \ ss[6] ^= ss[5]; k[8*(i)+14] = g ^= k[8*(i)+ 6]; \ ss[7] ^= ss[6]; k[8*(i)+15] = g ^= k[8*(i)+ 7]; \ } #define kdl8(k,i) \ { ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 8] = ss[0]; ss[1] ^= ss[0]; k[8*(i)+ 9] = ss[1]; \ ss[2] ^= ss[1]; k[8*(i)+10] = ss[2]; ss[3] ^= ss[2]; k[8*(i)+11] = ss[3]; \ } #if defined(AES_128) || defined(AES_VAR) aes_rval aes_decrypt_key128(const void *in_key, aes_decrypt_ctx cx[1]) { aes_32t ss[5]; #ifdef d_vars d_vars; #endif cx->ks[0] = ss[0] = word_in(in_key, 0); cx->ks[1] = ss[1] = word_in(in_key, 1); cx->ks[2] = ss[2] = word_in(in_key, 2); cx->ks[3] = ss[3] = word_in(in_key, 3); #if DEC_UNROLL == NONE { aes_32t i; for(i = 0; i < (11 * N_COLS - 1) / 4; ++i) ke4(cx->ks, i); #if !(DEC_ROUND == NO_TABLES) for(i = N_COLS; i < 10 * N_COLS; ++i) cx->ks[i] = inv_mcol(cx->ks[i]); #endif } #else kdf4(cx->ks, 0); kd4(cx->ks, 1); kd4(cx->ks, 2); kd4(cx->ks, 3); kd4(cx->ks, 4); kd4(cx->ks, 5); kd4(cx->ks, 6); kd4(cx->ks, 7); kd4(cx->ks, 8); kdl4(cx->ks, 9); #endif /* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */ /* key and must be non-zero for 128 and 192 bits keys */ cx->ks[53] = cx->ks[45] = 0; cx->ks[52] = 10; #ifdef AES_ERR_CHK return aes_good; #endif } #endif #if defined(AES_192) || defined(AES_VAR) aes_rval aes_decrypt_key192(const void *in_key, aes_decrypt_ctx cx[1]) { aes_32t ss[7]; #ifdef d_vars d_vars; #endif cx->ks[0] = ss[0] = word_in(in_key, 0); cx->ks[1] = ss[1] = word_in(in_key, 1); cx->ks[2] = ss[2] = word_in(in_key, 2); cx->ks[3] = ss[3] = word_in(in_key, 3); #if DEC_UNROLL == NONE cx->ks[4] = ss[4] = word_in(in_key, 4); cx->ks[5] = ss[5] = word_in(in_key, 5); { aes_32t i; for(i = 0; i < (13 * N_COLS - 1) / 6; ++i) ke6(cx->ks, i); #if !(DEC_ROUND == NO_TABLES) for(i = N_COLS; i < 12 * N_COLS; ++i) cx->ks[i] = inv_mcol(cx->ks[i]); #endif } #else cx->ks[4] = ff(ss[4] = word_in(in_key, 4)); cx->ks[5] = ff(ss[5] = word_in(in_key, 5)); kdf6(cx->ks, 0); kd6(cx->ks, 1); kd6(cx->ks, 2); kd6(cx->ks, 3); kd6(cx->ks, 4); kd6(cx->ks, 5); kd6(cx->ks, 6); kdl6(cx->ks, 7); #endif /* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */ /* key and must be non-zero for 128 and 192 bits keys */ cx->ks[53] = cx->ks[45]; cx->ks[52] = 12; #ifdef AES_ERR_CHK return aes_good; #endif } #endif #if defined(AES_256) || defined(AES_VAR) aes_rval aes_decrypt_key256(const void *in_key, aes_decrypt_ctx cx[1]) { aes_32t ss[8]; #ifdef d_vars d_vars; #endif cx->ks[0] = ss[0] = word_in(in_key, 0); cx->ks[1] = ss[1] = word_in(in_key, 1); cx->ks[2] = ss[2] = word_in(in_key, 2); cx->ks[3] = ss[3] = word_in(in_key, 3); #if DEC_UNROLL == NONE cx->ks[4] = ss[4] = word_in(in_key, 4); cx->ks[5] = ss[5] = word_in(in_key, 5); cx->ks[6] = ss[6] = word_in(in_key, 6); cx->ks[7] = ss[7] = word_in(in_key, 7); { aes_32t i; for(i = 0; i < (15 * N_COLS - 1) / 8; ++i) ke8(cx->ks, i); #if !(DEC_ROUND == NO_TABLES) for(i = N_COLS; i < 14 * N_COLS; ++i) cx->ks[i] = inv_mcol(cx->ks[i]); #endif } #else cx->ks[4] = ff(ss[4] = word_in(in_key, 4)); cx->ks[5] = ff(ss[5] = word_in(in_key, 5)); cx->ks[6] = ff(ss[6] = word_in(in_key, 6)); cx->ks[7] = ff(ss[7] = word_in(in_key, 7)); kdf8(cx->ks, 0); kd8(cx->ks, 1); kd8(cx->ks, 2); kd8(cx->ks, 3); kd8(cx->ks, 4); kd8(cx->ks, 5); kdl8(cx->ks, 6); #endif #ifdef AES_ERR_CHK return aes_good; #endif } #endif #if defined(AES_VAR) aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1]) { switch(key_len) { #ifdef AES_ERR_CHK case 16: case 128: return aes_decrypt_key128(in_key, cx); case 24: case 192: return aes_decrypt_key192(in_key, cx); case 32: case 256: return aes_decrypt_key256(in_key, cx); default: return aes_error; #else case 16: case 128: aes_decrypt_key128(in_key, cx); return; case 24: case 192: aes_decrypt_key192(in_key, cx); return; case 32: case 256: aes_decrypt_key256(in_key, cx); return; #endif } } #endif #endif irrlicht-1.8.3/source/Irrlicht/aesGladman/aescrypt.cpp0000644000000000000000000002434012574354552021532 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2003, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 This file contains the code for implementing encryption and decryption for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It can optionally be replaced by code written in assembler using NASM. For further details see the file aesopt.h */ #include "aesopt.h" #define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c]) #define so(y,x,c) word_out(y, c, s(x,c)) #if defined(ARRAYS) #define locals(y,x) x[4],y[4] #else #define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 #endif #define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ s(y,2) = s(x,2); s(y,3) = s(x,3); #define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) #define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) #define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) #if defined(ENCRYPTION) && !defined(AES_ASM) /* Visual C++ .Net v7.1 provides the fastest encryption code when using Pentium optimization with small code but this is poor for decryption so we need to control this with the following VC++ pragmas */ #if defined(_MSC_VER) #pragma optimize( "s", on ) #endif /* Given the column (c) of the output state variable, the following macros give the input state variables which are needed in its computation for each row (r) of the state. All the alternative macros give the same end values but expand into different ways of calculating these values. In particular the complex macro used for dynamically variable block sizes is designed to expand to a compile time constant whenever possible but will expand to conditional clauses on some branches (I am grateful to Frank Yellin for this construction) */ #define fwd_var(x,r,c)\ ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\ : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) #if defined(FT4_SET) #undef dec_fmvars #define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) #elif defined(FT1_SET) #undef dec_fmvars #define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c)) #else #define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c))) #endif #if defined(FL4_SET) #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c)) #elif defined(FL1_SET) #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c)) #else #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c)) #endif aes_rval aes_encrypt(const void *in_blk, void *out_blk, const aes_encrypt_ctx cx[1]) { aes_32t locals(b0, b1); const aes_32t *kp = cx->ks; #ifdef dec_fmvars dec_fmvars; /* declare variables for fwd_mcol() if needed */ #endif aes_32t nr = (kp[45] ^ kp[52] ^ kp[53] ? kp[52] : 14); #ifdef AES_ERR_CHK if( (nr != 10 || !(kp[0] | kp[3] | kp[4])) && (nr != 12 || !(kp[0] | kp[5] | kp[6])) && (nr != 14 || !(kp[0] | kp[7] | kp[8])) ) return aes_error; #endif state_in(b0, in_blk, kp); #if (ENC_UNROLL == FULL) switch(nr) { case 14: round(fwd_rnd, b1, b0, kp + 1 * N_COLS); round(fwd_rnd, b0, b1, kp + 2 * N_COLS); kp += 2 * N_COLS; case 12: round(fwd_rnd, b1, b0, kp + 1 * N_COLS); round(fwd_rnd, b0, b1, kp + 2 * N_COLS); kp += 2 * N_COLS; case 10: round(fwd_rnd, b1, b0, kp + 1 * N_COLS); round(fwd_rnd, b0, b1, kp + 2 * N_COLS); round(fwd_rnd, b1, b0, kp + 3 * N_COLS); round(fwd_rnd, b0, b1, kp + 4 * N_COLS); round(fwd_rnd, b1, b0, kp + 5 * N_COLS); round(fwd_rnd, b0, b1, kp + 6 * N_COLS); round(fwd_rnd, b1, b0, kp + 7 * N_COLS); round(fwd_rnd, b0, b1, kp + 8 * N_COLS); round(fwd_rnd, b1, b0, kp + 9 * N_COLS); round(fwd_lrnd, b0, b1, kp +10 * N_COLS); } #else #if (ENC_UNROLL == PARTIAL) { aes_32t rnd; for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd) { kp += N_COLS; round(fwd_rnd, b1, b0, kp); kp += N_COLS; round(fwd_rnd, b0, b1, kp); } kp += N_COLS; round(fwd_rnd, b1, b0, kp); #else { aes_32t rnd; for(rnd = 0; rnd < nr - 1; ++rnd) { kp += N_COLS; round(fwd_rnd, b1, b0, kp); l_copy(b0, b1); } #endif kp += N_COLS; round(fwd_lrnd, b0, b1, kp); } #endif state_out(out_blk, b0); #ifdef AES_ERR_CHK return aes_good; #endif } #endif #if defined(DECRYPTION) && !defined(AES_ASM) /* Visual C++ .Net v7.1 provides the fastest encryption code when using Pentium optimization with small code but this is poor for decryption so we need to control this with the following VC++ pragmas */ #if defined(_MSC_VER) #pragma optimize( "t", on ) #endif /* Given the column (c) of the output state variable, the following macros give the input state variables which are needed in its computation for each row (r) of the state. All the alternative macros give the same end values but expand into different ways of calculating these values. In particular the complex macro used for dynamically variable block sizes is designed to expand to a compile time constant whenever possible but will expand to conditional clauses on some branches (I am grateful to Frank Yellin for this construction) */ #define inv_var(x,r,c)\ ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\ : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))) #if defined(IT4_SET) #undef dec_imvars #define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c)) #elif defined(IT1_SET) #undef dec_imvars #define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c)) #else #define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))) #endif #if defined(IL4_SET) #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c)) #elif defined(IL1_SET) #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c)) #else #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)) #endif aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx[1]) { aes_32t locals(b0, b1); #ifdef dec_imvars dec_imvars; /* declare variables for inv_mcol() if needed */ #endif aes_32t nr = (cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] ? cx->ks[52] : 14); const aes_32t *kp = cx->ks + nr * N_COLS; #ifdef AES_ERR_CHK if( (nr != 10 || !(cx->ks[0] | cx->ks[3] | cx->ks[4])) && (nr != 12 || !(cx->ks[0] | cx->ks[5] | cx->ks[6])) && (nr != 14 || !(cx->ks[0] | cx->ks[7] | cx->ks[8])) ) return aes_error; #endif state_in(b0, in_blk, kp); #if (DEC_UNROLL == FULL) switch(nr) { case 14: round(inv_rnd, b1, b0, kp - 1 * N_COLS); round(inv_rnd, b0, b1, kp - 2 * N_COLS); kp -= 2 * N_COLS; case 12: round(inv_rnd, b1, b0, kp - 1 * N_COLS); round(inv_rnd, b0, b1, kp - 2 * N_COLS); kp -= 2 * N_COLS; case 10: round(inv_rnd, b1, b0, kp - 1 * N_COLS); round(inv_rnd, b0, b1, kp - 2 * N_COLS); round(inv_rnd, b1, b0, kp - 3 * N_COLS); round(inv_rnd, b0, b1, kp - 4 * N_COLS); round(inv_rnd, b1, b0, kp - 5 * N_COLS); round(inv_rnd, b0, b1, kp - 6 * N_COLS); round(inv_rnd, b1, b0, kp - 7 * N_COLS); round(inv_rnd, b0, b1, kp - 8 * N_COLS); round(inv_rnd, b1, b0, kp - 9 * N_COLS); round(inv_lrnd, b0, b1, kp - 10 * N_COLS); } #else #if (DEC_UNROLL == PARTIAL) { aes_32t rnd; for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd) { kp -= N_COLS; round(inv_rnd, b1, b0, kp); kp -= N_COLS; round(inv_rnd, b0, b1, kp); } kp -= N_COLS; round(inv_rnd, b1, b0, kp); #else { aes_32t rnd; for(rnd = 0; rnd < nr - 1; ++rnd) { kp -= N_COLS; round(inv_rnd, b1, b0, kp); l_copy(b0, b1); } #endif kp -= N_COLS; round(inv_lrnd, b0, b1, kp); } #endif state_out(out_blk, b0); #ifdef AES_ERR_CHK return aes_good; #endif } #endif irrlicht-1.8.3/source/Irrlicht/aesGladman/aes.h0000644000000000000000000001044712574354552020120 0ustar rootroot/* --------------------------------------------------------------------------- Copyright (c) 2003, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- Issue Date: 26/08/2003 This file contains the definitions required to use AES in C. See aesopt.h for optimisation details. */ #ifndef _AES_H #define _AES_H #include "irrMath.h" #define AES_128 /* define if AES with 128 bit keys is needed */ #define AES_192 /* define if AES with 192 bit keys is needed */ #define AES_256 /* define if AES with 256 bit keys is needed */ #define AES_VAR /* define if a variable key size is needed */ /* The following must also be set in assembler files if being used */ #define AES_ENCRYPT /* if support for encryption is needed */ #define AES_DECRYPT /* if support for decryption is needed */ #define AES_ERR_CHK /* for parameter checks & error return codes */ typedef irr::u8 aes_08t; typedef irr::u32 aes_32t; #define AES_BLOCK_SIZE 16 /* the AES block size in bytes */ #define N_COLS 4 /* the number of columns in the state */ /* a maximum of 60 32-bit words are needed for the key schedule */ #define KS_LENGTH 64 #ifdef AES_ERR_CHK #define aes_ret int #define aes_good 0 #define aes_error -1 #else #define aes_ret void #endif #ifndef AES_DLL /* implement normal/DLL functions */ #define aes_rval aes_ret #else #define aes_rval aes_ret __declspec(dllexport) _stdcall #endif /* This routine must be called before first use if non-static */ /* tables are being used */ void gen_tabs(void); /* The key length (klen) is input in bytes when it is in the range */ /* 16 <= klen <= 32 or in bits when in the range 128 <= klen <= 256 */ #ifdef AES_ENCRYPT typedef struct { aes_32t ks[KS_LENGTH]; } aes_encrypt_ctx; #if defined(AES_128) || defined(AES_VAR) aes_rval aes_encrypt_key128(const void *in_key, aes_encrypt_ctx cx[1]); #endif #if defined(AES_192) || defined(AES_VAR) aes_rval aes_encrypt_key192(const void *in_key, aes_encrypt_ctx cx[1]); #endif #if defined(AES_256) || defined(AES_VAR) aes_rval aes_encrypt_key256(const void *in_key, aes_encrypt_ctx cx[1]); #endif #if defined(AES_VAR) aes_rval aes_encrypt_key(const void *in_key, int key_len, aes_encrypt_ctx cx[1]); #endif aes_rval aes_encrypt(const void *in_blk, void *out_blk, const aes_encrypt_ctx cx[1]); #endif #ifdef AES_DECRYPT typedef struct { aes_32t ks[KS_LENGTH]; } aes_decrypt_ctx; #if defined(AES_128) || defined(AES_VAR) aes_rval aes_decrypt_key128(const void *in_key, aes_decrypt_ctx cx[1]); #endif #if defined(AES_192) || defined(AES_VAR) aes_rval aes_decrypt_key192(const void *in_key, aes_decrypt_ctx cx[1]); #endif #if defined(AES_256) || defined(AES_VAR) aes_rval aes_decrypt_key256(const void *in_key, aes_decrypt_ctx cx[1]); #endif #if defined(AES_VAR) aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1]); #endif aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx[1]); #endif #endif irrlicht-1.8.3/readme.txt0000644000000000000000000002603512574354552014061 0ustar rootroot========================================================================== The Irrlicht Engine SDK version 1.8.3 ========================================================================== Welcome the Irrlicht Engine SDK. Content of this file: 1. Directory Structure Overview 2. How To Start 3. Requirements 4. Release Notes 5. License 6. Contact ========================================================================== 1. Directory Structure Overview ========================================================================== You will find some directories after uncompressing the archive of the SDK. These are: \bin The compiled library Irrlicht.DLL and some compiled demo and example applications, just start them to see the Irrlicht Engine in action. Windows only. \doc Documentation of the Irrlicht Engine. \examples Examples and tutorials showing how to use the engine with C++. \include Header files to include when programming with the engine. \lib Libs to link with your programs when using the engine. \media Graphics and sound resources for the demo applications and examples. \source The source code of the Irrlicht Engine. This code is not needed to develop applications with the engine, but it is included to enable recompilation and debugging, if necessary. \tools Useful tools (with sourcecode) for the engine. ========================================================================== 2. How to start ========================================================================== To see the engine in action in Windows, just go to the \bin\Win32-VisualStudio directory, and start some applications. There should also be an application named Demo.exe which should show the most interesting features of Irrlicht. To start developing own applications and games with the engine take a look at the 01.HelloWorld example in the \examples directory. There is also a .html file with a tutorial which should be easily comprehensible. The Irrlicht Engine is a static lib under linux. A precompiled version can be generated from the sources using the Makefile in source/Irrlicht. Run 'make' in that subfolder. After this you should be able to 'make' all example applications in /examples by calling the buildAllExamples script. You can run the examples then from the bin folder. It is also possible to use Irrlicht as shared object (libIrrlicht.so.versionNumber). Use the proper makefile target for this by running 'make sharedlib' in the source folder. See the Makefile for details. For OSX you can find an XCode project file in source/Irrlicht/MacOSX. This will build the libIrrlicht.a library necessary to create the apps. ========================================================================== 3. Requirements ========================================================================== You can use one of the following compilers/IDEs to develop applications with Irrlicht or recompile the engine. However, other compilers/IDEs may work as well, we simply didn't test them. * gcc 4.x * Visual Studio 2008(9.0)-2012(11.0) * Code::Blocks (& gcc or visual studio toolkit) If you ever want to (re)compile the engine yourself (which means you don't want to use the precompiled version) you need the following: * Windows: * Needed: PlatformSDK (which usually comes with all IDEs, download it separately for MSVC Express 2005) * Optional: DirectX SDK, for D3D9 support * Optional: DirectX SDK prior to May 2006, for D3D8 support * Linux: * Needed: XServer with include files * Optional: OpenGL headers and libraries (libGL.so) for OpenGL support GLX + XF86VidMode [package x11proto-xf86vidmode-dev] or XRandr (X11 support libraries, the latter two for fullscreen mode) * OSX: * Needed: XCode and Cocoa framework * Needed: OpenGL headers and libraries ========================================================================== 4. Release Notes ========================================================================== Informations about changes in this new version of the engine can be found in changes.txt. Please note that the textures, 3D models and levels are copyright by their authors and not covered by the Irrlicht engine license. ========================================================================== 5. License ========================================================================== The license of the Irrlicht Engine is based on the zlib/libpng license. Even though this license does not require you to mention that you are using the Irrlicht Engine in your product, an acknowledgement would be highly appreciated. Please note that the Irrlicht Engine is based in part on the work of the Independent JPEG Group, the zlib, and libpng. This means that if you use the Irrlicht Engine in your product, you must acknowledge somewhere in your documentation that you've used the IJG code and libpng. It would also be nice to mention that you use the Irrlicht Engine and the zlib. See the README files in the jpeglib and the zlib for further informations. The Irrlicht Engine License =========================== Copyright (C) 2002-2015 Nikolaus Gebhardt This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgement in the product documentation would be appreciated but is not required. 2. Altered source versions must be clearly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. ========================================================================== 6. Contact ========================================================================== If you have problems, questions or suggestions, please visit the official homepage of the Irrlicht Engine: http://irrlicht.sourceforge.net You will find forums, bugtrackers, patches, tutorials, and other stuff which will help you out. If want to contact the team of the engine, please send an email to Nikolaus Gebhardt: irrlicht@users.sourceforge.net Please also not that parts of the engine have been written or contributed by other people. Especially: (There are probably more people, sorry if I forgot one. See http://irrlicht.sourceforge.net/author.html for more informations) Christian Stehno (hybrid) Contribution Coordinator/Developer Michael Zeilfelder (cutealien) GUI Developer Patryk Nadrowski (Nadro) Developer Yoran Bosman (Yoran) Webserver administrator Gareth Davidson (bitplane) Developer/ Forum admin Thomas Alten (burningwater) Wrote the burningsvideo software rasterizer Luke P. Hoschke (luke) Wrote the b3d loader, the new animation system, VBOs and other things Colin MacDonald (rogerborg) All hands person Ahmed Hilali (blindside) The shader and advanced effects man Dean Wadsworth (varmint) OSX port maintainer and game developer Alvaro F. Celis (afecelis) Lots of work in the community, for example video tutorials about Irrlicht, forum admin John Goewert (Saigumi) Wrote some tutorials for the Irrlicht Engine and doing admin stuff Jam Takes care of moderating the forums and keeps them clean from those evil spammers. Many others (this list hasn't been updated in a while, but they are often mentioned in changes.txt) Etienne Petitjean wrote the MacPort of the engine Mark Jeacocke Wrote lots of helpful comments and ideas in the forums and per email. Julio Gorgé Created the 'Unofficial DirectX 9.0 Driver for the Irrlicht Engine' Andy Spurgeon Wrote the Dev-Cpp tutorial. André Simon Wrote the Codewarrior tutorial. KnightToFlight Created the unoffical terrain renderer addon for the Irrlicht Engine. Jon Pry Wrote the code to load compressed TGA files. Matthew Couch Wrote the tokamak integration tutorial. Max Winkel Wrote the splitscreen tutorial. Gorgon Zola Wrote the ODE integration tutorial. Dean P. Macri Sent in code for curved surfaces and PCX Loading. Sirshane Made several bug fixes, sent in code for making the mouse cursor invisible in Linux. Matthias Gall Sent in code for a spline scene node animator and reported lots of bugs. Mario Gruber Suggested triangle fan drawing and sent in code for this. Ariaci Spotted out a bug in the ATI driver. Dr Andros C Bragianos Improved texture mapping in cube scene node. Philipp Dortmann Sent in code for stencil buffer support for OpenGL. Jerome Nichols Created the Irrlicht/Ruby interface located at irr.rubyforge.org Vash TheStampede Sent code for missing Draw2DLine() implementations MattyBoy XBOX support suggestions Oliver Klems createImageFromData() method suggestion/implementation Jox really, really a lot of bug fixes, and the LMTS file loader Zola Quaternion method additions Tomasz Nowakowski various bug fixes Nicholas Bray stencil shadow bug fixes with OpenGL REAPER mouswheel events for scrollbar Calimero various bug fixes like vector2d operators Haddock bugfix in the linked list G.o.D XML parser fix Erik Zilli Translated some of the tutorials from my stuttering english into real english. :) Martin Piskernig Linux bugfixing and testing Soconne Wrote the original terrain renderer were Irrlichts terrain renderer of Irrlicht is based on it. Spintz GeoMipMap scene node, terrain renderer of Irrlicht is based on it. Murphy McCauley OCT file loader, MIM tools Saurav Mohapatra IrrCSM, and lots of addons, suggestions and bug reports Zhuck Dimitry My3D Tools Terry Welsh Allowed me to use the textures of his 'Parallax Mapping with Offset Limiting' paper for the parallax demo of Irrlicht rt Wrote the original .png loader for Irrlicht Salvatore Russo Wrote the original .dmf loader for Irrlicht Vox Various bug reports and fixes atomice Contributed code for a ms3d loader enhancement William Finlayson OpenGL RTT, GLSL support and the reflection 2 layer material for OpenGL. Delight Various code contributions for Irrlicht.NET (particle system, basic shader support and more) Michael Zoech Improved GLSL support Jean-loup Gailly, Mark Adler Created the zlib and libpng Guy Eric Schalnat, Andreas Dilger, Glenn Randers-Pehrson and others Created libpng The Independent JPEG Group Created JPEG lib Dr Brian Gladman AES Created aesGladman irrlicht-1.8.3/include/0000755000000000000000000000000012574354552013500 5ustar rootrootirrlicht-1.8.3/include/vector3d.h0000644000000000000000000004141312574354552015405 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_POINT_3D_H_INCLUDED__ #define __IRR_POINT_3D_H_INCLUDED__ #include "irrMath.h" namespace irr { namespace core { //! 3d vector template class with lots of operators and methods. /** The vector3d class is used in Irrlicht for three main purposes: 1) As a direction vector (most of the methods assume this). 2) As a position in 3d space (which is synonymous with a direction vector from the origin to this position). 3) To hold three Euler rotations, where X is pitch, Y is yaw and Z is roll. */ template class vector3d { public: //! Default constructor (null vector). vector3d() : X(0), Y(0), Z(0) {} //! Constructor with three different values vector3d(T nx, T ny, T nz) : X(nx), Y(ny), Z(nz) {} //! Constructor with the same value for all elements explicit vector3d(T n) : X(n), Y(n), Z(n) {} //! Copy constructor vector3d(const vector3d& other) : X(other.X), Y(other.Y), Z(other.Z) {} // operators vector3d operator-() const { return vector3d(-X, -Y, -Z); } vector3d& operator=(const vector3d& other) { X = other.X; Y = other.Y; Z = other.Z; return *this; } vector3d operator+(const vector3d& other) const { return vector3d(X + other.X, Y + other.Y, Z + other.Z); } vector3d& operator+=(const vector3d& other) { X+=other.X; Y+=other.Y; Z+=other.Z; return *this; } vector3d operator+(const T val) const { return vector3d(X + val, Y + val, Z + val); } vector3d& operator+=(const T val) { X+=val; Y+=val; Z+=val; return *this; } vector3d operator-(const vector3d& other) const { return vector3d(X - other.X, Y - other.Y, Z - other.Z); } vector3d& operator-=(const vector3d& other) { X-=other.X; Y-=other.Y; Z-=other.Z; return *this; } vector3d operator-(const T val) const { return vector3d(X - val, Y - val, Z - val); } vector3d& operator-=(const T val) { X-=val; Y-=val; Z-=val; return *this; } vector3d operator*(const vector3d& other) const { return vector3d(X * other.X, Y * other.Y, Z * other.Z); } vector3d& operator*=(const vector3d& other) { X*=other.X; Y*=other.Y; Z*=other.Z; return *this; } vector3d operator*(const T v) const { return vector3d(X * v, Y * v, Z * v); } vector3d& operator*=(const T v) { X*=v; Y*=v; Z*=v; return *this; } vector3d operator/(const vector3d& other) const { return vector3d(X / other.X, Y / other.Y, Z / other.Z); } vector3d& operator/=(const vector3d& other) { X/=other.X; Y/=other.Y; Z/=other.Z; return *this; } vector3d operator/(const T v) const { T i=(T)1.0/v; return vector3d(X * i, Y * i, Z * i); } vector3d& operator/=(const T v) { T i=(T)1.0/v; X*=i; Y*=i; Z*=i; return *this; } //! sort in order X, Y, Z. Equality with rounding tolerance. bool operator<=(const vector3d&other) const { return (X=(const vector3d&other) const { return (X>other.X || core::equals(X, other.X)) || (core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y))) || (core::equals(X, other.X) && core::equals(Y, other.Y) && (Z>other.Z || core::equals(Z, other.Z))); } //! sort in order X, Y, Z. Difference must be above rounding tolerance. bool operator<(const vector3d&other) const { return (X(const vector3d&other) const { return (X>other.X && !core::equals(X, other.X)) || (core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y)) || (core::equals(X, other.X) && core::equals(Y, other.Y) && Z>other.Z && !core::equals(Z, other.Z)); } //! use weak float compare bool operator==(const vector3d& other) const { return this->equals(other); } bool operator!=(const vector3d& other) const { return !this->equals(other); } // functions //! returns if this vector equals the other one, taking floating point rounding errors into account bool equals(const vector3d& other, const T tolerance = (T)ROUNDING_ERROR_f32 ) const { return core::equals(X, other.X, tolerance) && core::equals(Y, other.Y, tolerance) && core::equals(Z, other.Z, tolerance); } vector3d& set(const T nx, const T ny, const T nz) {X=nx; Y=ny; Z=nz; return *this;} vector3d& set(const vector3d& p) {X=p.X; Y=p.Y; Z=p.Z;return *this;} //! Get length of the vector. T getLength() const { return core::squareroot( X*X + Y*Y + Z*Z ); } //! Get squared length of the vector. /** This is useful because it is much faster than getLength(). \return Squared length of the vector. */ T getLengthSQ() const { return X*X + Y*Y + Z*Z; } //! Get the dot product with another vector. T dotProduct(const vector3d& other) const { return X*other.X + Y*other.Y + Z*other.Z; } //! Get distance from another point. /** Here, the vector is interpreted as point in 3 dimensional space. */ T getDistanceFrom(const vector3d& other) const { return vector3d(X - other.X, Y - other.Y, Z - other.Z).getLength(); } //! Returns squared distance from another point. /** Here, the vector is interpreted as point in 3 dimensional space. */ T getDistanceFromSQ(const vector3d& other) const { return vector3d(X - other.X, Y - other.Y, Z - other.Z).getLengthSQ(); } //! Calculates the cross product with another vector. /** \param p Vector to multiply with. \return Crossproduct of this vector with p. */ vector3d crossProduct(const vector3d& p) const { return vector3d(Y * p.Z - Z * p.Y, Z * p.X - X * p.Z, X * p.Y - Y * p.X); } //! Returns if this vector interpreted as a point is on a line between two other points. /** It is assumed that the point is on the line. \param begin Beginning vector to compare between. \param end Ending vector to compare between. \return True if this vector is between begin and end, false if not. */ bool isBetweenPoints(const vector3d& begin, const vector3d& end) const { const T f = (end - begin).getLengthSQ(); return getDistanceFromSQ(begin) <= f && getDistanceFromSQ(end) <= f; } //! Normalizes the vector. /** In case of the 0 vector the result is still 0, otherwise the length of the vector will be 1. \return Reference to this vector after normalization. */ vector3d& normalize() { f64 length = X*X + Y*Y + Z*Z; if (length == 0 ) // this check isn't an optimization but prevents getting NAN in the sqrt. return *this; length = core::reciprocal_squareroot(length); X = (T)(X * length); Y = (T)(Y * length); Z = (T)(Z * length); return *this; } //! Sets the length of the vector to a new value vector3d& setLength(T newlength) { normalize(); return (*this *= newlength); } //! Inverts the vector. vector3d& invert() { X *= -1; Y *= -1; Z *= -1; return *this; } //! Rotates the vector by a specified number of degrees around the Y axis and the specified center. /** \param degrees Number of degrees to rotate around the Y axis. \param center The center of the rotation. */ void rotateXZBy(f64 degrees, const vector3d& center=vector3d()) { degrees *= DEGTORAD64; f64 cs = cos(degrees); f64 sn = sin(degrees); X -= center.X; Z -= center.Z; set((T)(X*cs - Z*sn), Y, (T)(X*sn + Z*cs)); X += center.X; Z += center.Z; } //! Rotates the vector by a specified number of degrees around the Z axis and the specified center. /** \param degrees: Number of degrees to rotate around the Z axis. \param center: The center of the rotation. */ void rotateXYBy(f64 degrees, const vector3d& center=vector3d()) { degrees *= DEGTORAD64; f64 cs = cos(degrees); f64 sn = sin(degrees); X -= center.X; Y -= center.Y; set((T)(X*cs - Y*sn), (T)(X*sn + Y*cs), Z); X += center.X; Y += center.Y; } //! Rotates the vector by a specified number of degrees around the X axis and the specified center. /** \param degrees: Number of degrees to rotate around the X axis. \param center: The center of the rotation. */ void rotateYZBy(f64 degrees, const vector3d& center=vector3d()) { degrees *= DEGTORAD64; f64 cs = cos(degrees); f64 sn = sin(degrees); Z -= center.Z; Y -= center.Y; set(X, (T)(Y*cs - Z*sn), (T)(Y*sn + Z*cs)); Z += center.Z; Y += center.Y; } //! Creates an interpolated vector between this vector and another vector. /** \param other The other vector to interpolate with. \param d Interpolation value between 0.0f (all the other vector) and 1.0f (all this vector). Note that this is the opposite direction of interpolation to getInterpolated_quadratic() \return An interpolated vector. This vector is not modified. */ vector3d getInterpolated(const vector3d& other, f64 d) const { const f64 inv = 1.0 - d; return vector3d((T)(other.X*inv + X*d), (T)(other.Y*inv + Y*d), (T)(other.Z*inv + Z*d)); } //! Creates a quadratically interpolated vector between this and two other vectors. /** \param v2 Second vector to interpolate with. \param v3 Third vector to interpolate with (maximum at 1.0f) \param d Interpolation value between 0.0f (all this vector) and 1.0f (all the 3rd vector). Note that this is the opposite direction of interpolation to getInterpolated() and interpolate() \return An interpolated vector. This vector is not modified. */ vector3d getInterpolated_quadratic(const vector3d& v2, const vector3d& v3, f64 d) const { // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d; const f64 inv = (T) 1.0 - d; const f64 mul0 = inv * inv; const f64 mul1 = (T) 2.0 * d * inv; const f64 mul2 = d * d; return vector3d ((T)(X * mul0 + v2.X * mul1 + v3.X * mul2), (T)(Y * mul0 + v2.Y * mul1 + v3.Y * mul2), (T)(Z * mul0 + v2.Z * mul1 + v3.Z * mul2)); } //! Sets this vector to the linearly interpolated vector between a and b. /** \param a first vector to interpolate with, maximum at 1.0f \param b second vector to interpolate with, maximum at 0.0f \param d Interpolation value between 0.0f (all vector b) and 1.0f (all vector a) Note that this is the opposite direction of interpolation to getInterpolated_quadratic() */ vector3d& interpolate(const vector3d& a, const vector3d& b, f64 d) { X = (T)((f64)b.X + ( ( a.X - b.X ) * d )); Y = (T)((f64)b.Y + ( ( a.Y - b.Y ) * d )); Z = (T)((f64)b.Z + ( ( a.Z - b.Z ) * d )); return *this; } //! Get the rotations that would make a (0,0,1) direction vector point in the same direction as this direction vector. /** Thanks to Arras on the Irrlicht forums for this method. This utility method is very useful for orienting scene nodes towards specific targets. For example, if this vector represents the difference between two scene nodes, then applying the result of getHorizontalAngle() to one scene node will point it at the other one. Example code: // Where target and seeker are of type ISceneNode* const vector3df toTarget(target->getAbsolutePosition() - seeker->getAbsolutePosition()); const vector3df requiredRotation = toTarget.getHorizontalAngle(); seeker->setRotation(requiredRotation); \return A rotation vector containing the X (pitch) and Y (raw) rotations (in degrees) that when applied to a +Z (e.g. 0, 0, 1) direction vector would make it point in the same direction as this vector. The Z (roll) rotation is always 0, since two Euler rotations are sufficient to point in any given direction. */ vector3d getHorizontalAngle() const { vector3d angle; const f64 tmp = (atan2((f64)X, (f64)Z) * RADTODEG64); angle.Y = (T)tmp; if (angle.Y < 0) angle.Y += 360; if (angle.Y >= 360) angle.Y -= 360; const f64 z1 = core::squareroot(X*X + Z*Z); angle.X = (T)(atan2((f64)z1, (f64)Y) * RADTODEG64 - 90.0); if (angle.X < 0) angle.X += 360; if (angle.X >= 360) angle.X -= 360; return angle; } //! Get the spherical coordinate angles /** This returns Euler degrees for the point represented by this vector. The calculation assumes the pole at (0,1,0) and returns the angles in X and Y. */ vector3d getSphericalCoordinateAngles() const { vector3d angle; const f64 length = X*X + Y*Y + Z*Z; if (length) { if (X!=0) { angle.Y = (T)(atan2((f64)Z,(f64)X) * RADTODEG64); } else if (Z<0) angle.Y=180; angle.X = (T)(acos(Y * core::reciprocal_squareroot(length)) * RADTODEG64); } return angle; } //! Builds a direction vector from (this) rotation vector. /** This vector is assumed to be a rotation vector composed of 3 Euler angle rotations, in degrees. The implementation performs the same calculations as using a matrix to do the rotation. \param[in] forwards The direction representing "forwards" which will be rotated by this vector. If you do not provide a direction, then the +Z axis (0, 0, 1) will be assumed to be forwards. \return A direction vector calculated by rotating the forwards direction by the 3 Euler angles (in degrees) represented by this vector. */ vector3d rotationToDirection(const vector3d & forwards = vector3d(0, 0, 1)) const { const f64 cr = cos( core::DEGTORAD64 * X ); const f64 sr = sin( core::DEGTORAD64 * X ); const f64 cp = cos( core::DEGTORAD64 * Y ); const f64 sp = sin( core::DEGTORAD64 * Y ); const f64 cy = cos( core::DEGTORAD64 * Z ); const f64 sy = sin( core::DEGTORAD64 * Z ); const f64 srsp = sr*sp; const f64 crsp = cr*sp; const f64 pseudoMatrix[] = { ( cp*cy ), ( cp*sy ), ( -sp ), ( srsp*cy-cr*sy ), ( srsp*sy+cr*cy ), ( sr*cp ), ( crsp*cy+sr*sy ), ( crsp*sy-sr*cy ), ( cr*cp )}; return vector3d( (T)(forwards.X * pseudoMatrix[0] + forwards.Y * pseudoMatrix[3] + forwards.Z * pseudoMatrix[6]), (T)(forwards.X * pseudoMatrix[1] + forwards.Y * pseudoMatrix[4] + forwards.Z * pseudoMatrix[7]), (T)(forwards.X * pseudoMatrix[2] + forwards.Y * pseudoMatrix[5] + forwards.Z * pseudoMatrix[8])); } //! Fills an array of 4 values with the vector data (usually floats). /** Useful for setting in shader constants for example. The fourth value will always be 0. */ void getAs4Values(T* array) const { array[0] = X; array[1] = Y; array[2] = Z; array[3] = 0; } //! Fills an array of 3 values with the vector data (usually floats). /** Useful for setting in shader constants for example.*/ void getAs3Values(T* array) const { array[0] = X; array[1] = Y; array[2] = Z; } //! X coordinate of the vector T X; //! Y coordinate of the vector T Y; //! Z coordinate of the vector T Z; }; //! partial specialization for integer vectors // Implementor note: inline keyword needed due to template specialization for s32. Otherwise put specialization into a .cpp template <> inline vector3d vector3d::operator /(s32 val) const {return core::vector3d(X/val,Y/val,Z/val);} template <> inline vector3d& vector3d::operator /=(s32 val) {X/=val;Y/=val;Z/=val; return *this;} template <> inline vector3d vector3d::getSphericalCoordinateAngles() const { vector3d angle; const f64 length = X*X + Y*Y + Z*Z; if (length) { if (X!=0) { angle.Y = round32((f32)(atan2((f64)Z,(f64)X) * RADTODEG64)); } else if (Z<0) angle.Y=180; angle.X = round32((f32)(acos(Y * core::reciprocal_squareroot(length)) * RADTODEG64)); } return angle; } //! Typedef for a f32 3d vector. typedef vector3d vector3df; //! Typedef for an integer 3d vector. typedef vector3d vector3di; //! Function multiplying a scalar and a vector component-wise. template vector3d operator*(const S scalar, const vector3d& vector) { return vector*scalar; } } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/vector2d.h0000644000000000000000000003023312574354552015402 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_POINT_2D_H_INCLUDED__ #define __IRR_POINT_2D_H_INCLUDED__ #include "irrMath.h" #include "dimension2d.h" namespace irr { namespace core { //! 2d vector template class with lots of operators and methods. /** As of Irrlicht 1.6, this class supercedes position2d, which should be considered deprecated. */ template class vector2d { public: //! Default constructor (null vector) vector2d() : X(0), Y(0) {} //! Constructor with two different values vector2d(T nx, T ny) : X(nx), Y(ny) {} //! Constructor with the same value for both members explicit vector2d(T n) : X(n), Y(n) {} //! Copy constructor vector2d(const vector2d& other) : X(other.X), Y(other.Y) {} vector2d(const dimension2d& other) : X(other.Width), Y(other.Height) {} // operators vector2d operator-() const { return vector2d(-X, -Y); } vector2d& operator=(const vector2d& other) { X = other.X; Y = other.Y; return *this; } vector2d& operator=(const dimension2d& other) { X = other.Width; Y = other.Height; return *this; } vector2d operator+(const vector2d& other) const { return vector2d(X + other.X, Y + other.Y); } vector2d operator+(const dimension2d& other) const { return vector2d(X + other.Width, Y + other.Height); } vector2d& operator+=(const vector2d& other) { X+=other.X; Y+=other.Y; return *this; } vector2d operator+(const T v) const { return vector2d(X + v, Y + v); } vector2d& operator+=(const T v) { X+=v; Y+=v; return *this; } vector2d& operator+=(const dimension2d& other) { X += other.Width; Y += other.Height; return *this; } vector2d operator-(const vector2d& other) const { return vector2d(X - other.X, Y - other.Y); } vector2d operator-(const dimension2d& other) const { return vector2d(X - other.Width, Y - other.Height); } vector2d& operator-=(const vector2d& other) { X-=other.X; Y-=other.Y; return *this; } vector2d operator-(const T v) const { return vector2d(X - v, Y - v); } vector2d& operator-=(const T v) { X-=v; Y-=v; return *this; } vector2d& operator-=(const dimension2d& other) { X -= other.Width; Y -= other.Height; return *this; } vector2d operator*(const vector2d& other) const { return vector2d(X * other.X, Y * other.Y); } vector2d& operator*=(const vector2d& other) { X*=other.X; Y*=other.Y; return *this; } vector2d operator*(const T v) const { return vector2d(X * v, Y * v); } vector2d& operator*=(const T v) { X*=v; Y*=v; return *this; } vector2d operator/(const vector2d& other) const { return vector2d(X / other.X, Y / other.Y); } vector2d& operator/=(const vector2d& other) { X/=other.X; Y/=other.Y; return *this; } vector2d operator/(const T v) const { return vector2d(X / v, Y / v); } vector2d& operator/=(const T v) { X/=v; Y/=v; return *this; } //! sort in order X, Y. Equality with rounding tolerance. bool operator<=(const vector2d&other) const { return (X=(const vector2d&other) const { return (X>other.X || core::equals(X, other.X)) || (core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y))); } //! sort in order X, Y. Difference must be above rounding tolerance. bool operator<(const vector2d&other) const { return (X(const vector2d&other) const { return (X>other.X && !core::equals(X, other.X)) || (core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y)); } bool operator==(const vector2d& other) const { return equals(other); } bool operator!=(const vector2d& other) const { return !equals(other); } // functions //! Checks if this vector equals the other one. /** Takes floating point rounding errors into account. \param other Vector to compare with. \return True if the two vector are (almost) equal, else false. */ bool equals(const vector2d& other) const { return core::equals(X, other.X) && core::equals(Y, other.Y); } vector2d& set(T nx, T ny) {X=nx; Y=ny; return *this; } vector2d& set(const vector2d& p) { X=p.X; Y=p.Y; return *this; } //! Gets the length of the vector. /** \return The length of the vector. */ T getLength() const { return core::squareroot( X*X + Y*Y ); } //! Get the squared length of this vector /** This is useful because it is much faster than getLength(). \return The squared length of the vector. */ T getLengthSQ() const { return X*X + Y*Y; } //! Get the dot product of this vector with another. /** \param other Other vector to take dot product with. \return The dot product of the two vectors. */ T dotProduct(const vector2d& other) const { return X*other.X + Y*other.Y; } //! Gets distance from another point. /** Here, the vector is interpreted as a point in 2-dimensional space. \param other Other vector to measure from. \return Distance from other point. */ T getDistanceFrom(const vector2d& other) const { return vector2d(X - other.X, Y - other.Y).getLength(); } //! Returns squared distance from another point. /** Here, the vector is interpreted as a point in 2-dimensional space. \param other Other vector to measure from. \return Squared distance from other point. */ T getDistanceFromSQ(const vector2d& other) const { return vector2d(X - other.X, Y - other.Y).getLengthSQ(); } //! rotates the point anticlockwise around a center by an amount of degrees. /** \param degrees Amount of degrees to rotate by, anticlockwise. \param center Rotation center. \return This vector after transformation. */ vector2d& rotateBy(f64 degrees, const vector2d& center=vector2d()) { degrees *= DEGTORAD64; const f64 cs = cos(degrees); const f64 sn = sin(degrees); X -= center.X; Y -= center.Y; set((T)(X*cs - Y*sn), (T)(X*sn + Y*cs)); X += center.X; Y += center.Y; return *this; } //! Normalize the vector. /** The null vector is left untouched. \return Reference to this vector, after normalization. */ vector2d& normalize() { f32 length = (f32)(X*X + Y*Y); if ( length == 0 ) return *this; length = core::reciprocal_squareroot ( length ); X = (T)(X * length); Y = (T)(Y * length); return *this; } //! Calculates the angle of this vector in degrees in the trigonometric sense. /** 0 is to the right (3 o'clock), values increase counter-clockwise. This method has been suggested by Pr3t3nd3r. \return Returns a value between 0 and 360. */ f64 getAngleTrig() const { if (Y == 0) return X < 0 ? 180 : 0; else if (X == 0) return Y < 0 ? 270 : 90; if ( Y > 0) if (X > 0) return atan((irr::f64)Y/(irr::f64)X) * RADTODEG64; else return 180.0-atan((irr::f64)Y/-(irr::f64)X) * RADTODEG64; else if (X > 0) return 360.0-atan(-(irr::f64)Y/(irr::f64)X) * RADTODEG64; else return 180.0+atan(-(irr::f64)Y/-(irr::f64)X) * RADTODEG64; } //! Calculates the angle of this vector in degrees in the counter trigonometric sense. /** 0 is to the right (3 o'clock), values increase clockwise. \return Returns a value between 0 and 360. */ inline f64 getAngle() const { if (Y == 0) // corrected thanks to a suggestion by Jox return X < 0 ? 180 : 0; else if (X == 0) return Y < 0 ? 90 : 270; // don't use getLength here to avoid precision loss with s32 vectors // avoid floating-point trouble as sqrt(y*y) is occasionally larger than y, so clamp const f64 tmp = core::clamp(Y / sqrt((f64)(X*X + Y*Y)), -1.0, 1.0); const f64 angle = atan( core::squareroot(1 - tmp*tmp) / tmp) * RADTODEG64; if (X>0 && Y>0) return angle + 270; else if (X>0 && Y<0) return angle + 90; else if (X<0 && Y<0) return 90 - angle; else if (X<0 && Y>0) return 270 - angle; return angle; } //! Calculates the angle between this vector and another one in degree. /** \param b Other vector to test with. \return Returns a value between 0 and 90. */ inline f64 getAngleWith(const vector2d& b) const { f64 tmp = (f64)(X*b.X + Y*b.Y); if (tmp == 0.0) return 90.0; tmp = tmp / core::squareroot((f64)((X*X + Y*Y) * (b.X*b.X + b.Y*b.Y))); if (tmp < 0.0) tmp = -tmp; if ( tmp > 1.0 ) // avoid floating-point trouble tmp = 1.0; return atan(sqrt(1 - tmp*tmp) / tmp) * RADTODEG64; } //! Returns if this vector interpreted as a point is on a line between two other points. /** It is assumed that the point is on the line. \param begin Beginning vector to compare between. \param end Ending vector to compare between. \return True if this vector is between begin and end, false if not. */ bool isBetweenPoints(const vector2d& begin, const vector2d& end) const { if (begin.X != end.X) { return ((begin.X <= X && X <= end.X) || (begin.X >= X && X >= end.X)); } else { return ((begin.Y <= Y && Y <= end.Y) || (begin.Y >= Y && Y >= end.Y)); } } //! Creates an interpolated vector between this vector and another vector. /** \param other The other vector to interpolate with. \param d Interpolation value between 0.0f (all the other vector) and 1.0f (all this vector). Note that this is the opposite direction of interpolation to getInterpolated_quadratic() \return An interpolated vector. This vector is not modified. */ vector2d getInterpolated(const vector2d& other, f64 d) const { f64 inv = 1.0f - d; return vector2d((T)(other.X*inv + X*d), (T)(other.Y*inv + Y*d)); } //! Creates a quadratically interpolated vector between this and two other vectors. /** \param v2 Second vector to interpolate with. \param v3 Third vector to interpolate with (maximum at 1.0f) \param d Interpolation value between 0.0f (all this vector) and 1.0f (all the 3rd vector). Note that this is the opposite direction of interpolation to getInterpolated() and interpolate() \return An interpolated vector. This vector is not modified. */ vector2d getInterpolated_quadratic(const vector2d& v2, const vector2d& v3, f64 d) const { // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d; const f64 inv = 1.0f - d; const f64 mul0 = inv * inv; const f64 mul1 = 2.0f * d * inv; const f64 mul2 = d * d; return vector2d ( (T)(X * mul0 + v2.X * mul1 + v3.X * mul2), (T)(Y * mul0 + v2.Y * mul1 + v3.Y * mul2)); } //! Sets this vector to the linearly interpolated vector between a and b. /** \param a first vector to interpolate with, maximum at 1.0f \param b second vector to interpolate with, maximum at 0.0f \param d Interpolation value between 0.0f (all vector b) and 1.0f (all vector a) Note that this is the opposite direction of interpolation to getInterpolated_quadratic() */ vector2d& interpolate(const vector2d& a, const vector2d& b, f64 d) { X = (T)((f64)b.X + ( ( a.X - b.X ) * d )); Y = (T)((f64)b.Y + ( ( a.Y - b.Y ) * d )); return *this; } //! X coordinate of vector. T X; //! Y coordinate of vector. T Y; }; //! Typedef for f32 2d vector. typedef vector2d vector2df; //! Typedef for integer 2d vector. typedef vector2d vector2di; template vector2d operator*(const S scalar, const vector2d& vector) { return vector*scalar; } // These methods are declared in dimension2d, but need definitions of vector2d template dimension2d::dimension2d(const vector2d& other) : Width(other.X), Height(other.Y) { } template bool dimension2d::operator==(const vector2d& other) const { return Width == other.X && Height == other.Y; } } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/triangle3d.h0000644000000000000000000002432312574354552015711 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_TRIANGLE_3D_H_INCLUDED__ #define __IRR_TRIANGLE_3D_H_INCLUDED__ #include "vector3d.h" #include "line3d.h" #include "plane3d.h" #include "aabbox3d.h" namespace irr { namespace core { //! 3d triangle template class for doing collision detection and other things. template class triangle3d { public: //! Constructor for an all 0 triangle triangle3d() {} //! Constructor for triangle with given three vertices triangle3d(vector3d v1, vector3d v2, vector3d v3) : pointA(v1), pointB(v2), pointC(v3) {} //! Equality operator bool operator==(const triangle3d& other) const { return other.pointA==pointA && other.pointB==pointB && other.pointC==pointC; } //! Inequality operator bool operator!=(const triangle3d& other) const { return !(*this==other); } //! Determines if the triangle is totally inside a bounding box. /** \param box Box to check. \return True if triangle is within the box, otherwise false. */ bool isTotalInsideBox(const aabbox3d& box) const { return (box.isPointInside(pointA) && box.isPointInside(pointB) && box.isPointInside(pointC)); } //! Determines if the triangle is totally outside a bounding box. /** \param box Box to check. \return True if triangle is outside the box, otherwise false. */ bool isTotalOutsideBox(const aabbox3d& box) const { return ((pointA.X > box.MaxEdge.X && pointB.X > box.MaxEdge.X && pointC.X > box.MaxEdge.X) || (pointA.Y > box.MaxEdge.Y && pointB.Y > box.MaxEdge.Y && pointC.Y > box.MaxEdge.Y) || (pointA.Z > box.MaxEdge.Z && pointB.Z > box.MaxEdge.Z && pointC.Z > box.MaxEdge.Z) || (pointA.X < box.MinEdge.X && pointB.X < box.MinEdge.X && pointC.X < box.MinEdge.X) || (pointA.Y < box.MinEdge.Y && pointB.Y < box.MinEdge.Y && pointC.Y < box.MinEdge.Y) || (pointA.Z < box.MinEdge.Z && pointB.Z < box.MinEdge.Z && pointC.Z < box.MinEdge.Z)); } //! Get the closest point on a triangle to a point on the same plane. /** \param p Point which must be on the same plane as the triangle. \return The closest point of the triangle */ core::vector3d closestPointOnTriangle(const core::vector3d& p) const { const core::vector3d rab = line3d(pointA, pointB).getClosestPoint(p); const core::vector3d rbc = line3d(pointB, pointC).getClosestPoint(p); const core::vector3d rca = line3d(pointC, pointA).getClosestPoint(p); const T d1 = rab.getDistanceFrom(p); const T d2 = rbc.getDistanceFrom(p); const T d3 = rca.getDistanceFrom(p); if (d1 < d2) return d1 < d3 ? rab : rca; return d2 < d3 ? rbc : rca; } //! Check if a point is inside the triangle (border-points count also as inside) /* \param p Point to test. Assumes that this point is already on the plane of the triangle. \return True if the point is inside the triangle, otherwise false. */ bool isPointInside(const vector3d& p) const { vector3d af64((f64)pointA.X, (f64)pointA.Y, (f64)pointA.Z); vector3d bf64((f64)pointB.X, (f64)pointB.Y, (f64)pointB.Z); vector3d cf64((f64)pointC.X, (f64)pointC.Y, (f64)pointC.Z); vector3d pf64((f64)p.X, (f64)p.Y, (f64)p.Z); return (isOnSameSide(pf64, af64, bf64, cf64) && isOnSameSide(pf64, bf64, af64, cf64) && isOnSameSide(pf64, cf64, af64, bf64)); } //! Check if a point is inside the triangle (border-points count also as inside) /** This method uses a barycentric coordinate system. It is faster than isPointInside but is more susceptible to floating point rounding errors. This will especially be noticable when the FPU is in single precision mode (which is for example set on default by Direct3D). \param p Point to test. Assumes that this point is already on the plane of the triangle. \return True if point is inside the triangle, otherwise false. */ bool isPointInsideFast(const vector3d& p) const { const vector3d a = pointC - pointA; const vector3d b = pointB - pointA; const vector3d c = p - pointA; const f64 dotAA = a.dotProduct( a); const f64 dotAB = a.dotProduct( b); const f64 dotAC = a.dotProduct( c); const f64 dotBB = b.dotProduct( b); const f64 dotBC = b.dotProduct( c); // get coordinates in barycentric coordinate system const f64 invDenom = 1/(dotAA * dotBB - dotAB * dotAB); const f64 u = (dotBB * dotAC - dotAB * dotBC) * invDenom; const f64 v = (dotAA * dotBC - dotAB * dotAC ) * invDenom; // We count border-points as inside to keep downward compatibility. // Rounding-error also needed for some test-cases. return (u > -ROUNDING_ERROR_f32) && (v >= 0) && (u + v < 1+ROUNDING_ERROR_f32); } //! Get an intersection with a 3d line. /** \param line Line to intersect with. \param outIntersection Place to store the intersection point, if there is one. \return True if there was an intersection, false if not. */ bool getIntersectionWithLimitedLine(const line3d& line, vector3d& outIntersection) const { return getIntersectionWithLine(line.start, line.getVector(), outIntersection) && outIntersection.isBetweenPoints(line.start, line.end); } //! Get an intersection with a 3d line. /** Please note that also points are returned as intersection which are on the line, but not between the start and end point of the line. If you want the returned point be between start and end use getIntersectionWithLimitedLine(). \param linePoint Point of the line to intersect with. \param lineVect Vector of the line to intersect with. \param outIntersection Place to store the intersection point, if there is one. \return True if there was an intersection, false if there was not. */ bool getIntersectionWithLine(const vector3d& linePoint, const vector3d& lineVect, vector3d& outIntersection) const { if (getIntersectionOfPlaneWithLine(linePoint, lineVect, outIntersection)) return isPointInside(outIntersection); return false; } //! Calculates the intersection between a 3d line and the plane the triangle is on. /** \param lineVect Vector of the line to intersect with. \param linePoint Point of the line to intersect with. \param outIntersection Place to store the intersection point, if there is one. \return True if there was an intersection, else false. */ bool getIntersectionOfPlaneWithLine(const vector3d& linePoint, const vector3d& lineVect, vector3d& outIntersection) const { // Work with f64 to get more precise results (makes enough difference to be worth the casts). const vector3d linePointf64(linePoint.X, linePoint.Y, linePoint.Z); const vector3d lineVectf64(lineVect.X, lineVect.Y, lineVect.Z); vector3d outIntersectionf64; core::triangle3d trianglef64(vector3d((f64)pointA.X, (f64)pointA.Y, (f64)pointA.Z) ,vector3d((f64)pointB.X, (f64)pointB.Y, (f64)pointB.Z) , vector3d((f64)pointC.X, (f64)pointC.Y, (f64)pointC.Z)); const vector3d normalf64 = trianglef64.getNormal().normalize(); f64 t2; if ( core::iszero ( t2 = normalf64.dotProduct(lineVectf64) ) ) return false; f64 d = trianglef64.pointA.dotProduct(normalf64); f64 t = -(normalf64.dotProduct(linePointf64) - d) / t2; outIntersectionf64 = linePointf64 + (lineVectf64 * t); outIntersection.X = (T)outIntersectionf64.X; outIntersection.Y = (T)outIntersectionf64.Y; outIntersection.Z = (T)outIntersectionf64.Z; return true; } //! Get the normal of the triangle. /** Please note: The normal is not always normalized. */ vector3d getNormal() const { return (pointB - pointA).crossProduct(pointC - pointA); } //! Test if the triangle would be front or backfacing from any point. /** Thus, this method assumes a camera position from which the triangle is definitely visible when looking at the given direction. Do not use this method with points as it will give wrong results! \param lookDirection Look direction. \return True if the plane is front facing and false if it is backfacing. */ bool isFrontFacing(const vector3d& lookDirection) const { const vector3d n = getNormal().normalize(); const f32 d = (f32)n.dotProduct(lookDirection); return F32_LOWER_EQUAL_0(d); } //! Get the plane of this triangle. plane3d getPlane() const { return plane3d(pointA, pointB, pointC); } //! Get the area of the triangle T getArea() const { return (pointB - pointA).crossProduct(pointC - pointA).getLength() * 0.5f; } //! sets the triangle's points void set(const core::vector3d& a, const core::vector3d& b, const core::vector3d& c) { pointA = a; pointB = b; pointC = c; } //! the three points of the triangle vector3d pointA; vector3d pointB; vector3d pointC; private: // Using f64 instead of to avoid integer overflows when T=int (maybe also less floating point troubles). bool isOnSameSide(const vector3d& p1, const vector3d& p2, const vector3d& a, const vector3d& b) const { vector3d bminusa = b - a; vector3d cp1 = bminusa.crossProduct(p1 - a); vector3d cp2 = bminusa.crossProduct(p2 - a); f64 res = cp1.dotProduct(cp2); if ( res < 0 ) { // This catches some floating point troubles. // Unfortunately slightly expensive and we don't really know the best epsilon for iszero. vector3d cp1 = bminusa.normalize().crossProduct((p1 - a).normalize()); if ( core::iszero(cp1.X, (f64)ROUNDING_ERROR_f32) && core::iszero(cp1.Y, (f64)ROUNDING_ERROR_f32) && core::iszero(cp1.Z, (f64)ROUNDING_ERROR_f32) ) { res = 0.f; } } return (res >= 0.0f); } }; //! Typedef for a f32 3d triangle. typedef triangle3d triangle3df; //! Typedef for an integer 3d triangle. typedef triangle3d triangle3di; } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/SViewFrustum.h0000644000000000000000000002525212574354552016302 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_VIEW_FRUSTUM_H_INCLUDED__ #define __S_VIEW_FRUSTUM_H_INCLUDED__ #include "plane3d.h" #include "vector3d.h" #include "line3d.h" #include "aabbox3d.h" #include "matrix4.h" #include "IVideoDriver.h" namespace irr { namespace scene { //! Defines the view frustum. That's the space visible by the camera. /** The view frustum is enclosed by 6 planes. These six planes share eight points. A bounding box around these eight points is also stored in this structure. */ struct SViewFrustum { enum VFPLANES { //! Far plane of the frustum. That is the plane farest away from the eye. VF_FAR_PLANE = 0, //! Near plane of the frustum. That is the plane nearest to the eye. VF_NEAR_PLANE, //! Left plane of the frustum. VF_LEFT_PLANE, //! Right plane of the frustum. VF_RIGHT_PLANE, //! Bottom plane of the frustum. VF_BOTTOM_PLANE, //! Top plane of the frustum. VF_TOP_PLANE, //! Amount of planes enclosing the view frustum. Should be 6. VF_PLANE_COUNT }; //! Default Constructor SViewFrustum() {} //! Copy Constructor SViewFrustum(const SViewFrustum& other); //! This constructor creates a view frustum based on a projection and/or view matrix. SViewFrustum(const core::matrix4& mat); //! This constructor creates a view frustum based on a projection and/or view matrix. inline void setFrom(const core::matrix4& mat); //! transforms the frustum by the matrix /** \param mat: Matrix by which the view frustum is transformed.*/ void transform(const core::matrix4& mat); //! returns the point which is on the far left upper corner inside the the view frustum. core::vector3df getFarLeftUp() const; //! returns the point which is on the far left bottom corner inside the the view frustum. core::vector3df getFarLeftDown() const; //! returns the point which is on the far right top corner inside the the view frustum. core::vector3df getFarRightUp() const; //! returns the point which is on the far right bottom corner inside the the view frustum. core::vector3df getFarRightDown() const; //! returns the point which is on the near left upper corner inside the the view frustum. core::vector3df getNearLeftUp() const; //! returns the point which is on the near left bottom corner inside the the view frustum. core::vector3df getNearLeftDown() const; //! returns the point which is on the near right top corner inside the the view frustum. core::vector3df getNearRightUp() const; //! returns the point which is on the near right bottom corner inside the the view frustum. core::vector3df getNearRightDown() const; //! returns a bounding box enclosing the whole view frustum const core::aabbox3d &getBoundingBox() const; //! recalculates the bounding box member based on the planes inline void recalculateBoundingBox(); //! get the given state's matrix based on frustum E_TRANSFORMATION_STATE core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state); //! get the given state's matrix based on frustum E_TRANSFORMATION_STATE const core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state) const; //! clips a line to the view frustum. /** \return True if the line was clipped, false if not */ bool clipLine(core::line3d& line) const; //! the position of the camera core::vector3df cameraPosition; //! all planes enclosing the view frustum. core::plane3d planes[VF_PLANE_COUNT]; //! bounding box around the view frustum core::aabbox3d boundingBox; private: //! Hold a copy of important transform matrices enum E_TRANSFORMATION_STATE_FRUSTUM { ETS_VIEW = 0, ETS_PROJECTION = 1, ETS_COUNT_FRUSTUM }; //! Hold a copy of important transform matrices core::matrix4 Matrices[ETS_COUNT_FRUSTUM]; }; /*! Copy constructor ViewFrustum */ inline SViewFrustum::SViewFrustum(const SViewFrustum& other) { cameraPosition=other.cameraPosition; boundingBox=other.boundingBox; u32 i; for (i=0; i &SViewFrustum::getBoundingBox() const { return boundingBox; } inline void SViewFrustum::recalculateBoundingBox() { boundingBox.reset ( cameraPosition ); boundingBox.addInternalPoint(getFarLeftUp()); boundingBox.addInternalPoint(getFarRightUp()); boundingBox.addInternalPoint(getFarLeftDown()); boundingBox.addInternalPoint(getFarRightDown()); } //! This constructor creates a view frustum based on a projection //! and/or view matrix. inline void SViewFrustum::setFrom(const core::matrix4& mat) { // left clipping plane planes[VF_LEFT_PLANE].Normal.X = mat[3 ] + mat[0]; planes[VF_LEFT_PLANE].Normal.Y = mat[7 ] + mat[4]; planes[VF_LEFT_PLANE].Normal.Z = mat[11] + mat[8]; planes[VF_LEFT_PLANE].D = mat[15] + mat[12]; // right clipping plane planes[VF_RIGHT_PLANE].Normal.X = mat[3 ] - mat[0]; planes[VF_RIGHT_PLANE].Normal.Y = mat[7 ] - mat[4]; planes[VF_RIGHT_PLANE].Normal.Z = mat[11] - mat[8]; planes[VF_RIGHT_PLANE].D = mat[15] - mat[12]; // top clipping plane planes[VF_TOP_PLANE].Normal.X = mat[3 ] - mat[1]; planes[VF_TOP_PLANE].Normal.Y = mat[7 ] - mat[5]; planes[VF_TOP_PLANE].Normal.Z = mat[11] - mat[9]; planes[VF_TOP_PLANE].D = mat[15] - mat[13]; // bottom clipping plane planes[VF_BOTTOM_PLANE].Normal.X = mat[3 ] + mat[1]; planes[VF_BOTTOM_PLANE].Normal.Y = mat[7 ] + mat[5]; planes[VF_BOTTOM_PLANE].Normal.Z = mat[11] + mat[9]; planes[VF_BOTTOM_PLANE].D = mat[15] + mat[13]; // far clipping plane planes[VF_FAR_PLANE].Normal.X = mat[3 ] - mat[2]; planes[VF_FAR_PLANE].Normal.Y = mat[7 ] - mat[6]; planes[VF_FAR_PLANE].Normal.Z = mat[11] - mat[10]; planes[VF_FAR_PLANE].D = mat[15] - mat[14]; // near clipping plane planes[VF_NEAR_PLANE].Normal.X = mat[2]; planes[VF_NEAR_PLANE].Normal.Y = mat[6]; planes[VF_NEAR_PLANE].Normal.Z = mat[10]; planes[VF_NEAR_PLANE].D = mat[14]; // normalize normals u32 i; for ( i=0; i != VF_PLANE_COUNT; ++i) { const f32 len = -core::reciprocal_squareroot( planes[i].Normal.getLengthSQ()); planes[i].Normal *= len; planes[i].D *= len; } // make bounding box recalculateBoundingBox(); } /*! View Frustum depends on Projection & View Matrix */ inline core::matrix4& SViewFrustum::getTransform(video::E_TRANSFORMATION_STATE state ) { u32 index = 0; switch ( state ) { case video::ETS_PROJECTION: index = SViewFrustum::ETS_PROJECTION; break; case video::ETS_VIEW: index = SViewFrustum::ETS_VIEW; break; default: break; } return Matrices [ index ]; } /*! View Frustum depends on Projection & View Matrix */ inline const core::matrix4& SViewFrustum::getTransform(video::E_TRANSFORMATION_STATE state ) const { u32 index = 0; switch ( state ) { case video::ETS_PROJECTION: index = SViewFrustum::ETS_PROJECTION; break; case video::ETS_VIEW: index = SViewFrustum::ETS_VIEW; break; default: break; } return Matrices [ index ]; } //! Clips a line to the frustum inline bool SViewFrustum::clipLine(core::line3d& line) const { bool wasClipped = false; for (u32 i=0; i < VF_PLANE_COUNT; ++i) { if (planes[i].classifyPointRelation(line.start) == core::ISREL3D_FRONT) { line.start = line.start.getInterpolated(line.end, planes[i].getKnownIntersectionWithLine(line.start, line.end)); wasClipped = true; } if (planes[i].classifyPointRelation(line.end) == core::ISREL3D_FRONT) { line.end = line.start.getInterpolated(line.end, planes[i].getKnownIntersectionWithLine(line.start, line.end)); wasClipped = true; } } return wasClipped; } } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/SVertexManipulator.h0000644000000000000000000002335012574354552017470 0ustar rootroot// Copyright (C) 2009-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_VERTEX_MANIPULATOR_H_INCLUDED__ #define __S_VERTEX_MANIPULATOR_H_INCLUDED__ #include "S3DVertex.h" #include "SColor.h" namespace irr { namespace scene { class IMesh; class IMeshBuffer; struct SMesh; //! Interface for vertex manipulators. /** You should derive your manipulator from this class if it shall be called for every vertex, getting as parameter just the vertex. */ struct IVertexManipulator { }; //! Vertex manipulator to set color to a fixed color for all vertices class SVertexColorSetManipulator : public IVertexManipulator { public: SVertexColorSetManipulator(video::SColor color) : Color(color) {} void operator()(video::S3DVertex& vertex) const { vertex.Color=Color; } private: video::SColor Color; }; //! Vertex manipulator to set the alpha value of the vertex color to a fixed value class SVertexColorSetAlphaManipulator : public IVertexManipulator { public: SVertexColorSetAlphaManipulator(u32 alpha) : Alpha(alpha) {} void operator()(video::S3DVertex& vertex) const { vertex.Color.setAlpha(Alpha); } private: u32 Alpha; }; //! Vertex manipulator which invertes the RGB values class SVertexColorInvertManipulator : public IVertexManipulator { public: void operator()(video::S3DVertex& vertex) const { vertex.Color.setRed(255-vertex.Color.getRed()); vertex.Color.setGreen(255-vertex.Color.getGreen()); vertex.Color.setBlue(255-vertex.Color.getBlue()); } }; //! Vertex manipulator to set vertex color to one of two values depending on a given threshold /** If average of the color value is >Threshold the High color is chosen, else Low. */ class SVertexColorThresholdManipulator : public IVertexManipulator { public: SVertexColorThresholdManipulator(u8 threshold, video::SColor low, video::SColor high) : Threshold(threshold), Low(low), High(high) {} void operator()(video::S3DVertex& vertex) const { vertex.Color = ((u8)vertex.Color.getAverage()>Threshold)?High:Low; } private: u8 Threshold; video::SColor Low; video::SColor High; }; //! Vertex manipulator which adjusts the brightness by the given amount /** A positive value increases brightness, a negative value darkens the colors. */ class SVertexColorBrightnessManipulator : public IVertexManipulator { public: SVertexColorBrightnessManipulator(s32 amount) : Amount(amount) {} void operator()(video::S3DVertex& vertex) const { vertex.Color.setRed(core::clamp(vertex.Color.getRed()+Amount, 0u, 255u)); vertex.Color.setGreen(core::clamp(vertex.Color.getGreen()+Amount, 0u, 255u)); vertex.Color.setBlue(core::clamp(vertex.Color.getBlue()+Amount, 0u, 255u)); } private: s32 Amount; }; //! Vertex manipulator which adjusts the contrast by the given factor /** Factors over 1 increase contrast, below 1 reduce it. */ class SVertexColorContrastManipulator : public IVertexManipulator { public: SVertexColorContrastManipulator(f32 factor) : Factor(factor) {} void operator()(video::S3DVertex& vertex) const { vertex.Color.setRed(core::clamp(core::round32((vertex.Color.getRed()-128)*Factor)+128, 0, 255)); vertex.Color.setGreen(core::clamp(core::round32((vertex.Color.getGreen()-128)*Factor)+128, 0, 255)); vertex.Color.setBlue(core::clamp(core::round32((vertex.Color.getBlue()-128)*Factor)+128, 0, 255)); } private: f32 Factor; }; //! Vertex manipulator which adjusts the contrast by the given factor and brightness by a signed amount. /** Factors over 1 increase contrast, below 1 reduce it. A positive amount increases brightness, a negative one darkens the colors. */ class SVertexColorContrastBrightnessManipulator : public IVertexManipulator { public: SVertexColorContrastBrightnessManipulator(f32 factor, s32 amount) : Factor(factor), Amount(amount+128) {} void operator()(video::S3DVertex& vertex) const { vertex.Color.setRed(core::clamp(core::round32((vertex.Color.getRed()-128)*Factor)+Amount, 0, 255)); vertex.Color.setGreen(core::clamp(core::round32((vertex.Color.getGreen()-128)*Factor)+Amount, 0, 255)); vertex.Color.setBlue(core::clamp(core::round32((vertex.Color.getBlue()-128)*Factor)+Amount, 0, 255)); } private: f32 Factor; s32 Amount; }; //! Vertex manipulator which adjusts the brightness by a gamma operation /** A value over one increases brightness, one below darkens the colors. */ class SVertexColorGammaManipulator : public IVertexManipulator { public: SVertexColorGammaManipulator(f32 gamma) : Gamma(1.f) { if (gamma != 0.f) Gamma = 1.f/gamma; } void operator()(video::S3DVertex& vertex) const { vertex.Color.setRed(core::clamp(core::round32(powf((f32)(vertex.Color.getRed()),Gamma)), 0, 255)); vertex.Color.setGreen(core::clamp(core::round32(powf((f32)(vertex.Color.getGreen()),Gamma)), 0, 255)); vertex.Color.setBlue(core::clamp(core::round32(powf((f32)(vertex.Color.getBlue()),Gamma)), 0, 255)); } private: f32 Gamma; }; //! Vertex manipulator which scales the color values /** Can e.g be used for white balance, factor would be 255.f/brightest color. */ class SVertexColorScaleManipulator : public IVertexManipulator { public: SVertexColorScaleManipulator(f32 factor) : Factor(factor) {} void operator()(video::S3DVertex& vertex) const { vertex.Color.setRed(core::clamp(core::round32(vertex.Color.getRed()*Factor), 0, 255)); vertex.Color.setGreen(core::clamp(core::round32(vertex.Color.getGreen()*Factor), 0, 255)); vertex.Color.setBlue(core::clamp(core::round32(vertex.Color.getBlue()*Factor), 0, 255)); } private: f32 Factor; }; //! Vertex manipulator which desaturates the color values /** Uses the lightness value of the color. */ class SVertexColorDesaturateToLightnessManipulator : public IVertexManipulator { public: void operator()(video::S3DVertex& vertex) const { vertex.Color=core::round32(vertex.Color.getLightness()); } }; //! Vertex manipulator which desaturates the color values /** Uses the average value of the color. */ class SVertexColorDesaturateToAverageManipulator : public IVertexManipulator { public: void operator()(video::S3DVertex& vertex) const { vertex.Color=vertex.Color.getAverage(); } }; //! Vertex manipulator which desaturates the color values /** Uses the luminance value of the color. */ class SVertexColorDesaturateToLuminanceManipulator : public IVertexManipulator { public: void operator()(video::S3DVertex& vertex) const { vertex.Color=core::round32(vertex.Color.getLuminance()); } }; //! Vertex manipulator which interpolates the color values /** Uses linear interpolation. */ class SVertexColorInterpolateLinearManipulator : public IVertexManipulator { public: SVertexColorInterpolateLinearManipulator(video::SColor color, f32 factor) : Color(color), Factor(factor) {} void operator()(video::S3DVertex& vertex) const { vertex.Color=vertex.Color.getInterpolated(Color, Factor); } private: video::SColor Color; f32 Factor; }; //! Vertex manipulator which interpolates the color values /** Uses linear interpolation. */ class SVertexColorInterpolateQuadraticManipulator : public IVertexManipulator { public: SVertexColorInterpolateQuadraticManipulator(video::SColor color1, video::SColor color2, f32 factor) : Color1(color1), Color2(color2), Factor(factor) {} void operator()(video::S3DVertex& vertex) const { vertex.Color=vertex.Color.getInterpolated_quadratic(Color1, Color2, Factor); } private: video::SColor Color1; video::SColor Color2; f32 Factor; }; //! Vertex manipulator which scales the position of the vertex class SVertexPositionScaleManipulator : public IVertexManipulator { public: SVertexPositionScaleManipulator(const core::vector3df& factor) : Factor(factor) {} template void operator()(VType& vertex) const { vertex.Pos *= Factor; } private: core::vector3df Factor; }; //! Vertex manipulator which scales the position of the vertex along the normals /** This can look more pleasing than the usual Scale operator, but depends on the mesh geometry. */ class SVertexPositionScaleAlongNormalsManipulator : public IVertexManipulator { public: SVertexPositionScaleAlongNormalsManipulator(const core::vector3df& factor) : Factor(factor) {} template void operator()(VType& vertex) const { vertex.Pos += vertex.Normal*Factor; } private: core::vector3df Factor; }; //! Vertex manipulator which transforms the position of the vertex class SVertexPositionTransformManipulator : public IVertexManipulator { public: SVertexPositionTransformManipulator(const core::matrix4& m) : Transformation(m) {} template void operator()(VType& vertex) const { Transformation.transformVect(vertex.Pos); } private: core::matrix4 Transformation; }; //! Vertex manipulator which scales the TCoords of the vertex class SVertexTCoordsScaleManipulator : public IVertexManipulator { public: SVertexTCoordsScaleManipulator(const core::vector2df& factor, u32 uvSet=1) : Factor(factor), UVSet(uvSet) {} void operator()(video::S3DVertex2TCoords& vertex) const { if (1==UVSet) vertex.TCoords *= Factor; else if (2==UVSet) vertex.TCoords2 *= Factor; } template void operator()(VType& vertex) const { if (1==UVSet) vertex.TCoords *= Factor; } private: core::vector2df Factor; u32 UVSet; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/SVertexIndex.h0000644000000000000000000000256512574354552016251 0ustar rootroot// Copyright (C) 2008-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_VERTEX_INDEX_H_INCLUDED__ #define __S_VERTEX_INDEX_H_INCLUDED__ #include "irrTypes.h" namespace irr { namespace video { enum E_INDEX_TYPE { EIT_16BIT = 0, EIT_32BIT }; /* //! vertex index used by the Irrlicht engine. template struct SSpecificVertexIndex { T Index; //! default constructor SSpecificVertexIndex() {} //! constructor SSpecificVertexIndex(u32 _index) :Index(_index) {} bool operator==(const SSpecificVertexIndex& other) const { return (Index == other.Index); } bool operator!=(const SSpecificVertexIndex& other) const { return (Index != other.Index); } bool operator<(const SSpecificVertexIndex& other) const { return (Index < other.Index); } SSpecificVertexIndex operator+(const u32& other) const { return SSpecificVertexIndex(Index + other); } operator const u32() const { return (const u32)Index; } E_INDEX_TYPE getType() const { if (sizeof(T)==sizeof(u16)) return video::EIT_16BIT; return video::EIT_32BIT; } }; //typedef SSpecificVertexIndex SVertexIndex; typedef u32 SVertexIndex; */ } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/SSkinMeshBuffer.h0000644000000000000000000002354312574354552016656 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SKIN_MESH_BUFFER_H_INCLUDED__ #define __I_SKIN_MESH_BUFFER_H_INCLUDED__ #include "IMeshBuffer.h" #include "S3DVertex.h" namespace irr { namespace scene { //! A mesh buffer able to choose between S3DVertex2TCoords, S3DVertex and S3DVertexTangents at runtime struct SSkinMeshBuffer : public IMeshBuffer { //! Default constructor SSkinMeshBuffer(video::E_VERTEX_TYPE vt=video::EVT_STANDARD) : ChangedID_Vertex(1), ChangedID_Index(1), VertexType(vt), MappingHint_Vertex(EHM_NEVER), MappingHint_Index(EHM_NEVER), BoundingBoxNeedsRecalculated(true) { #ifdef _DEBUG setDebugName("SSkinMeshBuffer"); #endif } //! Get Material of this buffer. virtual const video::SMaterial& getMaterial() const { return Material; } //! Get Material of this buffer. virtual video::SMaterial& getMaterial() { return Material; } //! Get standard vertex at given index virtual video::S3DVertex *getVertex(u32 index) { switch (VertexType) { case video::EVT_2TCOORDS: return (video::S3DVertex*)&Vertices_2TCoords[index]; case video::EVT_TANGENTS: return (video::S3DVertex*)&Vertices_Tangents[index]; default: return &Vertices_Standard[index]; } } //! Get pointer to vertex array virtual const void* getVertices() const { switch (VertexType) { case video::EVT_2TCOORDS: return Vertices_2TCoords.const_pointer(); case video::EVT_TANGENTS: return Vertices_Tangents.const_pointer(); default: return Vertices_Standard.const_pointer(); } } //! Get pointer to vertex array virtual void* getVertices() { switch (VertexType) { case video::EVT_2TCOORDS: return Vertices_2TCoords.pointer(); case video::EVT_TANGENTS: return Vertices_Tangents.pointer(); default: return Vertices_Standard.pointer(); } } //! Get vertex count virtual u32 getVertexCount() const { switch (VertexType) { case video::EVT_2TCOORDS: return Vertices_2TCoords.size(); case video::EVT_TANGENTS: return Vertices_Tangents.size(); default: return Vertices_Standard.size(); } } //! Get type of index data which is stored in this meshbuffer. /** \return Index type of this buffer. */ virtual video::E_INDEX_TYPE getIndexType() const { return video::EIT_16BIT; } //! Get pointer to index array virtual const u16* getIndices() const { return Indices.const_pointer(); } //! Get pointer to index array virtual u16* getIndices() { return Indices.pointer(); } //! Get index count virtual u32 getIndexCount() const { return Indices.size(); } //! Get bounding box virtual const core::aabbox3d& getBoundingBox() const { return BoundingBox; } //! Set bounding box virtual void setBoundingBox( const core::aabbox3df& box) { BoundingBox = box; } //! Recalculate bounding box virtual void recalculateBoundingBox() { if(!BoundingBoxNeedsRecalculated) return; BoundingBoxNeedsRecalculated = false; switch (VertexType) { case video::EVT_STANDARD: { if (Vertices_Standard.empty()) BoundingBox.reset(0,0,0); else { BoundingBox.reset(Vertices_Standard[0].Pos); for (u32 i=1; i Vertices_Tangents; core::array Vertices_2TCoords; core::array Vertices_Standard; core::array Indices; u32 ChangedID_Vertex; u32 ChangedID_Index; //ISkinnedMesh::SJoint *AttachedJoint; core::matrix4 Transformation; video::SMaterial Material; video::E_VERTEX_TYPE VertexType; core::aabbox3d BoundingBox; // hardware mapping hint E_HARDWARE_MAPPING MappingHint_Vertex:3; E_HARDWARE_MAPPING MappingHint_Index:3; bool BoundingBoxNeedsRecalculated:1; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/SSharedMeshBuffer.h0000644000000000000000000001430212574354552017151 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_SHARED_MESH_BUFFER_H_INCLUDED__ #define __S_SHARED_MESH_BUFFER_H_INCLUDED__ #include "irrArray.h" #include "IMeshBuffer.h" namespace irr { namespace scene { //! Implementation of the IMeshBuffer interface with shared vertex list struct SSharedMeshBuffer : public IMeshBuffer { //! constructor SSharedMeshBuffer() : IMeshBuffer(), Vertices(0), ChangedID_Vertex(1), ChangedID_Index(1), MappingHintVertex(EHM_NEVER), MappingHintIndex(EHM_NEVER) { #ifdef _DEBUG setDebugName("SSharedMeshBuffer"); #endif } //! constructor SSharedMeshBuffer(core::array *vertices) : IMeshBuffer(), Vertices(vertices) { #ifdef _DEBUG setDebugName("SSharedMeshBuffer"); #endif } //! returns the material of this meshbuffer virtual const video::SMaterial& getMaterial() const { return Material; } //! returns the material of this meshbuffer virtual video::SMaterial& getMaterial() { return Material; } //! returns pointer to vertices virtual const void* getVertices() const { if (Vertices) return Vertices->const_pointer(); else return 0; } //! returns pointer to vertices virtual void* getVertices() { if (Vertices) return Vertices->pointer(); else return 0; } //! returns amount of vertices virtual u32 getVertexCount() const { if (Vertices) return Vertices->size(); else return 0; } //! returns pointer to Indices virtual const u16* getIndices() const { return Indices.const_pointer(); } //! returns pointer to Indices virtual u16* getIndices() { return Indices.pointer(); } //! returns amount of indices virtual u32 getIndexCount() const { return Indices.size(); } //! Get type of index data which is stored in this meshbuffer. virtual video::E_INDEX_TYPE getIndexType() const { return video::EIT_16BIT; } //! returns an axis aligned bounding box virtual const core::aabbox3d& getBoundingBox() const { return BoundingBox; } //! set user axis aligned bounding box virtual void setBoundingBox( const core::aabbox3df& box) { BoundingBox = box; } //! returns which type of vertex data is stored. virtual video::E_VERTEX_TYPE getVertexType() const { return video::EVT_STANDARD; } //! recalculates the bounding box. should be called if the mesh changed. virtual void recalculateBoundingBox() { if (!Vertices || Vertices->empty() || Indices.empty()) BoundingBox.reset(0,0,0); else { BoundingBox.reset((*Vertices)[Indices[0]].Pos); for (u32 i=1; i *Vertices; //! Array of Indices core::array Indices; //! ID used for hardware buffer management u32 ChangedID_Vertex; //! ID used for hardware buffer management u32 ChangedID_Index; //! Bounding box core::aabbox3df BoundingBox; //! hardware mapping hint E_HARDWARE_MAPPING MappingHintVertex; E_HARDWARE_MAPPING MappingHintIndex; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/SParticle.h0000644000000000000000000000246312574354552015544 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_PARTICLE_H_INCLUDED__ #define __S_PARTICLE_H_INCLUDED__ #include "vector3d.h" #include "dimension2d.h" #include "SColor.h" namespace irr { namespace scene { //! Struct for holding particle data struct SParticle { //! Position of the particle core::vector3df pos; //! Direction and speed of the particle core::vector3df vector; //! Start life time of the particle u32 startTime; //! End life time of the particle u32 endTime; //! Current color of the particle video::SColor color; //! Original color of the particle. /** That's the color of the particle it had when it was emitted. */ video::SColor startColor; //! Original direction and speed of the particle. /** The direction and speed the particle had when it was emitted. */ core::vector3df startVector; //! Scale of the particle. /** The current scale of the particle. */ core::dimension2df size; //! Original scale of the particle. /** The scale of the particle when it was emitted. */ core::dimension2df startSize; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/SMeshBufferTangents.h0000644000000000000000000000034412574354552017527 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // replaced by template #include "CMeshBuffer.h" irrlicht-1.8.3/include/SMeshBufferLightMap.h0000644000000000000000000000034412574354552017451 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // replaced by template #include "CMeshBuffer.h" irrlicht-1.8.3/include/SMeshBuffer.h0000644000000000000000000000034412574354552016023 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // replaced by template #include "CMeshBuffer.h" irrlicht-1.8.3/include/SMesh.h0000644000000000000000000000636212574354552014677 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_MESH_H_INCLUDED__ #define __S_MESH_H_INCLUDED__ #include "IMesh.h" #include "IMeshBuffer.h" #include "aabbox3d.h" #include "irrArray.h" namespace irr { namespace scene { //! Simple implementation of the IMesh interface. struct SMesh : public IMesh { //! constructor SMesh() { #ifdef _DEBUG setDebugName("SMesh"); #endif } //! destructor virtual ~SMesh() { // drop buffers for (u32 i=0; idrop(); } //! clean mesh virtual void clear() { for (u32 i=0; idrop(); MeshBuffers.clear(); BoundingBox.reset ( 0.f, 0.f, 0.f ); } //! returns amount of mesh buffers. virtual u32 getMeshBufferCount() const { return MeshBuffers.size(); } //! returns pointer to a mesh buffer virtual IMeshBuffer* getMeshBuffer(u32 nr) const { return MeshBuffers[nr]; } //! returns a meshbuffer which fits a material /** reverse search */ virtual IMeshBuffer* getMeshBuffer( const video::SMaterial & material) const { for (s32 i = (s32)MeshBuffers.size()-1; i >= 0; --i) { if ( material == MeshBuffers[i]->getMaterial()) return MeshBuffers[i]; } return 0; } //! returns an axis aligned bounding box virtual const core::aabbox3d& getBoundingBox() const { return BoundingBox; } //! set user axis aligned bounding box virtual void setBoundingBox( const core::aabbox3df& box) { BoundingBox = box; } //! recalculates the bounding box void recalculateBoundingBox() { if (MeshBuffers.size()) { BoundingBox = MeshBuffers[0]->getBoundingBox(); for (u32 i=1; igetBoundingBox()); } else BoundingBox.reset(0.0f, 0.0f, 0.0f); } //! adds a MeshBuffer /** The bounding box is not updated automatically. */ void addMeshBuffer(IMeshBuffer* buf) { if (buf) { buf->grab(); MeshBuffers.push_back(buf); } } //! sets a flag of all contained materials to a new value virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) { for (u32 i=0; igetMaterial().setFlag(flag, newvalue); } //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint( E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX ) { for (u32 i=0; isetHardwareMappingHint(newMappingHint, buffer); } //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) { for (u32 i=0; isetDirty(buffer); } //! The meshbuffers of this mesh core::array MeshBuffers; //! The bounding box of this mesh core::aabbox3d BoundingBox; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/SMaterialLayer.h0000644000000000000000000001457512574354552016543 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_MATERIAL_LAYER_H_INCLUDED__ #define __S_MATERIAL_LAYER_H_INCLUDED__ #include "matrix4.h" #include "irrAllocator.h" namespace irr { namespace video { class ITexture; //! Texture coord clamp mode outside [0.0, 1.0] enum E_TEXTURE_CLAMP { //! Texture repeats ETC_REPEAT = 0, //! Texture is clamped to the last pixel ETC_CLAMP, //! Texture is clamped to the edge pixel ETC_CLAMP_TO_EDGE, //! Texture is clamped to the border pixel (if exists) ETC_CLAMP_TO_BORDER, //! Texture is alternatingly mirrored (0..1..0..1..0..) ETC_MIRROR, //! Texture is mirrored once and then clamped (0..1..0) ETC_MIRROR_CLAMP, //! Texture is mirrored once and then clamped to edge ETC_MIRROR_CLAMP_TO_EDGE, //! Texture is mirrored once and then clamped to border ETC_MIRROR_CLAMP_TO_BORDER }; static const char* const aTextureClampNames[] = { "texture_clamp_repeat", "texture_clamp_clamp", "texture_clamp_clamp_to_edge", "texture_clamp_clamp_to_border", "texture_clamp_mirror", "texture_clamp_mirror_clamp", "texture_clamp_mirror_clamp_to_edge", "texture_clamp_mirror_clamp_to_border", 0}; //! Struct for holding material parameters which exist per texture layer class SMaterialLayer { public: //! Default constructor SMaterialLayer() : Texture(0), TextureWrapU(ETC_REPEAT), TextureWrapV(ETC_REPEAT), BilinearFilter(true), TrilinearFilter(false), AnisotropicFilter(0), LODBias(0), TextureMatrix(0) {} //! Copy constructor /** \param other Material layer to copy from. */ SMaterialLayer(const SMaterialLayer& other) { // This pointer is checked during assignment TextureMatrix = 0; *this = other; } //! Destructor ~SMaterialLayer() { MatrixAllocator.destruct(TextureMatrix); MatrixAllocator.deallocate(TextureMatrix); } //! Assignment operator /** \param other Material layer to copy from. \return This material layer, updated. */ SMaterialLayer& operator=(const SMaterialLayer& other) { // Check for self-assignment! if (this == &other) return *this; Texture = other.Texture; if (TextureMatrix) { if (other.TextureMatrix) *TextureMatrix = *other.TextureMatrix; else { MatrixAllocator.destruct(TextureMatrix); MatrixAllocator.deallocate(TextureMatrix); TextureMatrix = 0; } } else { if (other.TextureMatrix) { TextureMatrix = MatrixAllocator.allocate(1); MatrixAllocator.construct(TextureMatrix,*other.TextureMatrix); } else TextureMatrix = 0; } TextureWrapU = other.TextureWrapU; TextureWrapV = other.TextureWrapV; BilinearFilter = other.BilinearFilter; TrilinearFilter = other.TrilinearFilter; AnisotropicFilter = other.AnisotropicFilter; LODBias = other.LODBias; return *this; } //! Gets the texture transformation matrix /** \return Texture matrix of this layer. */ core::matrix4& getTextureMatrix() { if (!TextureMatrix) { TextureMatrix = MatrixAllocator.allocate(1); MatrixAllocator.construct(TextureMatrix,core::IdentityMatrix); } return *TextureMatrix; } //! Gets the immutable texture transformation matrix /** \return Texture matrix of this layer. */ const core::matrix4& getTextureMatrix() const { if (TextureMatrix) return *TextureMatrix; else return core::IdentityMatrix; } //! Sets the texture transformation matrix to mat /** \param mat New texture matrix for this layer. */ void setTextureMatrix(const core::matrix4& mat) { if (!TextureMatrix) { TextureMatrix = MatrixAllocator.allocate(1); MatrixAllocator.construct(TextureMatrix,mat); } else *TextureMatrix = mat; } //! Inequality operator /** \param b Layer to compare to. \return True if layers are different, else false. */ inline bool operator!=(const SMaterialLayer& b) const { bool different = Texture != b.Texture || TextureWrapU != b.TextureWrapU || TextureWrapV != b.TextureWrapV || BilinearFilter != b.BilinearFilter || TrilinearFilter != b.TrilinearFilter || AnisotropicFilter != b.AnisotropicFilter || LODBias != b.LODBias; if (different) return true; else different |= (TextureMatrix != b.TextureMatrix) && TextureMatrix && b.TextureMatrix && (*TextureMatrix != *(b.TextureMatrix)); return different; } //! Equality operator /** \param b Layer to compare to. \return True if layers are equal, else false. */ inline bool operator==(const SMaterialLayer& b) const { return !(b!=*this); } //! Texture ITexture* Texture; //! Texture Clamp Mode /** Values are taken from E_TEXTURE_CLAMP. */ u8 TextureWrapU:4; u8 TextureWrapV:4; //! Is bilinear filtering enabled? Default: true bool BilinearFilter:1; //! Is trilinear filtering enabled? Default: false /** If the trilinear filter flag is enabled, the bilinear filtering flag is ignored. */ bool TrilinearFilter:1; //! Is anisotropic filtering enabled? Default: 0, disabled /** In Irrlicht you can use anisotropic texture filtering in conjunction with bilinear or trilinear texture filtering to improve rendering results. Primitives will look less blurry with this flag switched on. The number gives the maximal anisotropy degree, and is often in the range 2-16. Value 1 is equivalent to 0, but should be avoided. */ u8 AnisotropicFilter; //! Bias for the mipmap choosing decision. /** This value can make the textures more or less blurry than with the default value of 0. The value (divided by 8.f) is added to the mipmap level chosen initially, and thus takes a smaller mipmap for a region if the value is positive. */ s8 LODBias; private: friend class SMaterial; irr::core::irrAllocator MatrixAllocator; //! Texture Matrix /** Do not access this element directly as the internal ressource management has to cope with Null pointers etc. */ core::matrix4* TextureMatrix; }; } // end namespace video } // end namespace irr #endif // __S_MATERIAL_LAYER_H_INCLUDED__ irrlicht-1.8.3/include/SMaterial.h0000644000000000000000000005620612574354552015543 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_MATERIAL_H_INCLUDED__ #define __S_MATERIAL_H_INCLUDED__ #include "SColor.h" #include "matrix4.h" #include "irrArray.h" #include "irrMath.h" #include "EMaterialTypes.h" #include "EMaterialFlags.h" #include "SMaterialLayer.h" namespace irr { namespace video { class ITexture; //! Flag for EMT_ONETEXTURE_BLEND, ( BlendFactor ) BlendFunc = source * sourceFactor + dest * destFactor enum E_BLEND_FACTOR { EBF_ZERO = 0, //!< src & dest (0, 0, 0, 0) EBF_ONE, //!< src & dest (1, 1, 1, 1) EBF_DST_COLOR, //!< src (destR, destG, destB, destA) EBF_ONE_MINUS_DST_COLOR, //!< src (1-destR, 1-destG, 1-destB, 1-destA) EBF_SRC_COLOR, //!< dest (srcR, srcG, srcB, srcA) EBF_ONE_MINUS_SRC_COLOR, //!< dest (1-srcR, 1-srcG, 1-srcB, 1-srcA) EBF_SRC_ALPHA, //!< src & dest (srcA, srcA, srcA, srcA) EBF_ONE_MINUS_SRC_ALPHA, //!< src & dest (1-srcA, 1-srcA, 1-srcA, 1-srcA) EBF_DST_ALPHA, //!< src & dest (destA, destA, destA, destA) EBF_ONE_MINUS_DST_ALPHA, //!< src & dest (1-destA, 1-destA, 1-destA, 1-destA) EBF_SRC_ALPHA_SATURATE //!< src (min(srcA, 1-destA), idem, ...) }; //! Values defining the blend operation used when blend is enabled enum E_BLEND_OPERATION { EBO_NONE = 0, //!< No blending happens EBO_ADD, //!< Default blending adds the color values EBO_SUBTRACT, //!< This mode subtracts the color values EBO_REVSUBTRACT,//!< This modes subtracts destination from source EBO_MIN, //!< Choose minimum value of each color channel EBO_MAX, //!< Choose maximum value of each color channel EBO_MIN_FACTOR, //!< Choose minimum value of each color channel after applying blend factors, not widely supported EBO_MAX_FACTOR, //!< Choose maximum value of each color channel after applying blend factors, not widely supported EBO_MIN_ALPHA, //!< Choose minimum value of each color channel based on alpha value, not widely supported EBO_MAX_ALPHA //!< Choose maximum value of each color channel based on alpha value, not widely supported }; //! MaterialTypeParam: e.g. DirectX: D3DTOP_MODULATE, D3DTOP_MODULATE2X, D3DTOP_MODULATE4X enum E_MODULATE_FUNC { EMFN_MODULATE_1X = 1, EMFN_MODULATE_2X = 2, EMFN_MODULATE_4X = 4 }; //! Comparison function, e.g. for depth buffer test enum E_COMPARISON_FUNC { //! Test never succeeds, this equals disable ECFN_NEVER=0, //! <= test, default for e.g. depth test ECFN_LESSEQUAL=1, //! Exact equality ECFN_EQUAL=2, //! exclusive less comparison, i.e. < ECFN_LESS, //! Succeeds almost always, except for exact equality ECFN_NOTEQUAL, //! >= test ECFN_GREATEREQUAL, //! inverse of <= ECFN_GREATER, //! test succeeds always ECFN_ALWAYS }; //! Enum values for enabling/disabling color planes for rendering enum E_COLOR_PLANE { //! No color enabled ECP_NONE=0, //! Alpha enabled ECP_ALPHA=1, //! Red enabled ECP_RED=2, //! Green enabled ECP_GREEN=4, //! Blue enabled ECP_BLUE=8, //! All colors, no alpha ECP_RGB=14, //! All planes enabled ECP_ALL=15 }; //! Source of the alpha value to take /** This is currently only supported in EMT_ONETEXTURE_BLEND. You can use an or'ed combination of values. Alpha values are modulated (multiplicated). */ enum E_ALPHA_SOURCE { //! Use no alpha, somewhat redundant with other settings EAS_NONE=0, //! Use vertex color alpha EAS_VERTEX_COLOR, //! Use texture alpha channel EAS_TEXTURE }; //! EMT_ONETEXTURE_BLEND: pack srcFact, dstFact, Modulate and alpha source to MaterialTypeParam /** alpha source can be an OR'ed combination of E_ALPHA_SOURCE values. */ inline f32 pack_textureBlendFunc ( const E_BLEND_FACTOR srcFact, const E_BLEND_FACTOR dstFact, const E_MODULATE_FUNC modulate=EMFN_MODULATE_1X, const u32 alphaSource=EAS_TEXTURE ) { const u32 tmp = (alphaSource << 12) | (modulate << 8) | (srcFact << 4) | dstFact; return FR(tmp); } //! EMT_ONETEXTURE_BLEND: unpack srcFact & dstFact and Modulo to MaterialTypeParam /** The fields don't use the full byte range, so we could pack even more... */ inline void unpack_textureBlendFunc ( E_BLEND_FACTOR &srcFact, E_BLEND_FACTOR &dstFact, E_MODULATE_FUNC &modulo, u32& alphaSource, const f32 param ) { const u32 state = IR(param); alphaSource = (state & 0x0000F000) >> 12; modulo = E_MODULATE_FUNC( ( state & 0x00000F00 ) >> 8 ); srcFact = E_BLEND_FACTOR ( ( state & 0x000000F0 ) >> 4 ); dstFact = E_BLEND_FACTOR ( ( state & 0x0000000F ) ); } //! EMT_ONETEXTURE_BLEND: has BlendFactor Alphablending inline bool textureBlendFunc_hasAlpha ( const E_BLEND_FACTOR factor ) { switch ( factor ) { case EBF_SRC_ALPHA: case EBF_ONE_MINUS_SRC_ALPHA: case EBF_DST_ALPHA: case EBF_ONE_MINUS_DST_ALPHA: case EBF_SRC_ALPHA_SATURATE: return true; default: return false; } } //! These flags are used to specify the anti-aliasing and smoothing modes /** Techniques supported are multisampling, geometry smoothing, and alpha to coverage. Some drivers don't support a per-material setting of the anti-aliasing modes. In those cases, FSAA/multisampling is defined by the device mode chosen upon creation via irr::SIrrCreationParameters. */ enum E_ANTI_ALIASING_MODE { //! Use to turn off anti-aliasing for this material EAAM_OFF=0, //! Default anti-aliasing mode EAAM_SIMPLE=1, //! High-quality anti-aliasing, not always supported, automatically enables SIMPLE mode EAAM_QUALITY=3, //! Line smoothing EAAM_LINE_SMOOTH=4, //! point smoothing, often in software and slow, only with OpenGL EAAM_POINT_SMOOTH=8, //! All typical anti-alias and smooth modes EAAM_FULL_BASIC=15, //! Enhanced anti-aliasing for transparent materials /** Usually used with EMT_TRANSPARENT_ALPHA_REF and multisampling. */ EAAM_ALPHA_TO_COVERAGE=16 }; //! These flags allow to define the interpretation of vertex color when lighting is enabled /** Without lighting being enabled the vertex color is the only value defining the fragment color. Once lighting is enabled, the four values for diffuse, ambient, emissive, and specular take over. With these flags it is possible to define which lighting factor shall be defined by the vertex color instead of the lighting factor which is the same for all faces of that material. The default is to use vertex color for the diffuse value, another pretty common value is to use vertex color for both diffuse and ambient factor. */ enum E_COLOR_MATERIAL { //! Don't use vertex color for lighting ECM_NONE=0, //! Use vertex color for diffuse light, this is default ECM_DIFFUSE, //! Use vertex color for ambient light ECM_AMBIENT, //! Use vertex color for emissive light ECM_EMISSIVE, //! Use vertex color for specular light ECM_SPECULAR, //! Use vertex color for both diffuse and ambient light ECM_DIFFUSE_AND_AMBIENT }; //! Flags for the definition of the polygon offset feature /** These flags define whether the offset should be into the screen, or towards the eye. */ enum E_POLYGON_OFFSET { //! Push pixel towards the far plane, away from the eye /** This is typically used for rendering inner areas. */ EPO_BACK=0, //! Pull pixels towards the camera. /** This is typically used for polygons which should appear on top of other elements, such as decals. */ EPO_FRONT=1 }; //! Names for polygon offset direction const c8* const PolygonOffsetDirectionNames[] = { "Back", "Front", 0 }; //! Maximum number of texture an SMaterial can have. const u32 MATERIAL_MAX_TEXTURES = _IRR_MATERIAL_MAX_TEXTURES_; //! Struct for holding parameters for a material renderer class SMaterial { public: //! Default constructor. Creates a solid, lit material with white colors SMaterial() : MaterialType(EMT_SOLID), AmbientColor(255,255,255,255), DiffuseColor(255,255,255,255), EmissiveColor(0,0,0,0), SpecularColor(255,255,255,255), Shininess(0.0f), MaterialTypeParam(0.0f), MaterialTypeParam2(0.0f), Thickness(1.0f), ZBuffer(ECFN_LESSEQUAL), AntiAliasing(EAAM_SIMPLE), ColorMask(ECP_ALL), ColorMaterial(ECM_DIFFUSE), BlendOperation(EBO_NONE), PolygonOffsetFactor(0), PolygonOffsetDirection(EPO_FRONT), Wireframe(false), PointCloud(false), GouraudShading(true), Lighting(true), ZWriteEnable(true), BackfaceCulling(true), FrontfaceCulling(false), FogEnable(false), NormalizeNormals(false), UseMipMaps(true) { } //! Copy constructor /** \param other Material to copy from. */ SMaterial(const SMaterial& other) { // These pointers are checked during assignment for (u32 i=0; igetMaterial(0).Shininess = 20.0f; \endcode You can change the color of the highlights using \code sceneNode->getMaterial(0).SpecularColor.set(255,255,255,255); \endcode The specular color of the dynamic lights (SLight::SpecularColor) will influence the the highlight color too, but they are set to a useful value by default when creating the light scene node. Here is a simple example on how to use specular highlights: \code // load and display mesh scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( smgr->getMesh("data/faerie.md2")); node->setMaterialTexture(0, driver->getTexture("data/Faerie2.pcx")); // set diffuse texture node->setMaterialFlag(video::EMF_LIGHTING, true); // enable dynamic lighting node->getMaterial(0).Shininess = 20.0f; // set size of specular highlights // add white light scene::ILightSceneNode* light = smgr->addLightSceneNode(0, core::vector3df(5,5,5), video::SColorf(1.0f, 1.0f, 1.0f)); \endcode */ f32 Shininess; //! Free parameter, dependent on the material type. /** Mostly ignored, used for example in EMT_PARALLAX_MAP_SOLID and EMT_TRANSPARENT_ALPHA_CHANNEL. */ f32 MaterialTypeParam; //! Second free parameter, dependent on the material type. /** Mostly ignored. */ f32 MaterialTypeParam2; //! Thickness of non-3dimensional elements such as lines and points. f32 Thickness; //! Is the ZBuffer enabled? Default: ECFN_LESSEQUAL /** Values are from E_COMPARISON_FUNC. */ u8 ZBuffer; //! Sets the antialiasing mode /** Values are chosen from E_ANTI_ALIASING_MODE. Default is EAAM_SIMPLE|EAAM_LINE_SMOOTH, i.e. simple multi-sample anti-aliasing and lime smoothing is enabled. */ u8 AntiAliasing; //! Defines the enabled color planes /** Values are defined as or'ed values of the E_COLOR_PLANE enum. Only enabled color planes will be rendered to the current render target. Typical use is to disable all colors when rendering only to depth or stencil buffer, or using Red and Green for Stereo rendering. */ u8 ColorMask:4; //! Defines the interpretation of vertex color in the lighting equation /** Values should be chosen from E_COLOR_MATERIAL. When lighting is enabled, vertex color can be used instead of the material values for light modulation. This allows to easily change e.g. the diffuse light behavior of each face. The default, ECM_DIFFUSE, will result in a very similar rendering as with lighting turned off, just with light shading. */ u8 ColorMaterial:3; //! Store the blend operation of choice /** Values to be chosen from E_BLEND_OPERATION. The actual way to use this value is not yet determined, so ignore it for now. */ E_BLEND_OPERATION BlendOperation:4; //! Factor specifying how far the polygon offset should be made /** Specifying 0 disables the polygon offset. The direction is specified spearately. The factor can be from 0 to 7.*/ u8 PolygonOffsetFactor:3; //! Flag defining the direction the polygon offset is applied to. /** Can be to front or to back, specififed by values from E_POLYGON_OFFSET. */ E_POLYGON_OFFSET PolygonOffsetDirection:1; //! Draw as wireframe or filled triangles? Default: false /** The user can access a material flag using \code material.Wireframe=true \endcode or \code material.setFlag(EMF_WIREFRAME, true); \endcode */ bool Wireframe:1; //! Draw as point cloud or filled triangles? Default: false bool PointCloud:1; //! Flat or Gouraud shading? Default: true bool GouraudShading:1; //! Will this material be lighted? Default: true bool Lighting:1; //! Is the zbuffer writeable or is it read-only. Default: true. /** This flag is forced to false if the MaterialType is a transparent type and the scene parameter ALLOW_ZWRITE_ON_TRANSPARENT is not set. */ bool ZWriteEnable:1; //! Is backface culling enabled? Default: true bool BackfaceCulling:1; //! Is frontface culling enabled? Default: false bool FrontfaceCulling:1; //! Is fog enabled? Default: false bool FogEnable:1; //! Should normals be normalized? /** Always use this if the mesh lit and scaled. Default: false */ bool NormalizeNormals:1; //! Shall mipmaps be used if available /** Sometimes, disabling mipmap usage can be useful. Default: true */ bool UseMipMaps:1; //! Gets the texture transformation matrix for level i /** \param i The desired level. Must not be larger than MATERIAL_MAX_TEXTURES. \return Texture matrix for texture level i. */ core::matrix4& getTextureMatrix(u32 i) { return TextureLayer[i].getTextureMatrix(); } //! Gets the immutable texture transformation matrix for level i /** \param i The desired level. \return Texture matrix for texture level i, or identity matrix for levels larger than MATERIAL_MAX_TEXTURES. */ const core::matrix4& getTextureMatrix(u32 i) const { if (i=MATERIAL_MAX_TEXTURES) return; TextureLayer[i].setTextureMatrix(mat); } //! Gets the i-th texture /** \param i The desired level. \return Texture for texture level i, if defined, else 0. */ ITexture* getTexture(u32 i) const { return i < MATERIAL_MAX_TEXTURES ? TextureLayer[i].Texture : 0; } //! Sets the i-th texture /** If i>=MATERIAL_MAX_TEXTURES this setting will be ignored. \param i The desired level. \param tex Texture for texture level i. */ void setTexture(u32 i, ITexture* tex) { if (i>=MATERIAL_MAX_TEXTURES) return; TextureLayer[i].Texture = tex; } //! Sets the Material flag to the given value /** \param flag The flag to be set. \param value The new value for the flag. */ void setFlag(E_MATERIAL_FLAG flag, bool value) { switch (flag) { case EMF_WIREFRAME: Wireframe = value; break; case EMF_POINTCLOUD: PointCloud = value; break; case EMF_GOURAUD_SHADING: GouraudShading = value; break; case EMF_LIGHTING: Lighting = value; break; case EMF_ZBUFFER: ZBuffer = value; break; case EMF_ZWRITE_ENABLE: ZWriteEnable = value; break; case EMF_BACK_FACE_CULLING: BackfaceCulling = value; break; case EMF_FRONT_FACE_CULLING: FrontfaceCulling = value; break; case EMF_BILINEAR_FILTER: { for (u32 i=0; i(800, 600)), Bits(16), ZBufferBits(16), Fullscreen(false), Stencilbuffer(false), Vsync(false), AntiAlias(0), HandleSRGB(false), WithAlphaChannel(false), Doublebuffer(true), IgnoreInput(false), Stereobuffer(false), HighPrecisionFPU(false), EventReceiver(0), WindowId(0), #ifdef _DEBUG LoggingLevel(ELL_DEBUG), #else LoggingLevel(ELL_INFORMATION), #endif DisplayAdapter(0), DriverMultithreaded(false), UsePerformanceTimer(true), SDK_version_do_not_use(IRRLICHT_SDK_VERSION) { } SIrrlichtCreationParameters(const SIrrlichtCreationParameters& other) : SDK_version_do_not_use(IRRLICHT_SDK_VERSION) {*this = other;} SIrrlichtCreationParameters& operator=(const SIrrlichtCreationParameters& other) { DeviceType = other.DeviceType; DriverType = other.DriverType; WindowSize = other.WindowSize; Bits = other.Bits; ZBufferBits = other.ZBufferBits; Fullscreen = other.Fullscreen; Stencilbuffer = other.Stencilbuffer; Vsync = other.Vsync; AntiAlias = other.AntiAlias; HandleSRGB = other.HandleSRGB; WithAlphaChannel = other.WithAlphaChannel; Doublebuffer = other.Doublebuffer; IgnoreInput = other.IgnoreInput; Stereobuffer = other.Stereobuffer; HighPrecisionFPU = other.HighPrecisionFPU; EventReceiver = other.EventReceiver; WindowId = other.WindowId; LoggingLevel = other.LoggingLevel; DriverMultithreaded = other.DriverMultithreaded; DisplayAdapter = other.DisplayAdapter; UsePerformanceTimer = other.UsePerformanceTimer; return *this; } //! Type of the device. /** This setting decides the windowing system used by the device, most device types are native to a specific operating system and so may not be available. EIDT_WIN32 is only available on Windows desktops, EIDT_WINCE is only available on Windows mobile devices, EIDT_COCOA is only available on Mac OSX, EIDT_X11 is available on Linux, Solaris, BSD and other operating systems which use X11, EIDT_SDL is available on most systems if compiled in, EIDT_CONSOLE is usually available but can only render to text, EIDT_BEST will select the best available device for your operating system. Default: EIDT_BEST. */ E_DEVICE_TYPE DeviceType; //! Type of video driver used to render graphics. /** This can currently be video::EDT_NULL, video::EDT_SOFTWARE, video::EDT_BURNINGSVIDEO, video::EDT_DIRECT3D8, video::EDT_DIRECT3D9, and video::EDT_OPENGL. Default: Software. */ video::E_DRIVER_TYPE DriverType; //! Size of the window or the video mode in fullscreen mode. Default: 800x600 core::dimension2d WindowSize; //! Minimum Bits per pixel of the color buffer in fullscreen mode. Ignored if windowed mode. Default: 16. u8 Bits; //! Minimum Bits per pixel of the depth buffer. Default: 16. u8 ZBufferBits; //! Should be set to true if the device should run in fullscreen. /** Otherwise the device runs in windowed mode. Default: false. */ bool Fullscreen; //! Specifies if the stencil buffer should be enabled. /** Set this to true, if you want the engine be able to draw stencil buffer shadows. Note that not all drivers are able to use the stencil buffer, hence it can be ignored during device creation. Without the stencil buffer no shadows will be drawn. Default: false. */ bool Stencilbuffer; //! Specifies vertical syncronisation. /** If set to true, the driver will wait for the vertical retrace period, otherwise not. May be silently ignored. Default: false */ bool Vsync; //! Specifies if the device should use fullscreen anti aliasing /** Makes sharp/pixelated edges softer, but requires more performance. Also, 2D elements might look blurred with this switched on. The resulting rendering quality also depends on the hardware and driver you are using, your program might look different on different hardware with this. So if you are writing a game/application with AntiAlias switched on, it would be a good idea to make it possible to switch this option off again by the user. The value is the maximal antialiasing factor requested for the device. The cretion method will automatically try smaller values if no window can be created with the given value. Value one is usually the same as 0 (disabled), but might be a special value on some platforms. On D3D devices it maps to NONMASKABLE. Default value: 0 - disabled */ u8 AntiAlias; //! Flag to enable proper sRGB and linear color handling /** In most situations, it is desireable to have the color handling in non-linear sRGB color space, and only do the intermediate color calculations in linear RGB space. If this flag is enabled, the device and driver try to assure that all color input and output are color corrected and only the internal color representation is linear. This means, that the color output is properly gamma-adjusted to provide the brighter colors for monitor display. And that blending and lighting give a more natural look, due to proper conversion from non-linear colors into linear color space for blend operations. If this flag is enabled, all texture colors (which are usually in sRGB space) are correctly displayed. However vertex colors and other explicitly set values have to be manually encoded in linear color space. Default value: false. */ bool HandleSRGB; //! Whether the main framebuffer uses an alpha channel. /** In some situations it might be desireable to get a color buffer with an alpha channel, e.g. when rendering into a transparent window or overlay. If this flag is set the device tries to create a framebuffer with alpha channel. If this flag is set, only color buffers with alpha channel are considered. Otherwise, it depends on the actual hardware if the colorbuffer has an alpha channel or not. Default value: false */ bool WithAlphaChannel; //! Whether the main framebuffer uses doublebuffering. /** This should be usually enabled, in order to avoid render artifacts on the visible framebuffer. However, it might be useful to use only one buffer on very small devices. If no doublebuffering is available, the drivers will fall back to single buffers. Default value: true */ bool Doublebuffer; //! Specifies if the device should ignore input events /** This is only relevant when using external I/O handlers. External windows need to take care of this themselves. Currently only supported by X11. Default value: false */ bool IgnoreInput; //! Specifies if the device should use stereo buffers /** Some high-end gfx cards support two framebuffers for direct support of stereoscopic output devices. If this flag is set the device tries to create a stereo context. Currently only supported by OpenGL. Default value: false */ bool Stereobuffer; //! Specifies if the device should use high precision FPU setting /** This is only relevant for DirectX Devices, which switch to low FPU precision by default for performance reasons. However, this may lead to problems with the other computations of the application. In this case setting this flag to true should help - on the expense of performance loss, though. Default value: false */ bool HighPrecisionFPU; //! A user created event receiver. IEventReceiver* EventReceiver; //! Window Id. /** If this is set to a value other than 0, the Irrlicht Engine will be created in an already existing window. For windows, set this to the HWND of the window you want. The windowSize and FullScreen options will be ignored when using the WindowId parameter. Default this is set to 0. To make Irrlicht run inside the custom window, you still will have to draw Irrlicht on your own. You can use this loop, as usual: \code while (device->run()) { driver->beginScene(true, true, 0); smgr->drawAll(); driver->endScene(); } \endcode Instead of this, you can also simply use your own message loop using GetMessage, DispatchMessage and whatever. Calling IrrlichtDevice::run() will cause Irrlicht to dispatch messages internally too. You need not call Device->run() if you want to do your own message dispatching loop, but Irrlicht will not be able to fetch user input then and you have to do it on your own using the window messages, DirectInput, or whatever. Also, you'll have to increment the Irrlicht timer. An alternative, own message dispatching loop without device->run() would look like this: \code MSG msg; while (true) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); if (msg.message == WM_QUIT) break; } // increase virtual timer time device->getTimer()->tick(); // draw engine picture driver->beginScene(true, true, 0); smgr->drawAll(); driver->endScene(); } \endcode However, there is no need to draw the picture this often. Just do it how you like. */ void* WindowId; //! Specifies the logging level used in the logging interface. /** The default value is ELL_INFORMATION. You can access the ILogger interface later on from the IrrlichtDevice with getLogger() and set another level. But if you need more or less logging information already from device creation, then you have to change it here. */ ELOG_LEVEL LoggingLevel; //! Allows to select which graphic card is used for rendering when more than one card is in the system. /** So far only supported on D3D */ u32 DisplayAdapter; //! Create the driver multithreaded. /** Default is false. Enabling this can slow down your application. Note that this does _not_ make Irrlicht threadsafe, but only the underlying driver-API for the graphiccard. So far only supported on D3D. */ bool DriverMultithreaded; //! Enables use of high performance timers on Windows platform. /** When performance timers are not used, standard GetTickCount() is used instead which usually has worse resolution, but also less problems with speed stepping and other techniques. */ bool UsePerformanceTimer; //! Don't use or change this parameter. /** Always set it to IRRLICHT_SDK_VERSION, which is done by default. This is needed for sdk version checks. */ const c8* const SDK_version_do_not_use; }; } // end namespace irr #endif irrlicht-1.8.3/include/SExposedVideoData.h0000644000000000000000000000452212574354552017167 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_EXPOSED_VIDEO_DATA_H_INCLUDED__ #define __S_EXPOSED_VIDEO_DATA_H_INCLUDED__ // forward declarations for internal pointers struct IDirect3D9; struct IDirect3DDevice9; struct IDirect3D8; struct IDirect3DDevice8; namespace irr { namespace video { //! structure for holding data describing a driver and operating system specific data. /** This data can be retrived by IVideoDriver::getExposedVideoData(). Use this with caution. This only should be used to make it possible to extend the engine easily without modification of its source. Note that this structure does not contain any valid data, if you are using the software or the null device. */ struct SExposedVideoData { SExposedVideoData() {OpenGLWin32.HDc=0; OpenGLWin32.HRc=0; OpenGLWin32.HWnd=0;} explicit SExposedVideoData(void* Window) {OpenGLWin32.HDc=0; OpenGLWin32.HRc=0; OpenGLWin32.HWnd=Window;} union { struct { //! Pointer to the IDirect3D9 interface IDirect3D9* D3D9; //! Pointer to the IDirect3DDevice9 interface IDirect3DDevice9* D3DDev9; //! Window handle. /** Get with for example HWND h = reinterpret_cast(exposedData.D3D9.HWnd) */ void* HWnd; } D3D9; struct { //! Pointer to the IDirect3D8 interface IDirect3D8* D3D8; //! Pointer to the IDirect3DDevice8 interface IDirect3DDevice8* D3DDev8; //! Window handle. /** Get with for example with: HWND h = reinterpret_cast(exposedData.D3D8.HWnd) */ void* HWnd; } D3D8; struct { //! Private GDI Device Context. /** Get if for example with: HDC h = reinterpret_cast(exposedData.OpenGLWin32.HDc) */ void* HDc; //! Permanent Rendering Context. /** Get if for example with: HGLRC h = reinterpret_cast(exposedData.OpenGLWin32.HRc) */ void* HRc; //! Window handle. /** Get with for example with: HWND h = reinterpret_cast(exposedData.OpenGLWin32.HWnd) */ void* HWnd; } OpenGLWin32; struct { // XWindow handles void* X11Display; void* X11Context; unsigned long X11Window; } OpenGLLinux; }; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/SColor.h0000644000000000000000000005222412574354552015057 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __COLOR_H_INCLUDED__ #define __COLOR_H_INCLUDED__ #include "irrTypes.h" #include "irrMath.h" namespace irr { namespace video { //! An enum for the color format of textures used by the Irrlicht Engine. /** A color format specifies how color information is stored. */ enum ECOLOR_FORMAT { //! 16 bit color format used by the software driver. /** It is thus preferred by all other irrlicht engine video drivers. There are 5 bits for every color component, and a single bit is left for alpha information. */ ECF_A1R5G5B5 = 0, //! Standard 16 bit color format. ECF_R5G6B5, //! 24 bit color, no alpha channel, but 8 bit for red, green and blue. ECF_R8G8B8, //! Default 32 bit color format. 8 bits are used for every component: red, green, blue and alpha. ECF_A8R8G8B8, /** Floating Point formats. The following formats may only be used for render target textures. */ //! 16 bit floating point format using 16 bits for the red channel. ECF_R16F, //! 32 bit floating point format using 16 bits for the red channel and 16 bits for the green channel. ECF_G16R16F, //! 64 bit floating point format 16 bits are used for the red, green, blue and alpha channels. ECF_A16B16G16R16F, //! 32 bit floating point format using 32 bits for the red channel. ECF_R32F, //! 64 bit floating point format using 32 bits for the red channel and 32 bits for the green channel. ECF_G32R32F, //! 128 bit floating point format. 32 bits are used for the red, green, blue and alpha channels. ECF_A32B32G32R32F, //! Unknown color format: ECF_UNKNOWN }; //! Creates a 16 bit A1R5G5B5 color inline u16 RGBA16(u32 r, u32 g, u32 b, u32 a=0xFF) { return (u16)((a & 0x80) << 8 | (r & 0xF8) << 7 | (g & 0xF8) << 2 | (b & 0xF8) >> 3); } //! Creates a 16 bit A1R5G5B5 color inline u16 RGB16(u32 r, u32 g, u32 b) { return RGBA16(r,g,b); } //! Creates a 16bit A1R5G5B5 color, based on 16bit input values inline u16 RGB16from16(u16 r, u16 g, u16 b) { return (0x8000 | (r & 0x1F) << 10 | (g & 0x1F) << 5 | (b & 0x1F)); } //! Converts a 32bit (X8R8G8B8) color to a 16bit A1R5G5B5 color inline u16 X8R8G8B8toA1R5G5B5(u32 color) { return (u16)(0x8000 | ( color & 0x00F80000) >> 9 | ( color & 0x0000F800) >> 6 | ( color & 0x000000F8) >> 3); } //! Converts a 32bit (A8R8G8B8) color to a 16bit A1R5G5B5 color inline u16 A8R8G8B8toA1R5G5B5(u32 color) { return (u16)(( color & 0x80000000) >> 16| ( color & 0x00F80000) >> 9 | ( color & 0x0000F800) >> 6 | ( color & 0x000000F8) >> 3); } //! Converts a 32bit (A8R8G8B8) color to a 16bit R5G6B5 color inline u16 A8R8G8B8toR5G6B5(u32 color) { return (u16)(( color & 0x00F80000) >> 8 | ( color & 0x0000FC00) >> 5 | ( color & 0x000000F8) >> 3); } //! Convert A8R8G8B8 Color from A1R5G5B5 color /** build a nicer 32bit Color by extending dest lower bits with source high bits. */ inline u32 A1R5G5B5toA8R8G8B8(u16 color) { return ( (( -( (s32) color & 0x00008000 ) >> (s32) 31 ) & 0xFF000000 ) | (( color & 0x00007C00 ) << 9) | (( color & 0x00007000 ) << 4) | (( color & 0x000003E0 ) << 6) | (( color & 0x00000380 ) << 1) | (( color & 0x0000001F ) << 3) | (( color & 0x0000001C ) >> 2) ); } //! Returns A8R8G8B8 Color from R5G6B5 color inline u32 R5G6B5toA8R8G8B8(u16 color) { return 0xFF000000 | ((color & 0xF800) << 8)| ((color & 0x07E0) << 5)| ((color & 0x001F) << 3); } //! Returns A1R5G5B5 Color from R5G6B5 color inline u16 R5G6B5toA1R5G5B5(u16 color) { return 0x8000 | (((color & 0xFFC0) >> 1) | (color & 0x1F)); } //! Returns R5G6B5 Color from A1R5G5B5 color inline u16 A1R5G5B5toR5G6B5(u16 color) { return (((color & 0x7FE0) << 1) | (color & 0x1F)); } //! Returns the alpha component from A1R5G5B5 color /** In Irrlicht, alpha refers to opacity. \return The alpha value of the color. 0 is transparent, 1 is opaque. */ inline u32 getAlpha(u16 color) { return ((color >> 15)&0x1); } //! Returns the red component from A1R5G5B5 color. /** Shift left by 3 to get 8 bit value. */ inline u32 getRed(u16 color) { return ((color >> 10)&0x1F); } //! Returns the green component from A1R5G5B5 color /** Shift left by 3 to get 8 bit value. */ inline u32 getGreen(u16 color) { return ((color >> 5)&0x1F); } //! Returns the blue component from A1R5G5B5 color /** Shift left by 3 to get 8 bit value. */ inline u32 getBlue(u16 color) { return (color & 0x1F); } //! Returns the average from a 16 bit A1R5G5B5 color inline s32 getAverage(s16 color) { return ((getRed(color)<<3) + (getGreen(color)<<3) + (getBlue(color)<<3)) / 3; } //! Class representing a 32 bit ARGB color. /** The color values for alpha, red, green, and blue are stored in a single u32. So all four values may be between 0 and 255. Alpha in Irrlicht is opacity, so 0 is fully transparent, 255 is fully opaque (solid). This class is used by most parts of the Irrlicht Engine to specify a color. Another way is using the class SColorf, which stores the color values in 4 floats. This class must consist of only one u32 and must not use virtual functions. */ class SColor { public: //! Constructor of the Color. Does nothing. /** The color value is not initialized to save time. */ SColor() {} //! Constructs the color from 4 values representing the alpha, red, green and blue component. /** Must be values between 0 and 255. */ SColor (u32 a, u32 r, u32 g, u32 b) : color(((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)) {} //! Constructs the color from a 32 bit value. Could be another color. SColor(u32 clr) : color(clr) {} //! Returns the alpha component of the color. /** The alpha component defines how opaque a color is. \return The alpha value of the color. 0 is fully transparent, 255 is fully opaque. */ u32 getAlpha() const { return color>>24; } //! Returns the red component of the color. /** \return Value between 0 and 255, specifying how red the color is. 0 means no red, 255 means full red. */ u32 getRed() const { return (color>>16) & 0xff; } //! Returns the green component of the color. /** \return Value between 0 and 255, specifying how green the color is. 0 means no green, 255 means full green. */ u32 getGreen() const { return (color>>8) & 0xff; } //! Returns the blue component of the color. /** \return Value between 0 and 255, specifying how blue the color is. 0 means no blue, 255 means full blue. */ u32 getBlue() const { return color & 0xff; } //! Get lightness of the color in the range [0,255] f32 getLightness() const { return 0.5f*(core::max_(core::max_(getRed(),getGreen()),getBlue())+core::min_(core::min_(getRed(),getGreen()),getBlue())); } //! Get luminance of the color in the range [0,255]. f32 getLuminance() const { return 0.3f*getRed() + 0.59f*getGreen() + 0.11f*getBlue(); } //! Get average intensity of the color in the range [0,255]. u32 getAverage() const { return ( getRed() + getGreen() + getBlue() ) / 3; } //! Sets the alpha component of the Color. /** The alpha component defines how transparent a color should be. \param a The alpha value of the color. 0 is fully transparent, 255 is fully opaque. */ void setAlpha(u32 a) { color = ((a & 0xff)<<24) | (color & 0x00ffffff); } //! Sets the red component of the Color. /** \param r: Has to be a value between 0 and 255. 0 means no red, 255 means full red. */ void setRed(u32 r) { color = ((r & 0xff)<<16) | (color & 0xff00ffff); } //! Sets the green component of the Color. /** \param g: Has to be a value between 0 and 255. 0 means no green, 255 means full green. */ void setGreen(u32 g) { color = ((g & 0xff)<<8) | (color & 0xffff00ff); } //! Sets the blue component of the Color. /** \param b: Has to be a value between 0 and 255. 0 means no blue, 255 means full blue. */ void setBlue(u32 b) { color = (b & 0xff) | (color & 0xffffff00); } //! Calculates a 16 bit A1R5G5B5 value of this color. /** \return 16 bit A1R5G5B5 value of this color. */ u16 toA1R5G5B5() const { return A8R8G8B8toA1R5G5B5(color); } //! Converts color to OpenGL color format /** From ARGB to RGBA in 4 byte components for endian aware passing to OpenGL \param dest: address where the 4x8 bit OpenGL color is stored. */ void toOpenGLColor(u8* dest) const { *dest = (u8)getRed(); *++dest = (u8)getGreen(); *++dest = (u8)getBlue(); *++dest = (u8)getAlpha(); } //! Sets all four components of the color at once. /** Constructs the color from 4 values representing the alpha, red, green and blue components of the color. Must be values between 0 and 255. \param a: Alpha component of the color. The alpha component defines how transparent a color should be. Has to be a value between 0 and 255. 255 means not transparent (opaque), 0 means fully transparent. \param r: Sets the red component of the Color. Has to be a value between 0 and 255. 0 means no red, 255 means full red. \param g: Sets the green component of the Color. Has to be a value between 0 and 255. 0 means no green, 255 means full green. \param b: Sets the blue component of the Color. Has to be a value between 0 and 255. 0 means no blue, 255 means full blue. */ void set(u32 a, u32 r, u32 g, u32 b) { color = (((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)); } void set(u32 col) { color = col; } //! Compares the color to another color. /** \return True if the colors are the same, and false if not. */ bool operator==(const SColor& other) const { return other.color == color; } //! Compares the color to another color. /** \return True if the colors are different, and false if they are the same. */ bool operator!=(const SColor& other) const { return other.color != color; } //! comparison operator /** \return True if this color is smaller than the other one */ bool operator<(const SColor& other) const { return (color < other.color); } //! Adds two colors, result is clamped to 0..255 values /** \param other Color to add to this color \return Addition of the two colors, clamped to 0..255 values */ SColor operator+(const SColor& other) const { return SColor(core::min_(getAlpha() + other.getAlpha(), 255u), core::min_(getRed() + other.getRed(), 255u), core::min_(getGreen() + other.getGreen(), 255u), core::min_(getBlue() + other.getBlue(), 255u)); } //! Interpolates the color with a f32 value to another color /** \param other: Other color \param d: value between 0.0f and 1.0f \return Interpolated color. */ SColor getInterpolated(const SColor &other, f32 d) const { d = core::clamp(d, 0.f, 1.f); const f32 inv = 1.0f - d; return SColor((u32)core::round32(other.getAlpha()*inv + getAlpha()*d), (u32)core::round32(other.getRed()*inv + getRed()*d), (u32)core::round32(other.getGreen()*inv + getGreen()*d), (u32)core::round32(other.getBlue()*inv + getBlue()*d)); } //! Returns interpolated color. ( quadratic ) /** \param c1: first color to interpolate with \param c2: second color to interpolate with \param d: value between 0.0f and 1.0f. */ SColor getInterpolated_quadratic(const SColor& c1, const SColor& c2, f32 d) const { // this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d; d = core::clamp(d, 0.f, 1.f); const f32 inv = 1.f - d; const f32 mul0 = inv * inv; const f32 mul1 = 2.f * d * inv; const f32 mul2 = d * d; return SColor( core::clamp( core::floor32( getAlpha() * mul0 + c1.getAlpha() * mul1 + c2.getAlpha() * mul2 ), 0, 255 ), core::clamp( core::floor32( getRed() * mul0 + c1.getRed() * mul1 + c2.getRed() * mul2 ), 0, 255 ), core::clamp ( core::floor32( getGreen() * mul0 + c1.getGreen() * mul1 + c2.getGreen() * mul2 ), 0, 255 ), core::clamp ( core::floor32( getBlue() * mul0 + c1.getBlue() * mul1 + c2.getBlue() * mul2 ), 0, 255 )); } //! set the color by expecting data in the given format /** \param data: must point to valid memory containing color information in the given format \param format: tells the format in which data is available */ void setData(const void *data, ECOLOR_FORMAT format) { switch (format) { case ECF_A1R5G5B5: color = A1R5G5B5toA8R8G8B8(*(u16*)data); break; case ECF_R5G6B5: color = R5G6B5toA8R8G8B8(*(u16*)data); break; case ECF_A8R8G8B8: color = *(u32*)data; break; case ECF_R8G8B8: { u8* p = (u8*)data; set(255, p[0],p[1],p[2]); } break; default: color = 0xffffffff; break; } } //! Write the color to data in the defined format /** \param data: target to write the color. Must contain sufficiently large memory to receive the number of bytes neede for format \param format: tells the format used to write the color into data */ void getData(void *data, ECOLOR_FORMAT format) { switch(format) { case ECF_A1R5G5B5: { u16 * dest = (u16*)data; *dest = video::A8R8G8B8toA1R5G5B5( color ); } break; case ECF_R5G6B5: { u16 * dest = (u16*)data; *dest = video::A8R8G8B8toR5G6B5( color ); } break; case ECF_R8G8B8: { u8* dest = (u8*)data; dest[0] = (u8)getRed(); dest[1] = (u8)getGreen(); dest[2] = (u8)getBlue(); } break; case ECF_A8R8G8B8: { u32 * dest = (u32*)data; *dest = color; } break; default: break; } } //! color in A8R8G8B8 Format u32 color; }; //! Class representing a color with four floats. /** The color values for red, green, blue and alpha are each stored in a 32 bit floating point variable. So all four values may be between 0.0f and 1.0f. Another, faster way to define colors is using the class SColor, which stores the color values in a single 32 bit integer. */ class SColorf { public: //! Default constructor for SColorf. /** Sets red, green and blue to 0.0f and alpha to 1.0f. */ SColorf() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {} //! Constructs a color from up to four color values: red, green, blue, and alpha. /** \param r: Red color component. Should be a value between 0.0f meaning no red and 1.0f, meaning full red. \param g: Green color component. Should be a value between 0.0f meaning no green and 1.0f, meaning full green. \param b: Blue color component. Should be a value between 0.0f meaning no blue and 1.0f, meaning full blue. \param a: Alpha color component of the color. The alpha component defines how transparent a color should be. Has to be a value between 0.0f and 1.0f, 1.0f means not transparent (opaque), 0.0f means fully transparent. */ SColorf(f32 r, f32 g, f32 b, f32 a = 1.0f) : r(r), g(g), b(b), a(a) {} //! Constructs a color from 32 bit Color. /** \param c: 32 bit color from which this SColorf class is constructed from. */ SColorf(SColor c) { const f32 inv = 1.0f / 255.0f; r = c.getRed() * inv; g = c.getGreen() * inv; b = c.getBlue() * inv; a = c.getAlpha() * inv; } //! Converts this color to a SColor without floats. SColor toSColor() const { return SColor((u32)core::round32(a*255.0f), (u32)core::round32(r*255.0f), (u32)core::round32(g*255.0f), (u32)core::round32(b*255.0f)); } //! Sets three color components to new values at once. /** \param rr: Red color component. Should be a value between 0.0f meaning no red (=black) and 1.0f, meaning full red. \param gg: Green color component. Should be a value between 0.0f meaning no green (=black) and 1.0f, meaning full green. \param bb: Blue color component. Should be a value between 0.0f meaning no blue (=black) and 1.0f, meaning full blue. */ void set(f32 rr, f32 gg, f32 bb) {r = rr; g =gg; b = bb; } //! Sets all four color components to new values at once. /** \param aa: Alpha component. Should be a value between 0.0f meaning fully transparent and 1.0f, meaning opaque. \param rr: Red color component. Should be a value between 0.0f meaning no red and 1.0f, meaning full red. \param gg: Green color component. Should be a value between 0.0f meaning no green and 1.0f, meaning full green. \param bb: Blue color component. Should be a value between 0.0f meaning no blue and 1.0f, meaning full blue. */ void set(f32 aa, f32 rr, f32 gg, f32 bb) {a = aa; r = rr; g =gg; b = bb; } //! Interpolates the color with a f32 value to another color /** \param other: Other color \param d: value between 0.0f and 1.0f \return Interpolated color. */ SColorf getInterpolated(const SColorf &other, f32 d) const { d = core::clamp(d, 0.f, 1.f); const f32 inv = 1.0f - d; return SColorf(other.r*inv + r*d, other.g*inv + g*d, other.b*inv + b*d, other.a*inv + a*d); } //! Returns interpolated color. ( quadratic ) /** \param c1: first color to interpolate with \param c2: second color to interpolate with \param d: value between 0.0f and 1.0f. */ inline SColorf getInterpolated_quadratic(const SColorf& c1, const SColorf& c2, f32 d) const { d = core::clamp(d, 0.f, 1.f); // this*(1-d)*(1-d) + 2 * c1 * (1-d) + c2 * d * d; const f32 inv = 1.f - d; const f32 mul0 = inv * inv; const f32 mul1 = 2.f * d * inv; const f32 mul2 = d * d; return SColorf (r * mul0 + c1.r * mul1 + c2.r * mul2, g * mul0 + c1.g * mul1 + c2.g * mul2, b * mul0 + c1.b * mul1 + c2.b * mul2, a * mul0 + c1.a * mul1 + c2.a * mul2); } //! Sets a color component by index. R=0, G=1, B=2, A=3 void setColorComponentValue(s32 index, f32 value) { switch(index) { case 0: r = value; break; case 1: g = value; break; case 2: b = value; break; case 3: a = value; break; } } //! Returns the alpha component of the color in the range 0.0 (transparent) to 1.0 (opaque) f32 getAlpha() const { return a; } //! Returns the red component of the color in the range 0.0 to 1.0 f32 getRed() const { return r; } //! Returns the green component of the color in the range 0.0 to 1.0 f32 getGreen() const { return g; } //! Returns the blue component of the color in the range 0.0 to 1.0 f32 getBlue() const { return b; } //! red color component f32 r; //! green color component f32 g; //! blue component f32 b; //! alpha color component f32 a; }; //! Class representing a color in HSL format /** The color values for hue, saturation, luminance are stored in 32bit floating point variables. Hue is in range [0,360], Luminance and Saturation are in percent [0,100] */ class SColorHSL { public: SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f ) : Hue ( h ), Saturation ( s ), Luminance ( l ) {} void fromRGB(const SColorf &color); void toRGB(SColorf &color) const; f32 Hue; f32 Saturation; f32 Luminance; private: inline f32 toRGB1(f32 rm1, f32 rm2, f32 rh) const; }; inline void SColorHSL::fromRGB(const SColorf &color) { const f32 maxVal = core::max_(color.getRed(), color.getGreen(), color.getBlue()); const f32 minVal = (f32)core::min_(color.getRed(), color.getGreen(), color.getBlue()); Luminance = (maxVal+minVal)*50; if (core::equals(maxVal, minVal)) { Hue=0.f; Saturation=0.f; return; } const f32 delta = maxVal-minVal; if ( Luminance <= 50 ) { Saturation = (delta)/(maxVal+minVal); } else { Saturation = (delta)/(2-maxVal-minVal); } Saturation *= 100; if (core::equals(maxVal, color.getRed())) Hue = (color.getGreen()-color.getBlue())/delta; else if (core::equals(maxVal, color.getGreen())) Hue = 2+((color.getBlue()-color.getRed())/delta); else // blue is max Hue = 4+((color.getRed()-color.getGreen())/delta); Hue *= 60.0f; while ( Hue < 0.f ) Hue += 360; } inline void SColorHSL::toRGB(SColorf &color) const { const f32 l = Luminance/100; if (core::iszero(Saturation)) // grey { color.set(l, l, l); return; } f32 rm2; if ( Luminance <= 50 ) { rm2 = l + l * (Saturation/100); } else { rm2 = l + (1 - l) * (Saturation/100); } const f32 rm1 = 2.0f * l - rm2; const f32 h = Hue / 360.0f; color.set( toRGB1(rm1, rm2, h + 1.f/3.f), toRGB1(rm1, rm2, h), toRGB1(rm1, rm2, h - 1.f/3.f) ); } // algorithm from Foley/Van-Dam inline f32 SColorHSL::toRGB1(f32 rm1, f32 rm2, f32 rh) const { if (rh<0) rh += 1; if (rh>1) rh -= 1; if (rh < 1.f/6.f) rm1 = rm1 + (rm2 - rm1) * rh*6.f; else if (rh < 0.5f) rm1 = rm2; else if (rh < 2.f/3.f) rm1 = rm1 + (rm2 - rm1) * ((2.f/3.f)-rh)*6.f; return rm1; } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/SceneParameters.h0000644000000000000000000001540112574354552016733 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_PARAMETERS_H_INCLUDED__ #define __I_SCENE_PARAMETERS_H_INCLUDED__ /*! \file SceneParameters.h \brief Header file containing all scene parameters for modifying mesh loading etc. This file includes all parameter names which can be set using ISceneManager::getParameters() to modify the behavior of plugins and mesh loaders. */ namespace irr { namespace scene { //! Name of the parameter for changing how Irrlicht handles the ZWrite flag for transparent (blending) materials /** The default behavior in Irrlicht is to disable writing to the z-buffer for all really transparent, i.e. blending materials. This avoids problems with intersecting faces, but can also break renderings. If transparent materials should use the SMaterial flag for ZWriteEnable just as other material types use this attribute. Use it like this: \code SceneManager->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); \endcode **/ const c8* const ALLOW_ZWRITE_ON_TRANSPARENT = "Allow_ZWrite_On_Transparent"; //! Name of the parameter for changing the texture path of the built-in csm loader. /** Use it like this: \code SceneManager->getParameters()->setAttribute(scene::CSM_TEXTURE_PATH, "path/to/your/textures"); \endcode **/ const c8* const CSM_TEXTURE_PATH = "CSM_TexturePath"; //! Name of the parameter for changing the texture path of the built-in lmts loader. /** Use it like this: \code SceneManager->getParameters()->setAttribute(scene::LMTS_TEXTURE_PATH, "path/to/your/textures"); \endcode **/ const c8* const LMTS_TEXTURE_PATH = "LMTS_TexturePath"; //! Name of the parameter for changing the texture path of the built-in my3d loader. /** Use it like this: \code SceneManager->getParameters()->setAttribute(scene::MY3D_TEXTURE_PATH, "path/to/your/textures"); \endcode **/ const c8* const MY3D_TEXTURE_PATH = "MY3D_TexturePath"; //! Name of the parameter specifying the COLLADA mesh loading mode /** Specifies if the COLLADA loader should create instances of the models, lights and cameras when loading COLLADA meshes. By default, this is set to false. If this is set to true, the ISceneManager::getMesh() method will only return a pointer to a dummy mesh and create instances of all meshes and lights and cameras in the collada file by itself. Example: \code SceneManager->getParameters()->setAttribute(scene::COLLADA_CREATE_SCENE_INSTANCES, true); \endcode */ const c8* const COLLADA_CREATE_SCENE_INSTANCES = "COLLADA_CreateSceneInstances"; //! Name of the parameter for changing the texture path of the built-in DMF loader. /** This path is prefixed to the file names defined in the Deled file when loading textures. This allows to alter the paths for a specific project setting. Use it like this: \code SceneManager->getStringParameters()->setAttribute(scene::DMF_TEXTURE_PATH, "path/to/your/textures"); \endcode **/ const c8* const DMF_TEXTURE_PATH = "DMF_TexturePath"; //! Name of the parameter for preserving DMF textures dir structure with built-in DMF loader. /** If this parameter is set to true, the texture directory defined in the Deled file is ignored, and only the texture name is used to find the proper file. Otherwise, the texture path is also used, which allows to use a nicer media layout. Use it like this: \code //this way you won't use this setting (default) SceneManager->getParameters()->setAttribute(scene::DMF_IGNORE_MATERIALS_DIRS, false); \endcode \code //this way you'll use this setting SceneManager->getParameters()->setAttribute(scene::DMF_IGNORE_MATERIALS_DIRS, true); \endcode **/ const c8* const DMF_IGNORE_MATERIALS_DIRS = "DMF_IgnoreMaterialsDir"; //! Name of the parameter for setting reference value of alpha in transparent materials. /** Use it like this: \code //this way you'll set alpha ref to 0.1 SceneManager->getParameters()->setAttribute(scene::DMF_ALPHA_CHANNEL_REF, 0.1); \endcode **/ const c8* const DMF_ALPHA_CHANNEL_REF = "DMF_AlphaRef"; //! Name of the parameter for choose to flip or not tga files. /** Use it like this: \code //this way you'll choose to flip alpha textures SceneManager->getParameters()->setAttribute(scene::DMF_FLIP_ALPHA_TEXTURES, true); \endcode **/ const c8* const DMF_FLIP_ALPHA_TEXTURES = "DMF_FlipAlpha"; //! Name of the parameter for changing the texture path of the built-in obj loader. /** Use it like this: \code SceneManager->getParameters()->setAttribute(scene::OBJ_TEXTURE_PATH, "path/to/your/textures"); \endcode **/ const c8* const OBJ_TEXTURE_PATH = "OBJ_TexturePath"; //! Flag to avoid loading group structures in .obj files /** Use it like this: \code SceneManager->getParameters()->setAttribute(scene::OBJ_LOADER_IGNORE_GROUPS, true); \endcode **/ const c8* const OBJ_LOADER_IGNORE_GROUPS = "OBJ_IgnoreGroups"; //! Flag to avoid loading material .mtl file for .obj files /** Use it like this: \code SceneManager->getParameters()->setAttribute(scene::OBJ_LOADER_IGNORE_MATERIAL_FILES, true); \endcode **/ const c8* const OBJ_LOADER_IGNORE_MATERIAL_FILES = "OBJ_IgnoreMaterialFiles"; //! Flag to ignore the b3d file's mipmapping flag /** Instead Irrlicht's texture creation flag is used. Use it like this: \code SceneManager->getParameters()->setAttribute(scene::B3D_LOADER_IGNORE_MIPMAP_FLAG, true); \endcode **/ const c8* const B3D_LOADER_IGNORE_MIPMAP_FLAG = "B3D_IgnoreMipmapFlag"; //! Name of the parameter for changing the texture path of the built-in b3d loader. /** Use it like this: \code SceneManager->getParameters()->setAttribute(scene::B3D_TEXTURE_PATH, "path/to/your/textures"); \endcode **/ const c8* const B3D_TEXTURE_PATH = "B3D_TexturePath"; //! Flag set as parameter when the scene manager is used as editor /** In this way special animators like deletion animators can be stopped from deleting scene nodes for example */ const c8* const IRR_SCENE_MANAGER_IS_EDITOR = "IRR_Editor"; //! Name of the parameter for setting the length of debug normals. /** Use it like this: \code SceneManager->getParameters()->setAttribute(scene::DEBUG_NORMAL_LENGTH, 1.5f); \endcode **/ const c8* const DEBUG_NORMAL_LENGTH = "DEBUG_Normal_Length"; //! Name of the parameter for setting the color of debug normals. /** Use it like this: \code SceneManager->getParameters()->setAttributeAsColor(scene::DEBUG_NORMAL_COLOR, video::SColor(255, 255, 255, 255)); \endcode **/ const c8* const DEBUG_NORMAL_COLOR = "DEBUG_Normal_Color"; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/SAnimatedMesh.h0000644000000000000000000001163012574354552016334 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_ANIMATED_MESH_H_INCLUDED__ #define __S_ANIMATED_MESH_H_INCLUDED__ #include "IAnimatedMesh.h" #include "IMesh.h" #include "aabbox3d.h" #include "irrArray.h" namespace irr { namespace scene { //! Simple implementation of the IAnimatedMesh interface. struct SAnimatedMesh : public IAnimatedMesh { //! constructor SAnimatedMesh(scene::IMesh* mesh=0, scene::E_ANIMATED_MESH_TYPE type=scene::EAMT_UNKNOWN) : IAnimatedMesh(), FramesPerSecond(25.f), Type(type) { #ifdef _DEBUG setDebugName("SAnimatedMesh"); #endif addMesh(mesh); recalculateBoundingBox(); } //! destructor virtual ~SAnimatedMesh() { // drop meshes for (u32 i=0; idrop(); } //! Gets the frame count of the animated mesh. /** \return Amount of frames. If the amount is 1, it is a static, non animated mesh. */ virtual u32 getFrameCount() const { return Meshes.size(); } //! Gets the default animation speed of the animated mesh. /** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */ virtual f32 getAnimationSpeed() const { return FramesPerSecond; } //! Gets the frame count of the animated mesh. /** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated. The actual speed is set in the scene node the mesh is instantiated in.*/ virtual void setAnimationSpeed(f32 fps) { FramesPerSecond=fps; } //! Returns the IMesh interface for a frame. /** \param frame: Frame number as zero based index. The maximum frame number is getFrameCount() - 1; \param detailLevel: Level of detail. 0 is the lowest, 255 the highest level of detail. Most meshes will ignore the detail level. \param startFrameLoop: start frame \param endFrameLoop: end frame \return The animated mesh based on a detail level. */ virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1) { if (Meshes.empty()) return 0; return Meshes[frame]; } //! adds a Mesh void addMesh(IMesh* mesh) { if (mesh) { mesh->grab(); Meshes.push_back(mesh); } } //! Returns an axis aligned bounding box of the mesh. /** \return A bounding box of this mesh is returned. */ virtual const core::aabbox3d& getBoundingBox() const { return Box; } //! set user axis aligned bounding box virtual void setBoundingBox(const core::aabbox3df& box) { Box = box; } //! Recalculates the bounding box. void recalculateBoundingBox() { Box.reset(0,0,0); if (Meshes.empty()) return; Box = Meshes[0]->getBoundingBox(); for (u32 i=1; igetBoundingBox()); } //! Returns the type of the animated mesh. virtual E_ANIMATED_MESH_TYPE getMeshType() const { return Type; } //! returns amount of mesh buffers. virtual u32 getMeshBufferCount() const { if (Meshes.empty()) return 0; return Meshes[0]->getMeshBufferCount(); } //! returns pointer to a mesh buffer virtual IMeshBuffer* getMeshBuffer(u32 nr) const { if (Meshes.empty()) return 0; return Meshes[0]->getMeshBuffer(nr); } //! Returns pointer to a mesh buffer which fits a material /** \param material: material to search for \return Returns the pointer to the mesh buffer or NULL if there is no such mesh buffer. */ virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const { if (Meshes.empty()) return 0; return Meshes[0]->getMeshBuffer(material); } //! Set a material flag for all meshbuffers of this mesh. virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) { for (u32 i=0; isetMaterialFlag(flag, newvalue); } //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint( E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX ) { for (u32 i=0; isetHardwareMappingHint(newMappingHint, buffer); } //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) { for (u32 i=0; isetDirty(buffer); } //! All meshes defining the animated mesh core::array Meshes; //! The bounding box of this mesh core::aabbox3d Box; //! Default animation speed of this mesh. f32 FramesPerSecond; //! The type of the mesh. E_ANIMATED_MESH_TYPE Type; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/S3DVertex.h0000644000000000000000000002022612574354552015442 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __S_3D_VERTEX_H_INCLUDED__ #define __S_3D_VERTEX_H_INCLUDED__ #include "vector3d.h" #include "vector2d.h" #include "SColor.h" namespace irr { namespace video { //! Enumeration for all vertex types there are. enum E_VERTEX_TYPE { //! Standard vertex type used by the Irrlicht engine, video::S3DVertex. EVT_STANDARD = 0, //! Vertex with two texture coordinates, video::S3DVertex2TCoords. /** Usually used for geometry with lightmaps or other special materials. */ EVT_2TCOORDS, //! Vertex with a tangent and binormal vector, video::S3DVertexTangents. /** Usually used for tangent space normal mapping. */ EVT_TANGENTS }; //! Array holding the built in vertex type names const char* const sBuiltInVertexTypeNames[] = { "standard", "2tcoords", "tangents", 0 }; //! standard vertex used by the Irrlicht engine. struct S3DVertex { //! default constructor S3DVertex() {} //! constructor S3DVertex(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv) : Pos(x,y,z), Normal(nx,ny,nz), Color(c), TCoords(tu,tv) {} //! constructor S3DVertex(const core::vector3df& pos, const core::vector3df& normal, SColor color, const core::vector2d& tcoords) : Pos(pos), Normal(normal), Color(color), TCoords(tcoords) {} //! Position core::vector3df Pos; //! Normal vector core::vector3df Normal; //! Color SColor Color; //! Texture coordinates core::vector2d TCoords; bool operator==(const S3DVertex& other) const { return ((Pos == other.Pos) && (Normal == other.Normal) && (Color == other.Color) && (TCoords == other.TCoords)); } bool operator!=(const S3DVertex& other) const { return ((Pos != other.Pos) || (Normal != other.Normal) || (Color != other.Color) || (TCoords != other.TCoords)); } bool operator<(const S3DVertex& other) const { return ((Pos < other.Pos) || ((Pos == other.Pos) && (Normal < other.Normal)) || ((Pos == other.Pos) && (Normal == other.Normal) && (Color < other.Color)) || ((Pos == other.Pos) && (Normal == other.Normal) && (Color == other.Color) && (TCoords < other.TCoords))); } E_VERTEX_TYPE getType() const { return EVT_STANDARD; } S3DVertex getInterpolated(const S3DVertex& other, f32 d) { d = core::clamp(d, 0.0f, 1.0f); return S3DVertex(Pos.getInterpolated(other.Pos, d), Normal.getInterpolated(other.Normal, d), Color.getInterpolated(other.Color, d), TCoords.getInterpolated(other.TCoords, d)); } }; //! Vertex with two texture coordinates. /** Usually used for geometry with lightmaps or other special materials. */ struct S3DVertex2TCoords : public S3DVertex { //! default constructor S3DVertex2TCoords() : S3DVertex() {} //! constructor with two different texture coords, but no normal S3DVertex2TCoords(f32 x, f32 y, f32 z, SColor c, f32 tu, f32 tv, f32 tu2, f32 tv2) : S3DVertex(x,y,z, 0.0f, 0.0f, 0.0f, c, tu,tv), TCoords2(tu2,tv2) {} //! constructor with two different texture coords, but no normal S3DVertex2TCoords(const core::vector3df& pos, SColor color, const core::vector2d& tcoords, const core::vector2d& tcoords2) : S3DVertex(pos, core::vector3df(), color, tcoords), TCoords2(tcoords2) {} //! constructor with all values S3DVertex2TCoords(const core::vector3df& pos, const core::vector3df& normal, const SColor& color, const core::vector2d& tcoords, const core::vector2d& tcoords2) : S3DVertex(pos, normal, color, tcoords), TCoords2(tcoords2) {} //! constructor with all values S3DVertex2TCoords(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv, f32 tu2, f32 tv2) : S3DVertex(x,y,z, nx,ny,nz, c, tu,tv), TCoords2(tu2,tv2) {} //! constructor with the same texture coords and normal S3DVertex2TCoords(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv) : S3DVertex(x,y,z, nx,ny,nz, c, tu,tv), TCoords2(tu,tv) {} //! constructor with the same texture coords and normal S3DVertex2TCoords(const core::vector3df& pos, const core::vector3df& normal, SColor color, const core::vector2d& tcoords) : S3DVertex(pos, normal, color, tcoords), TCoords2(tcoords) {} //! constructor from S3DVertex S3DVertex2TCoords(S3DVertex& o) : S3DVertex(o) {} //! Second set of texture coordinates core::vector2d TCoords2; //! Equality operator bool operator==(const S3DVertex2TCoords& other) const { return ((static_cast(*this)==other) && (TCoords2 == other.TCoords2)); } //! Inequality operator bool operator!=(const S3DVertex2TCoords& other) const { return ((static_cast(*this)!=other) || (TCoords2 != other.TCoords2)); } bool operator<(const S3DVertex2TCoords& other) const { return ((static_cast(*this) < other) || ((static_cast(*this) == other) && (TCoords2 < other.TCoords2))); } E_VERTEX_TYPE getType() const { return EVT_2TCOORDS; } S3DVertex2TCoords getInterpolated(const S3DVertex2TCoords& other, f32 d) { d = core::clamp(d, 0.0f, 1.0f); return S3DVertex2TCoords(Pos.getInterpolated(other.Pos, d), Normal.getInterpolated(other.Normal, d), Color.getInterpolated(other.Color, d), TCoords.getInterpolated(other.TCoords, d), TCoords2.getInterpolated(other.TCoords2, d)); } }; //! Vertex with a tangent and binormal vector. /** Usually used for tangent space normal mapping. */ struct S3DVertexTangents : public S3DVertex { //! default constructor S3DVertexTangents() : S3DVertex() { } //! constructor S3DVertexTangents(f32 x, f32 y, f32 z, f32 nx=0.0f, f32 ny=0.0f, f32 nz=0.0f, SColor c = 0xFFFFFFFF, f32 tu=0.0f, f32 tv=0.0f, f32 tanx=0.0f, f32 tany=0.0f, f32 tanz=0.0f, f32 bx=0.0f, f32 by=0.0f, f32 bz=0.0f) : S3DVertex(x,y,z, nx,ny,nz, c, tu,tv), Tangent(tanx,tany,tanz), Binormal(bx,by,bz) { } //! constructor S3DVertexTangents(const core::vector3df& pos, SColor c, const core::vector2df& tcoords) : S3DVertex(pos, core::vector3df(), c, tcoords) { } //! constructor S3DVertexTangents(const core::vector3df& pos, const core::vector3df& normal, SColor c, const core::vector2df& tcoords, const core::vector3df& tangent=core::vector3df(), const core::vector3df& binormal=core::vector3df()) : S3DVertex(pos, normal, c, tcoords), Tangent(tangent), Binormal(binormal) { } //! Tangent vector along the x-axis of the texture core::vector3df Tangent; //! Binormal vector (tangent x normal) core::vector3df Binormal; bool operator==(const S3DVertexTangents& other) const { return ((static_cast(*this)==other) && (Tangent == other.Tangent) && (Binormal == other.Binormal)); } bool operator!=(const S3DVertexTangents& other) const { return ((static_cast(*this)!=other) || (Tangent != other.Tangent) || (Binormal != other.Binormal)); } bool operator<(const S3DVertexTangents& other) const { return ((static_cast(*this) < other) || ((static_cast(*this) == other) && (Tangent < other.Tangent)) || ((static_cast(*this) == other) && (Tangent == other.Tangent) && (Binormal < other.Binormal))); } E_VERTEX_TYPE getType() const { return EVT_TANGENTS; } S3DVertexTangents getInterpolated(const S3DVertexTangents& other, f32 d) { d = core::clamp(d, 0.0f, 1.0f); return S3DVertexTangents(Pos.getInterpolated(other.Pos, d), Normal.getInterpolated(other.Normal, d), Color.getInterpolated(other.Color, d), TCoords.getInterpolated(other.TCoords, d), Tangent.getInterpolated(other.Tangent, d), Binormal.getInterpolated(other.Binormal, d)); } }; inline u32 getVertexPitchFromType(E_VERTEX_TYPE vertexType) { switch (vertexType) { case video::EVT_2TCOORDS: return sizeof(video::S3DVertex2TCoords); case video::EVT_TANGENTS: return sizeof(video::S3DVertexTangents); default: return sizeof(video::S3DVertex); } } } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/rect.h0000644000000000000000000001672112574354552014615 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_RECT_H_INCLUDED__ #define __IRR_RECT_H_INCLUDED__ #include "irrTypes.h" #include "dimension2d.h" #include "position2d.h" namespace irr { namespace core { //! Rectangle template. /** Mostly used by 2D GUI elements and for 2D drawing methods. It has 2 positions instead of position and dimension and a fast method for collision detection with other rectangles and points. Coordinates are (0,0) for top-left corner, and increasing to the right and to the bottom. */ template class rect { public: //! Default constructor creating empty rectangle at (0,0) rect() : UpperLeftCorner(0,0), LowerRightCorner(0,0) {} //! Constructor with two corners rect(T x, T y, T x2, T y2) : UpperLeftCorner(x,y), LowerRightCorner(x2,y2) {} //! Constructor with two corners rect(const position2d& upperLeft, const position2d& lowerRight) : UpperLeftCorner(upperLeft), LowerRightCorner(lowerRight) {} //! Constructor with upper left corner and dimension template rect(const position2d& pos, const dimension2d& size) : UpperLeftCorner(pos), LowerRightCorner(pos.X + size.Width, pos.Y + size.Height) {} //! move right by given numbers rect operator+(const position2d& pos) const { rect ret(*this); return ret+=pos; } //! move right by given numbers rect& operator+=(const position2d& pos) { UpperLeftCorner += pos; LowerRightCorner += pos; return *this; } //! move left by given numbers rect operator-(const position2d& pos) const { rect ret(*this); return ret-=pos; } //! move left by given numbers rect& operator-=(const position2d& pos) { UpperLeftCorner -= pos; LowerRightCorner -= pos; return *this; } //! equality operator bool operator==(const rect& other) const { return (UpperLeftCorner == other.UpperLeftCorner && LowerRightCorner == other.LowerRightCorner); } //! inequality operator bool operator!=(const rect& other) const { return (UpperLeftCorner != other.UpperLeftCorner || LowerRightCorner != other.LowerRightCorner); } //! compares size of rectangles bool operator<(const rect& other) const { return getArea() < other.getArea(); } //! Returns size of rectangle T getArea() const { return getWidth() * getHeight(); } //! Returns if a 2d point is within this rectangle. /** \param pos Position to test if it lies within this rectangle. \return True if the position is within the rectangle, false if not. */ bool isPointInside(const position2d& pos) const { return (UpperLeftCorner.X <= pos.X && UpperLeftCorner.Y <= pos.Y && LowerRightCorner.X >= pos.X && LowerRightCorner.Y >= pos.Y); } //! Check if the rectangle collides with another rectangle. /** \param other Rectangle to test collision with \return True if the rectangles collide. */ bool isRectCollided(const rect& other) const { return (LowerRightCorner.Y > other.UpperLeftCorner.Y && UpperLeftCorner.Y < other.LowerRightCorner.Y && LowerRightCorner.X > other.UpperLeftCorner.X && UpperLeftCorner.X < other.LowerRightCorner.X); } //! Clips this rectangle with another one. /** \param other Rectangle to clip with */ void clipAgainst(const rect& other) { if (other.LowerRightCorner.X < LowerRightCorner.X) LowerRightCorner.X = other.LowerRightCorner.X; if (other.LowerRightCorner.Y < LowerRightCorner.Y) LowerRightCorner.Y = other.LowerRightCorner.Y; if (other.UpperLeftCorner.X > UpperLeftCorner.X) UpperLeftCorner.X = other.UpperLeftCorner.X; if (other.UpperLeftCorner.Y > UpperLeftCorner.Y) UpperLeftCorner.Y = other.UpperLeftCorner.Y; // correct possible invalid rect resulting from clipping if (UpperLeftCorner.Y > LowerRightCorner.Y) UpperLeftCorner.Y = LowerRightCorner.Y; if (UpperLeftCorner.X > LowerRightCorner.X) UpperLeftCorner.X = LowerRightCorner.X; } //! Moves this rectangle to fit inside another one. /** \return True on success, false if not possible */ bool constrainTo(const rect& other) { if (other.getWidth() < getWidth() || other.getHeight() < getHeight()) return false; T diff = other.LowerRightCorner.X - LowerRightCorner.X; if (diff < 0) { LowerRightCorner.X += diff; UpperLeftCorner.X += diff; } diff = other.LowerRightCorner.Y - LowerRightCorner.Y; if (diff < 0) { LowerRightCorner.Y += diff; UpperLeftCorner.Y += diff; } diff = UpperLeftCorner.X - other.UpperLeftCorner.X; if (diff < 0) { UpperLeftCorner.X -= diff; LowerRightCorner.X -= diff; } diff = UpperLeftCorner.Y - other.UpperLeftCorner.Y; if (diff < 0) { UpperLeftCorner.Y -= diff; LowerRightCorner.Y -= diff; } return true; } //! Get width of rectangle. T getWidth() const { return LowerRightCorner.X - UpperLeftCorner.X; } //! Get height of rectangle. T getHeight() const { return LowerRightCorner.Y - UpperLeftCorner.Y; } //! If the lower right corner of the rect is smaller then the upper left, the points are swapped. void repair() { if (LowerRightCorner.X < UpperLeftCorner.X) { T t = LowerRightCorner.X; LowerRightCorner.X = UpperLeftCorner.X; UpperLeftCorner.X = t; } if (LowerRightCorner.Y < UpperLeftCorner.Y) { T t = LowerRightCorner.Y; LowerRightCorner.Y = UpperLeftCorner.Y; UpperLeftCorner.Y = t; } } //! Returns if the rect is valid to draw. /** It would be invalid if the UpperLeftCorner is lower or more right than the LowerRightCorner. */ bool isValid() const { return ((LowerRightCorner.X >= UpperLeftCorner.X) && (LowerRightCorner.Y >= UpperLeftCorner.Y)); } //! Get the center of the rectangle position2d getCenter() const { return position2d( (UpperLeftCorner.X + LowerRightCorner.X) / 2, (UpperLeftCorner.Y + LowerRightCorner.Y) / 2); } //! Get the dimensions of the rectangle dimension2d getSize() const { return dimension2d(getWidth(), getHeight()); } //! Adds a point to the rectangle /** Causes the rectangle to grow bigger if point is outside of the box \param p Point to add to the box. */ void addInternalPoint(const position2d& p) { addInternalPoint(p.X, p.Y); } //! Adds a point to the bounding rectangle /** Causes the rectangle to grow bigger if point is outside of the box \param x X-Coordinate of the point to add to this box. \param y Y-Coordinate of the point to add to this box. */ void addInternalPoint(T x, T y) { if (x>LowerRightCorner.X) LowerRightCorner.X = x; if (y>LowerRightCorner.Y) LowerRightCorner.Y = y; if (x UpperLeftCorner; //! Lower right corner position2d LowerRightCorner; }; //! Rectangle with float values typedef rect rectf; //! Rectangle with int values typedef rect recti; } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/quaternion.h0000644000000000000000000004273412574354552016050 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_QUATERNION_H_INCLUDED__ #define __IRR_QUATERNION_H_INCLUDED__ #include "irrTypes.h" #include "irrMath.h" #include "matrix4.h" #include "vector3d.h" // Between Irrlicht 1.7 and Irrlicht 1.8 the quaternion-matrix conversions got fixed. // This define disables all involved functions completely to allow finding all places // where the wrong conversions had been in use. #define IRR_TEST_BROKEN_QUATERNION_USE 0 namespace irr { namespace core { //! Quaternion class for representing rotations. /** It provides cheap combinations and avoids gimbal locks. Also useful for interpolations. */ class quaternion { public: //! Default Constructor quaternion() : X(0.0f), Y(0.0f), Z(0.0f), W(1.0f) {} //! Constructor quaternion(f32 x, f32 y, f32 z, f32 w) : X(x), Y(y), Z(z), W(w) { } //! Constructor which converts euler angles (radians) to a quaternion quaternion(f32 x, f32 y, f32 z); //! Constructor which converts euler angles (radians) to a quaternion quaternion(const vector3df& vec); #if !IRR_TEST_BROKEN_QUATERNION_USE //! Constructor which converts a matrix to a quaternion quaternion(const matrix4& mat); #endif //! Equalilty operator bool operator==(const quaternion& other) const; //! inequality operator bool operator!=(const quaternion& other) const; //! Assignment operator inline quaternion& operator=(const quaternion& other); #if !IRR_TEST_BROKEN_QUATERNION_USE //! Matrix assignment operator inline quaternion& operator=(const matrix4& other); #endif //! Add operator quaternion operator+(const quaternion& other) const; //! Multiplication operator quaternion operator*(const quaternion& other) const; //! Multiplication operator with scalar quaternion operator*(f32 s) const; //! Multiplication operator with scalar quaternion& operator*=(f32 s); //! Multiplication operator vector3df operator*(const vector3df& v) const; //! Multiplication operator quaternion& operator*=(const quaternion& other); //! Calculates the dot product inline f32 dotProduct(const quaternion& other) const; //! Sets new quaternion inline quaternion& set(f32 x, f32 y, f32 z, f32 w); //! Sets new quaternion based on euler angles (radians) inline quaternion& set(f32 x, f32 y, f32 z); //! Sets new quaternion based on euler angles (radians) inline quaternion& set(const core::vector3df& vec); //! Sets new quaternion from other quaternion inline quaternion& set(const core::quaternion& quat); //! returns if this quaternion equals the other one, taking floating point rounding errors into account inline bool equals(const quaternion& other, const f32 tolerance = ROUNDING_ERROR_f32 ) const; //! Normalizes the quaternion inline quaternion& normalize(); #if !IRR_TEST_BROKEN_QUATERNION_USE //! Creates a matrix from this quaternion matrix4 getMatrix() const; #endif //! Creates a matrix from this quaternion void getMatrix( matrix4 &dest, const core::vector3df &translation=core::vector3df() ) const; /*! Creates a matrix from this quaternion Rotate about a center point shortcut for core::quaternion q; q.rotationFromTo ( vin[i].Normal, forward ); q.getMatrixCenter ( lookat, center, newPos ); core::matrix4 m2; m2.setInverseTranslation ( center ); lookat *= m2; core::matrix4 m3; m2.setTranslation ( newPos ); lookat *= m3; */ void getMatrixCenter( matrix4 &dest, const core::vector3df ¢er, const core::vector3df &translation ) const; //! Creates a matrix from this quaternion inline void getMatrix_transposed( matrix4 &dest ) const; //! Inverts this quaternion quaternion& makeInverse(); //! Set this quaternion to the linear interpolation between two quaternions /** \param q1 First quaternion to be interpolated. \param q2 Second quaternion to be interpolated. \param time Progress of interpolation. For time=0 the result is q1, for time=1 the result is q2. Otherwise interpolation between q1 and q2. */ quaternion& lerp(quaternion q1, quaternion q2, f32 time); //! Set this quaternion to the result of the spherical interpolation between two quaternions /** \param q1 First quaternion to be interpolated. \param q2 Second quaternion to be interpolated. \param time Progress of interpolation. For time=0 the result is q1, for time=1 the result is q2. Otherwise interpolation between q1 and q2. \param threshold To avoid inaccuracies at the end (time=1) the interpolation switches to linear interpolation at some point. This value defines how much of the remaining interpolation will be calculated with lerp. Everything from 1-threshold up will be linear interpolation. */ quaternion& slerp(quaternion q1, quaternion q2, f32 time, f32 threshold=.05f); //! Create quaternion from rotation angle and rotation axis. /** Axis must be unit length. The quaternion representing the rotation is q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k). \param angle Rotation Angle in radians. \param axis Rotation axis. */ quaternion& fromAngleAxis (f32 angle, const vector3df& axis); //! Fills an angle (radians) around an axis (unit vector) void toAngleAxis (f32 &angle, core::vector3df& axis) const; //! Output this quaternion to an euler angle (radians) void toEuler(vector3df& euler) const; //! Set quaternion to identity quaternion& makeIdentity(); //! Set quaternion to represent a rotation from one vector to another. quaternion& rotationFromTo(const vector3df& from, const vector3df& to); //! Quaternion elements. f32 X; // vectorial (imaginary) part f32 Y; f32 Z; f32 W; // real part }; // Constructor which converts euler angles to a quaternion inline quaternion::quaternion(f32 x, f32 y, f32 z) { set(x,y,z); } // Constructor which converts euler angles to a quaternion inline quaternion::quaternion(const vector3df& vec) { set(vec.X,vec.Y,vec.Z); } #if !IRR_TEST_BROKEN_QUATERNION_USE // Constructor which converts a matrix to a quaternion inline quaternion::quaternion(const matrix4& mat) { (*this) = mat; } #endif // equal operator inline bool quaternion::operator==(const quaternion& other) const { return ((X == other.X) && (Y == other.Y) && (Z == other.Z) && (W == other.W)); } // inequality operator inline bool quaternion::operator!=(const quaternion& other) const { return !(*this == other); } // assignment operator inline quaternion& quaternion::operator=(const quaternion& other) { X = other.X; Y = other.Y; Z = other.Z; W = other.W; return *this; } #if !IRR_TEST_BROKEN_QUATERNION_USE // matrix assignment operator inline quaternion& quaternion::operator=(const matrix4& m) { const f32 diag = m[0] + m[5] + m[10] + 1; if( diag > 0.0f ) { const f32 scale = sqrtf(diag) * 2.0f; // get scale from diagonal // TODO: speed this up X = (m[6] - m[9]) / scale; Y = (m[8] - m[2]) / scale; Z = (m[1] - m[4]) / scale; W = 0.25f * scale; } else { if (m[0]>m[5] && m[0]>m[10]) { // 1st element of diag is greatest value // find scale according to 1st element, and double it const f32 scale = sqrtf(1.0f + m[0] - m[5] - m[10]) * 2.0f; // TODO: speed this up X = 0.25f * scale; Y = (m[4] + m[1]) / scale; Z = (m[2] + m[8]) / scale; W = (m[6] - m[9]) / scale; } else if (m[5]>m[10]) { // 2nd element of diag is greatest value // find scale according to 2nd element, and double it const f32 scale = sqrtf(1.0f + m[5] - m[0] - m[10]) * 2.0f; // TODO: speed this up X = (m[4] + m[1]) / scale; Y = 0.25f * scale; Z = (m[9] + m[6]) / scale; W = (m[8] - m[2]) / scale; } else { // 3rd element of diag is greatest value // find scale according to 3rd element, and double it const f32 scale = sqrtf(1.0f + m[10] - m[0] - m[5]) * 2.0f; // TODO: speed this up X = (m[8] + m[2]) / scale; Y = (m[9] + m[6]) / scale; Z = 0.25f * scale; W = (m[1] - m[4]) / scale; } } return normalize(); } #endif // multiplication operator inline quaternion quaternion::operator*(const quaternion& other) const { quaternion tmp; tmp.W = (other.W * W) - (other.X * X) - (other.Y * Y) - (other.Z * Z); tmp.X = (other.W * X) + (other.X * W) + (other.Y * Z) - (other.Z * Y); tmp.Y = (other.W * Y) + (other.Y * W) + (other.Z * X) - (other.X * Z); tmp.Z = (other.W * Z) + (other.Z * W) + (other.X * Y) - (other.Y * X); return tmp; } // multiplication operator inline quaternion quaternion::operator*(f32 s) const { return quaternion(s*X, s*Y, s*Z, s*W); } // multiplication operator inline quaternion& quaternion::operator*=(f32 s) { X*=s; Y*=s; Z*=s; W*=s; return *this; } // multiplication operator inline quaternion& quaternion::operator*=(const quaternion& other) { return (*this = other * (*this)); } // add operator inline quaternion quaternion::operator+(const quaternion& b) const { return quaternion(X+b.X, Y+b.Y, Z+b.Z, W+b.W); } #if !IRR_TEST_BROKEN_QUATERNION_USE // Creates a matrix from this quaternion inline matrix4 quaternion::getMatrix() const { core::matrix4 m; getMatrix(m); return m; } #endif /*! Creates a matrix from this quaternion */ inline void quaternion::getMatrix(matrix4 &dest, const core::vector3df ¢er) const { dest[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z; dest[1] = 2.0f*X*Y + 2.0f*Z*W; dest[2] = 2.0f*X*Z - 2.0f*Y*W; dest[3] = 0.0f; dest[4] = 2.0f*X*Y - 2.0f*Z*W; dest[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z; dest[6] = 2.0f*Z*Y + 2.0f*X*W; dest[7] = 0.0f; dest[8] = 2.0f*X*Z + 2.0f*Y*W; dest[9] = 2.0f*Z*Y - 2.0f*X*W; dest[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y; dest[11] = 0.0f; dest[12] = center.X; dest[13] = center.Y; dest[14] = center.Z; dest[15] = 1.f; dest.setDefinitelyIdentityMatrix ( false ); } /*! Creates a matrix from this quaternion Rotate about a center point shortcut for core::quaternion q; q.rotationFromTo(vin[i].Normal, forward); q.getMatrix(lookat, center); core::matrix4 m2; m2.setInverseTranslation(center); lookat *= m2; */ inline void quaternion::getMatrixCenter(matrix4 &dest, const core::vector3df ¢er, const core::vector3df &translation) const { dest[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z; dest[1] = 2.0f*X*Y + 2.0f*Z*W; dest[2] = 2.0f*X*Z - 2.0f*Y*W; dest[3] = 0.0f; dest[4] = 2.0f*X*Y - 2.0f*Z*W; dest[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z; dest[6] = 2.0f*Z*Y + 2.0f*X*W; dest[7] = 0.0f; dest[8] = 2.0f*X*Z + 2.0f*Y*W; dest[9] = 2.0f*Z*Y - 2.0f*X*W; dest[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y; dest[11] = 0.0f; dest.setRotationCenter ( center, translation ); } // Creates a matrix from this quaternion inline void quaternion::getMatrix_transposed(matrix4 &dest) const { dest[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z; dest[4] = 2.0f*X*Y + 2.0f*Z*W; dest[8] = 2.0f*X*Z - 2.0f*Y*W; dest[12] = 0.0f; dest[1] = 2.0f*X*Y - 2.0f*Z*W; dest[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z; dest[9] = 2.0f*Z*Y + 2.0f*X*W; dest[13] = 0.0f; dest[2] = 2.0f*X*Z + 2.0f*Y*W; dest[6] = 2.0f*Z*Y - 2.0f*X*W; dest[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y; dest[14] = 0.0f; dest[3] = 0.f; dest[7] = 0.f; dest[11] = 0.f; dest[15] = 1.f; dest.setDefinitelyIdentityMatrix(false); } // Inverts this quaternion inline quaternion& quaternion::makeInverse() { X = -X; Y = -Y; Z = -Z; return *this; } // sets new quaternion inline quaternion& quaternion::set(f32 x, f32 y, f32 z, f32 w) { X = x; Y = y; Z = z; W = w; return *this; } // sets new quaternion based on euler angles inline quaternion& quaternion::set(f32 x, f32 y, f32 z) { f64 angle; angle = x * 0.5; const f64 sr = sin(angle); const f64 cr = cos(angle); angle = y * 0.5; const f64 sp = sin(angle); const f64 cp = cos(angle); angle = z * 0.5; const f64 sy = sin(angle); const f64 cy = cos(angle); const f64 cpcy = cp * cy; const f64 spcy = sp * cy; const f64 cpsy = cp * sy; const f64 spsy = sp * sy; X = (f32)(sr * cpcy - cr * spsy); Y = (f32)(cr * spcy + sr * cpsy); Z = (f32)(cr * cpsy - sr * spcy); W = (f32)(cr * cpcy + sr * spsy); return normalize(); } // sets new quaternion based on euler angles inline quaternion& quaternion::set(const core::vector3df& vec) { return set(vec.X, vec.Y, vec.Z); } // sets new quaternion based on other quaternion inline quaternion& quaternion::set(const core::quaternion& quat) { return (*this=quat); } //! returns if this quaternion equals the other one, taking floating point rounding errors into account inline bool quaternion::equals(const quaternion& other, const f32 tolerance) const { return core::equals(X, other.X, tolerance) && core::equals(Y, other.Y, tolerance) && core::equals(Z, other.Z, tolerance) && core::equals(W, other.W, tolerance); } // normalizes the quaternion inline quaternion& quaternion::normalize() { const f32 n = X*X + Y*Y + Z*Z + W*W; if (n == 1) return *this; //n = 1.0f / sqrtf(n); return (*this *= reciprocal_squareroot ( n )); } // set this quaternion to the result of the linear interpolation between two quaternions inline quaternion& quaternion::lerp(quaternion q1, quaternion q2, f32 time) { const f32 scale = 1.0f - time; return (*this = (q1*scale) + (q2*time)); } // set this quaternion to the result of the interpolation between two quaternions inline quaternion& quaternion::slerp(quaternion q1, quaternion q2, f32 time, f32 threshold) { f32 angle = q1.dotProduct(q2); // make sure we use the short rotation if (angle < 0.0f) { q1 *= -1.0f; angle *= -1.0f; } if (angle <= (1-threshold)) // spherical interpolation { const f32 theta = acosf(angle); const f32 invsintheta = reciprocal(sinf(theta)); const f32 scale = sinf(theta * (1.0f-time)) * invsintheta; const f32 invscale = sinf(theta * time) * invsintheta; return (*this = (q1*scale) + (q2*invscale)); } else // linear interploation return lerp(q1,q2,time); } // calculates the dot product inline f32 quaternion::dotProduct(const quaternion& q2) const { return (X * q2.X) + (Y * q2.Y) + (Z * q2.Z) + (W * q2.W); } //! axis must be unit length, angle in radians inline quaternion& quaternion::fromAngleAxis(f32 angle, const vector3df& axis) { const f32 fHalfAngle = 0.5f*angle; const f32 fSin = sinf(fHalfAngle); W = cosf(fHalfAngle); X = fSin*axis.X; Y = fSin*axis.Y; Z = fSin*axis.Z; return *this; } inline void quaternion::toAngleAxis(f32 &angle, core::vector3df &axis) const { const f32 scale = sqrtf(X*X + Y*Y + Z*Z); if (core::iszero(scale) || W > 1.0f || W < -1.0f) { angle = 0.0f; axis.X = 0.0f; axis.Y = 1.0f; axis.Z = 0.0f; } else { const f32 invscale = reciprocal(scale); angle = 2.0f * acosf(W); axis.X = X * invscale; axis.Y = Y * invscale; axis.Z = Z * invscale; } } inline void quaternion::toEuler(vector3df& euler) const { const f64 sqw = W*W; const f64 sqx = X*X; const f64 sqy = Y*Y; const f64 sqz = Z*Z; const f64 test = 2.0 * (Y*W - X*Z); if (core::equals(test, 1.0, 0.000001)) { // heading = rotation about z-axis euler.Z = (f32) (-2.0*atan2(X, W)); // bank = rotation about x-axis euler.X = 0; // attitude = rotation about y-axis euler.Y = (f32) (core::PI64/2.0); } else if (core::equals(test, -1.0, 0.000001)) { // heading = rotation about z-axis euler.Z = (f32) (2.0*atan2(X, W)); // bank = rotation about x-axis euler.X = 0; // attitude = rotation about y-axis euler.Y = (f32) (core::PI64/-2.0); } else { // heading = rotation about z-axis euler.Z = (f32) atan2(2.0 * (X*Y +Z*W),(sqx - sqy - sqz + sqw)); // bank = rotation about x-axis euler.X = (f32) atan2(2.0 * (Y*Z +X*W),(-sqx - sqy + sqz + sqw)); // attitude = rotation about y-axis euler.Y = (f32) asin( clamp(test, -1.0, 1.0) ); } } inline vector3df quaternion::operator* (const vector3df& v) const { // nVidia SDK implementation vector3df uv, uuv; vector3df qvec(X, Y, Z); uv = qvec.crossProduct(v); uuv = qvec.crossProduct(uv); uv *= (2.0f * W); uuv *= 2.0f; return v + uv + uuv; } // set quaternion to identity inline core::quaternion& quaternion::makeIdentity() { W = 1.f; X = 0.f; Y = 0.f; Z = 0.f; return *this; } inline core::quaternion& quaternion::rotationFromTo(const vector3df& from, const vector3df& to) { // Based on Stan Melax's article in Game Programming Gems // Copy, since cannot modify local vector3df v0 = from; vector3df v1 = to; v0.normalize(); v1.normalize(); const f32 d = v0.dotProduct(v1); if (d >= 1.0f) // If dot == 1, vectors are the same { return makeIdentity(); } else if (d <= -1.0f) // exactly opposite { core::vector3df axis(1.0f, 0.f, 0.f); axis = axis.crossProduct(v0); if (axis.getLength()==0) { axis.set(0.f,1.f,0.f); axis = axis.crossProduct(v0); } // same as fromAngleAxis(core::PI, axis).normalize(); return set(axis.X, axis.Y, axis.Z, 0).normalize(); } const f32 s = sqrtf( (1+d)*2 ); // optimize inv_sqrt const f32 invs = 1.f / s; const vector3df c = v0.crossProduct(v1)*invs; return set(c.X, c.Y, c.Z, s * 0.5f).normalize(); } } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/position2d.h0000644000000000000000000000173212574354552015746 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h //! As of Irrlicht 1.6, position2d is a synonym for vector2d. /** You should consider position2d to be deprecated, and use vector2d by preference. */ #ifndef __IRR_POSITION_H_INCLUDED__ #define __IRR_POSITION_H_INCLUDED__ #include "vector2d.h" namespace irr { namespace core { // Use typedefs where possible as they are more explicit... //! \deprecated position2d is now a synonym for vector2d, but vector2d should be used directly. typedef vector2d position2df; //! \deprecated position2d is now a synonym for vector2d, but vector2d should be used directly. typedef vector2d position2di; } // namespace core } // namespace irr // ...and use a #define to catch the rest, for (e.g.) position2d #define position2d vector2d #endif // __IRR_POSITION_H_INCLUDED__ irrlicht-1.8.3/include/plane3d.h0000644000000000000000000001725212574354552015206 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_PLANE_3D_H_INCLUDED__ #define __IRR_PLANE_3D_H_INCLUDED__ #include "irrMath.h" #include "vector3d.h" namespace irr { namespace core { //! Enumeration for intersection relations of 3d objects enum EIntersectionRelation3D { ISREL3D_FRONT = 0, ISREL3D_BACK, ISREL3D_PLANAR, ISREL3D_SPANNING, ISREL3D_CLIPPED }; //! Template plane class with some intersection testing methods. /** It has to be ensured, that the normal is always normalized. The constructors and setters of this class will not ensure this automatically. So any normal passed in has to be normalized in advance. No change to the normal will be made by any of the class methods. */ template class plane3d { public: // Constructors plane3d(): Normal(0,1,0) { recalculateD(vector3d(0,0,0)); } plane3d(const vector3d& MPoint, const vector3d& Normal) : Normal(Normal) { recalculateD(MPoint); } plane3d(T px, T py, T pz, T nx, T ny, T nz) : Normal(nx, ny, nz) { recalculateD(vector3d(px, py, pz)); } plane3d(const vector3d& point1, const vector3d& point2, const vector3d& point3) { setPlane(point1, point2, point3); } plane3d(const vector3d & normal, const T d) : Normal(normal), D(d) { } // operators inline bool operator==(const plane3d& other) const { return (equals(D, other.D) && Normal==other.Normal);} inline bool operator!=(const plane3d& other) const { return !(*this == other);} // functions void setPlane(const vector3d& point, const vector3d& nvector) { Normal = nvector; recalculateD(point); } void setPlane(const vector3d& nvect, T d) { Normal = nvect; D = d; } void setPlane(const vector3d& point1, const vector3d& point2, const vector3d& point3) { // creates the plane from 3 memberpoints Normal = (point2 - point1).crossProduct(point3 - point1); Normal.normalize(); recalculateD(point1); } //! Get an intersection with a 3d line. /** \param lineVect Vector of the line to intersect with. \param linePoint Point of the line to intersect with. \param outIntersection Place to store the intersection point, if there is one. \return True if there was an intersection, false if there was not. */ bool getIntersectionWithLine(const vector3d& linePoint, const vector3d& lineVect, vector3d& outIntersection) const { T t2 = Normal.dotProduct(lineVect); if (t2 == 0) return false; T t =- (Normal.dotProduct(linePoint) + D) / t2; outIntersection = linePoint + (lineVect * t); return true; } //! Get percentage of line between two points where an intersection with this plane happens. /** Only useful if known that there is an intersection. \param linePoint1 Point1 of the line to intersect with. \param linePoint2 Point2 of the line to intersect with. \return Where on a line between two points an intersection with this plane happened. For example, 0.5 is returned if the intersection happened exactly in the middle of the two points. */ f32 getKnownIntersectionWithLine(const vector3d& linePoint1, const vector3d& linePoint2) const { vector3d vect = linePoint2 - linePoint1; T t2 = (f32)Normal.dotProduct(vect); return (f32)-((Normal.dotProduct(linePoint1) + D) / t2); } //! Get an intersection with a 3d line, limited between two 3d points. /** \param linePoint1 Point 1 of the line. \param linePoint2 Point 2 of the line. \param outIntersection Place to store the intersection point, if there is one. \return True if there was an intersection, false if there was not. */ bool getIntersectionWithLimitedLine( const vector3d& linePoint1, const vector3d& linePoint2, vector3d& outIntersection) const { return (getIntersectionWithLine(linePoint1, linePoint2 - linePoint1, outIntersection) && outIntersection.isBetweenPoints(linePoint1, linePoint2)); } //! Classifies the relation of a point to this plane. /** \param point Point to classify its relation. \return ISREL3D_FRONT if the point is in front of the plane, ISREL3D_BACK if the point is behind of the plane, and ISREL3D_PLANAR if the point is within the plane. */ EIntersectionRelation3D classifyPointRelation(const vector3d& point) const { const T d = Normal.dotProduct(point) + D; if (d < -ROUNDING_ERROR_f32) return ISREL3D_BACK; if (d > ROUNDING_ERROR_f32) return ISREL3D_FRONT; return ISREL3D_PLANAR; } //! Recalculates the distance from origin by applying a new member point to the plane. void recalculateD(const vector3d& MPoint) { D = - MPoint.dotProduct(Normal); } //! Gets a member point of the plane. vector3d getMemberPoint() const { return Normal * -D; } //! Tests if there is an intersection with the other plane /** \return True if there is a intersection. */ bool existsIntersection(const plane3d& other) const { vector3d cross = other.Normal.crossProduct(Normal); return cross.getLength() > core::ROUNDING_ERROR_f32; } //! Intersects this plane with another. /** \param other Other plane to intersect with. \param outLinePoint Base point of intersection line. \param outLineVect Vector of intersection. \return True if there is a intersection, false if not. */ bool getIntersectionWithPlane(const plane3d& other, vector3d& outLinePoint, vector3d& outLineVect) const { const T fn00 = Normal.getLength(); const T fn01 = Normal.dotProduct(other.Normal); const T fn11 = other.Normal.getLength(); const f64 det = fn00*fn11 - fn01*fn01; if (fabs(det) < ROUNDING_ERROR_f64 ) return false; const f64 invdet = 1.0 / det; const f64 fc0 = (fn11*-D + fn01*other.D) * invdet; const f64 fc1 = (fn00*-other.D + fn01*D) * invdet; outLineVect = Normal.crossProduct(other.Normal); outLinePoint = Normal*(T)fc0 + other.Normal*(T)fc1; return true; } //! Get the intersection point with two other planes if there is one. bool getIntersectionWithPlanes(const plane3d& o1, const plane3d& o2, vector3d& outPoint) const { vector3d linePoint, lineVect; if (getIntersectionWithPlane(o1, linePoint, lineVect)) return o2.getIntersectionWithLine(linePoint, lineVect, outPoint); return false; } //! Test if the triangle would be front or backfacing from any point. /** Thus, this method assumes a camera position from which the triangle is definitely visible when looking into the given direction. Note that this only works if the normal is Normalized. Do not use this method with points as it will give wrong results! \param lookDirection: Look direction. \return True if the plane is front facing and false if it is backfacing. */ bool isFrontFacing(const vector3d& lookDirection) const { const f32 d = Normal.dotProduct(lookDirection); return F32_LOWER_EQUAL_0 ( d ); } //! Get the distance to a point. /** Note that this only works if the normal is normalized. */ T getDistanceTo(const vector3d& point) const { return point.dotProduct(Normal) + D; } //! Normal vector of the plane. vector3d Normal; //! Distance from origin. T D; }; //! Typedef for a f32 3d plane. typedef plane3d plane3df; //! Typedef for an integer 3d plane. typedef plane3d plane3di; } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/path.h0000644000000000000000000000370012574354552014605 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_PATH_H_INCLUDED__ #define __IRR_PATH_H_INCLUDED__ #include "irrString.h" namespace irr { namespace io { //! Type used for all file system related strings. /** This type will transparently handle different file system encodings. */ typedef core::string path; //! Used in places where we identify objects by a filename, but don't actually work with the real filename /** Irrlicht is internally not case-sensitive when it comes to names. Also this class is a first step towards support for correctly serializing renamed objects. */ struct SNamedPath { //! Constructor SNamedPath() {} //! Constructor SNamedPath(const path& p) : Path(p), InternalName( PathToName(p) ) { } //! Is smaller comparator bool operator <(const SNamedPath& other) const { return InternalName < other.InternalName; } //! Set the path. void setPath(const path& p) { Path = p; InternalName = PathToName(p); } //! Get the path. const path& getPath() const { return Path; }; //! Get the name which is used to identify the file. //! This string is similar to the names and filenames used before Irrlicht 1.7 const path& getInternalName() const { return InternalName; } //! Implicit cast to io::path operator core::stringc() const { return core::stringc(getPath()); } //! Implicit cast to io::path operator core::stringw() const { return core::stringw(getPath()); } protected: // convert the given path string to a name string. path PathToName(const path& p) const { path name(p); name.replace( '\\', '/' ); name.make_lower(); return name; } private: path Path; path InternalName; }; } // io } // irr #endif // __IRR_PATH_H_INCLUDED__ irrlicht-1.8.3/include/matrix4.h0000644000000000000000000017574412574354552015263 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_MATRIX_H_INCLUDED__ #define __IRR_MATRIX_H_INCLUDED__ #include "irrMath.h" #include "vector3d.h" #include "vector2d.h" #include "plane3d.h" #include "aabbox3d.h" #include "rect.h" #include "irrString.h" // enable this to keep track of changes to the matrix // and make simpler identity check for seldomly changing matrices // otherwise identity check will always compare the elements //#define USE_MATRIX_TEST // this is only for debugging purposes //#define USE_MATRIX_TEST_DEBUG #if defined( USE_MATRIX_TEST_DEBUG ) struct MatrixTest { MatrixTest () : ID(0), Calls(0) {} char buf[256]; int Calls; int ID; }; static MatrixTest MTest; #endif namespace irr { namespace core { //! 4x4 matrix. Mostly used as transformation matrix for 3d calculations. /** The matrix is a D3D style matrix, row major with translations in the 4th row. */ template class CMatrix4 { public: //! Constructor Flags enum eConstructor { EM4CONST_NOTHING = 0, EM4CONST_COPY, EM4CONST_IDENTITY, EM4CONST_TRANSPOSED, EM4CONST_INVERSE, EM4CONST_INVERSE_TRANSPOSED }; //! Default constructor /** \param constructor Choose the initialization style */ CMatrix4( eConstructor constructor = EM4CONST_IDENTITY ); //! Copy constructor /** \param other Other matrix to copy from \param constructor Choose the initialization style */ CMatrix4(const CMatrix4& other, eConstructor constructor = EM4CONST_COPY); //! Simple operator for directly accessing every element of the matrix. T& operator()(const s32 row, const s32 col) { #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return M[ row * 4 + col ]; } //! Simple operator for directly accessing every element of the matrix. const T& operator()(const s32 row, const s32 col) const { return M[row * 4 + col]; } //! Simple operator for linearly accessing every element of the matrix. T& operator[](u32 index) { #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return M[index]; } //! Simple operator for linearly accessing every element of the matrix. const T& operator[](u32 index) const { return M[index]; } //! Sets this matrix equal to the other matrix. inline CMatrix4& operator=(const CMatrix4 &other); //! Sets all elements of this matrix to the value. inline CMatrix4& operator=(const T& scalar); //! Returns pointer to internal array const T* pointer() const { return M; } T* pointer() { #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return M; } //! Returns true if other matrix is equal to this matrix. bool operator==(const CMatrix4 &other) const; //! Returns true if other matrix is not equal to this matrix. bool operator!=(const CMatrix4 &other) const; //! Add another matrix. CMatrix4 operator+(const CMatrix4& other) const; //! Add another matrix. CMatrix4& operator+=(const CMatrix4& other); //! Subtract another matrix. CMatrix4 operator-(const CMatrix4& other) const; //! Subtract another matrix. CMatrix4& operator-=(const CMatrix4& other); //! set this matrix to the product of two matrices /** Calculate b*a */ inline CMatrix4& setbyproduct(const CMatrix4& other_a,const CMatrix4& other_b ); //! Set this matrix to the product of two matrices /** Calculate b*a, no optimization used, use it if you know you never have a identity matrix */ CMatrix4& setbyproduct_nocheck(const CMatrix4& other_a,const CMatrix4& other_b ); //! Multiply by another matrix. /** Calculate other*this */ CMatrix4 operator*(const CMatrix4& other) const; //! Multiply by another matrix. /** Calculate and return other*this */ CMatrix4& operator*=(const CMatrix4& other); //! Multiply by scalar. CMatrix4 operator*(const T& scalar) const; //! Multiply by scalar. CMatrix4& operator*=(const T& scalar); //! Set matrix to identity. inline CMatrix4& makeIdentity(); //! Returns true if the matrix is the identity matrix inline bool isIdentity() const; //! Returns true if the matrix is orthogonal inline bool isOrthogonal() const; //! Returns true if the matrix is the identity matrix bool isIdentity_integer_base () const; //! Set the translation of the current matrix. Will erase any previous values. CMatrix4& setTranslation( const vector3d& translation ); //! Gets the current translation vector3d getTranslation() const; //! Set the inverse translation of the current matrix. Will erase any previous values. CMatrix4& setInverseTranslation( const vector3d& translation ); //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified. inline CMatrix4& setRotationRadians( const vector3d& rotation ); //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified. CMatrix4& setRotationDegrees( const vector3d& rotation ); //! Returns the rotation, as set by setRotation(). /** This code was orginally written by by Chev. */ core::vector3d getRotationDegrees() const; //! Make an inverted rotation matrix from Euler angles. /** The 4th row and column are unmodified. */ inline CMatrix4& setInverseRotationRadians( const vector3d& rotation ); //! Make an inverted rotation matrix from Euler angles. /** The 4th row and column are unmodified. */ inline CMatrix4& setInverseRotationDegrees( const vector3d& rotation ); //! Make a rotation matrix from angle and axis, assuming left handed rotation. /** The 4th row and column are unmodified. */ inline CMatrix4& setRotationAxisRadians(const T& angle, const vector3d& axis); //! Set Scale CMatrix4& setScale( const vector3d& scale ); //! Set Scale CMatrix4& setScale( const T scale ) { return setScale(core::vector3d(scale,scale,scale)); } //! Get Scale core::vector3d getScale() const; //! Translate a vector by the inverse of the translation part of this matrix. void inverseTranslateVect( vector3df& vect ) const; //! Rotate a vector by the inverse of the rotation part of this matrix. void inverseRotateVect( vector3df& vect ) const; //! Rotate a vector by the rotation part of this matrix. void rotateVect( vector3df& vect ) const; //! An alternate transform vector method, writing into a second vector void rotateVect(core::vector3df& out, const core::vector3df& in) const; //! An alternate transform vector method, writing into an array of 3 floats void rotateVect(T *out,const core::vector3df &in) const; //! Transforms the vector by this matrix void transformVect( vector3df& vect) const; //! Transforms input vector by this matrix and stores result in output vector void transformVect( vector3df& out, const vector3df& in ) const; //! An alternate transform vector method, writing into an array of 4 floats void transformVect(T *out,const core::vector3df &in) const; //! An alternate transform vector method, reading from and writing to an array of 3 floats void transformVec3(T *out, const T * in) const; //! Translate a vector by the translation part of this matrix. void translateVect( vector3df& vect ) const; //! Transforms a plane by this matrix void transformPlane( core::plane3d &plane) const; //! Transforms a plane by this matrix void transformPlane( const core::plane3d &in, core::plane3d &out) const; //! Transforms a axis aligned bounding box /** The result box of this operation may not be accurate at all. For correct results, use transformBoxEx() */ void transformBox(core::aabbox3d& box) const; //! Transforms a axis aligned bounding box /** The result box of this operation should by accurate, but this operation is slower than transformBox(). */ void transformBoxEx(core::aabbox3d& box) const; //! Multiplies this matrix by a 1x4 matrix void multiplyWith1x4Matrix(T* matrix) const; //! Calculates inverse of matrix. Slow. /** \return Returns false if there is no inverse matrix.*/ bool makeInverse(); //! Inverts a primitive matrix which only contains a translation and a rotation /** \param out: where result matrix is written to. */ bool getInversePrimitive ( CMatrix4& out ) const; //! Gets the inversed matrix of this one /** \param out: where result matrix is written to. \return Returns false if there is no inverse matrix. */ bool getInverse(CMatrix4& out) const; //! Builds a right-handed perspective projection matrix based on a field of view CMatrix4& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar); //! Builds a left-handed perspective projection matrix based on a field of view CMatrix4& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar); //! Builds a left-handed perspective projection matrix based on a field of view, with far plane at infinity CMatrix4& buildProjectionMatrixPerspectiveFovInfinityLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon=0); //! Builds a right-handed perspective projection matrix. CMatrix4& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); //! Builds a left-handed perspective projection matrix. CMatrix4& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); //! Builds a left-handed orthogonal projection matrix. CMatrix4& buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); //! Builds a right-handed orthogonal projection matrix. CMatrix4& buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); //! Builds a left-handed look-at matrix. CMatrix4& buildCameraLookAtMatrixLH( const vector3df& position, const vector3df& target, const vector3df& upVector); //! Builds a right-handed look-at matrix. CMatrix4& buildCameraLookAtMatrixRH( const vector3df& position, const vector3df& target, const vector3df& upVector); //! Builds a matrix that flattens geometry into a plane. /** \param light: light source \param plane: plane into which the geometry if flattened into \param point: value between 0 and 1, describing the light source. If this is 1, it is a point light, if it is 0, it is a directional light. */ CMatrix4& buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f); //! Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates. /** Used to scale <-1,-1><1,1> to viewport, for example from <-1,-1> <1,1> to the viewport <0,0><0,640> */ CMatrix4& buildNDCToDCMatrix( const core::rect& area, f32 zScale); //! Creates a new matrix as interpolated matrix from two other ones. /** \param b: other matrix to interpolate with \param time: Must be a value between 0 and 1. */ CMatrix4 interpolate(const core::CMatrix4& b, f32 time) const; //! Gets transposed matrix CMatrix4 getTransposed() const; //! Gets transposed matrix inline void getTransposed( CMatrix4& dest ) const; //! Builds a matrix that rotates from one vector to another /** \param from: vector to rotate from \param to: vector to rotate to */ CMatrix4& buildRotateFromTo(const core::vector3df& from, const core::vector3df& to); //! Builds a combined matrix which translates to a center before rotation and translates from origin afterwards /** \param center Position to rotate around \param translate Translation applied after the rotation */ void setRotationCenter(const core::vector3df& center, const core::vector3df& translate); //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis /** \param camPos: viewer position in world coo \param center: object position in world-coo and rotation pivot \param translation: object final translation from center \param axis: axis to rotate about \param from: source vector to rotate from */ void buildAxisAlignedBillboard(const core::vector3df& camPos, const core::vector3df& center, const core::vector3df& translation, const core::vector3df& axis, const core::vector3df& from); /* construct 2D Texture transformations rotate about center, scale, and transform. */ //! Set to a texture transformation matrix with the given parameters. CMatrix4& buildTextureTransform( f32 rotateRad, const core::vector2df &rotatecenter, const core::vector2df &translate, const core::vector2df &scale); //! Set texture transformation rotation /** Rotate about z axis, recenter at (0.5,0.5). Doesn't clear other elements than those affected \param radAngle Angle in radians \return Altered matrix */ CMatrix4& setTextureRotationCenter( f32 radAngle ); //! Set texture transformation translation /** Doesn't clear other elements than those affected. \param x Offset on x axis \param y Offset on y axis \return Altered matrix */ CMatrix4& setTextureTranslate( f32 x, f32 y ); //! Set texture transformation translation, using a transposed representation /** Doesn't clear other elements than those affected. \param x Offset on x axis \param y Offset on y axis \return Altered matrix */ CMatrix4& setTextureTranslateTransposed( f32 x, f32 y ); //! Set texture transformation scale /** Doesn't clear other elements than those affected. \param sx Scale factor on x axis \param sy Scale factor on y axis \return Altered matrix. */ CMatrix4& setTextureScale( f32 sx, f32 sy ); //! Set texture transformation scale, and recenter at (0.5,0.5) /** Doesn't clear other elements than those affected. \param sx Scale factor on x axis \param sy Scale factor on y axis \return Altered matrix. */ CMatrix4& setTextureScaleCenter( f32 sx, f32 sy ); //! Sets all matrix data members at once CMatrix4& setM(const T* data); //! Sets if the matrix is definitely identity matrix void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix); //! Gets if the matrix is definitely identity matrix bool getDefinitelyIdentityMatrix() const; //! Compare two matrices using the equal method bool equals(const core::CMatrix4& other, const T tolerance=(T)ROUNDING_ERROR_f64) const; private: //! Matrix data, stored in row-major order T M[16]; #if defined ( USE_MATRIX_TEST ) //! Flag is this matrix is identity matrix mutable u32 definitelyIdentityMatrix; #endif #if defined ( USE_MATRIX_TEST_DEBUG ) u32 id; mutable u32 calls; #endif }; // Default constructor template inline CMatrix4::CMatrix4( eConstructor constructor ) #if defined ( USE_MATRIX_TEST ) : definitelyIdentityMatrix(BIT_UNTESTED) #endif #if defined ( USE_MATRIX_TEST_DEBUG ) ,id ( MTest.ID++), calls ( 0 ) #endif { switch ( constructor ) { case EM4CONST_NOTHING: case EM4CONST_COPY: break; case EM4CONST_IDENTITY: case EM4CONST_INVERSE: default: makeIdentity(); break; } } // Copy constructor template inline CMatrix4::CMatrix4( const CMatrix4& other, eConstructor constructor) #if defined ( USE_MATRIX_TEST ) : definitelyIdentityMatrix(BIT_UNTESTED) #endif #if defined ( USE_MATRIX_TEST_DEBUG ) ,id ( MTest.ID++), calls ( 0 ) #endif { switch ( constructor ) { case EM4CONST_IDENTITY: makeIdentity(); break; case EM4CONST_NOTHING: break; case EM4CONST_COPY: *this = other; break; case EM4CONST_TRANSPOSED: other.getTransposed(*this); break; case EM4CONST_INVERSE: if (!other.getInverse(*this)) memset(M, 0, 16*sizeof(T)); break; case EM4CONST_INVERSE_TRANSPOSED: if (!other.getInverse(*this)) memset(M, 0, 16*sizeof(T)); else *this=getTransposed(); break; } } //! Add another matrix. template inline CMatrix4 CMatrix4::operator+(const CMatrix4& other) const { CMatrix4 temp ( EM4CONST_NOTHING ); temp[0] = M[0]+other[0]; temp[1] = M[1]+other[1]; temp[2] = M[2]+other[2]; temp[3] = M[3]+other[3]; temp[4] = M[4]+other[4]; temp[5] = M[5]+other[5]; temp[6] = M[6]+other[6]; temp[7] = M[7]+other[7]; temp[8] = M[8]+other[8]; temp[9] = M[9]+other[9]; temp[10] = M[10]+other[10]; temp[11] = M[11]+other[11]; temp[12] = M[12]+other[12]; temp[13] = M[13]+other[13]; temp[14] = M[14]+other[14]; temp[15] = M[15]+other[15]; return temp; } //! Add another matrix. template inline CMatrix4& CMatrix4::operator+=(const CMatrix4& other) { M[0]+=other[0]; M[1]+=other[1]; M[2]+=other[2]; M[3]+=other[3]; M[4]+=other[4]; M[5]+=other[5]; M[6]+=other[6]; M[7]+=other[7]; M[8]+=other[8]; M[9]+=other[9]; M[10]+=other[10]; M[11]+=other[11]; M[12]+=other[12]; M[13]+=other[13]; M[14]+=other[14]; M[15]+=other[15]; return *this; } //! Subtract another matrix. template inline CMatrix4 CMatrix4::operator-(const CMatrix4& other) const { CMatrix4 temp ( EM4CONST_NOTHING ); temp[0] = M[0]-other[0]; temp[1] = M[1]-other[1]; temp[2] = M[2]-other[2]; temp[3] = M[3]-other[3]; temp[4] = M[4]-other[4]; temp[5] = M[5]-other[5]; temp[6] = M[6]-other[6]; temp[7] = M[7]-other[7]; temp[8] = M[8]-other[8]; temp[9] = M[9]-other[9]; temp[10] = M[10]-other[10]; temp[11] = M[11]-other[11]; temp[12] = M[12]-other[12]; temp[13] = M[13]-other[13]; temp[14] = M[14]-other[14]; temp[15] = M[15]-other[15]; return temp; } //! Subtract another matrix. template inline CMatrix4& CMatrix4::operator-=(const CMatrix4& other) { M[0]-=other[0]; M[1]-=other[1]; M[2]-=other[2]; M[3]-=other[3]; M[4]-=other[4]; M[5]-=other[5]; M[6]-=other[6]; M[7]-=other[7]; M[8]-=other[8]; M[9]-=other[9]; M[10]-=other[10]; M[11]-=other[11]; M[12]-=other[12]; M[13]-=other[13]; M[14]-=other[14]; M[15]-=other[15]; return *this; } //! Multiply by scalar. template inline CMatrix4 CMatrix4::operator*(const T& scalar) const { CMatrix4 temp ( EM4CONST_NOTHING ); temp[0] = M[0]*scalar; temp[1] = M[1]*scalar; temp[2] = M[2]*scalar; temp[3] = M[3]*scalar; temp[4] = M[4]*scalar; temp[5] = M[5]*scalar; temp[6] = M[6]*scalar; temp[7] = M[7]*scalar; temp[8] = M[8]*scalar; temp[9] = M[9]*scalar; temp[10] = M[10]*scalar; temp[11] = M[11]*scalar; temp[12] = M[12]*scalar; temp[13] = M[13]*scalar; temp[14] = M[14]*scalar; temp[15] = M[15]*scalar; return temp; } //! Multiply by scalar. template inline CMatrix4& CMatrix4::operator*=(const T& scalar) { M[0]*=scalar; M[1]*=scalar; M[2]*=scalar; M[3]*=scalar; M[4]*=scalar; M[5]*=scalar; M[6]*=scalar; M[7]*=scalar; M[8]*=scalar; M[9]*=scalar; M[10]*=scalar; M[11]*=scalar; M[12]*=scalar; M[13]*=scalar; M[14]*=scalar; M[15]*=scalar; return *this; } //! Multiply by another matrix. template inline CMatrix4& CMatrix4::operator*=(const CMatrix4& other) { #if defined ( USE_MATRIX_TEST ) // do checks on your own in order to avoid copy creation if ( !other.isIdentity() ) { if ( this->isIdentity() ) { return (*this = other); } else { CMatrix4 temp ( *this ); return setbyproduct_nocheck( temp, other ); } } return *this; #else CMatrix4 temp ( *this ); return setbyproduct_nocheck( temp, other ); #endif } //! multiply by another matrix // set this matrix to the product of two other matrices // goal is to reduce stack use and copy template inline CMatrix4& CMatrix4::setbyproduct_nocheck(const CMatrix4& other_a,const CMatrix4& other_b ) { const T *m1 = other_a.M; const T *m2 = other_b.M; M[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3]; M[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3]; M[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3]; M[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3]; M[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7]; M[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7]; M[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7]; M[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7]; M[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11]; M[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11]; M[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11]; M[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11]; M[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15]; M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15]; M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15]; M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15]; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } //! multiply by another matrix // set this matrix to the product of two other matrices // goal is to reduce stack use and copy template inline CMatrix4& CMatrix4::setbyproduct(const CMatrix4& other_a, const CMatrix4& other_b ) { #if defined ( USE_MATRIX_TEST ) if ( other_a.isIdentity () ) return (*this = other_b); else if ( other_b.isIdentity () ) return (*this = other_a); else return setbyproduct_nocheck(other_a,other_b); #else return setbyproduct_nocheck(other_a,other_b); #endif } //! multiply by another matrix template inline CMatrix4 CMatrix4::operator*(const CMatrix4& m2) const { #if defined ( USE_MATRIX_TEST ) // Testing purpose.. if ( this->isIdentity() ) return m2; if ( m2.isIdentity() ) return *this; #endif CMatrix4 m3 ( EM4CONST_NOTHING ); const T *m1 = M; m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3]; m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3]; m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3]; m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3]; m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7]; m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7]; m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7]; m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7]; m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11]; m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11]; m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11]; m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11]; m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15]; m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15]; m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15]; m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15]; return m3; } template inline vector3d CMatrix4::getTranslation() const { return vector3d(M[12], M[13], M[14]); } template inline CMatrix4& CMatrix4::setTranslation( const vector3d& translation ) { M[12] = translation.X; M[13] = translation.Y; M[14] = translation.Z; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } template inline CMatrix4& CMatrix4::setInverseTranslation( const vector3d& translation ) { M[12] = -translation.X; M[13] = -translation.Y; M[14] = -translation.Z; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } template inline CMatrix4& CMatrix4::setScale( const vector3d& scale ) { M[0] = scale.X; M[5] = scale.Y; M[10] = scale.Z; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } //! Returns the absolute values of the scales of the matrix. /** Note that this returns the absolute (positive) values unless only scale is set. Unfortunately it does not appear to be possible to extract any original negative values. The best that we could do would be to arbitrarily make one scale negative if one or three of them were negative. FIXME - return the original values. */ template inline vector3d CMatrix4::getScale() const { // See http://www.robertblum.com/articles/2005/02/14/decomposing-matrices // Deal with the 0 rotation case first // Prior to Irrlicht 1.6, we always returned this value. if(core::iszero(M[1]) && core::iszero(M[2]) && core::iszero(M[4]) && core::iszero(M[6]) && core::iszero(M[8]) && core::iszero(M[9])) return vector3d(M[0], M[5], M[10]); // We have to do the full calculation. return vector3d(sqrtf(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]), sqrtf(M[4] * M[4] + M[5] * M[5] + M[6] * M[6]), sqrtf(M[8] * M[8] + M[9] * M[9] + M[10] * M[10])); } template inline CMatrix4& CMatrix4::setRotationDegrees( const vector3d& rotation ) { return setRotationRadians( rotation * core::DEGTORAD ); } template inline CMatrix4& CMatrix4::setInverseRotationDegrees( const vector3d& rotation ) { return setInverseRotationRadians( rotation * core::DEGTORAD ); } template inline CMatrix4& CMatrix4::setRotationRadians( const vector3d& rotation ) { const f64 cr = cos( rotation.X ); const f64 sr = sin( rotation.X ); const f64 cp = cos( rotation.Y ); const f64 sp = sin( rotation.Y ); const f64 cy = cos( rotation.Z ); const f64 sy = sin( rotation.Z ); M[0] = (T)( cp*cy ); M[1] = (T)( cp*sy ); M[2] = (T)( -sp ); const f64 srsp = sr*sp; const f64 crsp = cr*sp; M[4] = (T)( srsp*cy-cr*sy ); M[5] = (T)( srsp*sy+cr*cy ); M[6] = (T)( sr*cp ); M[8] = (T)( crsp*cy+sr*sy ); M[9] = (T)( crsp*sy-sr*cy ); M[10] = (T)( cr*cp ); #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } //! Returns a rotation that is equivalent to that set by setRotationDegrees(). /** This code was sent in by Chev. Note that it does not necessarily return the *same* Euler angles as those set by setRotationDegrees(), but the rotation will be equivalent, i.e. will have the same result when used to rotate a vector or node. */ template inline core::vector3d CMatrix4::getRotationDegrees() const { const CMatrix4 &mat = *this; core::vector3d scale = getScale(); // we need to check for negative scale on to axes, which would bring up wrong results if (scale.Y<0 && scale.Z<0) { scale.Y =-scale.Y; scale.Z =-scale.Z; } else if (scale.X<0 && scale.Z<0) { scale.X =-scale.X; scale.Z =-scale.Z; } else if (scale.X<0 && scale.Y<0) { scale.X =-scale.X; scale.Y =-scale.Y; } const core::vector3d invScale(core::reciprocal(scale.X),core::reciprocal(scale.Y),core::reciprocal(scale.Z)); f64 Y = -asin(core::clamp(mat[2]*invScale.X, -1.0, 1.0)); const f64 C = cos(Y); Y *= RADTODEG64; f64 rotx, roty, X, Z; if (!core::iszero(C)) { const f64 invC = core::reciprocal(C); rotx = mat[10] * invC * invScale.Z; roty = mat[6] * invC * invScale.Y; X = atan2( roty, rotx ) * RADTODEG64; rotx = mat[0] * invC * invScale.X; roty = mat[1] * invC * invScale.X; Z = atan2( roty, rotx ) * RADTODEG64; } else { X = 0.0; rotx = mat[5] * invScale.Y; roty = -mat[4] * invScale.Y; Z = atan2( roty, rotx ) * RADTODEG64; } // fix values that get below zero if (X < 0.0) X += 360.0; if (Y < 0.0) Y += 360.0; if (Z < 0.0) Z += 360.0; return vector3d((T)X,(T)Y,(T)Z); } //! Sets matrix to rotation matrix of inverse angles given as parameters template inline CMatrix4& CMatrix4::setInverseRotationRadians( const vector3d& rotation ) { f64 cr = cos( rotation.X ); f64 sr = sin( rotation.X ); f64 cp = cos( rotation.Y ); f64 sp = sin( rotation.Y ); f64 cy = cos( rotation.Z ); f64 sy = sin( rotation.Z ); M[0] = (T)( cp*cy ); M[4] = (T)( cp*sy ); M[8] = (T)( -sp ); f64 srsp = sr*sp; f64 crsp = cr*sp; M[1] = (T)( srsp*cy-cr*sy ); M[5] = (T)( srsp*sy+cr*cy ); M[9] = (T)( sr*cp ); M[2] = (T)( crsp*cy+sr*sy ); M[6] = (T)( crsp*sy-sr*cy ); M[10] = (T)( cr*cp ); #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } //! Sets matrix to rotation matrix defined by axis and angle, assuming LH rotation template inline CMatrix4& CMatrix4::setRotationAxisRadians( const T& angle, const vector3d& axis ) { const f64 c = cos(angle); const f64 s = sin(angle); const f64 t = 1.0 - c; const f64 tx = t * axis.X; const f64 ty = t * axis.Y; const f64 tz = t * axis.Z; const f64 sx = s * axis.X; const f64 sy = s * axis.Y; const f64 sz = s * axis.Z; M[0] = (T)(tx * axis.X + c); M[1] = (T)(tx * axis.Y + sz); M[2] = (T)(tx * axis.Z - sy); M[4] = (T)(ty * axis.X - sz); M[5] = (T)(ty * axis.Y + c); M[6] = (T)(ty * axis.Z + sx); M[8] = (T)(tz * axis.X + sy); M[9] = (T)(tz * axis.Y - sx); M[10] = (T)(tz * axis.Z + c); #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } /*! */ template inline CMatrix4& CMatrix4::makeIdentity() { memset(M, 0, 16*sizeof(T)); M[0] = M[5] = M[10] = M[15] = (T)1; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=true; #endif return *this; } /* check identity with epsilon solve floating range problems.. */ template inline bool CMatrix4::isIdentity() const { #if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix) return true; #endif if (!core::equals( M[12], (T)0 ) || !core::equals( M[13], (T)0 ) || !core::equals( M[14], (T)0 ) || !core::equals( M[15], (T)1 )) return false; if (!core::equals( M[ 0], (T)1 ) || !core::equals( M[ 1], (T)0 ) || !core::equals( M[ 2], (T)0 ) || !core::equals( M[ 3], (T)0 )) return false; if (!core::equals( M[ 4], (T)0 ) || !core::equals( M[ 5], (T)1 ) || !core::equals( M[ 6], (T)0 ) || !core::equals( M[ 7], (T)0 )) return false; if (!core::equals( M[ 8], (T)0 ) || !core::equals( M[ 9], (T)0 ) || !core::equals( M[10], (T)1 ) || !core::equals( M[11], (T)0 )) return false; /* if (!core::equals( M[ 0], (T)1 ) || !core::equals( M[ 5], (T)1 ) || !core::equals( M[10], (T)1 ) || !core::equals( M[15], (T)1 )) return false; for (s32 i=0; i<4; ++i) for (s32 j=0; j<4; ++j) if ((j != i) && (!iszero((*this)(i,j)))) return false; */ #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=true; #endif return true; } /* Check orthogonality of matrix. */ template inline bool CMatrix4::isOrthogonal() const { T dp=M[0] * M[4 ] + M[1] * M[5 ] + M[2 ] * M[6 ] + M[3 ] * M[7 ]; if (!iszero(dp)) return false; dp = M[0] * M[8 ] + M[1] * M[9 ] + M[2 ] * M[10] + M[3 ] * M[11]; if (!iszero(dp)) return false; dp = M[0] * M[12] + M[1] * M[13] + M[2 ] * M[14] + M[3 ] * M[15]; if (!iszero(dp)) return false; dp = M[4] * M[8 ] + M[5] * M[9 ] + M[6 ] * M[10] + M[7 ] * M[11]; if (!iszero(dp)) return false; dp = M[4] * M[12] + M[5] * M[13] + M[6 ] * M[14] + M[7 ] * M[15]; if (!iszero(dp)) return false; dp = M[8] * M[12] + M[9] * M[13] + M[10] * M[14] + M[11] * M[15]; return (iszero(dp)); } /* doesn't solve floating range problems.. but takes care on +/- 0 on translation because we are changing it.. reducing floating point branches but it needs the floats in memory.. */ template inline bool CMatrix4::isIdentity_integer_base() const { #if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix) return true; #endif if(IR(M[0])!=F32_VALUE_1) return false; if(IR(M[1])!=0) return false; if(IR(M[2])!=0) return false; if(IR(M[3])!=0) return false; if(IR(M[4])!=0) return false; if(IR(M[5])!=F32_VALUE_1) return false; if(IR(M[6])!=0) return false; if(IR(M[7])!=0) return false; if(IR(M[8])!=0) return false; if(IR(M[9])!=0) return false; if(IR(M[10])!=F32_VALUE_1) return false; if(IR(M[11])!=0) return false; if(IR(M[12])!=0) return false; if(IR(M[13])!=0) return false; if(IR(M[13])!=0) return false; if(IR(M[15])!=F32_VALUE_1) return false; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=true; #endif return true; } template inline void CMatrix4::rotateVect( vector3df& vect ) const { vector3df tmp = vect; vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8]; vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9]; vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10]; } //! An alternate transform vector method, writing into a second vector template inline void CMatrix4::rotateVect(core::vector3df& out, const core::vector3df& in) const { out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8]; out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9]; out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10]; } //! An alternate transform vector method, writing into an array of 3 floats template inline void CMatrix4::rotateVect(T *out, const core::vector3df& in) const { out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8]; out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9]; out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10]; } template inline void CMatrix4::inverseRotateVect( vector3df& vect ) const { vector3df tmp = vect; vect.X = tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2]; vect.Y = tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6]; vect.Z = tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10]; } template inline void CMatrix4::transformVect( vector3df& vect) const { f32 vector[3]; vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12]; vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13]; vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14]; vect.X = vector[0]; vect.Y = vector[1]; vect.Z = vector[2]; } template inline void CMatrix4::transformVect( vector3df& out, const vector3df& in) const { out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12]; out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13]; out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14]; } template inline void CMatrix4::transformVect(T *out, const core::vector3df &in) const { out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12]; out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13]; out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14]; out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15]; } template inline void CMatrix4::transformVec3(T *out, const T * in) const { out[0] = in[0]*M[0] + in[1]*M[4] + in[2]*M[8] + M[12]; out[1] = in[0]*M[1] + in[1]*M[5] + in[2]*M[9] + M[13]; out[2] = in[0]*M[2] + in[1]*M[6] + in[2]*M[10] + M[14]; } //! Transforms a plane by this matrix template inline void CMatrix4::transformPlane( core::plane3d &plane) const { vector3df member; // Transform the plane member point, i.e. rotate, translate and scale it. transformVect(member, plane.getMemberPoint()); // Transform the normal by the transposed inverse of the matrix CMatrix4 transposedInverse(*this, EM4CONST_INVERSE_TRANSPOSED); vector3df normal = plane.Normal; transposedInverse.transformVect(normal); plane.setPlane(member, normal); } //! Transforms a plane by this matrix template inline void CMatrix4::transformPlane( const core::plane3d &in, core::plane3d &out) const { out = in; transformPlane( out ); } //! Transforms a axis aligned bounding box template inline void CMatrix4::transformBox(core::aabbox3d& box) const { #if defined ( USE_MATRIX_TEST ) if (isIdentity()) return; #endif transformVect(box.MinEdge); transformVect(box.MaxEdge); box.repair(); } //! Transforms a axis aligned bounding box more accurately than transformBox() template inline void CMatrix4::transformBoxEx(core::aabbox3d& box) const { #if defined ( USE_MATRIX_TEST ) if (isIdentity()) return; #endif const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z}; const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z}; f32 Bmin[3]; f32 Bmax[3]; Bmin[0] = Bmax[0] = M[12]; Bmin[1] = Bmax[1] = M[13]; Bmin[2] = Bmax[2] = M[14]; const CMatrix4 &m = *this; for (u32 i = 0; i < 3; ++i) { for (u32 j = 0; j < 3; ++j) { const f32 a = m(j,i) * Amin[j]; const f32 b = m(j,i) * Amax[j]; if (a < b) { Bmin[i] += a; Bmax[i] += b; } else { Bmin[i] += b; Bmax[i] += a; } } } box.MinEdge.X = Bmin[0]; box.MinEdge.Y = Bmin[1]; box.MinEdge.Z = Bmin[2]; box.MaxEdge.X = Bmax[0]; box.MaxEdge.Y = Bmax[1]; box.MaxEdge.Z = Bmax[2]; } //! Multiplies this matrix by a 1x4 matrix template inline void CMatrix4::multiplyWith1x4Matrix(T* matrix) const { /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ T mat[4]; mat[0] = matrix[0]; mat[1] = matrix[1]; mat[2] = matrix[2]; mat[3] = matrix[3]; matrix[0] = M[0]*mat[0] + M[4]*mat[1] + M[8]*mat[2] + M[12]*mat[3]; matrix[1] = M[1]*mat[0] + M[5]*mat[1] + M[9]*mat[2] + M[13]*mat[3]; matrix[2] = M[2]*mat[0] + M[6]*mat[1] + M[10]*mat[2] + M[14]*mat[3]; matrix[3] = M[3]*mat[0] + M[7]*mat[1] + M[11]*mat[2] + M[15]*mat[3]; } template inline void CMatrix4::inverseTranslateVect( vector3df& vect ) const { vect.X = vect.X-M[12]; vect.Y = vect.Y-M[13]; vect.Z = vect.Z-M[14]; } template inline void CMatrix4::translateVect( vector3df& vect ) const { vect.X = vect.X+M[12]; vect.Y = vect.Y+M[13]; vect.Z = vect.Z+M[14]; } template inline bool CMatrix4::getInverse(CMatrix4& out) const { /// Calculates the inverse of this Matrix /// The inverse is calculated using Cramers rule. /// If no inverse exists then 'false' is returned. #if defined ( USE_MATRIX_TEST ) if ( this->isIdentity() ) { out=*this; return true; } #endif const CMatrix4 &m = *this; f32 d = (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) - (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) + (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)) + (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) - (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) + (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)); if( core::iszero ( d, FLT_MIN ) ) return false; d = core::reciprocal ( d ); out(0, 0) = d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) + m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) + m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1))); out(0, 1) = d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) + m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) + m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1))); out(0, 2) = d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) + m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) + m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1))); out(0, 3) = d * (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) + m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) + m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2))); out(1, 0) = d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) + m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) + m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3))); out(1, 1) = d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) + m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) + m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3))); out(1, 2) = d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) + m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) + m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3))); out(1, 3) = d * (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) + m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) + m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2))); out(2, 0) = d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) + m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) + m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3))); out(2, 1) = d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) + m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) + m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3))); out(2, 2) = d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) + m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) + m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3))); out(2, 3) = d * (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) + m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) + m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0))); out(3, 0) = d * (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) + m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) + m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1))); out(3, 1) = d * (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) + m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) + m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1))); out(3, 2) = d * (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) + m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) + m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1))); out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) + m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) + m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))); #if defined ( USE_MATRIX_TEST ) out.definitelyIdentityMatrix = definitelyIdentityMatrix; #endif return true; } //! Inverts a primitive matrix which only contains a translation and a rotation //! \param out: where result matrix is written to. template inline bool CMatrix4::getInversePrimitive ( CMatrix4& out ) const { out.M[0 ] = M[0]; out.M[1 ] = M[4]; out.M[2 ] = M[8]; out.M[3 ] = 0; out.M[4 ] = M[1]; out.M[5 ] = M[5]; out.M[6 ] = M[9]; out.M[7 ] = 0; out.M[8 ] = M[2]; out.M[9 ] = M[6]; out.M[10] = M[10]; out.M[11] = 0; out.M[12] = (T)-(M[12]*M[0] + M[13]*M[1] + M[14]*M[2]); out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]); out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]); out.M[15] = 1; #if defined ( USE_MATRIX_TEST ) out.definitelyIdentityMatrix = definitelyIdentityMatrix; #endif return true; } /*! */ template inline bool CMatrix4::makeInverse() { #if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix) return true; #endif CMatrix4 temp ( EM4CONST_NOTHING ); if (getInverse(temp)) { *this = temp; return true; } return false; } template inline CMatrix4& CMatrix4::operator=(const CMatrix4 &other) { if (this==&other) return *this; memcpy(M, other.M, 16*sizeof(T)); #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=other.definitelyIdentityMatrix; #endif return *this; } template inline CMatrix4& CMatrix4::operator=(const T& scalar) { for (s32 i = 0; i < 16; ++i) M[i]=scalar; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } template inline bool CMatrix4::operator==(const CMatrix4 &other) const { #if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix && other.definitelyIdentityMatrix) return true; #endif for (s32 i = 0; i < 16; ++i) if (M[i] != other.M[i]) return false; return true; } template inline bool CMatrix4::operator!=(const CMatrix4 &other) const { return !(*this == other); } // Builds a right-handed perspective projection matrix based on a field of view template inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveFovRH( f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar) { const f64 h = reciprocal(tan(fieldOfViewRadians*0.5)); _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero const T w = static_cast(h / aspectRatio); _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero M[0] = w; M[1] = 0; M[2] = 0; M[3] = 0; M[4] = 0; M[5] = (T)h; M[6] = 0; M[7] = 0; M[8] = 0; M[9] = 0; M[10] = (T)(zFar/(zNear-zFar)); // DirectX version // M[10] = (T)(zFar+zNear/(zNear-zFar)); // OpenGL version M[11] = -1; M[12] = 0; M[13] = 0; M[14] = (T)(zNear*zFar/(zNear-zFar)); // DirectX version // M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version M[15] = 0; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } // Builds a left-handed perspective projection matrix based on a field of view template inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveFovLH( f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar) { const f64 h = reciprocal(tan(fieldOfViewRadians*0.5)); _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero const T w = static_cast(h / aspectRatio); _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero M[0] = w; M[1] = 0; M[2] = 0; M[3] = 0; M[4] = 0; M[5] = (T)h; M[6] = 0; M[7] = 0; M[8] = 0; M[9] = 0; M[10] = (T)(zFar/(zFar-zNear)); M[11] = 1; M[12] = 0; M[13] = 0; M[14] = (T)(-zNear*zFar/(zFar-zNear)); M[15] = 0; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } // Builds a left-handed perspective projection matrix based on a field of view, with far plane culling at infinity template inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveFovInfinityLH( f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon) { const f64 h = reciprocal(tan(fieldOfViewRadians*0.5)); _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero const T w = static_cast(h / aspectRatio); M[0] = w; M[1] = 0; M[2] = 0; M[3] = 0; M[4] = 0; M[5] = (T)h; M[6] = 0; M[7] = 0; M[8] = 0; M[9] = 0; M[10] = (T)(1.f-epsilon); M[11] = 1; M[12] = 0; M[13] = 0; M[14] = (T)(zNear*(epsilon-1.f)); M[15] = 0; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } // Builds a left-handed orthogonal projection matrix. template inline CMatrix4& CMatrix4::buildProjectionMatrixOrthoLH( f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) { _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero M[0] = (T)(2/widthOfViewVolume); M[1] = 0; M[2] = 0; M[3] = 0; M[4] = 0; M[5] = (T)(2/heightOfViewVolume); M[6] = 0; M[7] = 0; M[8] = 0; M[9] = 0; M[10] = (T)(1/(zFar-zNear)); M[11] = 0; M[12] = 0; M[13] = 0; M[14] = (T)(zNear/(zNear-zFar)); M[15] = 1; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } // Builds a right-handed orthogonal projection matrix. template inline CMatrix4& CMatrix4::buildProjectionMatrixOrthoRH( f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) { _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero M[0] = (T)(2/widthOfViewVolume); M[1] = 0; M[2] = 0; M[3] = 0; M[4] = 0; M[5] = (T)(2/heightOfViewVolume); M[6] = 0; M[7] = 0; M[8] = 0; M[9] = 0; M[10] = (T)(1/(zNear-zFar)); M[11] = 0; M[12] = 0; M[13] = 0; M[14] = (T)(zNear/(zNear-zFar)); M[15] = 1; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } // Builds a right-handed perspective projection matrix. template inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveRH( f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) { _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero M[0] = (T)(2*zNear/widthOfViewVolume); M[1] = 0; M[2] = 0; M[3] = 0; M[4] = 0; M[5] = (T)(2*zNear/heightOfViewVolume); M[6] = 0; M[7] = 0; M[8] = 0; M[9] = 0; M[10] = (T)(zFar/(zNear-zFar)); M[11] = -1; M[12] = 0; M[13] = 0; M[14] = (T)(zNear*zFar/(zNear-zFar)); M[15] = 0; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } // Builds a left-handed perspective projection matrix. template inline CMatrix4& CMatrix4::buildProjectionMatrixPerspectiveLH( f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) { _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero M[0] = (T)(2*zNear/widthOfViewVolume); M[1] = 0; M[2] = 0; M[3] = 0; M[4] = 0; M[5] = (T)(2*zNear/heightOfViewVolume); M[6] = 0; M[7] = 0; M[8] = 0; M[9] = 0; M[10] = (T)(zFar/(zFar-zNear)); M[11] = 1; M[12] = 0; M[13] = 0; M[14] = (T)(zNear*zFar/(zNear-zFar)); M[15] = 0; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } // Builds a matrix that flattens geometry into a plane. template inline CMatrix4& CMatrix4::buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point) { plane.Normal.normalize(); const f32 d = plane.Normal.dotProduct(light); M[ 0] = (T)(-plane.Normal.X * light.X + d); M[ 1] = (T)(-plane.Normal.X * light.Y); M[ 2] = (T)(-plane.Normal.X * light.Z); M[ 3] = (T)(-plane.Normal.X * point); M[ 4] = (T)(-plane.Normal.Y * light.X); M[ 5] = (T)(-plane.Normal.Y * light.Y + d); M[ 6] = (T)(-plane.Normal.Y * light.Z); M[ 7] = (T)(-plane.Normal.Y * point); M[ 8] = (T)(-plane.Normal.Z * light.X); M[ 9] = (T)(-plane.Normal.Z * light.Y); M[10] = (T)(-plane.Normal.Z * light.Z + d); M[11] = (T)(-plane.Normal.Z * point); M[12] = (T)(-plane.D * light.X); M[13] = (T)(-plane.D * light.Y); M[14] = (T)(-plane.D * light.Z); M[15] = (T)(-plane.D * point + d); #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } // Builds a left-handed look-at matrix. template inline CMatrix4& CMatrix4::buildCameraLookAtMatrixLH( const vector3df& position, const vector3df& target, const vector3df& upVector) { vector3df zaxis = target - position; zaxis.normalize(); vector3df xaxis = upVector.crossProduct(zaxis); xaxis.normalize(); vector3df yaxis = zaxis.crossProduct(xaxis); M[0] = (T)xaxis.X; M[1] = (T)yaxis.X; M[2] = (T)zaxis.X; M[3] = 0; M[4] = (T)xaxis.Y; M[5] = (T)yaxis.Y; M[6] = (T)zaxis.Y; M[7] = 0; M[8] = (T)xaxis.Z; M[9] = (T)yaxis.Z; M[10] = (T)zaxis.Z; M[11] = 0; M[12] = (T)-xaxis.dotProduct(position); M[13] = (T)-yaxis.dotProduct(position); M[14] = (T)-zaxis.dotProduct(position); M[15] = 1; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } // Builds a right-handed look-at matrix. template inline CMatrix4& CMatrix4::buildCameraLookAtMatrixRH( const vector3df& position, const vector3df& target, const vector3df& upVector) { vector3df zaxis = position - target; zaxis.normalize(); vector3df xaxis = upVector.crossProduct(zaxis); xaxis.normalize(); vector3df yaxis = zaxis.crossProduct(xaxis); M[0] = (T)xaxis.X; M[1] = (T)yaxis.X; M[2] = (T)zaxis.X; M[3] = 0; M[4] = (T)xaxis.Y; M[5] = (T)yaxis.Y; M[6] = (T)zaxis.Y; M[7] = 0; M[8] = (T)xaxis.Z; M[9] = (T)yaxis.Z; M[10] = (T)zaxis.Z; M[11] = 0; M[12] = (T)-xaxis.dotProduct(position); M[13] = (T)-yaxis.dotProduct(position); M[14] = (T)-zaxis.dotProduct(position); M[15] = 1; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } // creates a new matrix as interpolated matrix from this and the passed one. template inline CMatrix4 CMatrix4::interpolate(const core::CMatrix4& b, f32 time) const { CMatrix4 mat ( EM4CONST_NOTHING ); for (u32 i=0; i < 16; i += 4) { mat.M[i+0] = (T)(M[i+0] + ( b.M[i+0] - M[i+0] ) * time); mat.M[i+1] = (T)(M[i+1] + ( b.M[i+1] - M[i+1] ) * time); mat.M[i+2] = (T)(M[i+2] + ( b.M[i+2] - M[i+2] ) * time); mat.M[i+3] = (T)(M[i+3] + ( b.M[i+3] - M[i+3] ) * time); } return mat; } // returns transposed matrix template inline CMatrix4 CMatrix4::getTransposed() const { CMatrix4 t ( EM4CONST_NOTHING ); getTransposed ( t ); return t; } // returns transposed matrix template inline void CMatrix4::getTransposed( CMatrix4& o ) const { o[ 0] = M[ 0]; o[ 1] = M[ 4]; o[ 2] = M[ 8]; o[ 3] = M[12]; o[ 4] = M[ 1]; o[ 5] = M[ 5]; o[ 6] = M[ 9]; o[ 7] = M[13]; o[ 8] = M[ 2]; o[ 9] = M[ 6]; o[10] = M[10]; o[11] = M[14]; o[12] = M[ 3]; o[13] = M[ 7]; o[14] = M[11]; o[15] = M[15]; #if defined ( USE_MATRIX_TEST ) o.definitelyIdentityMatrix=definitelyIdentityMatrix; #endif } // used to scale <-1,-1><1,1> to viewport template inline CMatrix4& CMatrix4::buildNDCToDCMatrix( const core::rect& viewport, f32 zScale) { const f32 scaleX = (viewport.getWidth() - 0.75f ) * 0.5f; const f32 scaleY = -(viewport.getHeight() - 0.75f ) * 0.5f; const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f ); const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f ); makeIdentity(); M[12] = (T)dx; M[13] = (T)dy; return setScale(core::vector3d((T)scaleX, (T)scaleY, (T)zScale)); } //! Builds a matrix that rotates from one vector to another /** \param from: vector to rotate from \param to: vector to rotate to http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm */ template inline CMatrix4& CMatrix4::buildRotateFromTo(const core::vector3df& from, const core::vector3df& to) { // unit vectors core::vector3df f(from); core::vector3df t(to); f.normalize(); t.normalize(); // axis multiplication by sin core::vector3df vs(t.crossProduct(f)); // axis of rotation core::vector3df v(vs); v.normalize(); // cosinus angle T ca = f.dotProduct(t); core::vector3df vt(v * (1 - ca)); M[0] = vt.X * v.X + ca; M[5] = vt.Y * v.Y + ca; M[10] = vt.Z * v.Z + ca; vt.X *= v.Y; vt.Z *= v.X; vt.Y *= v.Z; M[1] = vt.X - vs.Z; M[2] = vt.Z + vs.Y; M[3] = 0; M[4] = vt.X + vs.Z; M[6] = vt.Y - vs.X; M[7] = 0; M[8] = vt.Z - vs.Y; M[9] = vt.Y + vs.X; M[11] = 0; M[12] = 0; M[13] = 0; M[14] = 0; M[15] = 1; return *this; } //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis /** \param camPos: viewer position in world coord \param center: object position in world-coord, rotation pivot \param translation: object final translation from center \param axis: axis to rotate about \param from: source vector to rotate from */ template inline void CMatrix4::buildAxisAlignedBillboard( const core::vector3df& camPos, const core::vector3df& center, const core::vector3df& translation, const core::vector3df& axis, const core::vector3df& from) { // axis of rotation core::vector3df up = axis; up.normalize(); const core::vector3df forward = (camPos - center).normalize(); const core::vector3df right = up.crossProduct(forward).normalize(); // correct look vector const core::vector3df look = right.crossProduct(up); // rotate from to // axis multiplication by sin const core::vector3df vs = look.crossProduct(from); // cosinus angle const f32 ca = from.dotProduct(look); core::vector3df vt(up * (1.f - ca)); M[0] = static_cast(vt.X * up.X + ca); M[5] = static_cast(vt.Y * up.Y + ca); M[10] = static_cast(vt.Z * up.Z + ca); vt.X *= up.Y; vt.Z *= up.X; vt.Y *= up.Z; M[1] = static_cast(vt.X - vs.Z); M[2] = static_cast(vt.Z + vs.Y); M[3] = 0; M[4] = static_cast(vt.X + vs.Z); M[6] = static_cast(vt.Y - vs.X); M[7] = 0; M[8] = static_cast(vt.Z - vs.Y); M[9] = static_cast(vt.Y + vs.X); M[11] = 0; setRotationCenter(center, translation); } //! Builds a combined matrix which translate to a center before rotation and translate afterwards template inline void CMatrix4::setRotationCenter(const core::vector3df& center, const core::vector3df& translation) { M[12] = -M[0]*center.X - M[4]*center.Y - M[8]*center.Z + (center.X - translation.X ); M[13] = -M[1]*center.X - M[5]*center.Y - M[9]*center.Z + (center.Y - translation.Y ); M[14] = -M[2]*center.X - M[6]*center.Y - M[10]*center.Z + (center.Z - translation.Z ); M[15] = (T) 1.0; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif } /*! Generate texture coordinates as linear functions so that: u = Ux*x + Uy*y + Uz*z + Uw v = Vx*x + Vy*y + Vz*z + Vw The matrix M for this case is: Ux Vx 0 0 Uy Vy 0 0 Uz Vz 0 0 Uw Vw 0 0 */ template inline CMatrix4& CMatrix4::buildTextureTransform( f32 rotateRad, const core::vector2df &rotatecenter, const core::vector2df &translate, const core::vector2df &scale) { const f32 c = cosf(rotateRad); const f32 s = sinf(rotateRad); M[0] = (T)(c * scale.X); M[1] = (T)(s * scale.Y); M[2] = 0; M[3] = 0; M[4] = (T)(-s * scale.X); M[5] = (T)(c * scale.Y); M[6] = 0; M[7] = 0; M[8] = (T)(c * scale.X * rotatecenter.X + -s * rotatecenter.Y + translate.X); M[9] = (T)(s * scale.Y * rotatecenter.X + c * rotatecenter.Y + translate.Y); M[10] = 1; M[11] = 0; M[12] = 0; M[13] = 0; M[14] = 0; M[15] = 1; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } // rotate about z axis, center ( 0.5, 0.5 ) template inline CMatrix4& CMatrix4::setTextureRotationCenter( f32 rotateRad ) { const f32 c = cosf(rotateRad); const f32 s = sinf(rotateRad); M[0] = (T)c; M[1] = (T)s; M[4] = (T)-s; M[5] = (T)c; M[8] = (T)(0.5f * ( s - c) + 0.5f); M[9] = (T)(-0.5f * ( s + c) + 0.5f); #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (rotateRad==0.0f); #endif return *this; } template inline CMatrix4& CMatrix4::setTextureTranslate ( f32 x, f32 y ) { M[8] = (T)x; M[9] = (T)y; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f); #endif return *this; } template inline CMatrix4& CMatrix4::setTextureTranslateTransposed ( f32 x, f32 y ) { M[2] = (T)x; M[6] = (T)y; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ; #endif return *this; } template inline CMatrix4& CMatrix4::setTextureScale ( f32 sx, f32 sy ) { M[0] = (T)sx; M[5] = (T)sy; #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f); #endif return *this; } template inline CMatrix4& CMatrix4::setTextureScaleCenter( f32 sx, f32 sy ) { M[0] = (T)sx; M[5] = (T)sy; M[8] = (T)(0.5f - 0.5f * sx); M[9] = (T)(0.5f - 0.5f * sy); #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f); #endif return *this; } // sets all matrix data members at once template inline CMatrix4& CMatrix4::setM(const T* data) { memcpy(M,data, 16*sizeof(T)); #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; #endif return *this; } // sets if the matrix is definitely identity matrix template inline void CMatrix4::setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix) { #if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = isDefinitelyIdentityMatrix; #endif } // gets if the matrix is definitely identity matrix template inline bool CMatrix4::getDefinitelyIdentityMatrix() const { #if defined ( USE_MATRIX_TEST ) return definitelyIdentityMatrix; #else return false; #endif } //! Compare two matrices using the equal method template inline bool CMatrix4::equals(const core::CMatrix4& other, const T tolerance) const { #if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix && other.definitelyIdentityMatrix) return true; #endif for (s32 i = 0; i < 16; ++i) if (!core::equals(M[i],other.M[i], tolerance)) return false; return true; } // Multiply by scalar. template inline CMatrix4 operator*(const T scalar, const CMatrix4& mat) { return mat*scalar; } //! Typedef for f32 matrix typedef CMatrix4 matrix4; //! global const identity matrix IRRLICHT_API extern const matrix4 IdentityMatrix; } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/line3d.h0000644000000000000000000001057612574354552015040 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_LINE_3D_H_INCLUDED__ #define __IRR_LINE_3D_H_INCLUDED__ #include "irrTypes.h" #include "vector3d.h" namespace irr { namespace core { //! 3D line between two points with intersection methods. template class line3d { public: //! Default constructor /** line from (0,0,0) to (1,1,1) */ line3d() : start(0,0,0), end(1,1,1) {} //! Constructor with two points line3d(T xa, T ya, T za, T xb, T yb, T zb) : start(xa, ya, za), end(xb, yb, zb) {} //! Constructor with two points as vectors line3d(const vector3d& start, const vector3d& end) : start(start), end(end) {} // operators line3d operator+(const vector3d& point) const { return line3d(start + point, end + point); } line3d& operator+=(const vector3d& point) { start += point; end += point; return *this; } line3d operator-(const vector3d& point) const { return line3d(start - point, end - point); } line3d& operator-=(const vector3d& point) { start -= point; end -= point; return *this; } bool operator==(const line3d& other) const { return (start==other.start && end==other.end) || (end==other.start && start==other.end);} bool operator!=(const line3d& other) const { return !(start==other.start && end==other.end) || (end==other.start && start==other.end);} // functions //! Set this line to a new line going through the two points. void setLine(const T& xa, const T& ya, const T& za, const T& xb, const T& yb, const T& zb) {start.set(xa, ya, za); end.set(xb, yb, zb);} //! Set this line to a new line going through the two points. void setLine(const vector3d& nstart, const vector3d& nend) {start.set(nstart); end.set(nend);} //! Set this line to new line given as parameter. void setLine(const line3d& line) {start.set(line.start); end.set(line.end);} //! Get length of line /** \return Length of line. */ T getLength() const { return start.getDistanceFrom(end); } //! Get squared length of line /** \return Squared length of line. */ T getLengthSQ() const { return start.getDistanceFromSQ(end); } //! Get middle of line /** \return Center of line. */ vector3d getMiddle() const { return (start + end)/(T)2; } //! Get vector of line /** \return vector of line. */ vector3d getVector() const { return end - start; } //! Check if the given point is between start and end of the line. /** Assumes that the point is already somewhere on the line. \param point The point to test. \return True if point is on the line between start and end, else false. */ bool isPointBetweenStartAndEnd(const vector3d& point) const { return point.isBetweenPoints(start, end); } //! Get the closest point on this line to a point /** \param point The point to compare to. \return The nearest point which is part of the line. */ vector3d getClosestPoint(const vector3d& point) const { vector3d c = point - start; vector3d v = end - start; T d = (T)v.getLength(); v /= d; T t = v.dotProduct(c); if (t < (T)0.0) return start; if (t > d) return end; v *= t; return start + v; } //! Check if the line intersects with a shpere /** \param sorigin: Origin of the shpere. \param sradius: Radius of the sphere. \param outdistance: The distance to the first intersection point. \return True if there is an intersection. If there is one, the distance to the first intersection point is stored in outdistance. */ bool getIntersectionWithSphere(vector3d sorigin, T sradius, f64& outdistance) const { const vector3d q = sorigin - start; T c = q.getLength(); T v = q.dotProduct(getVector().normalize()); T d = sradius * sradius - (c*c - v*v); if (d < 0.0) return false; outdistance = v - core::squareroot ( d ); return true; } // member variables //! Start point of line vector3d start; //! End point of line vector3d end; }; //! Typedef for an f32 line. typedef line3d line3df; //! Typedef for an integer line. typedef line3d line3di; } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/line2d.h0000644000000000000000000002403712574354552015034 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_LINE_2D_H_INCLUDED__ #define __IRR_LINE_2D_H_INCLUDED__ #include "irrTypes.h" #include "vector2d.h" namespace irr { namespace core { //! 2D line between two points with intersection methods. template class line2d { public: //! Default constructor for line going from (0,0) to (1,1). line2d() : start(0,0), end(1,1) {} //! Constructor for line between the two points. line2d(T xa, T ya, T xb, T yb) : start(xa, ya), end(xb, yb) {} //! Constructor for line between the two points given as vectors. line2d(const vector2d& start, const vector2d& end) : start(start), end(end) {} //! Copy constructor. line2d(const line2d& other) : start(other.start), end(other.end) {} // operators line2d operator+(const vector2d& point) const { return line2d(start + point, end + point); } line2d& operator+=(const vector2d& point) { start += point; end += point; return *this; } line2d operator-(const vector2d& point) const { return line2d(start - point, end - point); } line2d& operator-=(const vector2d& point) { start -= point; end -= point; return *this; } bool operator==(const line2d& other) const { return (start==other.start && end==other.end) || (end==other.start && start==other.end);} bool operator!=(const line2d& other) const { return !(start==other.start && end==other.end) || (end==other.start && start==other.end);} // functions //! Set this line to new line going through the two points. void setLine(const T& xa, const T& ya, const T& xb, const T& yb){start.set(xa, ya); end.set(xb, yb);} //! Set this line to new line going through the two points. void setLine(const vector2d& nstart, const vector2d& nend){start.set(nstart); end.set(nend);} //! Set this line to new line given as parameter. void setLine(const line2d& line){start.set(line.start); end.set(line.end);} //! Get length of line /** \return Length of the line. */ T getLength() const { return start.getDistanceFrom(end); } //! Get squared length of the line /** \return Squared length of line. */ T getLengthSQ() const { return start.getDistanceFromSQ(end); } //! Get middle of the line /** \return center of the line. */ vector2d getMiddle() const { return (start + end)/(T)2; } //! Get the vector of the line. /** \return The vector of the line. */ vector2d getVector() const { return vector2d(end.X - start.X, end.Y - start.Y); } //! Tests if this line intersects with another line. /** \param l: Other line to test intersection with. \param checkOnlySegments: Default is to check intersection between the begin and endpoints. When set to false the function will check for the first intersection point when extending the lines. \param out: If there is an intersection, the location of the intersection will be stored in this vector. \return True if there is an intersection, false if not. */ bool intersectWith(const line2d& l, vector2d& out, bool checkOnlySegments=true) const { // Uses the method given at: // http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ const f32 commonDenominator = (f32)(l.end.Y - l.start.Y)*(end.X - start.X) - (l.end.X - l.start.X)*(end.Y - start.Y); const f32 numeratorA = (f32)(l.end.X - l.start.X)*(start.Y - l.start.Y) - (l.end.Y - l.start.Y)*(start.X -l.start.X); const f32 numeratorB = (f32)(end.X - start.X)*(start.Y - l.start.Y) - (end.Y - start.Y)*(start.X -l.start.X); if(equals(commonDenominator, 0.f)) { // The lines are either coincident or parallel // if both numerators are 0, the lines are coincident if(equals(numeratorA, 0.f) && equals(numeratorB, 0.f)) { // Try and find a common endpoint if(l.start == start || l.end == start) out = start; else if(l.end == end || l.start == end) out = end; // now check if the two segments are disjunct else if (l.start.X>start.X && l.end.X>start.X && l.start.X>end.X && l.end.X>end.X) return false; else if (l.start.Y>start.Y && l.end.Y>start.Y && l.start.Y>end.Y && l.end.Y>end.Y) return false; else if (l.start.X maxp; vector2d minp; if ((start.X>l.start.X && start.X>l.end.X && start.X>end.X) || (start.Y>l.start.Y && start.Y>l.end.Y && start.Y>end.Y)) maxp=start; else if ((end.X>l.start.X && end.X>l.end.X && end.X>start.X) || (end.Y>l.start.Y && end.Y>l.end.Y && end.Y>start.Y)) maxp=end; else if ((l.start.X>start.X && l.start.X>l.end.X && l.start.X>end.X) || (l.start.Y>start.Y && l.start.Y>l.end.Y && l.start.Y>end.Y)) maxp=l.start; else maxp=l.end; if (maxp != start && ((start.X(); if (start != maxp && start != minp) out += start; if (end != maxp && end != minp) out += end; if (l.start != maxp && l.start != minp) out += l.start; if (l.end != maxp && l.end != minp) out += l.end; out.X = (T)(out.X/2); out.Y = (T)(out.Y/2); } return true; // coincident } return false; // parallel } // Get the point of intersection on this line, checking that // it is within the line segment. const f32 uA = numeratorA / commonDenominator; if(checkOnlySegments && (uA < 0.f || uA > 1.f) ) return false; // Outside the line segment const f32 uB = numeratorB / commonDenominator; if(checkOnlySegments && (uB < 0.f || uB > 1.f)) return false; // Outside the line segment // Calculate the intersection point. out.X = (T)(start.X + uA * (end.X - start.X)); out.Y = (T)(start.Y + uA * (end.Y - start.Y)); return true; } //! Get unit vector of the line. /** \return Unit vector of this line. */ vector2d getUnitVector() const { T len = (T)(1.0 / getLength()); return vector2d((end.X - start.X) * len, (end.Y - start.Y) * len); } //! Get angle between this line and given line. /** \param l Other line for test. \return Angle in degrees. */ f64 getAngleWith(const line2d& l) const { vector2d vect = getVector(); vector2d vect2 = l.getVector(); return vect.getAngleWith(vect2); } //! Tells us if the given point lies to the left, right, or on the line. /** \return 0 if the point is on the line <0 if to the left, or >0 if to the right. */ T getPointOrientation(const vector2d& point) const { return ( (end.X - start.X) * (point.Y - start.Y) - (point.X - start.X) * (end.Y - start.Y) ); } //! Check if the given point is a member of the line /** \return True if point is between start and end, else false. */ bool isPointOnLine(const vector2d& point) const { T d = getPointOrientation(point); return (d == 0 && point.isBetweenPoints(start, end)); } //! Check if the given point is between start and end of the line. /** Assumes that the point is already somewhere on the line. */ bool isPointBetweenStartAndEnd(const vector2d& point) const { return point.isBetweenPoints(start, end); } //! Get the closest point on this line to a point /** \param checkOnlySegments: Default (true) is to return a point on the line-segment (between begin and end) of the line. When set to false the function will check for the first the closest point on the the line even when outside the segment. */ vector2d getClosestPoint(const vector2d& point, bool checkOnlySegments=true) const { vector2d c((f64)(point.X-start.X), (f64)(point.Y- start.Y)); vector2d v((f64)(end.X-start.X), (f64)(end.Y-start.Y)); f64 d = v.getLength(); if ( d == 0 ) // can't tell much when the line is just a single point return start; v /= d; f64 t = v.dotProduct(c); if ( checkOnlySegments ) { if (t < 0) return vector2d((T)start.X, (T)start.Y); if (t > d) return vector2d((T)end.X, (T)end.Y); } v *= t; return vector2d((T)(start.X + v.X), (T)(start.Y + v.Y)); } //! Start point of the line. vector2d start; //! End point of the line. vector2d end; }; // partial specialization to optimize lines (avoiding casts) template <> inline vector2df line2d::getClosestPoint(const vector2df& point, bool checkOnlySegments) const { vector2df c = point - start; vector2df v = end - start; f32 d = (f32)v.getLength(); if ( d == 0 ) // can't tell much when the line is just a single point return start; v /= d; f32 t = v.dotProduct(c); if ( checkOnlySegments ) { if (t < 0) return start; if (t > d) return end; } v *= t; return start + v; } //! Typedef for an f32 line. typedef line2d line2df; //! Typedef for an integer line. typedef line2d line2di; } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/Keycodes.h0000644000000000000000000001722712574354552015430 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_KEY_CODES_H_INCLUDED__ #define __IRR_KEY_CODES_H_INCLUDED__ namespace irr { enum EKEY_CODE { KEY_LBUTTON = 0x01, // Left mouse button KEY_RBUTTON = 0x02, // Right mouse button KEY_CANCEL = 0x03, // Control-break processing KEY_MBUTTON = 0x04, // Middle mouse button (three-button mouse) KEY_XBUTTON1 = 0x05, // Windows 2000/XP: X1 mouse button KEY_XBUTTON2 = 0x06, // Windows 2000/XP: X2 mouse button KEY_BACK = 0x08, // BACKSPACE key KEY_TAB = 0x09, // TAB key KEY_CLEAR = 0x0C, // CLEAR key KEY_RETURN = 0x0D, // ENTER key KEY_SHIFT = 0x10, // SHIFT key KEY_CONTROL = 0x11, // CTRL key KEY_MENU = 0x12, // ALT key KEY_PAUSE = 0x13, // PAUSE key KEY_CAPITAL = 0x14, // CAPS LOCK key KEY_KANA = 0x15, // IME Kana mode KEY_HANGUEL = 0x15, // IME Hanguel mode (maintained for compatibility use KEY_HANGUL) KEY_HANGUL = 0x15, // IME Hangul mode KEY_JUNJA = 0x17, // IME Junja mode KEY_FINAL = 0x18, // IME final mode KEY_HANJA = 0x19, // IME Hanja mode KEY_KANJI = 0x19, // IME Kanji mode KEY_ESCAPE = 0x1B, // ESC key KEY_CONVERT = 0x1C, // IME convert KEY_NONCONVERT = 0x1D, // IME nonconvert KEY_ACCEPT = 0x1E, // IME accept KEY_MODECHANGE = 0x1F, // IME mode change request KEY_SPACE = 0x20, // SPACEBAR KEY_PRIOR = 0x21, // PAGE UP key KEY_NEXT = 0x22, // PAGE DOWN key KEY_END = 0x23, // END key KEY_HOME = 0x24, // HOME key KEY_LEFT = 0x25, // LEFT ARROW key KEY_UP = 0x26, // UP ARROW key KEY_RIGHT = 0x27, // RIGHT ARROW key KEY_DOWN = 0x28, // DOWN ARROW key KEY_SELECT = 0x29, // SELECT key KEY_PRINT = 0x2A, // PRINT key KEY_EXECUT = 0x2B, // EXECUTE key KEY_SNAPSHOT = 0x2C, // PRINT SCREEN key KEY_INSERT = 0x2D, // INS key KEY_DELETE = 0x2E, // DEL key KEY_HELP = 0x2F, // HELP key KEY_KEY_0 = 0x30, // 0 key KEY_KEY_1 = 0x31, // 1 key KEY_KEY_2 = 0x32, // 2 key KEY_KEY_3 = 0x33, // 3 key KEY_KEY_4 = 0x34, // 4 key KEY_KEY_5 = 0x35, // 5 key KEY_KEY_6 = 0x36, // 6 key KEY_KEY_7 = 0x37, // 7 key KEY_KEY_8 = 0x38, // 8 key KEY_KEY_9 = 0x39, // 9 key KEY_KEY_A = 0x41, // A key KEY_KEY_B = 0x42, // B key KEY_KEY_C = 0x43, // C key KEY_KEY_D = 0x44, // D key KEY_KEY_E = 0x45, // E key KEY_KEY_F = 0x46, // F key KEY_KEY_G = 0x47, // G key KEY_KEY_H = 0x48, // H key KEY_KEY_I = 0x49, // I key KEY_KEY_J = 0x4A, // J key KEY_KEY_K = 0x4B, // K key KEY_KEY_L = 0x4C, // L key KEY_KEY_M = 0x4D, // M key KEY_KEY_N = 0x4E, // N key KEY_KEY_O = 0x4F, // O key KEY_KEY_P = 0x50, // P key KEY_KEY_Q = 0x51, // Q key KEY_KEY_R = 0x52, // R key KEY_KEY_S = 0x53, // S key KEY_KEY_T = 0x54, // T key KEY_KEY_U = 0x55, // U key KEY_KEY_V = 0x56, // V key KEY_KEY_W = 0x57, // W key KEY_KEY_X = 0x58, // X key KEY_KEY_Y = 0x59, // Y key KEY_KEY_Z = 0x5A, // Z key KEY_LWIN = 0x5B, // Left Windows key (Microsoft® Natural® keyboard) KEY_RWIN = 0x5C, // Right Windows key (Natural keyboard) KEY_APPS = 0x5D, // Applications key (Natural keyboard) KEY_SLEEP = 0x5F, // Computer Sleep key KEY_NUMPAD0 = 0x60, // Numeric keypad 0 key KEY_NUMPAD1 = 0x61, // Numeric keypad 1 key KEY_NUMPAD2 = 0x62, // Numeric keypad 2 key KEY_NUMPAD3 = 0x63, // Numeric keypad 3 key KEY_NUMPAD4 = 0x64, // Numeric keypad 4 key KEY_NUMPAD5 = 0x65, // Numeric keypad 5 key KEY_NUMPAD6 = 0x66, // Numeric keypad 6 key KEY_NUMPAD7 = 0x67, // Numeric keypad 7 key KEY_NUMPAD8 = 0x68, // Numeric keypad 8 key KEY_NUMPAD9 = 0x69, // Numeric keypad 9 key KEY_MULTIPLY = 0x6A, // Multiply key KEY_ADD = 0x6B, // Add key KEY_SEPARATOR = 0x6C, // Separator key KEY_SUBTRACT = 0x6D, // Subtract key KEY_DECIMAL = 0x6E, // Decimal key KEY_DIVIDE = 0x6F, // Divide key KEY_F1 = 0x70, // F1 key KEY_F2 = 0x71, // F2 key KEY_F3 = 0x72, // F3 key KEY_F4 = 0x73, // F4 key KEY_F5 = 0x74, // F5 key KEY_F6 = 0x75, // F6 key KEY_F7 = 0x76, // F7 key KEY_F8 = 0x77, // F8 key KEY_F9 = 0x78, // F9 key KEY_F10 = 0x79, // F10 key KEY_F11 = 0x7A, // F11 key KEY_F12 = 0x7B, // F12 key KEY_F13 = 0x7C, // F13 key KEY_F14 = 0x7D, // F14 key KEY_F15 = 0x7E, // F15 key KEY_F16 = 0x7F, // F16 key KEY_F17 = 0x80, // F17 key KEY_F18 = 0x81, // F18 key KEY_F19 = 0x82, // F19 key KEY_F20 = 0x83, // F20 key KEY_F21 = 0x84, // F21 key KEY_F22 = 0x85, // F22 key KEY_F23 = 0x86, // F23 key KEY_F24 = 0x87, // F24 key KEY_NUMLOCK = 0x90, // NUM LOCK key KEY_SCROLL = 0x91, // SCROLL LOCK key KEY_LSHIFT = 0xA0, // Left SHIFT key KEY_RSHIFT = 0xA1, // Right SHIFT key KEY_LCONTROL = 0xA2, // Left CONTROL key KEY_RCONTROL = 0xA3, // Right CONTROL key KEY_LMENU = 0xA4, // Left MENU key KEY_RMENU = 0xA5, // Right MENU key KEY_OEM_1 = 0xBA, // for US ";:" KEY_PLUS = 0xBB, // Plus Key "+" KEY_COMMA = 0xBC, // Comma Key "," KEY_MINUS = 0xBD, // Minus Key "-" KEY_PERIOD = 0xBE, // Period Key "." KEY_OEM_2 = 0xBF, // for US "/?" KEY_OEM_3 = 0xC0, // for US "`~" KEY_OEM_4 = 0xDB, // for US "[{" KEY_OEM_5 = 0xDC, // for US "\|" KEY_OEM_6 = 0xDD, // for US "]}" KEY_OEM_7 = 0xDE, // for US "'"" KEY_OEM_8 = 0xDF, // None KEY_OEM_AX = 0xE1, // for Japan "AX" KEY_OEM_102 = 0xE2, // "<>" or "\|" KEY_ATTN = 0xF6, // Attn key KEY_CRSEL = 0xF7, // CrSel key KEY_EXSEL = 0xF8, // ExSel key KEY_EREOF = 0xF9, // Erase EOF key KEY_PLAY = 0xFA, // Play key KEY_ZOOM = 0xFB, // Zoom key KEY_PA1 = 0xFD, // PA1 key KEY_OEM_CLEAR = 0xFE, // Clear key KEY_KEY_CODES_COUNT = 0xFF // this is not a key, but the amount of keycodes there are. }; } // end namespace irr #endif irrlicht-1.8.3/include/IXMLWriter.h0000644000000000000000000000546412574354552015630 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_XML_WRITER_H_INCLUDED__ #define __I_XML_WRITER_H_INCLUDED__ #include "IReferenceCounted.h" #include "irrArray.h" #include "irrString.h" namespace irr { namespace io { //! Interface providing methods for making it easier to write XML files. /** This XML Writer writes xml files using in the platform dependent wchar_t format and sets the xml-encoding correspondingly. */ class IXMLWriter : public virtual IReferenceCounted { public: //! Writes an xml 1.0 header. /** Looks like <?xml version="1.0"?>. This should always be called before writing anything other, because also the text file header for unicode texts is written out with this method. */ virtual void writeXMLHeader() = 0; //! Writes an xml element with maximal 5 attributes like "" or //! <foo optAttr="value" />. /** The element can be empty or not. \param name: Name of the element \param empty: Specifies if the element should be empty. Like "". If You set this to false, something like this is written instead: "". \param attr1Name: 1st attributes name \param attr1Value: 1st attributes value \param attr2Name: 2nd attributes name \param attr2Value: 2nd attributes value \param attr3Name: 3rd attributes name \param attr3Value: 3rd attributes value \param attr4Name: 4th attributes name \param attr4Value: 4th attributes value \param attr5Name: 5th attributes name \param attr5Value: 5th attributes value */ virtual void writeElement(const wchar_t* name, bool empty=false, const wchar_t* attr1Name = 0, const wchar_t* attr1Value = 0, const wchar_t* attr2Name = 0, const wchar_t* attr2Value = 0, const wchar_t* attr3Name = 0, const wchar_t* attr3Value = 0, const wchar_t* attr4Name = 0, const wchar_t* attr4Value = 0, const wchar_t* attr5Name = 0, const wchar_t* attr5Value = 0) = 0; //! Writes an xml element with any number of attributes virtual void writeElement(const wchar_t* name, bool empty, core::array &names, core::array &values) = 0; //! Writes a comment into the xml file virtual void writeComment(const wchar_t* comment) = 0; //! Writes the closing tag for an element. Like "" virtual void writeClosingTag(const wchar_t* name) = 0; //! Writes a text into the file. /** All occurrences of special characters such as & (&), < (<), > (>), and " (") are automaticly replaced. */ virtual void writeText(const wchar_t* text) = 0; //! Writes a line break virtual void writeLineBreak() = 0; }; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/include/IXMLReader.h0000644000000000000000000000211312574354552015542 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_XML_READER_H_INCLUDED__ #define __I_XML_READER_H_INCLUDED__ #include "IReferenceCounted.h" #include "irrXML.h" namespace irr { namespace io { //! An xml reader for wide characters, derived from IReferenceCounted. /** This XML Parser can read any type of text files from any source Irrlicht can read. Just call IFileSystem::createXMLReader(). For more informations on how to use the parser, see IIrrXMLReader */ typedef IIrrXMLReader IXMLReader; //! An xml reader for ASCII or UTF-8 characters, derived from IReferenceCounted. /** This XML Parser can read any type of text files from any source Irrlicht can read. Just call IFileSystem::createXMLReaderUTF8(). For more informations on how to use the parser, see IIrrXMLReader */ typedef IIrrXMLReader IXMLReaderUTF8; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/include/IWriteFile.h0000644000000000000000000000304612574354552015657 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_WRITE_FILE_H_INCLUDED__ #define __I_WRITE_FILE_H_INCLUDED__ #include "IReferenceCounted.h" #include "path.h" namespace irr { namespace io { //! Interface providing write access to a file. class IWriteFile : public virtual IReferenceCounted { public: //! Writes an amount of bytes to the file. /** \param buffer Pointer to buffer of bytes to write. \param sizeToWrite Amount of bytes to write to the file. \return How much bytes were written. */ virtual s32 write(const void* buffer, u32 sizeToWrite) = 0; //! Changes position in file /** \param finalPos Destination position in the file. \param relativeMovement If set to true, the position in the file is changed relative to current position. Otherwise the position is changed from begin of file. \return True if successful, otherwise false. */ virtual bool seek(long finalPos, bool relativeMovement = false) = 0; //! Get the current position in the file. /** \return Current position in the file in bytes. */ virtual long getPos() const = 0; //! Get name of file. /** \return File name as zero terminated character string. */ virtual const path& getFileName() const = 0; }; //! Internal function, please do not use. IWriteFile* createWriteFile(const io::path& fileName, bool append); } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/include/IVolumeLightSceneNode.h0000644000000000000000000000334512574354552020012 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // // created by Dean Wadsworth aka Varmint Dec 31 2007 #ifndef __I_VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ #define __I_VOLUME_LIGHT_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" namespace irr { namespace scene { class IMeshBuffer; class IVolumeLightSceneNode : public ISceneNode { public: //! constructor IVolumeLightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) : ISceneNode(parent, mgr, id, position, rotation, scale) {}; //! Returns type of the scene node virtual ESCENE_NODE_TYPE getType() const { return ESNT_VOLUME_LIGHT; } //! Sets the number of segments across the U axis virtual void setSubDivideU(const u32 inU) =0; //! Sets the number of segments across the V axis virtual void setSubDivideV(const u32 inV) =0; //! Returns the number of segments across the U axis virtual u32 getSubDivideU() const =0; //! Returns the number of segments across the V axis virtual u32 getSubDivideV() const =0; //! Sets the color of the base of the light virtual void setFootColor(const video::SColor inColor) =0; //! Sets the color of the tip of the light virtual void setTailColor(const video::SColor inColor) =0; //! Returns the color of the base of the light virtual video::SColor getFootColor() const =0; //! Returns the color of the tip of the light virtual video::SColor getTailColor() const =0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IVideoModeList.h0000644000000000000000000000455312574354552016500 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_I_VIDEO_MODE_LIST_H_INCLUDED__ #define __IRR_I_VIDEO_MODE_LIST_H_INCLUDED__ #include "IReferenceCounted.h" #include "dimension2d.h" namespace irr { namespace video { //! A list of all available video modes. /** You can get a list via IrrlichtDevice::getVideoModeList(). If you are confused now, because you think you have to create an Irrlicht Device with a video mode before being able to get the video mode list, let me tell you that there is no need to start up an Irrlicht Device with EDT_DIRECT3D8, EDT_OPENGL or EDT_SOFTWARE: For this (and for lots of other reasons) the null device, EDT_NULL exists.*/ class IVideoModeList : public virtual IReferenceCounted { public: //! Gets amount of video modes in the list. /** \return Returns amount of video modes. */ virtual s32 getVideoModeCount() const = 0; //! Get the screen size of a video mode in pixels. /** \param modeNumber: zero based index of the video mode. \return Size of screen in pixels of the specified video mode. */ virtual core::dimension2d getVideoModeResolution(s32 modeNumber) const = 0; //! Get a supported screen size with certain constraints. /** \param minSize: Minimum dimensions required. \param maxSize: Maximum dimensions allowed. \return Size of screen in pixels which matches the requirements. as good as possible. */ virtual core::dimension2d getVideoModeResolution(const core::dimension2d& minSize, const core::dimension2d& maxSize) const = 0; //! Get the pixel depth of a video mode in bits. /** \param modeNumber: zero based index of the video mode. \return Size of each pixel of the specified video mode in bits. */ virtual s32 getVideoModeDepth(s32 modeNumber) const = 0; //! Get current desktop screen resolution. /** \return Size of screen in pixels of the current desktop video mode. */ virtual const core::dimension2d& getDesktopResolution() const = 0; //! Get the pixel depth of a video mode in bits. /** \return Size of each pixel of the current desktop video mode in bits. */ virtual s32 getDesktopDepth() const = 0; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/IVideoDriver.h0000644000000000000000000020475312574354552016217 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_I_VIDEO_DRIVER_H_INCLUDED__ #define __IRR_I_VIDEO_DRIVER_H_INCLUDED__ #include "rect.h" #include "SColor.h" #include "ITexture.h" #include "irrArray.h" #include "matrix4.h" #include "plane3d.h" #include "dimension2d.h" #include "position2d.h" #include "SMaterial.h" #include "IMeshBuffer.h" #include "triangle3d.h" #include "EDriverTypes.h" #include "EDriverFeatures.h" #include "SExposedVideoData.h" namespace irr { namespace io { class IAttributes; struct SAttributeReadWriteOptions; class IReadFile; class IWriteFile; } // end namespace io namespace scene { class IMeshBuffer; class IMesh; class IMeshManipulator; class ISceneNode; } // end namespace scene namespace video { struct S3DVertex; struct S3DVertex2TCoords; struct S3DVertexTangents; struct SLight; class IImageLoader; class IImageWriter; class IMaterialRenderer; class IGPUProgrammingServices; //! enumeration for geometry transformation states enum E_TRANSFORMATION_STATE { //! View transformation ETS_VIEW = 0, //! World transformation ETS_WORLD, //! Projection transformation ETS_PROJECTION, //! Texture transformation ETS_TEXTURE_0, //! Texture transformation ETS_TEXTURE_1, //! Texture transformation ETS_TEXTURE_2, //! Texture transformation ETS_TEXTURE_3, #if _IRR_MATERIAL_MAX_TEXTURES_>4 //! Texture transformation ETS_TEXTURE_4, #if _IRR_MATERIAL_MAX_TEXTURES_>5 //! Texture transformation ETS_TEXTURE_5, #if _IRR_MATERIAL_MAX_TEXTURES_>6 //! Texture transformation ETS_TEXTURE_6, #if _IRR_MATERIAL_MAX_TEXTURES_>7 //! Texture transformation ETS_TEXTURE_7, #endif #endif #endif #endif //! Not used ETS_COUNT }; //! enumeration for signaling resources which were lost after the last render cycle /** These values can be signaled by the driver, telling the app that some resources were lost and need to be recreated. Irrlicht will sometimes recreate the actual objects, but the content needs to be recreated by the application. */ enum E_LOST_RESOURCE { //! The whole device/driver is lost ELR_DEVICE = 1, //! All texture are lost, rare problem ELR_TEXTURES = 2, //! The Render Target Textures are lost, typical problem for D3D ELR_RTTS = 4, //! The HW buffers are lost, will be recreated automatically, but might require some more time this frame ELR_HW_BUFFERS = 8 }; //! Special render targets, which usually map to dedicated hardware /** These render targets (besides 0 and 1) need not be supported by gfx cards */ enum E_RENDER_TARGET { //! Render target is the main color frame buffer ERT_FRAME_BUFFER=0, //! Render target is a render texture ERT_RENDER_TEXTURE, //! Multi-Render target textures ERT_MULTI_RENDER_TEXTURES, //! Render target is the main color frame buffer ERT_STEREO_LEFT_BUFFER, //! Render target is the right color buffer (left is the main buffer) ERT_STEREO_RIGHT_BUFFER, //! Render to both stereo buffers at once ERT_STEREO_BOTH_BUFFERS, //! Auxiliary buffer 0 ERT_AUX_BUFFER0, //! Auxiliary buffer 1 ERT_AUX_BUFFER1, //! Auxiliary buffer 2 ERT_AUX_BUFFER2, //! Auxiliary buffer 3 ERT_AUX_BUFFER3, //! Auxiliary buffer 4 ERT_AUX_BUFFER4 }; //! Enum for the types of fog distributions to choose from enum E_FOG_TYPE { EFT_FOG_EXP=0, EFT_FOG_LINEAR, EFT_FOG_EXP2 }; const c8* const FogTypeNames[] = { "FogExp", "FogLinear", "FogExp2", 0 }; struct SOverrideMaterial { //! The Material values SMaterial Material; //! Which values are taken for override /** OR'ed values from E_MATERIAL_FLAGS. */ u32 EnableFlags; //! Set in which render passes the material override is active. /** OR'ed values from E_SCENE_NODE_RENDER_PASS. */ u16 EnablePasses; //! Global enable flag, overwritten by the SceneManager in each pass /** The Scenemanager uses the EnablePass array and sets Enabled to true if the Override material is enabled in the current pass. */ bool Enabled; //! Default constructor SOverrideMaterial() : EnableFlags(0), EnablePasses(0), Enabled(false) {} //! Apply the enabled overrides void apply(SMaterial& material) { if (Enabled) { for (u32 i=0; i<32; ++i) { const u32 num=(1<* sourceRect=0) =0; //! Presents the rendered image to the screen. /** Applications must call this method after performing any rendering. \return False if failed and true if succeeded. */ virtual bool endScene() =0; //! Queries the features of the driver. /** Returns true if a feature is available \param feature Feature to query. \return True if the feature is available, false if not. */ virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const =0; //! Disable a feature of the driver. /** Can also be used to enable the features again. It is not possible to enable unsupported features this way, though. \param feature Feature to disable. \param flag When true the feature is disabled, otherwise it is enabled. */ virtual void disableFeature(E_VIDEO_DRIVER_FEATURE feature, bool flag=true) =0; //! Get attributes of the actual video driver /** The following names can be queried for the given types: MaxTextures (int) The maximum number of simultaneous textures supported by the driver. This can be less than the supported number of textures of the driver. Use _IRR_MATERIAL_MAX_TEXTURES_ to adapt the number. MaxSupportedTextures (int) The maximum number of simultaneous textures supported by the fixed function pipeline of the (hw) driver. The actual supported number of textures supported by the engine can be lower. MaxLights (int) Number of hardware lights supported in the fixed function pipieline of the driver, typically 6-8. Use light manager or deferred shading for more. MaxAnisotropy (int) Number of anisotropy levels supported for filtering. At least 1, max is typically at 16 or 32. MaxUserClipPlanes (int) Number of additional clip planes, which can be set by the user via dedicated driver methods. MaxAuxBuffers (int) Special render buffers, which are currently not really usable inside Irrlicht. Only supported by OpenGL MaxMultipleRenderTargets (int) Number of render targets which can be bound simultaneously. Rendering to MRTs is done via shaders. MaxIndices (int) Number of indices which can be used in one render call (i.e. one mesh buffer). MaxTextureSize (int) Dimension that a texture may have, both in width and height. MaxGeometryVerticesOut (int) Number of vertices the geometry shader can output in one pass. Only OpenGL so far. MaxTextureLODBias (float) Maximum value for LOD bias. Is usually at around 16, but can be lower on some systems. Version (int) Version of the driver. Should be Major*100+Minor ShaderLanguageVersion (int) Version of the high level shader language. Should be Major*100+Minor. AntiAlias (int) Number of Samples the driver uses for each pixel. 0 and 1 means anti aliasing is off, typical values are 2,4,8,16,32 */ virtual const io::IAttributes& getDriverAttributes() const=0; //! Check if the driver was recently reset. /** For d3d devices you will need to recreate the RTTs if the driver was reset. Should be queried right after beginScene(). */ virtual bool checkDriverReset() =0; //! Sets transformation matrices. /** \param state Transformation type to be set, e.g. view, world, or projection. \param mat Matrix describing the transformation. */ virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) =0; //! Returns the transformation set by setTransform /** \param state Transformation type to query \return Matrix describing the transformation. */ virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const =0; //! Retrieve the number of image loaders /** \return Number of image loaders */ virtual u32 getImageLoaderCount() const = 0; //! Retrieve the given image loader /** \param n The index of the loader to retrieve. This parameter is an 0-based array index. \return A pointer to the specified loader, 0 if the index is incorrect. */ virtual IImageLoader* getImageLoader(u32 n) = 0; //! Retrieve the number of image writers /** \return Number of image writers */ virtual u32 getImageWriterCount() const = 0; //! Retrieve the given image writer /** \param n The index of the writer to retrieve. This parameter is an 0-based array index. \return A pointer to the specified writer, 0 if the index is incorrect. */ virtual IImageWriter* getImageWriter(u32 n) = 0; //! Sets a material. /** All 3d drawing functions will draw geometry using this material thereafter. \param material: Material to be used from now on. */ virtual void setMaterial(const SMaterial& material) =0; //! Get access to a named texture. /** Loads the texture from disk if it is not already loaded and generates mipmap levels if desired. Texture loading can be influenced using the setTextureCreationFlag() method. The texture can be in several imageformats, such as BMP, JPG, TGA, PCX, PNG, and PSD. \param filename Filename of the texture to be loaded. \return Pointer to the texture, or 0 if the texture could not be loaded. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ITexture* getTexture(const io::path& filename) = 0; //! Get access to a named texture. /** Loads the texture from disk if it is not already loaded and generates mipmap levels if desired. Texture loading can be influenced using the setTextureCreationFlag() method. The texture can be in several imageformats, such as BMP, JPG, TGA, PCX, PNG, and PSD. \param file Pointer to an already opened file. \return Pointer to the texture, or 0 if the texture could not be loaded. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ITexture* getTexture(io::IReadFile* file) =0; //! Returns a texture by index /** \param index: Index of the texture, must be smaller than getTextureCount() Please note that this index might change when adding or removing textures \return Pointer to the texture, or 0 if the texture was not set or index is out of bounds. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ITexture* getTextureByIndex(u32 index) =0; //! Returns amount of textures currently loaded /** \return Amount of textures currently loaded */ virtual u32 getTextureCount() const = 0; //! Renames a texture /** \param texture Pointer to the texture to rename. \param newName New name for the texture. This should be a unique name. */ virtual void renameTexture(ITexture* texture, const io::path& newName) = 0; //! Creates an empty texture of specified size. /** \param size: Size of the texture. \param name A name for the texture. Later calls to getTexture() with this name will return this texture \param format Desired color format of the texture. Please note that the driver may choose to create the texture in another color format. \return Pointer to the newly created texture. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ITexture* addTexture(const core::dimension2d& size, const io::path& name, ECOLOR_FORMAT format = ECF_A8R8G8B8) = 0; //! Creates a texture from an IImage. /** \param name A name for the texture. Later calls of getTexture() with this name will return this texture \param image Image the texture is created from. \param mipmapData Optional pointer to a set of images which build up the whole mipmap set. Must be images of the same color type as image. If this parameter is not given, the mipmaps are derived from image. \return Pointer to the newly created texture. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ITexture* addTexture(const io::path& name, IImage* image, void* mipmapData=0) = 0; //! Adds a new render target texture to the texture cache. /** \param size Size of the texture, in pixels. Width and height should be a power of two (e.g. 64, 128, 256, 512, ...) and it should not be bigger than the backbuffer, because it shares the zbuffer with the screen buffer. \param name An optional name for the RTT. \param format The color format of the render target. Floating point formats are supported. \return Pointer to the created texture or 0 if the texture could not be created. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const io::path& name = "rt", const ECOLOR_FORMAT format = ECF_UNKNOWN) =0; //! Removes a texture from the texture cache and deletes it. /** This method can free a lot of memory! Please note that after calling this, the pointer to the ITexture may no longer be valid, if it was not grabbed before by other parts of the engine for storing it longer. So it is a good idea to set all materials which are using this texture to 0 or another texture first. \param texture Texture to delete from the engine cache. */ virtual void removeTexture(ITexture* texture) =0; //! Removes all textures from the texture cache and deletes them. /** This method can free a lot of memory! Please note that after calling this, the pointer to the ITexture may no longer be valid, if it was not grabbed before by other parts of the engine for storing it longer. So it is a good idea to set all materials which are using this texture to 0 or another texture first. */ virtual void removeAllTextures() =0; //! Remove hardware buffer virtual void removeHardwareBuffer(const scene::IMeshBuffer* mb) =0; //! Remove all hardware buffers virtual void removeAllHardwareBuffers() =0; //! Create occlusion query. /** Use node for identification and mesh for occlusion test. */ virtual void addOcclusionQuery(scene::ISceneNode* node, const scene::IMesh* mesh=0) =0; //! Remove occlusion query. virtual void removeOcclusionQuery(scene::ISceneNode* node) =0; //! Remove all occlusion queries. virtual void removeAllOcclusionQueries() =0; //! Run occlusion query. Draws mesh stored in query. /** If the mesh shall not be rendered visible, use overrideMaterial to disable the color and depth buffer. */ virtual void runOcclusionQuery(scene::ISceneNode* node, bool visible=false) =0; //! Run all occlusion queries. Draws all meshes stored in queries. /** If the meshes shall not be rendered visible, use overrideMaterial to disable the color and depth buffer. */ virtual void runAllOcclusionQueries(bool visible=false) =0; //! Update occlusion query. Retrieves results from GPU. /** If the query shall not block, set the flag to false. Update might not occur in this case, though */ virtual void updateOcclusionQuery(scene::ISceneNode* node, bool block=true) =0; //! Update all occlusion queries. Retrieves results from GPU. /** If the query shall not block, set the flag to false. Update might not occur in this case, though */ virtual void updateAllOcclusionQueries(bool block=true) =0; //! Return query result. /** Return value is the number of visible pixels/fragments. The value is a safe approximation, i.e. can be larger than the actual value of pixels. */ virtual u32 getOcclusionQueryResult(scene::ISceneNode* node) const =0; //! Sets a boolean alpha channel on the texture based on a color key. /** This makes the texture fully transparent at the texels where this color key can be found when using for example draw2DImage with useAlphachannel==true. The alpha of other texels is not modified. \param texture Texture whose alpha channel is modified. \param color Color key color. Every texel with this color will become fully transparent as described above. Please note that the colors of a texture may be converted when loading it, so the color values may not be exactly the same in the engine and for example in picture edit programs. To avoid this problem, you could use the makeColorKeyTexture method, which takes the position of a pixel instead a color value. \param zeroTexels \deprecated If set to true, then any texels that match the color key will have their color, as well as their alpha, set to zero (i.e. black). This behavior matches the legacy (buggy) behavior prior to release 1.5 and is provided for backwards compatibility only. This parameter may be removed by Irrlicht 1.9. */ virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor color, bool zeroTexels = false) const =0; //! Sets a boolean alpha channel on the texture based on the color at a position. /** This makes the texture fully transparent at the texels where the color key can be found when using for example draw2DImage with useAlphachannel==true. The alpha of other texels is not modified. \param texture Texture whose alpha channel is modified. \param colorKeyPixelPos Position of a pixel with the color key color. Every texel with this color will become fully transparent as described above. \param zeroTexels \deprecated If set to true, then any texels that match the color key will have their color, as well as their alpha, set to zero (i.e. black). This behavior matches the legacy (buggy) behavior prior to release 1.5 and is provided for backwards compatibility only. This parameter may be removed by Irrlicht 1.9. */ virtual void makeColorKeyTexture(video::ITexture* texture, core::position2d colorKeyPixelPos, bool zeroTexels = false) const =0; //! Creates a normal map from a height map texture. /** If the target texture has 32 bit, the height value is stored in the alpha component of the texture as addition. This value is used by the video::EMT_PARALLAX_MAP_SOLID material and similar materials. \param texture Texture whose alpha channel is modified. \param amplitude Constant value by which the height information is multiplied.*/ virtual void makeNormalMapTexture(video::ITexture* texture, f32 amplitude=1.0f) const =0; //! Sets a new render target. /** This will only work if the driver supports the EVDF_RENDER_TO_TARGET feature, which can be queried with queryFeature(). Usually, rendering to textures is done in this way: \code // create render target ITexture* target = driver->addRenderTargetTexture(core::dimension2d(128,128), "rtt1"); // ... driver->setRenderTarget(target); // set render target // .. draw stuff here driver->setRenderTarget(0); // set previous render target \endcode Please note that you cannot render 3D or 2D geometry with a render target as texture on it when you are rendering the scene into this render target at the same time. It is usually only possible to render into a texture between the IVideoDriver::beginScene() and endScene() method calls. \param texture New render target. Must be a texture created with IVideoDriver::addRenderTargetTexture(). If set to 0, it sets the previous render target which was set before the last setRenderTarget() call. \param clearBackBuffer Clears the backbuffer of the render target with the color parameter \param clearZBuffer Clears the zBuffer of the rendertarget. Note that because the frame buffer may share the zbuffer with the rendertarget, its zbuffer might be partially cleared too by this. \param color The background color for the render target. \return True if sucessful and false if not. */ virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=video::SColor(0,0,0,0)) =0; //! set or reset special render targets /** This method enables access to special color buffers such as stereoscopic buffers or auxiliary buffers. \param target Enum value for the render target \param clearTarget Clears the target buffer with the color parameter \param clearZBuffer Clears the zBuffer of the rendertarget. Note that because the main frame buffer may share the zbuffer with the rendertarget, its zbuffer might be partially cleared too by this. \param color The background color for the render target. \return True if sucessful and false if not. */ virtual bool setRenderTarget(E_RENDER_TARGET target, bool clearTarget=true, bool clearZBuffer=true, SColor color=video::SColor(0,0,0,0)) =0; //! Sets new multiple render targets. virtual bool setRenderTarget(const core::array& texture, bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=video::SColor(0,0,0,0)) =0; //! Sets a new viewport. /** Every rendering operation is done into this new area. \param area: Rectangle defining the new area of rendering operations. */ virtual void setViewPort(const core::rect& area) =0; //! Gets the area of the current viewport. /** \return Rectangle of the current viewport. */ virtual const core::rect& getViewPort() const =0; //! Draws a vertex primitive list /** Note that, depending on the index type, some vertices might be not accessible through the index list. The limit is at 65535 vertices for 16bit indices. Please note that currently not all primitives are available for all drivers, and some might be emulated via triangle renders. \param vertices Pointer to array of vertices. \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. These define the vertices used for each primitive. Depending on the pType, indices are interpreted as single objects (for point like primitives), pairs (for lines), triplets (for triangles), or quads. \param primCount Amount of Primitives \param vType Vertex type, e.g. video::EVT_STANDARD for S3DVertex. \param pType Primitive type, e.g. scene::EPT_TRIANGLE_FAN for a triangle fan. \param iType Index type, e.g. video::EIT_16BIT for 16bit indices. */ virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primCount, E_VERTEX_TYPE vType=EVT_STANDARD, scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, E_INDEX_TYPE iType=EIT_16BIT) =0; //! Draws a vertex primitive list in 2d /** Compared to the general (3d) version of this method, this one sets up a 2d render mode, and uses only x and y of vectors. Note that, depending on the index type, some vertices might be not accessible through the index list. The limit is at 65535 vertices for 16bit indices. Please note that currently not all primitives are available for all drivers, and some might be emulated via triangle renders. This function is not available for the sw drivers. \param vertices Pointer to array of vertices. \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. These define the vertices used for each primitive. Depending on the pType, indices are interpreted as single objects (for point like primitives), pairs (for lines), triplets (for triangles), or quads. \param primCount Amount of Primitives \param vType Vertex type, e.g. video::EVT_STANDARD for S3DVertex. \param pType Primitive type, e.g. scene::EPT_TRIANGLE_FAN for a triangle fan. \param iType Index type, e.g. video::EIT_16BIT for 16bit indices. */ virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primCount, E_VERTEX_TYPE vType=EVT_STANDARD, scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, E_INDEX_TYPE iType=EIT_16BIT) =0; //! Draws an indexed triangle list. /** Note that there may be at maximum 65536 vertices, because the index list is an array of 16 bit values each with a maximum value of 65536. If there are more than 65536 vertices in the list, results of this operation are not defined. \param vertices Pointer to array of vertices. \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. \param triangleCount Amount of Triangles. Usually amount of indices / 3. */ void drawIndexedTriangleList(const S3DVertex* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) { drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT); } //! Draws an indexed triangle list. /** Note that there may be at maximum 65536 vertices, because the index list is an array of 16 bit values each with a maximum value of 65536. If there are more than 65536 vertices in the list, results of this operation are not defined. \param vertices Pointer to array of vertices. \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. \param triangleCount Amount of Triangles. Usually amount of indices / 3. */ void drawIndexedTriangleList(const S3DVertex2TCoords* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) { drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_2TCOORDS, scene::EPT_TRIANGLES, EIT_16BIT); } //! Draws an indexed triangle list. /** Note that there may be at maximum 65536 vertices, because the index list is an array of 16 bit values each with a maximum value of 65536. If there are more than 65536 vertices in the list, results of this operation are not defined. \param vertices Pointer to array of vertices. \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. \param triangleCount Amount of Triangles. Usually amount of indices / 3. */ void drawIndexedTriangleList(const S3DVertexTangents* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) { drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_TANGENTS, scene::EPT_TRIANGLES, EIT_16BIT); } //! Draws an indexed triangle fan. /** Note that there may be at maximum 65536 vertices, because the index list is an array of 16 bit values each with a maximum value of 65536. If there are more than 65536 vertices in the list, results of this operation are not defined. \param vertices Pointer to array of vertices. \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. \param triangleCount Amount of Triangles. Usually amount of indices - 2. */ void drawIndexedTriangleFan(const S3DVertex* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) { drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_STANDARD, scene::EPT_TRIANGLE_FAN, EIT_16BIT); } //! Draws an indexed triangle fan. /** Note that there may be at maximum 65536 vertices, because the index list is an array of 16 bit values each with a maximum value of 65536. If there are more than 65536 vertices in the list, results of this operation are not defined. \param vertices Pointer to array of vertices. \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. \param triangleCount Amount of Triangles. Usually amount of indices - 2. */ void drawIndexedTriangleFan(const S3DVertex2TCoords* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) { drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_2TCOORDS, scene::EPT_TRIANGLE_FAN, EIT_16BIT); } //! Draws an indexed triangle fan. /** Note that there may be at maximum 65536 vertices, because the index list is an array of 16 bit values each with a maximum value of 65536. If there are more than 65536 vertices in the list, results of this operation are not defined. \param vertices Pointer to array of vertices. \param vertexCount Amount of vertices in the array. \param indexList Pointer to array of indices. \param triangleCount Amount of Triangles. Usually amount of indices - 2. */ void drawIndexedTriangleFan(const S3DVertexTangents* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) { drawVertexPrimitiveList(vertices, vertexCount, indexList, triangleCount, EVT_TANGENTS, scene::EPT_TRIANGLE_FAN, EIT_16BIT); } //! Draws a 3d line. /** For some implementations, this method simply calls drawVertexPrimitiveList for some triangles. Note that the line is drawn using the current transformation matrix and material. So if you need to draw the 3D line independently of the current transformation, use \code driver->setMaterial(someMaterial); driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); \endcode for some properly set up material before drawing the line. Some drivers support line thickness set in the material. \param start Start of the 3d line. \param end End of the 3d line. \param color Color of the line. */ virtual void draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color = SColor(255,255,255,255)) =0; //! Draws a 3d triangle. /** This method calls drawVertexPrimitiveList for some triangles. This method works with all drivers because it simply calls drawVertexPrimitiveList, but it is hence not very fast. Note that the triangle is drawn using the current transformation matrix and material. So if you need to draw it independently of the current transformation, use \code driver->setMaterial(someMaterial); driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); \endcode for some properly set up material before drawing the triangle. \param triangle The triangle to draw. \param color Color of the line. */ virtual void draw3DTriangle(const core::triangle3df& triangle, SColor color = SColor(255,255,255,255)) =0; //! Draws a 3d axis aligned box. /** This method simply calls draw3DLine for the edges of the box. Note that the box is drawn using the current transformation matrix and material. So if you need to draw it independently of the current transformation, use \code driver->setMaterial(someMaterial); driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); \endcode for some properly set up material before drawing the box. \param box The axis aligned box to draw \param color Color to use while drawing the box. */ virtual void draw3DBox(const core::aabbox3d& box, SColor color = SColor(255,255,255,255)) =0; //! Draws a 2d image without any special effects /** \param texture Pointer to texture to use. \param destPos Upper left 2d destination position where the image will be drawn. */ virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos) =0; //! Draws a 2d image using a color /** (if color is other than Color(255,255,255,255)) and the alpha channel of the texture. \param texture Texture to be drawn. \param destPos Upper left 2d destination position where the image will be drawn. \param sourceRect Source rectangle in the image. \param clipRect Pointer to rectangle on the screen where the image is clipped to. If this pointer is NULL the image is not clipped. \param color Color with which the image is drawn. If the color equals Color(255,255,255,255) it is ignored. Note that the alpha component is used: If alpha is other than 255, the image will be transparent. \param useAlphaChannelOfTexture: If true, the alpha channel of the texture is used to draw the image.*/ virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect =0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) =0; //! Draws a set of 2d images, using a color and the alpha channel of the texture. /** The images are drawn beginning at pos and concatenated in one line. All drawings are clipped against clipRect (if != 0). The subtextures are defined by the array of sourceRects and are chosen by the indices given. \param texture Texture to be drawn. \param pos Upper left 2d destination position where the image will be drawn. \param sourceRects Source rectangles of the image. \param indices List of indices which choose the actual rectangle used each time. \param kerningWidth Offset to Position on X \param clipRect Pointer to rectangle on the screen where the image is clipped to. If this pointer is 0 then the image is not clipped. \param color Color with which the image is drawn. Note that the alpha component is used. If alpha is other than 255, the image will be transparent. \param useAlphaChannelOfTexture: If true, the alpha channel of the texture is used to draw the image. */ virtual void draw2DImageBatch(const video::ITexture* texture, const core::position2d& pos, const core::array >& sourceRects, const core::array& indices, s32 kerningWidth=0, const core::rect* clipRect=0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) =0; //! Draws a set of 2d images, using a color and the alpha channel of the texture. /** All drawings are clipped against clipRect (if != 0). The subtextures are defined by the array of sourceRects and are positioned using the array of positions. \param texture Texture to be drawn. \param positions Array of upper left 2d destinations where the images will be drawn. \param sourceRects Source rectangles of the image. \param clipRect Pointer to rectangle on the screen where the images are clipped to. If this pointer is 0 then the image is not clipped. \param color Color with which the image is drawn. Note that the alpha component is used. If alpha is other than 255, the image will be transparent. \param useAlphaChannelOfTexture: If true, the alpha channel of the texture is used to draw the image. */ virtual void draw2DImageBatch(const video::ITexture* texture, const core::array >& positions, const core::array >& sourceRects, const core::rect* clipRect=0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) =0; //! Draws a part of the texture into the rectangle. Note that colors must be an array of 4 colors if used. /** Suggested and first implemented by zola. \param texture The texture to draw from \param destRect The rectangle to draw into \param sourceRect The rectangle denoting a part of the texture \param clipRect Clips the destination rectangle (may be 0) \param colors Array of 4 colors denoting the color values of the corners of the destRect \param useAlphaChannelOfTexture True if alpha channel will be blended. */ virtual void draw2DImage(const video::ITexture* texture, const core::rect& destRect, const core::rect& sourceRect, const core::rect* clipRect =0, const video::SColor * const colors=0, bool useAlphaChannelOfTexture=false) =0; //! Draws a 2d rectangle. /** \param color Color of the rectangle to draw. The alpha component will not be ignored and specifies how transparent the rectangle will be. \param pos Position of the rectangle. \param clip Pointer to rectangle against which the rectangle will be clipped. If the pointer is null, no clipping will be performed. */ virtual void draw2DRectangle(SColor color, const core::rect& pos, const core::rect* clip =0) =0; //! Draws a 2d rectangle with a gradient. /** \param colorLeftUp Color of the upper left corner to draw. The alpha component will not be ignored and specifies how transparent the rectangle will be. \param colorRightUp Color of the upper right corner to draw. The alpha component will not be ignored and specifies how transparent the rectangle will be. \param colorLeftDown Color of the lower left corner to draw. The alpha component will not be ignored and specifies how transparent the rectangle will be. \param colorRightDown Color of the lower right corner to draw. The alpha component will not be ignored and specifies how transparent the rectangle will be. \param pos Position of the rectangle. \param clip Pointer to rectangle against which the rectangle will be clipped. If the pointer is null, no clipping will be performed. */ virtual void draw2DRectangle(const core::rect& pos, SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, const core::rect* clip =0) =0; //! Draws the outline of a 2D rectangle. /** \param pos Position of the rectangle. \param color Color of the rectangle to draw. The alpha component specifies how transparent the rectangle outline will be. */ virtual void draw2DRectangleOutline(const core::recti& pos, SColor color=SColor(255,255,255,255)) =0; //! Draws a 2d line. Both start and end will be included in coloring. /** \param start Screen coordinates of the start of the line in pixels. \param end Screen coordinates of the start of the line in pixels. \param color Color of the line to draw. */ virtual void draw2DLine(const core::position2d& start, const core::position2d& end, SColor color=SColor(255,255,255,255)) =0; //! Draws a pixel. /** \param x The x-position of the pixel. \param y The y-position of the pixel. \param color Color of the pixel to draw. */ virtual void drawPixel(u32 x, u32 y, const SColor& color) =0; //! Draws a non filled concyclic regular 2d polyon. /** This method can be used to draw circles, but also triangles, tetragons, pentagons, hexagons, heptagons, octagons, enneagons, decagons, hendecagons, dodecagon, triskaidecagons, etc. I think you'll got it now. And all this by simply specifying the vertex count. Welcome to the wonders of geometry. \param center Position of center of circle (pixels). \param radius Radius of circle in pixels. \param color Color of the circle. \param vertexCount Amount of vertices of the polygon. Specify 2 to draw a line, 3 to draw a triangle, 4 for tetragons and a lot (>10) for nearly a circle. */ virtual void draw2DPolygon(core::position2d center, f32 radius, video::SColor color=SColor(100,255,255,255), s32 vertexCount=10) =0; //! Draws a shadow volume into the stencil buffer. /** To draw a stencil shadow, do this: First, draw all geometry. Then use this method, to draw the shadow volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. Please note that the code for the opengl version of the method is based on free code sent in by Philipp Dortmann, lots of thanks go to him! \param triangles Array of 3d vectors, specifying the shadow volume. \param zfail If set to true, zfail method is used, otherwise zpass. \param debugDataVisible The debug data that is enabled for this shadow node */ virtual void drawStencilShadowVolume(const core::array& triangles, bool zfail=true, u32 debugDataVisible=0) =0; //! Fills the stencil shadow with color. /** After the shadow volume has been drawn into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this to draw the color of the shadow. Please note that the code for the opengl version of the method is based on free code sent in by Philipp Dortmann, lots of thanks go to him! \param clearStencilBuffer Set this to false, if you want to draw every shadow with the same color, and only want to call drawStencilShadow() once after all shadow volumes have been drawn. Set this to true, if you want to paint every shadow with its own color. \param leftUpEdge Color of the shadow in the upper left corner of screen. \param rightUpEdge Color of the shadow in the upper right corner of screen. \param leftDownEdge Color of the shadow in the lower left corner of screen. \param rightDownEdge Color of the shadow in the lower right corner of screen. */ virtual void drawStencilShadow(bool clearStencilBuffer=false, video::SColor leftUpEdge = video::SColor(255,0,0,0), video::SColor rightUpEdge = video::SColor(255,0,0,0), video::SColor leftDownEdge = video::SColor(255,0,0,0), video::SColor rightDownEdge = video::SColor(255,0,0,0)) =0; //! Draws a mesh buffer /** \param mb Buffer to draw */ virtual void drawMeshBuffer(const scene::IMeshBuffer* mb) =0; //! Draws normals of a mesh buffer /** \param mb Buffer to draw the normals of \param length length scale factor of the normals \param color Color the normals are rendered with */ virtual void drawMeshBufferNormals(const scene::IMeshBuffer* mb, f32 length=10.f, SColor color=0xffffffff) =0; //! Sets the fog mode. /** These are global values attached to each 3d object rendered, which has the fog flag enabled in its material. \param color Color of the fog \param fogType Type of fog used \param start Only used in linear fog mode (linearFog=true). Specifies where fog starts. \param end Only used in linear fog mode (linearFog=true). Specifies where fog ends. \param density Only used in exponential fog mode (linearFog=false). Must be a value between 0 and 1. \param pixelFog Set this to false for vertex fog, and true if you want per-pixel fog. \param rangeFog Set this to true to enable range-based vertex fog. The distance from the viewer is used to compute the fog, not the z-coordinate. This is better, but slower. This might not be available with all drivers and fog settings. */ virtual void setFog(SColor color=SColor(0,255,255,255), E_FOG_TYPE fogType=EFT_FOG_LINEAR, f32 start=50.0f, f32 end=100.0f, f32 density=0.01f, bool pixelFog=false, bool rangeFog=false) =0; //! Gets the fog mode. virtual void getFog(SColor& color, E_FOG_TYPE& fogType, f32& start, f32& end, f32& density, bool& pixelFog, bool& rangeFog) = 0; //! Get the current color format of the color buffer /** \return Color format of the color buffer. */ virtual ECOLOR_FORMAT getColorFormat() const =0; //! Get the size of the screen or render window. /** \return Size of screen or render window. */ virtual const core::dimension2d& getScreenSize() const =0; //! Get the size of the current render target /** This method will return the screen size if the driver doesn't support render to texture, or if the current render target is the screen. \return Size of render target or screen/window */ virtual const core::dimension2d& getCurrentRenderTargetSize() const =0; //! Returns current frames per second value. /** This value is updated approximately every 1.5 seconds and is only intended to provide a rough guide to the average frame rate. It is not suitable for use in performing timing calculations or framerate independent movement. \return Approximate amount of frames per second drawn. */ virtual s32 getFPS() const =0; //! Returns amount of primitives (mostly triangles) which were drawn in the last frame. /** Together with getFPS() very useful method for statistics. \param mode Defines if the primitives drawn are accumulated or counted per frame. \return Amount of primitives drawn in the last frame. */ virtual u32 getPrimitiveCountDrawn( u32 mode =0 ) const =0; //! Deletes all dynamic lights which were previously added with addDynamicLight(). virtual void deleteAllDynamicLights() =0; //! adds a dynamic light, returning an index to the light //! \param light: the light data to use to create the light //! \return An index to the light, or -1 if an error occurs virtual s32 addDynamicLight(const SLight& light) =0; //! Returns the maximal amount of dynamic lights the device can handle /** \return Maximal amount of dynamic lights. */ virtual u32 getMaximalDynamicLightAmount() const =0; //! Returns amount of dynamic lights currently set /** \return Amount of dynamic lights currently set */ virtual u32 getDynamicLightCount() const =0; //! Returns light data which was previously set by IVideoDriver::addDynamicLight(). /** \param idx Zero based index of the light. Must be 0 or greater and smaller than IVideoDriver::getDynamicLightCount. \return Light data. */ virtual const SLight& getDynamicLight(u32 idx) const =0; //! Turns a dynamic light on or off //! \param lightIndex: the index returned by addDynamicLight //! \param turnOn: true to turn the light on, false to turn it off virtual void turnLightOn(s32 lightIndex, bool turnOn) =0; //! Gets name of this video driver. /** \return Returns the name of the video driver, e.g. in case of the Direct3D8 driver, it would return "Direct3D 8.1". */ virtual const wchar_t* getName() const =0; //! Adds an external image loader to the engine. /** This is useful if the Irrlicht Engine should be able to load textures of currently unsupported file formats (e.g. gif). The IImageLoader only needs to be implemented for loading this file format. A pointer to the implementation can be passed to the engine using this method. \param loader Pointer to the external loader created. */ virtual void addExternalImageLoader(IImageLoader* loader) =0; //! Adds an external image writer to the engine. /** This is useful if the Irrlicht Engine should be able to write textures of currently unsupported file formats (e.g .gif). The IImageWriter only needs to be implemented for writing this file format. A pointer to the implementation can be passed to the engine using this method. \param writer: Pointer to the external writer created. */ virtual void addExternalImageWriter(IImageWriter* writer) =0; //! Returns the maximum amount of primitives /** (mostly vertices) which the device is able to render with one drawVertexPrimitiveList call. \return Maximum amount of primitives. */ virtual u32 getMaximalPrimitiveCount() const =0; //! Enables or disables a texture creation flag. /** These flags define how textures should be created. By changing this value, you can influence for example the speed of rendering a lot. But please note that the video drivers take this value only as recommendation. It could happen that you enable the ETCF_ALWAYS_16_BIT mode, but the driver still creates 32 bit textures. \param flag Texture creation flag. \param enabled Specifies if the given flag should be enabled or disabled. */ virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled=true) =0; //! Returns if a texture creation flag is enabled or disabled. /** You can change this value using setTextureCreationFlag(). \param flag Texture creation flag. \return The current texture creation flag enabled mode. */ virtual bool getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const =0; //! Creates a software image from a file. /** No hardware texture will be created for this image. This method is useful for example if you want to read a heightmap for a terrain renderer. \param filename Name of the file from which the image is created. \return The created image. If you no longer need the image, you should call IImage::drop(). See IReferenceCounted::drop() for more information. */ virtual IImage* createImageFromFile(const io::path& filename) = 0; //! Creates a software image from a file. /** No hardware texture will be created for this image. This method is useful for example if you want to read a heightmap for a terrain renderer. \param file File from which the image is created. \return The created image. If you no longer need the image, you should call IImage::drop(). See IReferenceCounted::drop() for more information. */ virtual IImage* createImageFromFile(io::IReadFile* file) =0; //! Writes the provided image to a file. /** Requires that there is a suitable image writer registered for writing the image. \param image Image to write. \param filename Name of the file to write. \param param Control parameter for the backend (e.g. compression level). \return True on successful write. */ virtual bool writeImageToFile(IImage* image, const io::path& filename, u32 param = 0) = 0; //! Writes the provided image to a file. /** Requires that there is a suitable image writer registered for writing the image. \param image Image to write. \param file An already open io::IWriteFile object. The name will be used to determine the appropriate image writer to use. \param param Control parameter for the backend (e.g. compression level). \return True on successful write. */ virtual bool writeImageToFile(IImage* image, io::IWriteFile* file, u32 param =0) =0; //! Creates a software image from a byte array. /** No hardware texture will be created for this image. This method is useful for example if you want to read a heightmap for a terrain renderer. \param format Desired color format of the texture \param size Desired size of the image \param data A byte array with pixel color information \param ownForeignMemory If true, the image will use the data pointer directly and own it afterwards. If false, the memory will by copied internally. \param deleteMemory Whether the memory is deallocated upon destruction. \return The created image. If you no longer need the image, you should call IImage::drop(). See IReferenceCounted::drop() for more information. */ virtual IImage* createImageFromData(ECOLOR_FORMAT format, const core::dimension2d& size, void *data, bool ownForeignMemory=false, bool deleteMemory = true) =0; //! Creates an empty software image. /** \param format Desired color format of the image. \param size Size of the image to create. \return The created image. If you no longer need the image, you should call IImage::drop(). See IReferenceCounted::drop() for more information. */ virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d& size) =0; //! Creates a software image by converting it to given format from another image. /** \deprecated Create an empty image and use copyTo(). This method may be removed by Irrlicht 1.9. \param format Desired color format of the image. \param imageToCopy Image to copy to the new image. \return The created image. If you no longer need the image, you should call IImage::drop(). See IReferenceCounted::drop() for more information. */ _IRR_DEPRECATED_ virtual IImage* createImage(ECOLOR_FORMAT format, IImage *imageToCopy) =0; //! Creates a software image from a part of another image. /** \deprecated Create an empty image and use copyTo(). This method may be removed by Irrlicht 1.9. \param imageToCopy Image to copy to the new image in part. \param pos Position of rectangle to copy. \param size Extents of rectangle to copy. \return The created image. If you no longer need the image, you should call IImage::drop(). See IReferenceCounted::drop() for more information. */ _IRR_DEPRECATED_ virtual IImage* createImage(IImage* imageToCopy, const core::position2d& pos, const core::dimension2d& size) =0; //! Creates a software image from a part of a texture. /** \param texture Texture to copy to the new image in part. \param pos Position of rectangle to copy. \param size Extents of rectangle to copy. \return The created image. If you no longer need the image, you should call IImage::drop(). See IReferenceCounted::drop() for more information. */ virtual IImage* createImage(ITexture* texture, const core::position2d& pos, const core::dimension2d& size) =0; //! Event handler for resize events. Only used by the engine internally. /** Used to notify the driver that the window was resized. Usually, there is no need to call this method. */ virtual void OnResize(const core::dimension2d& size) =0; //! Adds a new material renderer to the video device. /** Use this method to extend the VideoDriver with new material types. To extend the engine using this method do the following: Derive a class from IMaterialRenderer and override the methods you need. For setting the right renderstates, you can try to get a pointer to the real rendering device using IVideoDriver::getExposedVideoData(). Add your class with IVideoDriver::addMaterialRenderer(). To use an object being displayed with your new material, set the MaterialType member of the SMaterial struct to the value returned by this method. If you simply want to create a new material using vertex and/or pixel shaders it would be easier to use the video::IGPUProgrammingServices interface which you can get using the getGPUProgrammingServices() method. \param renderer A pointer to the new renderer. \param name Optional name for the material renderer entry. \return The number of the material type which can be set in SMaterial::MaterialType to use the renderer. -1 is returned if an error occured. For example if you tried to add an material renderer to the software renderer or the null device, which do not accept material renderers. */ virtual s32 addMaterialRenderer(IMaterialRenderer* renderer, const c8* name =0) =0; //! Get access to a material renderer by index. /** \param idx Id of the material renderer. Can be a value of the E_MATERIAL_TYPE enum or a value which was returned by addMaterialRenderer(). \return Pointer to material renderer or null if not existing. */ virtual IMaterialRenderer* getMaterialRenderer(u32 idx) =0; //! Get amount of currently available material renderers. /** \return Amount of currently available material renderers. */ virtual u32 getMaterialRendererCount() const =0; //! Get name of a material renderer /** This string can, e.g., be used to test if a specific renderer already has been registered/created, or use this string to store data about materials: This returned name will be also used when serializing materials. \param idx Id of the material renderer. Can be a value of the E_MATERIAL_TYPE enum or a value which was returned by addMaterialRenderer(). \return String with the name of the renderer, or 0 if not exisiting */ virtual const c8* getMaterialRendererName(u32 idx) const =0; //! Sets the name of a material renderer. /** Will have no effect on built-in material renderers. \param idx: Id of the material renderer. Can be a value of the E_MATERIAL_TYPE enum or a value which was returned by addMaterialRenderer(). \param name: New name of the material renderer. */ virtual void setMaterialRendererName(s32 idx, const c8* name) =0; //! Creates material attributes list from a material /** This method is useful for serialization and more. Please note that the video driver will use the material renderer names from getMaterialRendererName() to write out the material type name, so they should be set before. \param material The material to serialize. \param options Additional options which might influence the serialization. \return The io::IAttributes container holding the material properties. */ virtual io::IAttributes* createAttributesFromMaterial(const video::SMaterial& material, io::SAttributeReadWriteOptions* options=0) =0; //! Fills an SMaterial structure from attributes. /** Please note that for setting material types of the material, the video driver will need to query the material renderers for their names, so all non built-in materials must have been created before calling this method. \param outMaterial The material to set the properties for. \param attributes The attributes to read from. */ virtual void fillMaterialStructureFromAttributes(video::SMaterial& outMaterial, io::IAttributes* attributes) =0; //! Returns driver and operating system specific data about the IVideoDriver. /** This method should only be used if the engine should be extended without having to modify the source of the engine. \return Collection of device dependent pointers. */ virtual const SExposedVideoData& getExposedVideoData() =0; //! Get type of video driver /** \return Type of driver. */ virtual E_DRIVER_TYPE getDriverType() const =0; //! Gets the IGPUProgrammingServices interface. /** \return Pointer to the IGPUProgrammingServices. Returns 0 if the video driver does not support this. For example the Software driver and the Null driver will always return 0. */ virtual IGPUProgrammingServices* getGPUProgrammingServices() =0; //! Returns a pointer to the mesh manipulator. virtual scene::IMeshManipulator* getMeshManipulator() =0; //! Clears the ZBuffer. /** Note that you usually need not to call this method, as it is automatically done in IVideoDriver::beginScene() or IVideoDriver::setRenderTarget() if you enable zBuffer. But if you have to render some special things, you can clear the zbuffer during the rendering process with this method any time. */ virtual void clearZBuffer() =0; //! Make a screenshot of the last rendered frame. /** \return An image created from the last rendered frame. */ virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER) =0; //! Check if the image is already loaded. /** Works similar to getTexture(), but does not load the texture if it is not currently loaded. \param filename Name of the texture. \return Pointer to loaded texture, or 0 if not found. */ virtual video::ITexture* findTexture(const io::path& filename) = 0; //! Set or unset a clipping plane. /** There are at least 6 clipping planes available for the user to set at will. \param index The plane index. Must be between 0 and MaxUserClipPlanes. \param plane The plane itself. \param enable If true, enable the clipping plane else disable it. \return True if the clipping plane is usable. */ virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false) =0; //! Enable or disable a clipping plane. /** There are at least 6 clipping planes available for the user to set at will. \param index The plane index. Must be between 0 and MaxUserClipPlanes. \param enable If true, enable the clipping plane else disable it. */ virtual void enableClipPlane(u32 index, bool enable) =0; //! Set the minimum number of vertices for which a hw buffer will be created /** \param count Number of vertices to set as minimum. */ virtual void setMinHardwareBufferVertexCount(u32 count) =0; //! Get the global Material, which might override local materials. /** Depending on the enable flags, values from this Material are used to override those of local materials of some meshbuffer being rendered. \return Reference to the Override Material. */ virtual SOverrideMaterial& getOverrideMaterial() =0; //! Get the 2d override material for altering its values /** The 2d override materual allows to alter certain render states of the 2d methods. Not all members of SMaterial are honored, especially not MaterialType and Textures. Moreover, the zbuffer is always ignored, and lighting is always off. All other flags can be changed, though some might have to effect in most cases. Please note that you have to enable/disable this effect with enableInitMaterial2D(). This effect is costly, as it increases the number of state changes considerably. Always reset the values when done. \return Material reference which should be altered to reflect the new settings. */ virtual SMaterial& getMaterial2D() =0; //! Enable the 2d override material /** \param enable Flag which tells whether the material shall be enabled or disabled. */ virtual void enableMaterial2D(bool enable=true) =0; //! Get the graphics card vendor name. virtual core::stringc getVendorInfo() =0; //! Only used by the engine internally. /** The ambient color is set in the scene manager, see scene::ISceneManager::setAmbientLight(). \param color New color of the ambient light. */ virtual void setAmbientLight(const SColorf& color) =0; //! Only used by the engine internally. /** Passes the global material flag AllowZWriteOnTransparent. Use the SceneManager attribute to set this value from your app. \param flag Default behavior is to disable ZWrite, i.e. false. */ virtual void setAllowZWriteOnTransparent(bool flag) =0; //! Get the maximum texture size supported. virtual core::dimension2du getMaxTextureSize() const =0; //! Color conversion convenience function /** Convert an image (as array of pixels) from source to destination array, thereby converting the color format. The pixel size is determined by the color formats. \param sP Pointer to source \param sF Color format of source \param sN Number of pixels to convert, both array must be large enough \param dP Pointer to destination \param dF Color format of destination */ virtual void convertColor(const void* sP, ECOLOR_FORMAT sF, s32 sN, void* dP, ECOLOR_FORMAT dF) const =0; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/IVertexBuffer.h0000644000000000000000000000307312574354552016374 0ustar rootroot// Copyright (C) 2008-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_VERTEX_BUFFER_H_INCLUDED__ #define __I_VERTEX_BUFFER_H_INCLUDED__ #include "IReferenceCounted.h" #include "irrArray.h" #include "S3DVertex.h" namespace irr { namespace scene { class IVertexBuffer : public virtual IReferenceCounted { public: virtual void* getData() =0; virtual video::E_VERTEX_TYPE getType() const =0; virtual void setType(video::E_VERTEX_TYPE vertexType) =0; virtual u32 stride() const =0; virtual u32 size() const =0; virtual void push_back(const video::S3DVertex &element) =0; virtual video::S3DVertex& operator [](const u32 index) const =0; virtual video::S3DVertex& getLast() =0; virtual void set_used(u32 usedNow) =0; virtual void reallocate(u32 new_size) =0; virtual u32 allocated_size() const =0; virtual video::S3DVertex* pointer() =0; //! get the current hardware mapping hint virtual E_HARDWARE_MAPPING getHardwareMappingHint() const =0; //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint ) =0; //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty() =0; //! Get the currently used ID for identification of changes. /** This shouldn't be used for anything outside the VideoDriver. */ virtual u32 getChangedID() const = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ITriangleSelector.h0000644000000000000000000001255012574354552017233 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_TRIANGLE_SELECTOR_H_INCLUDED__ #define __I_TRIANGLE_SELECTOR_H_INCLUDED__ #include "IReferenceCounted.h" #include "triangle3d.h" #include "aabbox3d.h" #include "matrix4.h" #include "line3d.h" namespace irr { namespace scene { class ISceneNode; //! Interface to return triangles with specific properties. /** Every ISceneNode may have a triangle selector, available with ISceneNode::getTriangleScelector() or ISceneManager::createTriangleSelector. This is used for doing collision detection: For example if you know, that a collision may have happened in the area between (1,1,1) and (10,10,10), you can get all triangles of the scene node in this area with the ITriangleSelector easily and check every triangle if it collided. */ class ITriangleSelector : public virtual IReferenceCounted { public: //! Get amount of all available triangles in this selector virtual s32 getTriangleCount() const = 0; //! Gets the triangles for one associated node. /** This returns all triangles for one scene node associated with this selector. If there is more than one scene node associated (e.g. for an IMetaTriangleSelector) this this function may be called multiple times to retrieve all triangles. \param triangles Array where the resulting triangles will be written to. \param arraySize Size of the target array. \param outTriangleCount: Amount of triangles which have been written into the array. \param transform Pointer to matrix for transforming the triangles before they are returned. Useful for example to scale all triangles down into an ellipsoid space. If this pointer is null, no transformation will be done. */ virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::matrix4* transform=0) const = 0; //! Gets the triangles for one associated node which may lie within a specific bounding box. /** This returns all triangles for one scene node associated with this selector. If there is more than one scene node associated (e.g. for an IMetaTriangleSelector) this this function may be called multiple times to retrieve all triangles. This method will return at least the triangles that intersect the box, but may return other triangles as well. \param triangles Array where the resulting triangles will be written to. \param arraySize Size of the target array. \param outTriangleCount Amount of triangles which have been written into the array. \param box Only triangles which are in this axis aligned bounding box will be written into the array. \param transform Pointer to matrix for transforming the triangles before they are returned. Useful for example to scale all triangles down into an ellipsoid space. If this pointer is null, no transformation will be done. */ virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::aabbox3d& box, const core::matrix4* transform=0) const = 0; //! Gets the triangles for one associated node which have or may have contact with a 3d line. /** This returns all triangles for one scene node associated with this selector. If there is more than one scene node associated (e.g. for an IMetaTriangleSelector) this this function may be called multiple times to retrieve all triangles. Please note that unoptimized triangle selectors also may return triangles which are not in contact at all with the 3d line. \param triangles Array where the resulting triangles will be written to. \param arraySize Size of the target array. \param outTriangleCount Amount of triangles which have been written into the array. \param line Only triangles which may be in contact with this 3d line will be written into the array. \param transform Pointer to matrix for transforming the triangles before they are returned. Useful for example to scale all triangles down into an ellipsoid space. If this pointer is null, no transformation will be done. */ virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform=0) const = 0; //! Get scene node associated with a given triangle. /** This allows to find which scene node (potentially of several) is associated with a specific triangle. \param triangleIndex: the index of the triangle for which you want to find the associated scene node. \return The scene node associated with that triangle. */ virtual ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const = 0; //! Get number of TriangleSelectors that are part of this one /** Only useful for MetaTriangleSelector, others return 1 */ virtual u32 getSelectorCount() const = 0; //! Get TriangleSelector based on index based on getSelectorCount /** Only useful for MetaTriangleSelector, others return 'this' or 0 */ virtual ITriangleSelector* getSelector(u32 index) = 0; //! Get TriangleSelector based on index based on getSelectorCount /** Only useful for MetaTriangleSelector, others return 'this' or 0 */ virtual const ITriangleSelector* getSelector(u32 index) const = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ITimer.h0000644000000000000000000000605212574354552015045 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_TIMER_H_INCLUDED__ #define __I_TIMER_H_INCLUDED__ #include "IReferenceCounted.h" namespace irr { //! Interface for getting and manipulating the virtual time class ITimer : public virtual IReferenceCounted { public: //! Returns current real time in milliseconds of the system. /** This value does not start with 0 when the application starts. For example in one implementation the value returned could be the amount of milliseconds which have elapsed since the system was started. */ virtual u32 getRealTime() const = 0; enum EWeekday { EWD_SUNDAY=0, EWD_MONDAY, EWD_TUESDAY, EWD_WEDNESDAY, EWD_THURSDAY, EWD_FRIDAY, EWD_SATURDAY }; struct RealTimeDate { // Hour of the day, from 0 to 23 u32 Hour; // Minute of the hour, from 0 to 59 u32 Minute; // Second of the minute, due to extra seconds from 0 to 61 u32 Second; // Year of the gregorian calender s32 Year; // Month of the year, from 1 to 12 u32 Month; // Day of the month, from 1 to 31 u32 Day; // Weekday for the current day EWeekday Weekday; // Day of the year, from 1 to 366 u32 Yearday; // Whether daylight saving is on bool IsDST; }; virtual RealTimeDate getRealTimeAndDate() const = 0; //! Returns current virtual time in milliseconds. /** This value starts with 0 and can be manipulated using setTime(), stopTimer(), startTimer(), etc. This value depends on the set speed of the timer if the timer is stopped, etc. If you need the system time, use getRealTime() */ virtual u32 getTime() const = 0; //! sets current virtual time virtual void setTime(u32 time) = 0; //! Stops the virtual timer. /** The timer is reference counted, which means everything which calls stop() will also have to call start(), otherwise the timer may not start/stop correctly again. */ virtual void stop() = 0; //! Starts the virtual timer. /** The timer is reference counted, which means everything which calls stop() will also have to call start(), otherwise the timer may not start/stop correctly again. */ virtual void start() = 0; //! Sets the speed of the timer /** The speed is the factor with which the time is running faster or slower then the real system time. */ virtual void setSpeed(f32 speed = 1.0f) = 0; //! Returns current speed of the timer /** The speed is the factor with which the time is running faster or slower then the real system time. */ virtual f32 getSpeed() const = 0; //! Returns if the virtual timer is currently stopped virtual bool isStopped() const = 0; //! Advances the virtual time /** Makes the virtual timer update the time value based on the real time. This is called automatically when calling IrrlichtDevice::run(), but you can call it manually if you don't use this method. */ virtual void tick() = 0; }; } // end namespace irr #endif irrlicht-1.8.3/include/ITexture.h0000644000000000000000000002153612574354552015431 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_TEXTURE_H_INCLUDED__ #define __I_TEXTURE_H_INCLUDED__ #include "IReferenceCounted.h" #include "IImage.h" #include "dimension2d.h" #include "EDriverTypes.h" #include "path.h" #include "matrix4.h" namespace irr { namespace video { //! Enumeration flags telling the video driver in which format textures should be created. enum E_TEXTURE_CREATION_FLAG { /** Forces the driver to create 16 bit textures always, independent of which format the file on disk has. When choosing this you may lose some color detail, but gain much speed and memory. 16 bit textures can be transferred twice as fast as 32 bit textures and only use half of the space in memory. When using this flag, it does not make sense to use the flags ETCF_ALWAYS_32_BIT, ETCF_OPTIMIZED_FOR_QUALITY, or ETCF_OPTIMIZED_FOR_SPEED at the same time. */ ETCF_ALWAYS_16_BIT = 0x00000001, /** Forces the driver to create 32 bit textures always, independent of which format the file on disk has. Please note that some drivers (like the software device) will ignore this, because they are only able to create and use 16 bit textures. When using this flag, it does not make sense to use the flags ETCF_ALWAYS_16_BIT, ETCF_OPTIMIZED_FOR_QUALITY, or ETCF_OPTIMIZED_FOR_SPEED at the same time. */ ETCF_ALWAYS_32_BIT = 0x00000002, /** Lets the driver decide in which format the textures are created and tries to make the textures look as good as possible. Usually it simply chooses the format in which the texture was stored on disk. When using this flag, it does not make sense to use the flags ETCF_ALWAYS_16_BIT, ETCF_ALWAYS_32_BIT, or ETCF_OPTIMIZED_FOR_SPEED at the same time. */ ETCF_OPTIMIZED_FOR_QUALITY = 0x00000004, /** Lets the driver decide in which format the textures are created and tries to create them maximizing render speed. When using this flag, it does not make sense to use the flags ETCF_ALWAYS_16_BIT, ETCF_ALWAYS_32_BIT, or ETCF_OPTIMIZED_FOR_QUALITY, at the same time. */ ETCF_OPTIMIZED_FOR_SPEED = 0x00000008, /** Automatically creates mip map levels for the textures. */ ETCF_CREATE_MIP_MAPS = 0x00000010, /** Discard any alpha layer and use non-alpha color format. */ ETCF_NO_ALPHA_CHANNEL = 0x00000020, //! Allow the Driver to use Non-Power-2-Textures /** BurningVideo can handle Non-Power-2 Textures in 2D (GUI), but not in 3D. */ ETCF_ALLOW_NON_POWER_2 = 0x00000040, /** This flag is never used, it only forces the compiler to compile these enumeration values to 32 bit. */ ETCF_FORCE_32_BIT_DO_NOT_USE = 0x7fffffff }; //! Enum for the mode for texture locking. Read-Only, write-only or read/write. enum E_TEXTURE_LOCK_MODE { //! The default mode. Texture can be read and written to. ETLM_READ_WRITE = 0, //! Read only. The texture is downloaded, but not uploaded again. /** Often used to read back shader generated textures. */ ETLM_READ_ONLY, //! Write only. The texture is not downloaded and might be uninitialised. /** The updated texture is uploaded to the GPU. Used for initialising the shader from the CPU. */ ETLM_WRITE_ONLY }; //! Interface of a Video Driver dependent Texture. /** An ITexture is created by an IVideoDriver by using IVideoDriver::addTexture or IVideoDriver::getTexture. After that, the texture may only be used by this VideoDriver. As you can imagine, textures of the DirectX and the OpenGL device will, e.g., not be compatible. An exception is the Software device and the NULL device, their textures are compatible. If you try to use a texture created by one device with an other device, the device will refuse to do that and write a warning or an error message to the output buffer. */ class ITexture : public virtual IReferenceCounted { public: //! constructor ITexture(const io::path& name) : NamedPath(name) { } //! Lock function. /** Locks the Texture and returns a pointer to access the pixels. After lock() has been called and all operations on the pixels are done, you must call unlock(). Locks are not accumulating, hence one unlock will do for an arbitrary number of previous locks. You should avoid locking different levels without unlocking inbetween, though, because only the last level locked will be unlocked. The size of the i-th mipmap level is defined as max(getSize().Width>>i,1) and max(getSize().Height>>i,1) \param mode Specifies what kind of changes to the locked texture are allowed. Unspecified behavior will arise if texture is written in read only mode or read from in write only mode. Support for this feature depends on the driver, so don't rely on the texture being write-protected when locking with read-only, etc. \param mipmapLevel Number of the mipmapLevel to lock. 0 is main texture. Non-existing levels will silently fail and return 0. \return Returns a pointer to the pixel data. The format of the pixel can be determined by using getColorFormat(). 0 is returned, if the texture cannot be locked. */ virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0) = 0; //! Unlock function. Must be called after a lock() to the texture. /** One should avoid to call unlock more than once before another lock. The last locked mip level will be unlocked. */ virtual void unlock() = 0; //! Get original size of the texture. /** The texture is usually scaled, if it was created with an unoptimal size. For example if the size was not a power of two. This method returns the size of the texture it had before it was scaled. Can be useful when drawing 2d images on the screen, which should have the exact size of the original texture. Use ITexture::getSize() if you want to know the real size it has now stored in the system. \return The original size of the texture. */ virtual const core::dimension2d& getOriginalSize() const = 0; //! Get dimension (=size) of the texture. /** \return The size of the texture. */ virtual const core::dimension2d& getSize() const = 0; //! Get driver type of texture. /** This is the driver, which created the texture. This method is used internally by the video devices, to check, if they may use a texture because textures may be incompatible between different devices. \return Driver type of texture. */ virtual E_DRIVER_TYPE getDriverType() const = 0; //! Get the color format of texture. /** \return The color format of texture. */ virtual ECOLOR_FORMAT getColorFormat() const = 0; //! Get pitch of the main texture (in bytes). /** The pitch is the amount of bytes used for a row of pixels in a texture. \return Pitch of texture in bytes. */ virtual u32 getPitch() const = 0; //! Check whether the texture has MipMaps /** \return True if texture has MipMaps, else false. */ virtual bool hasMipMaps() const { return false; } //! Returns if the texture has an alpha channel virtual bool hasAlpha() const { return getColorFormat () == video::ECF_A8R8G8B8 || getColorFormat () == video::ECF_A1R5G5B5; } //! Regenerates the mip map levels of the texture. /** Required after modifying the texture, usually after calling unlock(). \param mipmapData Optional parameter to pass in image data which will be used instead of the previously stored or automatically generated mipmap data. The data has to be a continuous pixel data for all mipmaps until 1x1 pixel. Each mipmap has to be half the width and height of the previous level. At least one pixel will be always kept.*/ virtual void regenerateMipMapLevels(void* mipmapData=0) = 0; //! Check whether the texture is a render target /** Render targets can be set as such in the video driver, in order to render a scene into the texture. Once unbound as render target, they can be used just as usual textures again. \return True if this is a render target, otherwise false. */ virtual bool isRenderTarget() const { return false; } //! Get name of texture (in most cases this is the filename) const io::SNamedPath& getName() const { return NamedPath; } protected: //! Helper function, helps to get the desired texture creation format from the flags. /** \return Either ETCF_ALWAYS_32_BIT, ETCF_ALWAYS_16_BIT, ETCF_OPTIMIZED_FOR_QUALITY, or ETCF_OPTIMIZED_FOR_SPEED. */ inline E_TEXTURE_CREATION_FLAG getTextureFormatFromFlags(u32 flags) { if (flags & ETCF_OPTIMIZED_FOR_SPEED) return ETCF_OPTIMIZED_FOR_SPEED; if (flags & ETCF_ALWAYS_16_BIT) return ETCF_ALWAYS_16_BIT; if (flags & ETCF_ALWAYS_32_BIT) return ETCF_ALWAYS_32_BIT; if (flags & ETCF_OPTIMIZED_FOR_QUALITY) return ETCF_OPTIMIZED_FOR_QUALITY; return ETCF_OPTIMIZED_FOR_SPEED; } io::SNamedPath NamedPath; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/ITextSceneNode.h0000644000000000000000000000157612574354552016503 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_TEXT_SCENE_NODE_H_INCLUDED__ #define __I_TEXT_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" namespace irr { namespace scene { //! A scene node for displaying 2d text at a position in three dimensional space class ITextSceneNode : public ISceneNode { public: //! constructor ITextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0)) : ISceneNode(parent, mgr, id, position) {} //! sets the text string virtual void setText(const wchar_t* text) = 0; //! sets the color of the text virtual void setTextColor(video::SColor color) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ITerrainSceneNode.h0000644000000000000000000002064712574354552017163 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // The code for the TerrainSceneNode is based on the terrain renderer by // Soconne and the GeoMipMapSceneNode developed by Spintz. They made their // code available for Irrlicht and allowed it to be distributed under this // licence. I only modified some parts. A lot of thanks go to them. #ifndef __I_TERRAIN_SCENE_NODE_H__ #define __I_TERRAIN_SCENE_NODE_H__ #include "ETerrainElements.h" #include "ISceneNode.h" #include "IDynamicMeshBuffer.h" #include "irrArray.h" namespace irr { namespace io { class IReadFile; } // end namespace io namespace scene { class IMesh; //! A scene node for displaying terrain using the geo mip map algorithm. /** The code for the TerrainSceneNode is based on the Terrain renderer by Soconne and * the GeoMipMapSceneNode developed by Spintz. They made their code available for Irrlicht * and allowed it to be distributed under this licence. I only modified some parts. * A lot of thanks go to them. * * This scene node is capable of very quickly loading * terrains and updating the indices at runtime to enable viewing very large terrains. It uses a * CLOD (Continuous Level of Detail) algorithm which updates the indices for each patch based on * a LOD (Level of Detail) which is determined based on a patch's distance from the camera. * * The Patch Size of the terrain must always be a size of ( 2^N+1, i.e. 8+1(9), 16+1(17), etc. ). * The MaxLOD available is directly dependent on the patch size of the terrain. LOD 0 contains all * of the indices to draw all the triangles at the max detail for a patch. As each LOD goes up by 1 * the step taken, in generating indices increases by - 2^LOD, so for LOD 1, the step taken is 2, for * LOD 2, the step taken is 4, LOD 3 - 8, etc. The step can be no larger than the size of the patch, * so having a LOD of 8, with a patch size of 17, is asking the algoritm to generate indices every * 2^8 ( 256 ) vertices, which is not possible with a patch size of 17. The maximum LOD for a patch * size of 17 is 2^4 ( 16 ). So, with a MaxLOD of 5, you'll have LOD 0 ( full detail ), LOD 1 ( every * 2 vertices ), LOD 2 ( every 4 vertices ), LOD 3 ( every 8 vertices ) and LOD 4 ( every 16 vertices ). **/ class ITerrainSceneNode : public ISceneNode { public: //! Constructor ITerrainSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0.0f, 0.0f, 0.0f), const core::vector3df& rotation = core::vector3df(0.0f, 0.0f, 0.0f), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f) ) : ISceneNode (parent, mgr, id, position, rotation, scale) {} //! Get the bounding box of the terrain. /** \return The bounding box of the entire terrain. */ virtual const core::aabbox3d& getBoundingBox() const =0; //! Get the bounding box of a patch /** \return The bounding box of the chosen patch. */ virtual const core::aabbox3d& getBoundingBox(s32 patchX, s32 patchZ) const =0; //! Get the number of indices currently in the meshbuffer /** \return The index count. */ virtual u32 getIndexCount() const =0; //! Get pointer to the mesh /** \return Pointer to the mesh. */ virtual IMesh* getMesh() =0; //! Get pointer to the buffer used by the terrain (most users will not need this) virtual IMeshBuffer* getRenderBuffer() =0; //! Gets the meshbuffer data based on a specified level of detail. /** \param mb A reference to an IDynamicMeshBuffer object \param LOD The level of detail you want the indices from. */ virtual void getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD=0) const =0; //! Gets the indices for a specified patch at a specified Level of Detail. /** \param indices A reference to an array of u32 indices. \param patchX Patch x coordinate. \param patchZ Patch z coordinate. \param LOD The level of detail to get for that patch. If -1, then get the CurrentLOD. If the CurrentLOD is set to -1, meaning it's not shown, then it will retrieve the triangles at the highest LOD (0). \return Number of indices put into the buffer. */ virtual s32 getIndicesForPatch(core::array& indices, s32 patchX, s32 patchZ, s32 LOD=0) =0; //! Populates an array with the CurrentLOD of each patch. /** \param LODs A reference to a core::array to hold the values \return Number of elements in the array */ virtual s32 getCurrentLODOfPatches(core::array& LODs) const =0; //! Manually sets the LOD of a patch /** \param patchX Patch x coordinate. \param patchZ Patch z coordinate. \param LOD The level of detail to set the patch to. */ virtual void setLODOfPatch(s32 patchX, s32 patchZ, s32 LOD=0) =0; //! Get center of terrain. virtual const core::vector3df& getTerrainCenter() const =0; //! Get height of a point of the terrain. virtual f32 getHeight(f32 x, f32 y) const =0; //! Sets the movement camera threshold. /** It is used to determine when to recalculate indices for the scene node. The default value is 10.0f. */ virtual void setCameraMovementDelta(f32 delta) =0; //! Sets the rotation camera threshold. /** It is used to determine when to recalculate indices for the scene node. The default value is 1.0f. */ virtual void setCameraRotationDelta(f32 delta) =0; //! Sets whether or not the node should dynamically update its associated selector when the geomipmap data changes. /** \param bVal: Boolean value representing whether or not to update selector dynamically. */ virtual void setDynamicSelectorUpdate(bool bVal) =0; //! Override the default generation of distance thresholds. /** For determining the LOD a patch is rendered at. If any LOD is overridden, then the scene node will no longer apply scaling factors to these values. If you override these distances, and then apply a scale to the scene node, it is your responsibility to update the new distances to work best with your new terrain size. */ virtual bool overrideLODDistance(s32 LOD, f64 newDistance) =0; //! Scales the base texture, similar to makePlanarTextureMapping. /** \param scale The scaling amount. Values above 1.0 increase the number of time the texture is drawn on the terrain. Values below 0 will decrease the number of times the texture is drawn on the terrain. Using negative values will flip the texture, as well as still scaling it. \param scale2 If set to 0 (default value), this will set the second texture coordinate set to the same values as in the first set. If this is another value than zero, it will scale the second texture coordinate set by this value. */ virtual void scaleTexture(f32 scale = 1.0f, f32 scale2=0.0f) =0; //! Initializes the terrain data. Loads the vertices from the heightMapFile. /** The file must contain a loadable image of the heightmap. The heightmap must be square. \param file The file to read the image from. File is not rewinded. \param vertexColor Color of all vertices. \param smoothFactor Number of smoothing passes. */ virtual bool loadHeightMap(io::IReadFile* file, video::SColor vertexColor=video::SColor(255,255,255,255), s32 smoothFactor=0) =0; //! Initializes the terrain data. Loads the vertices from the heightMapFile. /** The data is interpreted as (signed) integers of the given bit size or floats (with 32bits, signed). Allowed bitsizes for integers are 8, 16, and 32. The heightmap must be square. \param file The file to read the RAW data from. File is not rewinded. \param bitsPerPixel Size of data if integers used, for floats always use 32. \param signedData Whether we use signed or unsigned ints, ignored for floats. \param floatVals Whether the data is float or int. \param width Width (and also Height, as it must be square) of the heightmap. Use 0 for autocalculating from the filesize. \param vertexColor Color of all vertices. \param smoothFactor Number of smoothing passes. */ virtual bool loadHeightMapRAW(io::IReadFile* file, s32 bitsPerPixel=16, bool signedData=false, bool floatVals=false, s32 width=0, video::SColor vertexColor=video::SColor(255,255,255,255), s32 smoothFactor=0) =0; }; } // end namespace scene } // end namespace irr #endif // __I_TERRAIN_SCENE_NODE_H__ irrlicht-1.8.3/include/ISkinnedMesh.h0000644000000000000000000001415012574354552016173 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SKINNED_MESH_H_INCLUDED__ #define __I_SKINNED_MESH_H_INCLUDED__ #include "irrArray.h" #include "IBoneSceneNode.h" #include "IAnimatedMesh.h" #include "SSkinMeshBuffer.h" namespace irr { namespace scene { enum E_INTERPOLATION_MODE { // constant does use the current key-values without interpolation EIM_CONSTANT = 0, // linear interpolation EIM_LINEAR, //! count of all available interpolation modes EIM_COUNT }; //! Interface for using some special functions of Skinned meshes class ISkinnedMesh : public IAnimatedMesh { public: //! Gets joint count. /** \return Amount of joints in the skeletal animated mesh. */ virtual u32 getJointCount() const = 0; //! Gets the name of a joint. /** \param number: Zero based index of joint. The last joint has the number getJointCount()-1; \return Name of joint and null if an error happened. */ virtual const c8* getJointName(u32 number) const = 0; //! Gets a joint number from its name /** \param name: Name of the joint. \return Number of the joint or -1 if not found. */ virtual s32 getJointNumber(const c8* name) const = 0; //! Use animation from another mesh /** The animation is linked (not copied) based on joint names so make sure they are unique. \return True if all joints in this mesh were matched up (empty names will not be matched, and it's case sensitive). Unmatched joints will not be animated. */ virtual bool useAnimationFrom(const ISkinnedMesh *mesh) = 0; //! Update Normals when Animating /** \param on If false don't animate, which is faster. Else update normals, which allows for proper lighting of animated meshes. */ virtual void updateNormalsWhenAnimating(bool on) = 0; //! Sets Interpolation Mode virtual void setInterpolationMode(E_INTERPOLATION_MODE mode) = 0; //! Animates this mesh's joints based on frame input virtual void animateMesh(f32 frame, f32 blend)=0; //! Preforms a software skin on this mesh based of joint positions virtual void skinMesh() = 0; //! converts the vertex type of all meshbuffers to tangents. /** E.g. used for bump mapping. */ virtual void convertMeshToTangents() = 0; //! Allows to enable hardware skinning. /* This feature is not implementated in Irrlicht yet */ virtual bool setHardwareSkinning(bool on) = 0; //! A vertex weight struct SWeight { //! Index of the mesh buffer u16 buffer_id; //I doubt 32bits is needed //! Index of the vertex u32 vertex_id; //Store global ID here //! Weight Strength/Percentage (0-1) f32 strength; private: //! Internal members used by CSkinnedMesh friend class CSkinnedMesh; bool *Moved; core::vector3df StaticPos; core::vector3df StaticNormal; }; //! Animation keyframe which describes a new position struct SPositionKey { f32 frame; core::vector3df position; }; //! Animation keyframe which describes a new scale struct SScaleKey { f32 frame; core::vector3df scale; }; //! Animation keyframe which describes a new rotation struct SRotationKey { f32 frame; core::quaternion rotation; }; //! Joints struct SJoint { SJoint() : UseAnimationFrom(0), GlobalSkinningSpace(false), positionHint(-1),scaleHint(-1),rotationHint(-1) { } //! The name of this joint core::stringc Name; //! Local matrix of this joint core::matrix4 LocalMatrix; //! List of child joints core::array Children; //! List of attached meshes core::array AttachedMeshes; //! Animation keys causing translation change core::array PositionKeys; //! Animation keys causing scale change core::array ScaleKeys; //! Animation keys causing rotation change core::array RotationKeys; //! Skin weights core::array Weights; //! Unnecessary for loaders, will be overwritten on finalize core::matrix4 GlobalMatrix; core::matrix4 GlobalAnimatedMatrix; core::matrix4 LocalAnimatedMatrix; core::vector3df Animatedposition; core::vector3df Animatedscale; core::quaternion Animatedrotation; core::matrix4 GlobalInversedMatrix; //the x format pre-calculates this private: //! Internal members used by CSkinnedMesh friend class CSkinnedMesh; SJoint *UseAnimationFrom; bool GlobalSkinningSpace; s32 positionHint; s32 scaleHint; s32 rotationHint; }; //Interface for the mesh loaders (finalize should lock these functions, and they should have some prefix like loader_ //these functions will use the needed arrays, set values, etc to help the loaders //! exposed for loaders: to add mesh buffers virtual core::array& getMeshBuffers() = 0; //! exposed for loaders: joints list virtual core::array& getAllJoints() = 0; //! exposed for loaders: joints list virtual const core::array& getAllJoints() const = 0; //! loaders should call this after populating the mesh virtual void finalize() = 0; //! Adds a new meshbuffer to the mesh, access it as last one virtual SSkinMeshBuffer* addMeshBuffer() = 0; //! Adds a new joint to the mesh, access it as last one virtual SJoint* addJoint(SJoint *parent=0) = 0; //! Adds a new weight to the mesh, access it as last one virtual SWeight* addWeight(SJoint *joint) = 0; //! Adds a new position key to the mesh, access it as last one virtual SPositionKey* addPositionKey(SJoint *joint) = 0; //! Adds a new scale key to the mesh, access it as last one virtual SScaleKey* addScaleKey(SJoint *joint) = 0; //! Adds a new rotation key to the mesh, access it as last one virtual SRotationKey* addRotationKey(SJoint *joint) = 0; //! Check if the mesh is non-animated virtual bool isStatic()=0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IShadowVolumeSceneNode.h0000644000000000000000000000175712574354552020175 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SHADOW_VOLUME_SCENE_NODE_H_INCLUDED__ #define __I_SHADOW_VOLUME_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" namespace irr { namespace scene { class IMesh; //! Scene node for rendering a shadow volume into a stencil buffer. class IShadowVolumeSceneNode : public ISceneNode { public: //! constructor IShadowVolumeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id) : ISceneNode(parent, mgr, id) {} //! Sets the mesh from which the shadow volume should be generated. /** To optimize shadow rendering, use a simpler mesh for shadows. */ virtual void setShadowMesh(const IMesh* mesh) = 0; //! Updates the shadow volumes for current light positions. virtual void updateShadowVolumes() = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IShaderConstantSetCallBack.h0000644000000000000000000000613612574354552020741 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SHADER_CONSTANT_SET_CALLBACT_H_INCLUDED__ #define __I_SHADER_CONSTANT_SET_CALLBACT_H_INCLUDED__ #include "IReferenceCounted.h" namespace irr { namespace video { class IMaterialRendererServices; class SMaterial; //! Interface making it possible to set constants for gpu programs every frame. /** Implement this interface in an own class and pass a pointer to it to one of the methods in IGPUProgrammingServices when creating a shader. The OnSetConstants method will be called every frame now. */ class IShaderConstantSetCallBack : public virtual IReferenceCounted { public: //! Called to let the callBack know the used material (optional method) /** \code class MyCallBack : public IShaderConstantSetCallBack { const video::SMaterial *UsedMaterial; OnSetMaterial(const video::SMaterial& material) { UsedMaterial=&material; } OnSetConstants(IMaterialRendererServices* services, s32 userData) { services->setVertexShaderConstant("myColor", reinterpret_cast(&UsedMaterial->color), 4); } } \endcode */ virtual void OnSetMaterial(const SMaterial& material) { } //! Called by the engine when the vertex and/or pixel shader constants for an material renderer should be set. /** Implement the IShaderConstantSetCallBack in an own class and implement your own OnSetConstants method using the given IMaterialRendererServices interface. Pass a pointer to this class to one of the methods in IGPUProgrammingServices when creating a shader. The OnSetConstants method will now be called every time before geometry is being drawn using your shader material. A sample implementation would look like this: \code virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData) { video::IVideoDriver* driver = services->getVideoDriver(); // set clip matrix at register 4 core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION)); worldViewProj *= driver->getTransform(video::ETS_VIEW); worldViewProj *= driver->getTransform(video::ETS_WORLD); services->setVertexShaderConstant(&worldViewProj.M[0], 4, 4); // for high level shading languages, this would be another solution: //services->setVertexShaderConstant("mWorldViewProj", worldViewProj.M, 16); // set some light color at register 9 video::SColorf col(0.0f,1.0f,1.0f,0.0f); services->setVertexShaderConstant(reinterpret_cast(&col), 9, 1); // for high level shading languages, this would be another solution: //services->setVertexShaderConstant("myColor", reinterpret_cast(&col), 4); } \endcode \param services: Pointer to an interface providing methods to set the constants for the shader. \param userData: Userdata int which can be specified when creating the shader. */ virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData) = 0; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/ISceneUserDataSerializer.h0000644000000000000000000000362112574354552020504 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_USER_DATA_SERIALIZER_H_INCLUDED__ #define __I_SCENE_USER_DATA_SERIALIZER_H_INCLUDED__ #include "IReferenceCounted.h" namespace irr { namespace io { class IAttributes; } // end namespace io namespace scene { class ISceneNode; //! Interface to read and write user data to and from .irr files. /** This interface is to be implemented by the user, to make it possible to read and write user data when reading or writing .irr files via ISceneManager. To be used with ISceneManager::loadScene() and ISceneManager::saveScene() */ class ISceneUserDataSerializer { public: virtual ~ISceneUserDataSerializer() {} //! Called when the scene manager create a scene node while loading a file. virtual void OnCreateNode(ISceneNode* node) = 0; //! Called when the scene manager read a scene node while loading a file. /** The userData pointer contains a list of attributes with userData which were attached to the scene node in the read scene file.*/ virtual void OnReadUserData(ISceneNode* forSceneNode, io::IAttributes* userData) = 0; //! Called when the scene manager is writing a scene node to an xml file for example. /** Implement this method and return a list of attributes containing the user data you want to be saved together with the scene node. Return 0 if no user data should be added. Please note that the scene manager will call drop() to the returned pointer after it no longer needs it, so if you didn't create a new object for the return value and returning a longer existing IAttributes object, simply call grab() before returning it. */ virtual io::IAttributes* createUserData(ISceneNode* forSceneNode) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ISceneNodeFactory.h0000644000000000000000000000605312574354552017161 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_NODE_FACTORY_H_INCLUDED__ #define __I_SCENE_NODE_FACTORY_H_INCLUDED__ #include "IReferenceCounted.h" #include "ESceneNodeTypes.h" namespace irr { namespace scene { class ISceneNode; //! Interface for dynamic creation of scene nodes /** To be able to add custom scene nodes to Irrlicht and to make it possible for the scene manager to save and load those external scene nodes, simply implement this interface and register it in you scene manager via ISceneManager::registerSceneNodeFactory. Note: When implementing your own scene node factory, don't call ISceneNodeManager::grab() to increase the reference counter of the scene node manager. This is not necessary because the scene node manager will grab() the factory anyway, and otherwise cyclic references will be created and the scene manager and all its nodes won't get deallocated. */ class ISceneNodeFactory : public virtual IReferenceCounted { public: //! adds a scene node to the scene graph based on its type id /** \param type: Type of the scene node to add. \param parent: Parent scene node of the new node, can be null to add the scene node to the root. \return Returns pointer to the new scene node or null if not successful. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addSceneNode(ESCENE_NODE_TYPE type, ISceneNode* parent=0) = 0; //! adds a scene node to the scene graph based on its type name /** \param typeName: Type name of the scene node to add. \param parent: Parent scene node of the new node, can be null to add the scene node to the root. \return Returns pointer to the new scene node or null if not successful. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addSceneNode(const c8* typeName, ISceneNode* parent=0) = 0; //! returns amount of scene node types this factory is able to create virtual u32 getCreatableSceneNodeTypeCount() const = 0; //! returns type of a createable scene node type /** \param idx: Index of scene node type in this factory. Must be a value between 0 and getCreatableSceneNodeTypeCount() */ virtual ESCENE_NODE_TYPE getCreateableSceneNodeType(u32 idx) const = 0; //! returns type name of a createable scene node type by index /** \param idx: Index of scene node type in this factory. Must be a value between 0 and getCreatableSceneNodeTypeCount() */ virtual const c8* getCreateableSceneNodeTypeName(u32 idx) const = 0; //! returns type name of a createable scene node type /** \param type: Type of scene node. \return: Returns name of scene node type if this factory can create the type, otherwise 0. */ virtual const c8* getCreateableSceneNodeTypeName(ESCENE_NODE_TYPE type) const = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ISceneNodeAnimatorFactory.h0000644000000000000000000000635112574354552020655 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_NODE_ANIMATOR_FACTORY_H_INCLUDED__ #define __I_SCENE_NODE_ANIMATOR_FACTORY_H_INCLUDED__ #include "IReferenceCounted.h" #include "ESceneNodeAnimatorTypes.h" namespace irr { namespace scene { class ISceneNode; class ISceneNodeAnimator; //! Interface for dynamic creation of scene node animators /** To be able to add custom scene node animators to Irrlicht and to make it possible for the scene manager to save and load those external animators, simply implement this interface and register it in you scene manager via ISceneManager::registerSceneNodeAnimatorFactory. Note: When implementing your own scene node factory, don't call ISceneNodeManager::grab() to increase the reference counter of the scene node manager. This is not necessary because the scene node manager will grab() the factory anyway, and otherwise cyclic references will be created and the scene manager and all its nodes won't get deallocated. */ class ISceneNodeAnimatorFactory : public virtual IReferenceCounted { public: //! creates a scene node animator based on its type id /** \param type: Type of the scene node animator to add. \param target: Target scene node of the new animator. \return Returns pointer to the new scene node animator or null if not successful. You need to drop this pointer after calling this, see IReferenceCounted::drop() for details. */ virtual ISceneNodeAnimator* createSceneNodeAnimator(ESCENE_NODE_ANIMATOR_TYPE type, ISceneNode* target) = 0; //! creates a scene node animator based on its type name /** \param typeName: Type of the scene node animator to add. \param target: Target scene node of the new animator. \return Returns pointer to the new scene node animator or null if not successful. You need to drop this pointer after calling this, see IReferenceCounted::drop() for details. */ virtual ISceneNodeAnimator* createSceneNodeAnimator(const c8* typeName, ISceneNode* target) = 0; //! returns amount of scene node animator types this factory is able to create virtual u32 getCreatableSceneNodeAnimatorTypeCount() const = 0; //! returns type of a createable scene node animator type /** \param idx: Index of scene node animator type in this factory. Must be a value between 0 and getCreatableSceneNodeTypeCount() */ virtual ESCENE_NODE_ANIMATOR_TYPE getCreateableSceneNodeAnimatorType(u32 idx) const = 0; //! returns type name of a createable scene node animator type /** \param idx: Index of scene node animator type in this factory. Must be a value between 0 and getCreatableSceneNodeAnimatorTypeCount() */ virtual const c8* getCreateableSceneNodeAnimatorTypeName(u32 idx) const = 0; //! returns type name of a createable scene node animator type /** \param type: Type of scene node animator. \return: Returns name of scene node animator type if this factory can create the type, otherwise 0. */ virtual const c8* getCreateableSceneNodeAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ISceneNodeAnimatorCollisionResponse.h0000644000000000000000000001666012574354552022724 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_NODE_ANIMATOR_COLLISION_RESPONSE_H_INCLUDED__ #define __I_SCENE_NODE_ANIMATOR_COLLISION_RESPONSE_H_INCLUDED__ #include "ISceneNode.h" namespace irr { namespace scene { class ISceneNodeAnimatorCollisionResponse; //! Callback interface for catching events of collisions. /** Implement this interface and use ISceneNodeAnimatorCollisionResponse::setCollisionCallback to be able to be notified if a collision has occurred. **/ class ICollisionCallback : public virtual IReferenceCounted { public: //! Will be called when a collision occurrs. /** See ISceneNodeAnimatorCollisionResponse::setCollisionCallback for more information. \param animator: Collision response animator in which the collision occurred. You can call this animator's methods to find the node, collisionPoint and/or collision triangle. \retval true if the collision was handled in the animator. The animator's target node will *not* be stopped at the collision point, but will instead move fully to the location that triggered the collision check. \retval false if the collision was not handled in the animator. The animator's target node will be moved to the collision position. */ virtual bool onCollision(const ISceneNodeAnimatorCollisionResponse& animator) = 0; }; //! Special scene node animator for doing automatic collision detection and response. /** This scene node animator can be attached to any single scene node and will then prevent it from moving through specified collision geometry (e.g. walls and floors of the) world, as well as having it fall under gravity. This animator provides a simple implementation of first person shooter cameras. Attach it to a camera, and the camera will behave as the player control in a first person shooter game: The camera stops and slides at walls, walks up stairs, falls down if there is no floor under it, and so on. The animator will treat any change in the position of its target scene node as movement, including a setPosition(), as movement. If you want to teleport the target scene node manually to a location without it being effected by collision geometry, then call setTargetNode(node) after calling node->setPosition(). */ class ISceneNodeAnimatorCollisionResponse : public ISceneNodeAnimator { public: //! Destructor virtual ~ISceneNodeAnimatorCollisionResponse() {} //! Check if the attached scene node is falling. /** Falling means that there is no blocking wall from the scene node in the direction of the gravity. The implementation of this method is very fast, no collision detection is done when invoking it. \return True if the scene node is falling, false if not. */ virtual bool isFalling() const = 0; //! Sets the radius of the ellipsoid for collision detection and response. /** If you have a scene node, and you are unsure about how big the radius should be, you could use the following code to determine it: \code core::aabbox box = yourSceneNode->getBoundingBox(); core::vector3df radius = box.MaxEdge - box.getCenter(); \endcode \param radius: New radius of the ellipsoid. */ virtual void setEllipsoidRadius(const core::vector3df& radius) = 0; //! Returns the radius of the ellipsoid for collision detection and response. /** \return Radius of the ellipsoid. */ virtual core::vector3df getEllipsoidRadius() const = 0; //! Sets the gravity of the environment. /** A good example value would be core::vector3df(0,-100.0f,0) for letting gravity affect all object to fall down. For bigger gravity, make increase the length of the vector. You can disable gravity by setting it to core::vector3df(0,0,0); \param gravity: New gravity vector. */ virtual void setGravity(const core::vector3df& gravity) = 0; //! Get current vector of gravity. //! \return Gravity vector. */ virtual core::vector3df getGravity() const = 0; //! 'Jump' the animator, by adding a jump speed opposite to its gravity /** \param jumpSpeed The initial speed of the jump; the velocity will be opposite to this animator's gravity vector. */ virtual void jump(f32 jumpSpeed) = 0; //! Should the Target react on collision ( default = true ) virtual void setAnimateTarget ( bool enable ) = 0; virtual bool getAnimateTarget () const = 0; //! Set translation of the collision ellipsoid. /** By default, the ellipsoid for collision detection is created around the center of the scene node, which means that the ellipsoid surrounds it completely. If this is not what you want, you may specify a translation for the ellipsoid. \param translation: Translation of the ellipsoid relative to the position of the scene node. */ virtual void setEllipsoidTranslation(const core::vector3df &translation) = 0; //! Get the translation of the ellipsoid for collision detection. /** See ISceneNodeAnimatorCollisionResponse::setEllipsoidTranslation() for more details. \return Translation of the ellipsoid relative to the position of the scene node. */ virtual core::vector3df getEllipsoidTranslation() const = 0; //! Sets a triangle selector holding all triangles of the world with which the scene node may collide. /** \param newWorld: New triangle selector containing triangles to let the scene node collide with. */ virtual void setWorld(ITriangleSelector* newWorld) = 0; //! Get the current triangle selector containing all triangles for collision detection. virtual ITriangleSelector* getWorld() const = 0; //! Set the single node that this animator will act on. /** \param node The new target node. Setting this will force the animator to update its last target position for the node, allowing setPosition() to teleport the node through collision geometry. */ virtual void setTargetNode(ISceneNode * node) = 0; //! Gets the single node that this animator is acting on. /** \return The node that this animator is acting on. */ virtual ISceneNode* getTargetNode(void) const = 0; //! Returns true if a collision occurred during the last animateNode() virtual bool collisionOccurred() const = 0; //! Returns the last point of collision. virtual const core::vector3df & getCollisionPoint() const = 0; //! Returns the last triangle that caused a collision virtual const core::triangle3df & getCollisionTriangle() const = 0; //! Returns the position that the target node will be moved to, unless the collision is consumed in a callback. /** If you have a collision callback registered, and it consumes the collision, then the node will ignore the collision and will not stop at this position. Instead, it will move fully to the position that caused the collision to occur. */ virtual const core::vector3df & getCollisionResultPosition(void) const = 0; //! Returns the node that was collided with. virtual ISceneNode* getCollisionNode(void) const = 0; //! Sets a callback interface which will be called if a collision occurs. /** \param callback: collision callback handler that will be called when a collision occurs. Set this to 0 to disable the callback. */ virtual void setCollisionCallback(ICollisionCallback* callback) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ISceneNodeAnimatorCameraMaya.h0000644000000000000000000000313612574354552021244 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_NODE_ANIMATOR_CAMERA_MAYA_H_INCLUDED__ #define __I_SCENE_NODE_ANIMATOR_CAMERA_MAYA_H_INCLUDED__ #include "ISceneNodeAnimator.h" namespace irr { namespace scene { //! Special scene node animator for Maya-style cameras /** This scene node animator can be attached to a camera to make it act like a 3d modelling tool. The camera is moving relative to the target with the mouse, by pressing either of the three buttons. In order to move the camera, set a new target for the camera. The distance defines the current orbit radius the camera moves on. Distance can be changed via the setter or by mouse events. */ class ISceneNodeAnimatorCameraMaya : public ISceneNodeAnimator { public: //! Returns the speed of movement virtual f32 getMoveSpeed() const = 0; //! Sets the speed of movement virtual void setMoveSpeed(f32 moveSpeed) = 0; //! Returns the rotation speed virtual f32 getRotateSpeed() const = 0; //! Set the rotation speed virtual void setRotateSpeed(f32 rotateSpeed) = 0; //! Returns the zoom speed virtual f32 getZoomSpeed() const = 0; //! Set the zoom speed virtual void setZoomSpeed(f32 zoomSpeed) = 0; //! Returns the current distance, i.e. orbit radius virtual f32 getDistance() const = 0; //! Set the distance virtual void setDistance(f32 distance) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ISceneNodeAnimatorCameraFPS.h0000644000000000000000000000446612574354552021014 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ #define __I_SCENE_NODE_ANIMATOR_CAMERA_FPS_H_INCLUDED__ #include "ISceneNodeAnimator.h" #include "IEventReceiver.h" #include "irrArray.h" namespace irr { struct SKeyMap; namespace scene { //! Special scene node animator for FPS cameras /** This scene node animator can be attached to a camera to make it act like a first person shooter */ class ISceneNodeAnimatorCameraFPS : public ISceneNodeAnimator { public: //! Returns the speed of movement in units per millisecond virtual f32 getMoveSpeed() const = 0; //! Sets the speed of movement in units per millisecond virtual void setMoveSpeed(f32 moveSpeed) = 0; //! Returns the rotation speed in degrees /** The degrees are equivalent to a half screen movement of the mouse, i.e. if the mouse cursor had been moved to the border of the screen since the last animation. */ virtual f32 getRotateSpeed() const = 0; //! Set the rotation speed in degrees virtual void setRotateSpeed(f32 rotateSpeed) = 0; //! Sets the keyboard mapping for this animator (old style) /** \param map Array of keyboard mappings, see irr::SKeyMap \param count Size of the keyboard map array. */ virtual void setKeyMap(SKeyMap *map, u32 count) = 0; //! Sets the keyboard mapping for this animator //! \param keymap The new keymap array virtual void setKeyMap(const core::array& keymap) = 0; //! Gets the keyboard mapping for this animator virtual const core::array& getKeyMap() const = 0; //! Sets whether vertical movement should be allowed. /** If vertical movement is enabled then the camera may fight with gravity causing camera shake. Disable this if the camera has a collision animator with gravity enabled. */ virtual void setVerticalMovement(bool allow) = 0; //! Sets whether the Y axis of the mouse should be inverted. /** If enabled then moving the mouse down will cause the camera to look up. It is disabled by default. */ virtual void setInvertMouse(bool invert) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ISceneNodeAnimator.h0000644000000000000000000000450212574354552017321 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_NODE_ANIMATOR_H_INCLUDED__ #define __I_SCENE_NODE_ANIMATOR_H_INCLUDED__ #include "IReferenceCounted.h" #include "vector3d.h" #include "ESceneNodeAnimatorTypes.h" #include "IAttributeExchangingObject.h" #include "IEventReceiver.h" namespace irr { namespace io { class IAttributes; } // end namespace io namespace scene { class ISceneNode; class ISceneManager; //! Animates a scene node. Can animate position, rotation, material, and so on. /** A scene node animator is able to animate a scene node in a very simple way. It may change its position, rotation, scale and/or material. There are lots of animators to choose from. You can create scene node animators with the ISceneManager interface. */ class ISceneNodeAnimator : public io::IAttributeExchangingObject, public IEventReceiver { public: //! Animates a scene node. /** \param node Node to animate. \param timeMs Current time in milli seconds. */ virtual void animateNode(ISceneNode* node, u32 timeMs) =0; //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer after calling this. */ virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0) =0; //! Returns true if this animator receives events. /** When attached to an active camera, this animator will be able to respond to events such as mouse and keyboard events. */ virtual bool isEventReceiverEnabled() const { return false; } //! Event receiver, override this function for camera controlling animators virtual bool OnEvent(const SEvent& event) { return false; } //! Returns type of the scene node animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_UNKNOWN; } //! Returns if the animator has finished. /** This is only valid for non-looping animators with a discrete end state. \return true if the animator has finished, false if it is still running. */ virtual bool hasFinished(void) const { return false; } }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ISceneNode.h0000644000000000000000000006357312574354552015643 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_NODE_H_INCLUDED__ #define __I_SCENE_NODE_H_INCLUDED__ #include "IAttributeExchangingObject.h" #include "ESceneNodeTypes.h" #include "ECullingTypes.h" #include "EDebugSceneTypes.h" #include "ISceneNodeAnimator.h" #include "ITriangleSelector.h" #include "SMaterial.h" #include "irrString.h" #include "aabbox3d.h" #include "matrix4.h" #include "irrList.h" #include "IAttributes.h" namespace irr { namespace scene { class ISceneManager; //! Typedef for list of scene nodes typedef core::list ISceneNodeList; //! Typedef for list of scene node animators typedef core::list ISceneNodeAnimatorList; //! Scene node interface. /** A scene node is a node in the hierarchical scene graph. Every scene node may have children, which are also scene nodes. Children move relative to their parent's position. If the parent of a node is not visible, its children won't be visible either. In this way, it is for example easily possible to attach a light to a moving car, or to place a walking character on a moving platform on a moving ship. */ class ISceneNode : virtual public io::IAttributeExchangingObject { public: //! Constructor ISceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) : RelativeTranslation(position), RelativeRotation(rotation), RelativeScale(scale), Parent(0), SceneManager(mgr), TriangleSelector(0), ID(id), AutomaticCullingState(EAC_BOX), DebugDataVisible(EDS_OFF), IsVisible(true), IsDebugObject(false) { if (parent) parent->addChild(this); updateAbsolutePosition(); } //! Destructor virtual ~ISceneNode() { // delete all children removeAll(); // delete all animators ISceneNodeAnimatorList::Iterator ait = Animators.begin(); for (; ait != Animators.end(); ++ait) (*ait)->drop(); if (TriangleSelector) TriangleSelector->drop(); } //! This method is called just before the rendering process of the whole scene. /** Nodes may register themselves in the render pipeline during this call, precalculate the geometry which should be renderered, and prevent their children from being able to register themselves if they are clipped by simply not calling their OnRegisterSceneNode method. If you are implementing your own scene node, you should overwrite this method with an implementation code looking like this: \code if (IsVisible) SceneManager->registerNodeForRendering(this); ISceneNode::OnRegisterSceneNode(); \endcode */ virtual void OnRegisterSceneNode() { if (IsVisible) { ISceneNodeList::Iterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->OnRegisterSceneNode(); } } //! OnAnimate() is called just before rendering the whole scene. /** Nodes may calculate or store animations here, and may do other useful things, depending on what they are. Also, OnAnimate() should be called for all child scene nodes here. This method will be called once per frame, independent of whether the scene node is visible or not. \param timeMs Current time in milliseconds. */ virtual void OnAnimate(u32 timeMs) { if (IsVisible) { // animate this node with all animators ISceneNodeAnimatorList::Iterator ait = Animators.begin(); while (ait != Animators.end()) { // continue to the next node before calling animateNode() // so that the animator may remove itself from the scene // node without the iterator becoming invalid ISceneNodeAnimator* anim = *ait; ++ait; anim->animateNode(this, timeMs); } // update absolute position updateAbsolutePosition(); // perform the post render process on all children ISceneNodeList::Iterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->OnAnimate(timeMs); } } //! Renders the node. virtual void render() = 0; //! Returns the name of the node. /** \return Name as character string. */ virtual const c8* getName() const { return Name.c_str(); } //! Sets the name of the node. /** \param name New name of the scene node. */ virtual void setName(const c8* name) { Name = name; } //! Sets the name of the node. /** \param name New name of the scene node. */ virtual void setName(const core::stringc& name) { Name = name; } //! Get the axis aligned, not transformed bounding box of this node. /** This means that if this node is an animated 3d character, moving in a room, the bounding box will always be around the origin. To get the box in real world coordinates, just transform it with the matrix you receive with getAbsoluteTransformation() or simply use getTransformedBoundingBox(), which does the same. \return The non-transformed bounding box. */ virtual const core::aabbox3d& getBoundingBox() const = 0; //! Get the axis aligned, transformed and animated absolute bounding box of this node. /** \return The transformed bounding box. */ virtual const core::aabbox3d getTransformedBoundingBox() const { core::aabbox3d box = getBoundingBox(); AbsoluteTransformation.transformBoxEx(box); return box; } //! Get the absolute transformation of the node. Is recalculated every OnAnimate()-call. /** NOTE: For speed reasons the absolute transformation is not automatically recalculated on each change of the relative transformation or by a transformation change of an parent. Instead the update usually happens once per frame in OnAnimate. You can enforce an update with updateAbsolutePosition(). \return The absolute transformation matrix. */ virtual const core::matrix4& getAbsoluteTransformation() const { return AbsoluteTransformation; } //! Returns the relative transformation of the scene node. /** The relative transformation is stored internally as 3 vectors: translation, rotation and scale. To get the relative transformation matrix, it is calculated from these values. \return The relative transformation matrix. */ virtual core::matrix4 getRelativeTransformation() const { core::matrix4 mat; mat.setRotationDegrees(RelativeRotation); mat.setTranslation(RelativeTranslation); if (RelativeScale != core::vector3df(1.f,1.f,1.f)) { core::matrix4 smat; smat.setScale(RelativeScale); mat *= smat; } return mat; } //! Returns whether the node should be visible (if all of its parents are visible). /** This is only an option set by the user, but has nothing to do with geometry culling \return The requested visibility of the node, true means visible (if all parents are also visible). */ virtual bool isVisible() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return IsVisible; } //! Check whether the node is truly visible, taking into accounts its parents' visibility /** \return true if the node and all its parents are visible, false if this or any parent node is invisible. */ virtual bool isTrulyVisible() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; if(!IsVisible) return false; if(!Parent) return true; return Parent->isTrulyVisible(); } //! Sets if the node should be visible or not. /** All children of this node won't be visible either, when set to false. Invisible nodes are not valid candidates for selection by collision manager bounding box methods. \param isVisible If the node shall be visible. */ virtual void setVisible(bool isVisible) { IsVisible = isVisible; } //! Get the id of the scene node. /** This id can be used to identify the node. \return The id. */ virtual s32 getID() const { return ID; } //! Sets the id of the scene node. /** This id can be used to identify the node. \param id The new id. */ virtual void setID(s32 id) { ID = id; } //! Adds a child to this scene node. /** If the scene node already has a parent it is first removed from the other parent. \param child A pointer to the new child. */ virtual void addChild(ISceneNode* child) { if (child && (child != this)) { // Change scene manager? if (SceneManager != child->SceneManager) child->setSceneManager(SceneManager); child->grab(); child->remove(); // remove from old parent Children.push_back(child); child->Parent = this; } } //! Removes a child from this scene node. /** If found in the children list, the child pointer is also dropped and might be deleted if no other grab exists. \param child A pointer to the child which shall be removed. \return True if the child was removed, and false if not, e.g. because it couldn't be found in the children list. */ virtual bool removeChild(ISceneNode* child) { ISceneNodeList::Iterator it = Children.begin(); for (; it != Children.end(); ++it) if ((*it) == child) { (*it)->Parent = 0; (*it)->drop(); Children.erase(it); return true; } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } //! Removes all children of this scene node /** The scene nodes found in the children list are also dropped and might be deleted if no other grab exists on them. */ virtual void removeAll() { ISceneNodeList::Iterator it = Children.begin(); for (; it != Children.end(); ++it) { (*it)->Parent = 0; (*it)->drop(); } Children.clear(); } //! Removes this scene node from the scene /** If no other grab exists for this node, it will be deleted. */ virtual void remove() { if (Parent) Parent->removeChild(this); } //! Adds an animator which should animate this node. /** \param animator A pointer to the new animator. */ virtual void addAnimator(ISceneNodeAnimator* animator) { if (animator) { Animators.push_back(animator); animator->grab(); } } //! Get a list of all scene node animators. /** \return The list of animators attached to this node. */ const core::list& getAnimators() const { return Animators; } //! Removes an animator from this scene node. /** If the animator is found, it is also dropped and might be deleted if not other grab exists for it. \param animator A pointer to the animator to be deleted. */ virtual void removeAnimator(ISceneNodeAnimator* animator) { ISceneNodeAnimatorList::Iterator it = Animators.begin(); for (; it != Animators.end(); ++it) { if ((*it) == animator) { (*it)->drop(); Animators.erase(it); return; } } } //! Removes all animators from this scene node. /** The animators might also be deleted if no other grab exists for them. */ virtual void removeAnimators() { ISceneNodeAnimatorList::Iterator it = Animators.begin(); for (; it != Animators.end(); ++it) (*it)->drop(); Animators.clear(); } //! Returns the material based on the zero based index i. /** To get the amount of materials used by this scene node, use getMaterialCount(). This function is needed for inserting the node into the scene hierarchy at an optimal position for minimizing renderstate changes, but can also be used to directly modify the material of a scene node. \param num Zero based index. The maximal value is getMaterialCount() - 1. \return The material at that index. */ virtual video::SMaterial& getMaterial(u32 num) { return video::IdentityMaterial; } //! Get amount of materials used by this scene node. /** \return Current amount of materials of this scene node. */ virtual u32 getMaterialCount() const { return 0; } //! Sets all material flags at once to a new value. /** Useful, for example, if you want the whole mesh to be affected by light. \param flag Which flag of all materials to be set. \param newvalue New value of that flag. */ void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) { for (u32 i=0; i= video::MATERIAL_MAX_TEXTURES) return; for (u32 i=0; i& getChildren() const { return Children; } //! Changes the parent of the scene node. /** \param newParent The new parent to be used. */ virtual void setParent(ISceneNode* newParent) { grab(); remove(); Parent = newParent; if (Parent) Parent->addChild(this); drop(); } //! Returns the triangle selector attached to this scene node. /** The Selector can be used by the engine for doing collision detection. You can create a TriangleSelector with ISceneManager::createTriangleSelector() or ISceneManager::createOctreeTriangleSelector and set it with ISceneNode::setTriangleSelector(). If a scene node got no triangle selector, but collision tests should be done with it, a triangle selector is created using the bounding box of the scene node. \return A pointer to the TriangleSelector or 0, if there is none. */ virtual ITriangleSelector* getTriangleSelector() const { return TriangleSelector; } //! Sets the triangle selector of the scene node. /** The Selector can be used by the engine for doing collision detection. You can create a TriangleSelector with ISceneManager::createTriangleSelector() or ISceneManager::createOctreeTriangleSelector(). Some nodes may create their own selector by default, so it would be good to check if there is already a selector in this node by calling ISceneNode::getTriangleSelector(). \param selector New triangle selector for this scene node. */ virtual void setTriangleSelector(ITriangleSelector* selector) { if (TriangleSelector != selector) { if (TriangleSelector) TriangleSelector->drop(); TriangleSelector = selector; if (TriangleSelector) TriangleSelector->grab(); } } //! Updates the absolute position based on the relative and the parents position /** Note: This does not recursively update the parents absolute positions, so if you have a deeper hierarchy you might want to update the parents first.*/ virtual void updateAbsolutePosition() { if (Parent) { AbsoluteTransformation = Parent->getAbsoluteTransformation() * getRelativeTransformation(); } else AbsoluteTransformation = getRelativeTransformation(); } //! Returns the parent of this scene node /** \return A pointer to the parent. */ scene::ISceneNode* getParent() const { return Parent; } //! Returns type of the scene node /** \return The type of this node. */ virtual ESCENE_NODE_TYPE getType() const { return ESNT_UNKNOWN; } //! Writes attributes of the scene node. /** Implement this to expose the attributes of your scene node for scripting languages, editors, debuggers or xml serialization purposes. \param out The attribute container to write into. \param options Additional options which might influence the serialization. */ virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { if (!out) return; out->addString ("Name", Name.c_str()); out->addInt ("Id", ID ); out->addVector3d("Position", getPosition() ); out->addVector3d("Rotation", getRotation() ); out->addVector3d("Scale", getScale() ); out->addBool ("Visible", IsVisible ); out->addInt ("AutomaticCulling", AutomaticCullingState); out->addInt ("DebugDataVisible", DebugDataVisible ); out->addBool ("IsDebugObject", IsDebugObject ); } //! Reads attributes of the scene node. /** Implement this to set the attributes of your scene node for scripting languages, editors, debuggers or xml deserialization purposes. \param in The attribute container to read from. \param options Additional options which might influence the deserialization. */ virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { if (!in) return; Name = in->getAttributeAsString("Name"); ID = in->getAttributeAsInt("Id"); setPosition(in->getAttributeAsVector3d("Position")); setRotation(in->getAttributeAsVector3d("Rotation")); setScale(in->getAttributeAsVector3d("Scale")); IsVisible = in->getAttributeAsBool("Visible"); s32 tmpState = in->getAttributeAsEnumeration("AutomaticCulling", scene::AutomaticCullingNames); if (tmpState != -1) AutomaticCullingState = (u32)tmpState; else AutomaticCullingState = in->getAttributeAsInt("AutomaticCulling"); DebugDataVisible = in->getAttributeAsInt("DebugDataVisible"); IsDebugObject = in->getAttributeAsBool("IsDebugObject"); updateAbsolutePosition(); } //! Creates a clone of this scene node and its children. /** \param newParent An optional new parent. \param newManager An optional new scene manager. \return The newly created clone of this node. */ virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) { return 0; // to be implemented by derived classes } //! Retrieve the scene manager for this node. /** \return The node's scene manager. */ virtual ISceneManager* getSceneManager(void) const { return SceneManager; } protected: //! A clone function for the ISceneNode members. /** This method can be used by clone() implementations of derived classes \param toCopyFrom The node from which the values are copied \param newManager The new scene manager. */ void cloneMembers(ISceneNode* toCopyFrom, ISceneManager* newManager) { Name = toCopyFrom->Name; AbsoluteTransformation = toCopyFrom->AbsoluteTransformation; RelativeTranslation = toCopyFrom->RelativeTranslation; RelativeRotation = toCopyFrom->RelativeRotation; RelativeScale = toCopyFrom->RelativeScale; ID = toCopyFrom->ID; setTriangleSelector(toCopyFrom->TriangleSelector); AutomaticCullingState = toCopyFrom->AutomaticCullingState; DebugDataVisible = toCopyFrom->DebugDataVisible; IsVisible = toCopyFrom->IsVisible; IsDebugObject = toCopyFrom->IsDebugObject; if (newManager) SceneManager = newManager; else SceneManager = toCopyFrom->SceneManager; // clone children ISceneNodeList::Iterator it = toCopyFrom->Children.begin(); for (; it != toCopyFrom->Children.end(); ++it) (*it)->clone(this, newManager); // clone animators ISceneNodeAnimatorList::Iterator ait = toCopyFrom->Animators.begin(); for (; ait != toCopyFrom->Animators.end(); ++ait) { ISceneNodeAnimator* anim = (*ait)->createClone(this, SceneManager); if (anim) { addAnimator(anim); anim->drop(); } } } //! Sets the new scene manager for this node and all children. //! Called by addChild when moving nodes between scene managers void setSceneManager(ISceneManager* newManager) { SceneManager = newManager; ISceneNodeList::Iterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->setSceneManager(newManager); } //! Name of the scene node. core::stringc Name; //! Absolute transformation of the node. core::matrix4 AbsoluteTransformation; //! Relative translation of the scene node. core::vector3df RelativeTranslation; //! Relative rotation of the scene node. core::vector3df RelativeRotation; //! Relative scale of the scene node. core::vector3df RelativeScale; //! Pointer to the parent ISceneNode* Parent; //! List of all children of this node core::list Children; //! List of all animator nodes core::list Animators; //! Pointer to the scene manager ISceneManager* SceneManager; //! Pointer to the triangle selector ITriangleSelector* TriangleSelector; //! ID of the node. s32 ID; //! Automatic culling state u32 AutomaticCullingState; //! Flag if debug data should be drawn, such as Bounding Boxes. u32 DebugDataVisible; //! Is the node visible? bool IsVisible; //! Is debug object? bool IsDebugObject; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ISceneManager.h0000644000000000000000000025560412574354552016326 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_MANAGER_H_INCLUDED__ #define __I_SCENE_MANAGER_H_INCLUDED__ #include "IReferenceCounted.h" #include "irrArray.h" #include "irrString.h" #include "path.h" #include "vector3d.h" #include "dimension2d.h" #include "SColor.h" #include "ETerrainElements.h" #include "ESceneNodeTypes.h" #include "ESceneNodeAnimatorTypes.h" #include "EMeshWriterEnums.h" #include "SceneParameters.h" #include "IGeometryCreator.h" #include "ISkinnedMesh.h" namespace irr { struct SKeyMap; struct SEvent; namespace io { class IReadFile; class IAttributes; class IWriteFile; class IFileSystem; } // end namespace io namespace gui { class IGUIFont; class IGUIEnvironment; } // end namespace gui namespace video { class IVideoDriver; class SMaterial; class IImage; class ITexture; } // end namespace video namespace scene { //! Enumeration for render passes. /** A parameter passed to the registerNodeForRendering() method of the ISceneManager, specifying when the node wants to be drawn in relation to the other nodes. */ enum E_SCENE_NODE_RENDER_PASS { //! No pass currently active ESNRP_NONE =0, //! Camera pass. The active view is set up here. The very first pass. ESNRP_CAMERA =1, //! In this pass, lights are transformed into camera space and added to the driver ESNRP_LIGHT =2, //! This is used for sky boxes. ESNRP_SKY_BOX =4, //! All normal objects can use this for registering themselves. /** This value will never be returned by ISceneManager::getSceneNodeRenderPass(). The scene manager will determine by itself if an object is transparent or solid and register the object as SNRT_TRANSPARENT or SNRT_SOLD automatically if you call registerNodeForRendering with this value (which is default). Note that it will register the node only as ONE type. If your scene node has both solid and transparent material types register it twice (one time as SNRT_SOLID, the other time as SNRT_TRANSPARENT) and in the render() method call getSceneNodeRenderPass() to find out the current render pass and render only the corresponding parts of the node. */ ESNRP_AUTOMATIC =24, //! Solid scene nodes or special scene nodes without materials. ESNRP_SOLID =8, //! Transparent scene nodes, drawn after solid nodes. They are sorted from back to front and drawn in that order. ESNRP_TRANSPARENT =16, //! Transparent effect scene nodes, drawn after Transparent nodes. They are sorted from back to front and drawn in that order. ESNRP_TRANSPARENT_EFFECT =32, //! Drawn after the solid nodes, before the transparent nodes, the time for drawing shadow volumes ESNRP_SHADOW =64 }; class IAnimatedMesh; class IAnimatedMeshSceneNode; class IBillboardSceneNode; class IBillboardTextSceneNode; class ICameraSceneNode; class IDummyTransformationSceneNode; class ILightManager; class ILightSceneNode; class IMesh; class IMeshBuffer; class IMeshCache; class IMeshLoader; class IMeshManipulator; class IMeshSceneNode; class IMeshWriter; class IMetaTriangleSelector; class IParticleSystemSceneNode; class ISceneCollisionManager; class ISceneLoader; class ISceneNode; class ISceneNodeAnimator; class ISceneNodeAnimatorCollisionResponse; class ISceneNodeAnimatorFactory; class ISceneNodeFactory; class ISceneUserDataSerializer; class ITerrainSceneNode; class ITextSceneNode; class ITriangleSelector; class IVolumeLightSceneNode; namespace quake3 { struct IShader; } // end namespace quake3 //! The Scene Manager manages scene nodes, mesh recources, cameras and all the other stuff. /** All Scene nodes can be created only here. There is a always growing list of scene nodes for lots of purposes: Indoor rendering scene nodes like the Octree (addOctreeSceneNode()) or the terrain renderer (addTerrainSceneNode()), different Camera scene nodes (addCameraSceneNode(), addCameraSceneNodeMaya()), scene nodes for Light (addLightSceneNode()), Billboards (addBillboardSceneNode()) and so on. A scene node is a node in the hierachical scene graph. Every scene node may have children, which are other scene nodes. Children move relative the their parents position. If the parent of a node is not visible, its children won't be visible, too. In this way, it is for example easily possible to attach a light to a moving car or to place a walking character on a moving platform on a moving ship. The SceneManager is also able to load 3d mesh files of different formats. Take a look at getMesh() to find out what formats are supported. If these formats are not enough, use addExternalMeshLoader() to add new formats to the engine. */ class ISceneManager : public virtual IReferenceCounted { public: //! Get pointer to an animateable mesh. Loads the file if not loaded already. /** * If you want to remove a loaded mesh from the cache again, use removeMesh(). * Currently there are the following mesh formats supported: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
FormatDescription
3D Studio (.3ds)Loader for 3D-Studio files which lots of 3D packages * are able to export. Only static meshes are currently * supported by this importer.
3D World Studio (.smf)Loader for Leadwerks SMF mesh files, a simple mesh format * containing static geometry for games. The proprietary .STF texture format * is not supported yet. This loader was originally written by Joseph Ellis.
Bliz Basic B3D (.b3d)Loader for blitz basic files, developed by Mark * Sibly. This is the ideal animated mesh format for game * characters as it is both rigidly defined and widely * supported by modeling and animation software. * As this format supports skeletal animations, an * ISkinnedMesh will be returned by this importer.
Cartography shop 4 (.csm)Cartography Shop is a modeling program for creating * architecture and calculating lighting. Irrlicht can * directly import .csm files thanks to the IrrCSM library * created by Saurav Mohapatra which is now integrated * directly in Irrlicht. If you are using this loader, * please note that you'll have to set the path of the * textures before loading .csm files. You can do this * using * SceneManager->getParameters()->setAttribute(scene::CSM_TEXTURE_PATH, * "path/to/your/textures");
COLLADA (.dae, .xml)COLLADA is an open Digital Asset Exchange Schema for * the interactive 3D industry. There are exporters and * importers for this format available for most of the * big 3d packagesat http://collada.org. Irrlicht can * import COLLADA files by using the * ISceneManager::getMesh() method. COLLADA files need * not contain only one single mesh but multiple meshes * and a whole scene setup with lights, cameras and mesh * instances, this loader can set up a scene as * described by the COLLADA file instead of loading and * returning one single mesh. By default, this loader * behaves like the other loaders and does not create * instances, but it can be switched into this mode by * using * SceneManager->getParameters()->setAttribute(COLLADA_CREATE_SCENE_INSTANCES, true); * Created scene nodes will be named as the names of the * nodes in the COLLADA file. The returned mesh is just * a dummy object in this mode. Meshes included in the * scene will be added into the scene manager with the * following naming scheme: * "path/to/file/file.dea#meshname". The loading of such * meshes is logged. Currently, this loader is able to * create meshes (made of only polygons), lights, and * cameras. Materials and animations are currently not * supported but this will change with future releases. *
Delgine DeleD (.dmf)DeleD (delgine.com) is a 3D editor and level-editor * combined into one and is specifically designed for 3D * game-development. With this loader, it is possible to * directly load all geometry is as well as textures and * lightmaps from .dmf files. To set texture and * material paths, see scene::DMF_USE_MATERIALS_DIRS and * scene::DMF_TEXTURE_PATH. It is also possible to flip * the alpha texture by setting * scene::DMF_FLIP_ALPHA_TEXTURES to true and to set the * material transparent reference value by setting * scene::DMF_ALPHA_CHANNEL_REF to a float between 0 and * 1. The loader is based on Salvatore Russo's .dmf * loader, I just changed some parts of it. Thanks to * Salvatore for his work and for allowing me to use his * code in Irrlicht and put it under Irrlicht's license. * For newer and more enchanced versions of the loader, * take a look at delgine.com. *
DirectX (.x)Platform independent importer (so not D3D-only) for * .x files. Most 3D packages can export these natively * and there are several tools for them available, e.g. * the Maya exporter included in the DX SDK. * .x files can include skeletal animations and Irrlicht * is able to play and display them, users can manipulate * the joints via the ISkinnedMesh interface. Currently, * Irrlicht only supports uncompressed .x files.
Half-Life model (.mdl)This loader opens Half-life 1 models, it was contributed * by Fabio Concas and adapted by Thomas Alten.
Irrlicht Mesh (.irrMesh)This is a static mesh format written in XML, native * to Irrlicht and written by the irr mesh writer. * This format is exported by the CopperCube engine's * lightmapper.
LightWave (.lwo)Native to NewTek's LightWave 3D, the LWO format is well * known and supported by many exporters. This loader will * import LWO2 models including lightmaps, bumpmaps and * reflection textures.
Maya (.obj)Most 3D software can create .obj files which contain * static geometry without material data. The material * files .mtl are also supported. This importer for * Irrlicht can load them directly.
Milkshape (.ms3d).MS3D files contain models and sometimes skeletal * animations from the Milkshape 3D modeling and animation * software. Like the other skeletal mesh loaders, oints * are exposed via the ISkinnedMesh animated mesh type.
My3D (.my3d).my3D is a flexible 3D file format. The My3DTools * contains plug-ins to export .my3D files from several * 3D packages. With this built-in importer, Irrlicht * can read and display those files directly. This * loader was written by Zhuck Dimitry who also created * the whole My3DTools package. If you are using this * loader, please note that you can set the path of the * textures before loading .my3d files. You can do this * using * SceneManager->getParameters()->setAttribute(scene::MY3D_TEXTURE_PATH, * "path/to/your/textures"); *
OCT (.oct)The oct file format contains 3D geometry and * lightmaps and can be loaded directly by Irrlicht. OCT * files
can be created by FSRad, Paul Nette's * radiosity processor or exported from Blender using * OCTTools which can be found in the exporters/OCTTools * directory of the SDK. Thanks to Murphy McCauley for * creating all this.
OGRE Meshes (.mesh)Ogre .mesh files contain 3D data for the OGRE 3D * engine. Irrlicht can read and display them directly * with this importer. To define materials for the mesh, * copy a .material file named like the corresponding * .mesh file where the .mesh file is. (For example * ogrehead.material for ogrehead.mesh). Thanks to * Christian Stehno who wrote and contributed this * loader.
Pulsar LMTools (.lmts)LMTools is a set of tools (Windows & Linux) for * creating lightmaps. Irrlicht can directly read .lmts * files thanks to
the importer created by Jonas * Petersen. If you are using this loader, please note * that you can set the path of the textures before * loading .lmts files. You can do this using * SceneManager->getParameters()->setAttribute(scene::LMTS_TEXTURE_PATH, * "path/to/your/textures"); * Notes for
this version of the loader:
* - It does not recognise/support user data in the * *.lmts files.
* - The TGAs generated by LMTools don't work in * Irrlicht for some reason (the textures are upside * down). Opening and resaving them in a graphics app * will solve the problem.
Quake 3 levels (.bsp)Quake 3 is a popular game by IDSoftware, and .pk3 * files contain .bsp files and textures/lightmaps * describing huge prelighted levels. Irrlicht can read * .pk3 and .bsp files directly and thus render Quake 3 * levels directly. Written by Nikolaus Gebhardt * enhanced by Dean P. Macri with the curved surfaces * feature.
Quake 2 models (.md2)Quake 2 models are characters with morph target * animation. Irrlicht can read, display and animate * them directly with this importer.
Quake 3 models (.md3)Quake 3 models are characters with morph target * animation, they contain mount points for weapons and body * parts and are typically made of several sections which are * manually joined together.
Stanford Triangle (.ply)Invented by Stanford University and known as the native * format of the infamous "Stanford Bunny" model, this is a * popular static mesh format used by 3D scanning hardware * and software. This loader supports extremely large models * in both ASCII and binary format, but only has rudimentary * material support in the form of vertex colors and texture * coordinates.
Stereolithography (.stl)The STL format is used for rapid prototyping and * computer-aided manufacturing, thus has no support for * materials.
* * To load and display a mesh quickly, just do this: * \code * SceneManager->addAnimatedMeshSceneNode( * SceneManager->getMesh("yourmesh.3ds")); * \endcode * If you would like to implement and add your own file format loader to Irrlicht, * see addExternalMeshLoader(). * \param filename: Filename of the mesh to load. * \return Null if failed, otherwise pointer to the mesh. * This pointer should not be dropped. See IReferenceCounted::drop() for more information. **/ virtual IAnimatedMesh* getMesh(const io::path& filename) = 0; //! Get pointer to an animateable mesh. Loads the file if not loaded already. /** Works just as getMesh(const char* filename). If you want to remove a loaded mesh from the cache again, use removeMesh(). \param file File handle of the mesh to load. \return NULL if failed and pointer to the mesh if successful. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IAnimatedMesh* getMesh(io::IReadFile* file) = 0; //! Get interface to the mesh cache which is shared beween all existing scene managers. /** With this interface, it is possible to manually add new loaded meshes (if ISceneManager::getMesh() is not sufficient), to remove them and to iterate through already loaded meshes. */ virtual IMeshCache* getMeshCache() = 0; //! Get the video driver. /** \return Pointer to the video Driver. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual video::IVideoDriver* getVideoDriver() = 0; //! Get the active GUIEnvironment /** \return Pointer to the GUIEnvironment This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual gui::IGUIEnvironment* getGUIEnvironment() = 0; //! Get the active FileSystem /** \return Pointer to the FileSystem This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual io::IFileSystem* getFileSystem() = 0; //! adds Volume Lighting Scene Node. /** Example Usage: scene::IVolumeLightSceneNode * n = smgr->addVolumeLightSceneNode(0, -1, 32, 32, //Subdivide U/V video::SColor(0, 180, 180, 180), //foot color video::SColor(0, 0, 0, 0) //tail color ); if (n) { n->setScale(core::vector3df(46.0f, 45.0f, 46.0f)); n->getMaterial(0).setTexture(0, smgr->getVideoDriver()->getTexture("lightFalloff.png")); } \return Pointer to the volumeLight if successful, otherwise NULL. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IVolumeLightSceneNode* addVolumeLightSceneNode(ISceneNode* parent=0, s32 id=-1, const u32 subdivU = 32, const u32 subdivV = 32, const video::SColor foot = video::SColor(51, 0, 230, 180), const video::SColor tail = video::SColor(0, 0, 0, 0), const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; //! Adds a cube scene node /** \param size: Size of the cube, uniformly in each dimension. \param parent: Parent of the scene node. Can be 0 if no parent. \param id: Id of the node. This id can be used to identify the scene node. \param position: Position of the space relative to its parent where the scene node will be placed. \param rotation: Initital rotation of the scene node. \param scale: Initial scale of the scene node. \return Pointer to the created test scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IMeshSceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; //! Adds a sphere scene node of the given radius and detail /** \param radius: Radius of the sphere. \param polyCount: The number of vertices in horizontal and vertical direction. The total polyCount of the sphere is polyCount*polyCount. This parameter must be less than 256 to stay within the 16-bit limit of the indices of a meshbuffer. \param parent: Parent of the scene node. Can be 0 if no parent. \param id: Id of the node. This id can be used to identify the scene node. \param position: Position of the space relative to its parent where the scene node will be placed. \param rotation: Initital rotation of the scene node. \param scale: Initial scale of the scene node. \return Pointer to the created test scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IMeshSceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; //! Adds a scene node for rendering an animated mesh model. /** \param mesh: Pointer to the loaded animated mesh to be displayed. \param parent: Parent of the scene node. Can be NULL if no parent. \param id: Id of the node. This id can be used to identify the scene node. \param position: Position of the space relative to its parent where the scene node will be placed. \param rotation: Initital rotation of the scene node. \param scale: Initial scale of the scene node. \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. \return Pointer to the created scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IAnimatedMeshSceneNode* addAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f), bool alsoAddIfMeshPointerZero=false) = 0; //! Adds a scene node for rendering a static mesh. /** \param mesh: Pointer to the loaded static mesh to be displayed. \param parent: Parent of the scene node. Can be NULL if no parent. \param id: Id of the node. This id can be used to identify the scene node. \param position: Position of the space relative to its parent where the scene node will be placed. \param rotation: Initital rotation of the scene node. \param scale: Initial scale of the scene node. \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. \return Pointer to the created scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IMeshSceneNode* addMeshSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f), bool alsoAddIfMeshPointerZero=false) = 0; //! Adds a scene node for rendering a animated water surface mesh. /** Looks really good when the Material type EMT_TRANSPARENT_REFLECTION is used. \param waveHeight: Height of the water waves. \param waveSpeed: Speed of the water waves. \param waveLength: Lenght of a water wave. \param mesh: Pointer to the loaded static mesh to be displayed with water waves on it. \param parent: Parent of the scene node. Can be NULL if no parent. \param id: Id of the node. This id can be used to identify the scene node. \param position: Position of the space relative to its parent where the scene node will be placed. \param rotation: Initital rotation of the scene node. \param scale: Initial scale of the scene node. \return Pointer to the created scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addWaterSurfaceSceneNode(IMesh* mesh, f32 waveHeight=2.0f, f32 waveSpeed=300.0f, f32 waveLength=10.0f, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; //! Adds a scene node for rendering using a octree to the scene graph. /** This a good method for rendering scenes with lots of geometry. The Octree is built on the fly from the mesh. \param mesh: The mesh containing all geometry from which the octree will be build. If this animated mesh has more than one frames in it, the first frame is taken. \param parent: Parent node of the octree node. \param id: id of the node. This id can be used to identify the node. \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. If a node gets less polys than this value it will not be split into smaller nodes. \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. \return Pointer to the Octree if successful, otherwise 0. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IMeshSceneNode* addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) = 0; //! Adds a scene node for rendering using a octree to the scene graph. /** \deprecated Use addOctreeSceneNode instead. This method may be removed by Irrlicht 1.9. */ _IRR_DEPRECATED_ IMeshSceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) { return addOctreeSceneNode(mesh, parent, id, minimalPolysPerNode, alsoAddIfMeshPointerZero); } //! Adds a scene node for rendering using a octree to the scene graph. /** This a good method for rendering scenes with lots of geometry. The Octree is built on the fly from the mesh, much faster then a bsp tree. \param mesh: The mesh containing all geometry from which the octree will be build. \param parent: Parent node of the octree node. \param id: id of the node. This id can be used to identify the node. \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. If a node gets less polys than this value it will not be split into smaller nodes. \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. \return Pointer to the octree if successful, otherwise 0. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IMeshSceneNode* addOctreeSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; //! Adds a scene node for rendering using a octree to the scene graph. /** \deprecated Use addOctreeSceneNode instead. This method may be removed by Irrlicht 1.9. */ _IRR_DEPRECATED_ IMeshSceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) { return addOctreeSceneNode(mesh, parent, id, minimalPolysPerNode, alsoAddIfMeshPointerZero); } //! Adds a camera scene node to the scene graph and sets it as active camera. /** This camera does not react on user input like for example the one created with addCameraSceneNodeFPS(). If you want to move or animate it, use animators or the ISceneNode::setPosition(), ICameraSceneNode::setTarget() etc methods. By default, a camera's look at position (set with setTarget()) and its scene node rotation (set with setRotation()) are independent. If you want to be able to control the direction that the camera looks by using setRotation() then call ICameraSceneNode::bindTargetAndRotation(true) on it. \param position: Position of the space relative to its parent where the camera will be placed. \param lookat: Position where the camera will look at. Also known as target. \param parent: Parent scene node of the camera. Can be null. If the parent moves, the camera will move too. \param id: id of the camera. This id can be used to identify the camera. \param makeActive Flag whether this camera should become the active one. Make sure you always have one active camera. \return Pointer to interface to camera if successful, otherwise 0. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ICameraSceneNode* addCameraSceneNode(ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& lookat = core::vector3df(0,0,100), s32 id=-1, bool makeActive=true) = 0; //! Adds a maya style user controlled camera scene node to the scene graph. /** This is a standard camera with an animator that provides mouse control similar to camera in the 3D Software Maya by Alias Wavefront. The camera does not react on setPosition anymore after applying this animator. Instead use setTarget, to fix the target the camera the camera hovers around. And setDistance to set the current distance from that target, i.e. the radius of the orbit the camera hovers on. \param parent: Parent scene node of the camera. Can be null. \param rotateSpeed: Rotation speed of the camera. \param zoomSpeed: Zoom speed of the camera. \param translationSpeed: TranslationSpeed of the camera. \param id: id of the camera. This id can be used to identify the camera. \param distance Initial distance of the camera from the object \param makeActive Flag whether this camera should become the active one. Make sure you always have one active camera. \return Returns a pointer to the interface of the camera if successful, otherwise 0. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ICameraSceneNode* addCameraSceneNodeMaya(ISceneNode* parent=0, f32 rotateSpeed=-1500.f, f32 zoomSpeed=200.f, f32 translationSpeed=1500.f, s32 id=-1, f32 distance=70.f, bool makeActive=true) =0; //! Adds a camera scene node with an animator which provides mouse and keyboard control appropriate for first person shooters (FPS). /** This FPS camera is intended to provide a demonstration of a camera that behaves like a typical First Person Shooter. It is useful for simple demos and prototyping but is not intended to provide a full solution for a production quality game. It binds the camera scene node rotation to the look-at target; @see ICameraSceneNode::bindTargetAndRotation(). With this camera, you look with the mouse, and move with cursor keys. If you want to change the key layout, you can specify your own keymap. For example to make the camera be controlled by the cursor keys AND the keys W,A,S, and D, do something like this: \code SKeyMap keyMap[8]; keyMap[0].Action = EKA_MOVE_FORWARD; keyMap[0].KeyCode = KEY_UP; keyMap[1].Action = EKA_MOVE_FORWARD; keyMap[1].KeyCode = KEY_KEY_W; keyMap[2].Action = EKA_MOVE_BACKWARD; keyMap[2].KeyCode = KEY_DOWN; keyMap[3].Action = EKA_MOVE_BACKWARD; keyMap[3].KeyCode = KEY_KEY_S; keyMap[4].Action = EKA_STRAFE_LEFT; keyMap[4].KeyCode = KEY_LEFT; keyMap[5].Action = EKA_STRAFE_LEFT; keyMap[5].KeyCode = KEY_KEY_A; keyMap[6].Action = EKA_STRAFE_RIGHT; keyMap[6].KeyCode = KEY_RIGHT; keyMap[7].Action = EKA_STRAFE_RIGHT; keyMap[7].KeyCode = KEY_KEY_D; camera = sceneManager->addCameraSceneNodeFPS(0, 100, 500, -1, keyMap, 8); \endcode \param parent: Parent scene node of the camera. Can be null. \param rotateSpeed: Speed in degress with which the camera is rotated. This can be done only with the mouse. \param moveSpeed: Speed in units per millisecond with which the camera is moved. Movement is done with the cursor keys. \param id: id of the camera. This id can be used to identify the camera. \param keyMapArray: Optional pointer to an array of a keymap, specifying what keys should be used to move the camera. If this is null, the default keymap is used. You can define actions more then one time in the array, to bind multiple keys to the same action. \param keyMapSize: Amount of items in the keymap array. \param noVerticalMovement: Setting this to true makes the camera only move within a horizontal plane, and disables vertical movement as known from most ego shooters. Default is 'false', with which it is possible to fly around in space, if no gravity is there. \param jumpSpeed: Speed with which the camera is moved when jumping. \param invertMouse: Setting this to true makes the camera look up when the mouse is moved down and down when the mouse is moved up, the default is 'false' which means it will follow the movement of the mouse cursor. \param makeActive Flag whether this camera should become the active one. Make sure you always have one active camera. \return Pointer to the interface of the camera if successful, otherwise 0. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, f32 rotateSpeed = 100.0f, f32 moveSpeed = 0.5f, s32 id=-1, SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, f32 jumpSpeed = 0.f, bool invertMouse=false, bool makeActive=true) = 0; //! Adds a dynamic light scene node to the scene graph. /** The light will cast dynamic light on all other scene nodes in the scene, which have the material flag video::MTF_LIGHTING turned on. (This is the default setting in most scene nodes). \param parent: Parent scene node of the light. Can be null. If the parent moves, the light will move too. \param position: Position of the space relative to its parent where the light will be placed. \param color: Diffuse color of the light. Ambient or Specular colors can be set manually with the ILightSceneNode::getLightData() method. \param radius: Radius of the light. \param id: id of the node. This id can be used to identify the node. \return Pointer to the interface of the light if successful, otherwise NULL. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ILightSceneNode* addLightSceneNode(ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), video::SColorf color = video::SColorf(1.0f, 1.0f, 1.0f), f32 radius=100.0f, s32 id=-1) = 0; //! Adds a billboard scene node to the scene graph. /** A billboard is like a 3d sprite: A 2d element, which always looks to the camera. It is usually used for things like explosions, fire, lensflares and things like that. \param parent Parent scene node of the billboard. Can be null. If the parent moves, the billboard will move too. \param size Size of the billboard. This size is 2 dimensional because a billboard only has width and height. \param position Position of the space relative to its parent where the billboard will be placed. \param id An id of the node. This id can be used to identify the node. \param colorTop The color of the vertices at the top of the billboard (default: white). \param colorBottom The color of the vertices at the bottom of the billboard (default: white). \return Pointer to the billboard if successful, otherwise NULL. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IBillboardSceneNode* addBillboardSceneNode(ISceneNode* parent = 0, const core::dimension2d& size = core::dimension2d(10.0f, 10.0f), const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1, video::SColor colorTop = 0xFFFFFFFF, video::SColor colorBottom = 0xFFFFFFFF) = 0; //! Adds a skybox scene node to the scene graph. /** A skybox is a big cube with 6 textures on it and is drawn around the camera position. \param top: Texture for the top plane of the box. \param bottom: Texture for the bottom plane of the box. \param left: Texture for the left plane of the box. \param right: Texture for the right plane of the box. \param front: Texture for the front plane of the box. \param back: Texture for the back plane of the box. \param parent: Parent scene node of the skybox. A skybox usually has no parent, so this should be null. Note: If a parent is set to the skybox, the box will not change how it is drawn. \param id: An id of the node. This id can be used to identify the node. \return Pointer to the sky box if successful, otherwise NULL. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, video::ITexture* left, video::ITexture* right, video::ITexture* front, video::ITexture* back, ISceneNode* parent = 0, s32 id=-1) = 0; //! Adds a skydome scene node to the scene graph. /** A skydome is a large (half-) sphere with a panoramic texture on the inside and is drawn around the camera position. \param texture: Texture for the dome. \param horiRes: Number of vertices of a horizontal layer of the sphere. \param vertRes: Number of vertices of a vertical layer of the sphere. \param texturePercentage: How much of the height of the texture is used. Should be between 0 and 1. \param spherePercentage: How much of the sphere is drawn. Value should be between 0 and 2, where 1 is an exact half-sphere and 2 is a full sphere. \param radius The Radius of the sphere \param parent: Parent scene node of the dome. A dome usually has no parent, so this should be null. Note: If a parent is set, the dome will not change how it is drawn. \param id: An id of the node. This id can be used to identify the node. \return Pointer to the sky dome if successful, otherwise NULL. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, u32 horiRes=16, u32 vertRes=8, f32 texturePercentage=0.9, f32 spherePercentage=2.0,f32 radius = 1000.f, ISceneNode* parent=0, s32 id=-1) = 0; //! Adds a particle system scene node to the scene graph. /** \param withDefaultEmitter: Creates a default working point emitter which emitts some particles. Set this to true to see a particle system in action. If set to false, you'll have to set the emitter you want by calling IParticleSystemSceneNode::setEmitter(). \param parent: Parent of the scene node. Can be NULL if no parent. \param id: Id of the node. This id can be used to identify the scene node. \param position: Position of the space relative to its parent where the scene node will be placed. \param rotation: Initital rotation of the scene node. \param scale: Initial scale of the scene node. \return Pointer to the created scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IParticleSystemSceneNode* addParticleSystemSceneNode( bool withDefaultEmitter=true, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; //! Adds a terrain scene node to the scene graph. /** This node implements is a simple terrain renderer which uses a technique known as geo mip mapping for reducing the detail of triangle blocks which are far away. The code for the TerrainSceneNode is based on the terrain renderer by Soconne and the GeoMipMapSceneNode developed by Spintz. They made their code available for Irrlicht and allowed it to be distributed under this licence. I only modified some parts. A lot of thanks go to them. This scene node is capable of loading terrains and updating the indices at runtime to enable viewing very large terrains very quickly. It uses a CLOD (Continuous Level of Detail) algorithm which updates the indices for each patch based on a LOD (Level of Detail) which is determined based on a patch's distance from the camera. The patch size of the terrain must always be a size of 2^N+1, i.e. 8+1(9), 16+1(17), etc. The MaxLOD available is directly dependent on the patch size of the terrain. LOD 0 contains all of the indices to draw all the triangles at the max detail for a patch. As each LOD goes up by 1 the step taken, in generating indices increases by -2^LOD, so for LOD 1, the step taken is 2, for LOD 2, the step taken is 4, LOD 3 - 8, etc. The step can be no larger than the size of the patch, so having a LOD of 8, with a patch size of 17, is asking the algoritm to generate indices every 2^8 ( 256 ) vertices, which is not possible with a patch size of 17. The maximum LOD for a patch size of 17 is 2^4 ( 16 ). So, with a MaxLOD of 5, you'll have LOD 0 ( full detail ), LOD 1 ( every 2 vertices ), LOD 2 ( every 4 vertices ), LOD 3 ( every 8 vertices ) and LOD 4 ( every 16 vertices ). \param heightMapFileName: The name of the file on disk, to read vertex data from. This should be a gray scale bitmap. \param parent: Parent of the scene node. Can be 0 if no parent. \param id: Id of the node. This id can be used to identify the scene node. \param position: The absolute position of this node. \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) \param scale: The scale factor for the terrain. If you're using a heightmap of size 129x129 and would like your terrain to be 12900x12900 in game units, then use a scale factor of ( core::vector ( 100.0f, 100.0f, 100.0f ). If you use a Y scaling factor of 0.0f, then your terrain will be flat. \param vertexColor: The default color of all the vertices. If no texture is associated with the scene node, then all vertices will be this color. Defaults to white. \param maxLOD: The maximum LOD (level of detail) for the node. Only change if you know what you are doing, this might lead to strange behavior. \param patchSize: patch size of the terrain. Only change if you know what you are doing, this might lead to strange behavior. \param smoothFactor: The number of times the vertices are smoothed. \param addAlsoIfHeightmapEmpty: Add terrain node even with empty heightmap. \return Pointer to the created scene node. Can be null if the terrain could not be created, for example because the heightmap could not be loaded. The returned pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ITerrainSceneNode* addTerrainSceneNode( const io::path& heightMapFileName, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), video::SColor vertexColor = video::SColor(255,255,255,255), s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0, bool addAlsoIfHeightmapEmpty = false) = 0; //! Adds a terrain scene node to the scene graph. /** Just like the other addTerrainSceneNode() method, but takes an IReadFile pointer as parameter for the heightmap. For more informations take a look at the other function. \param heightMapFile: The file handle to read vertex data from. This should be a gray scale bitmap. \param parent: Parent of the scene node. Can be 0 if no parent. \param id: Id of the node. This id can be used to identify the scene node. \param position: The absolute position of this node. \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) \param scale: The scale factor for the terrain. If you're using a heightmap of size 129x129 and would like your terrain to be 12900x12900 in game units, then use a scale factor of ( core::vector ( 100.0f, 100.0f, 100.0f ). If you use a Y scaling factor of 0.0f, then your terrain will be flat. \param vertexColor: The default color of all the vertices. If no texture is associated with the scene node, then all vertices will be this color. Defaults to white. \param maxLOD: The maximum LOD (level of detail) for the node. Only change if you know what you are doing, this might lead to strange behavior. \param patchSize: patch size of the terrain. Only change if you know what you are doing, this might lead to strange behavior. \param smoothFactor: The number of times the vertices are smoothed. \param addAlsoIfHeightmapEmpty: Add terrain node even with empty heightmap. \return Pointer to the created scene node. Can be null if the terrain could not be created, for example because the heightmap could not be loaded. The returned pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ITerrainSceneNode* addTerrainSceneNode( io::IReadFile* heightMapFile, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), video::SColor vertexColor = video::SColor(255,255,255,255), s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0, bool addAlsoIfHeightmapEmpty = false) = 0; //! Adds a quake3 scene node to the scene graph. /** A Quake3 Scene renders multiple meshes for a specific HighLanguage Shader (Quake3 Style ) \return Pointer to the quake3 scene node if successful, otherwise NULL. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IMeshSceneNode* addQuake3SceneNode(const IMeshBuffer* meshBuffer, const quake3::IShader * shader, ISceneNode* parent=0, s32 id=-1 ) = 0; //! Adds an empty scene node to the scene graph. /** Can be used for doing advanced transformations or structuring the scene graph. \return Pointer to the created scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addEmptySceneNode(ISceneNode* parent=0, s32 id=-1) = 0; //! Adds a dummy transformation scene node to the scene graph. /** This scene node does not render itself, and does not respond to set/getPosition, set/getRotation and set/getScale. Its just a simple scene node that takes a matrix as relative transformation, making it possible to insert any transformation anywhere into the scene graph. \return Pointer to the created scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IDummyTransformationSceneNode* addDummyTransformationSceneNode( ISceneNode* parent=0, s32 id=-1) = 0; //! Adds a text scene node, which is able to display 2d text at a position in three dimensional space virtual ITextSceneNode* addTextSceneNode(gui::IGUIFont* font, const wchar_t* text, video::SColor color=video::SColor(100,255,255,255), ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1) = 0; //! Adds a text scene node, which uses billboards. The node, and the text on it, will scale with distance. /** \param font The font to use on the billboard. Pass 0 to use the GUI environment's default font. \param text The text to display on the billboard. \param parent The billboard's parent. Pass 0 to use the root scene node. \param size The billboard's width and height. \param position The billboards position relative to its parent. \param id: An id of the node. This id can be used to identify the node. \param colorTop: The color of the vertices at the top of the billboard (default: white). \param colorBottom: The color of the vertices at the bottom of the billboard (default: white). \return Pointer to the billboard if successful, otherwise NULL. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IBillboardTextSceneNode* addBillboardTextSceneNode( gui::IGUIFont* font, const wchar_t* text, ISceneNode* parent = 0, const core::dimension2d& size = core::dimension2d(10.0f, 10.0f), const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1, video::SColor colorTop = 0xFFFFFFFF, video::SColor colorBottom = 0xFFFFFFFF) = 0; //! Adds a Hill Plane mesh to the mesh pool. /** The mesh is generated on the fly and looks like a plane with some hills on it. It is uses mostly for quick tests of the engine only. You can specify how many hills there should be on the plane and how high they should be. Also you must specify a name for the mesh, because the mesh is added to the mesh pool, and can be retrieved again using ISceneManager::getMesh() with the name as parameter. \param name: The name of this mesh which must be specified in order to be able to retrieve the mesh later with ISceneManager::getMesh(). \param tileSize: Size of a tile of the mesh. (10.0f, 10.0f) would be a good value to start, for example. \param tileCount: Specifies how much tiles there will be. If you specifiy for example that a tile has the size (10.0f, 10.0f) and the tileCount is (10,10), than you get a field of 100 tiles which has the dimension 100.0fx100.0f. \param material: Material of the hill mesh. \param hillHeight: Height of the hills. If you specify a negative value you will get holes instead of hills. If the height is 0, no hills will be created. \param countHills: Amount of hills on the plane. There will be countHills.X hills along the X axis and countHills.Y along the Y axis. So in total there will be countHills.X * countHills.Y hills. \param textureRepeatCount: Defines how often the texture will be repeated in x and y direction. return Null if the creation failed. The reason could be that you specified some invalid parameters or that a mesh with that name already exists. If successful, a pointer to the mesh is returned. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IAnimatedMesh* addHillPlaneMesh(const io::path& name, const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material = 0, f32 hillHeight = 0.0f, const core::dimension2d& countHills = core::dimension2d(0.0f, 0.0f), const core::dimension2d& textureRepeatCount = core::dimension2d(1.0f, 1.0f)) = 0; //! Adds a static terrain mesh to the mesh pool. /** The mesh is generated on the fly from a texture file and a height map file. Both files may be huge (8000x8000 pixels would be no problem) because the generator splits the files into smaller textures if necessary. You must specify a name for the mesh, because the mesh is added to the mesh pool, and can be retrieved again using ISceneManager::getMesh() with the name as parameter. \param meshname: The name of this mesh which must be specified in order to be able to retrieve the mesh later with ISceneManager::getMesh(). \param texture: Texture for the terrain. Please note that this is not a hardware texture as usual (ITexture), but an IImage software texture. You can load this texture with IVideoDriver::createImageFromFile(). \param heightmap: A grayscaled heightmap image. Like the texture, it can be created with IVideoDriver::createImageFromFile(). The amount of triangles created depends on the size of this texture, so use a small heightmap to increase rendering speed. \param stretchSize: Parameter defining how big a is pixel on the heightmap. \param maxHeight: Defines how high a white pixel on the heighmap is. \param defaultVertexBlockSize: Defines the initial dimension between vertices. \return Null if the creation failed. The reason could be that you specified some invalid parameters, that a mesh with that name already exists, or that a texture could not be found. If successful, a pointer to the mesh is returned. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IAnimatedMesh* addTerrainMesh(const io::path& meshname, video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize = core::dimension2d(10.0f,10.0f), f32 maxHeight=200.0f, const core::dimension2d& defaultVertexBlockSize = core::dimension2d(64,64)) = 0; //! add a static arrow mesh to the meshpool /** \param name Name of the mesh \param vtxColorCylinder color of the cylinder \param vtxColorCone color of the cone \param tesselationCylinder Number of quads the cylinder side consists of \param tesselationCone Number of triangles the cone's roof consits of \param height Total height of the arrow \param cylinderHeight Total height of the cylinder, should be lesser than total height \param widthCylinder Diameter of the cylinder \param widthCone Diameter of the cone's base, should be not smaller than the cylinder's diameter \return Pointer to the arrow mesh if successful, otherwise 0. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IAnimatedMesh* addArrowMesh(const io::path& name, video::SColor vtxColorCylinder=0xFFFFFFFF, video::SColor vtxColorCone=0xFFFFFFFF, u32 tesselationCylinder=4, u32 tesselationCone=8, f32 height=1.f, f32 cylinderHeight=0.6f, f32 widthCylinder=0.05f, f32 widthCone=0.3f) = 0; //! add a static sphere mesh to the meshpool /** \param name Name of the mesh \param radius Radius of the sphere \param polyCountX Number of quads used for the horizontal tiling \param polyCountY Number of quads used for the vertical tiling \return Pointer to the sphere mesh if successful, otherwise 0. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IAnimatedMesh* addSphereMesh(const io::path& name, f32 radius=5.f, u32 polyCountX = 16, u32 polyCountY = 16) = 0; //! Add a volume light mesh to the meshpool /** \param name Name of the mesh \param SubdivideU Horizontal subdivision count \param SubdivideV Vertical subdivision count \param FootColor Color of the bottom of the light \param TailColor Color of the top of the light \return Pointer to the volume light mesh if successful, otherwise 0. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IAnimatedMesh* addVolumeLightMesh(const io::path& name, const u32 SubdivideU = 32, const u32 SubdivideV = 32, const video::SColor FootColor = video::SColor(51, 0, 230, 180), const video::SColor TailColor = video::SColor(0, 0, 0, 0)) = 0; //! Gets the root scene node. /** This is the scene node which is parent of all scene nodes. The root scene node is a special scene node which only exists to manage all scene nodes. It will not be rendered and cannot be removed from the scene. \return Pointer to the root scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* getRootSceneNode() = 0; //! Get the first scene node with the specified id. /** \param id: The id to search for \param start: Scene node to start from. All children of this scene node are searched. If null is specified, the root scene node is taken. \return Pointer to the first scene node with this id, and null if no scene node could be found. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* getSceneNodeFromId(s32 id, ISceneNode* start=0) = 0; //! Get the first scene node with the specified name. /** \param name: The name to search for \param start: Scene node to start from. All children of this scene node are searched. If null is specified, the root scene node is taken. \return Pointer to the first scene node with this id, and null if no scene node could be found. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* getSceneNodeFromName(const c8* name, ISceneNode* start=0) = 0; //! Get the first scene node with the specified type. /** \param type: The type to search for \param start: Scene node to start from. All children of this scene node are searched. If null is specified, the root scene node is taken. \return Pointer to the first scene node with this type, and null if no scene node could be found. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* getSceneNodeFromType(scene::ESCENE_NODE_TYPE type, ISceneNode* start=0) = 0; //! Get scene nodes by type. /** \param type: Type of scene node to find (ESNT_ANY will return all child nodes). \param outNodes: array to be filled with results. \param start: Scene node to start from. All children of this scene node are searched. If null is specified, the root scene node is taken. */ virtual void getSceneNodesFromType(ESCENE_NODE_TYPE type, core::array& outNodes, ISceneNode* start=0) = 0; //! Get the current active camera. /** \return The active camera is returned. Note that this can be NULL, if there was no camera created yet. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ICameraSceneNode* getActiveCamera() const =0; //! Sets the currently active camera. /** The previous active camera will be deactivated. \param camera: The new camera which should be active. */ virtual void setActiveCamera(ICameraSceneNode* camera) = 0; //! Sets the color of stencil buffers shadows drawn by the scene manager. virtual void setShadowColor(video::SColor color = video::SColor(150,0,0,0)) = 0; //! Get the current color of shadows. virtual video::SColor getShadowColor() const = 0; //! Registers a node for rendering it at a specific time. /** This method should only be used by SceneNodes when they get a ISceneNode::OnRegisterSceneNode() call. \param node: Node to register for drawing. Usually scene nodes would set 'this' as parameter here because they want to be drawn. \param pass: Specifies when the node wants to be drawn in relation to the other nodes. For example, if the node is a shadow, it usually wants to be drawn after all other nodes and will use ESNRP_SHADOW for this. See scene::E_SCENE_NODE_RENDER_PASS for details. \return scene will be rendered ( passed culling ) */ virtual u32 registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS pass = ESNRP_AUTOMATIC) = 0; //! Draws all the scene nodes. /** This can only be invoked between IVideoDriver::beginScene() and IVideoDriver::endScene(). Please note that the scene is not only drawn when calling this, but also animated by existing scene node animators, culling of scene nodes is done, etc. */ virtual void drawAll() = 0; //! Creates a rotation animator, which rotates the attached scene node around itself. /** \param rotationSpeed Specifies the speed of the animation in degree per 10 milliseconds. \return The animator. Attach it to a scene node with ISceneNode::addAnimator() and the animator will animate it. If you no longer need the animator, you should call ISceneNodeAnimator::drop(). See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimator* createRotationAnimator(const core::vector3df& rotationSpeed) = 0; //! Creates a fly circle animator, which lets the attached scene node fly around a center. /** \param center: Center of the circle. \param radius: Radius of the circle. \param speed: The orbital speed, in radians per millisecond. \param direction: Specifies the upvector used for alignment of the mesh. \param startPosition: The position on the circle where the animator will begin. Value is in multiples of a circle, i.e. 0.5 is half way around. (phase) \param radiusEllipsoid: if radiusEllipsoid != 0 then radius2 froms a ellipsoid begin. Value is in multiples of a circle, i.e. 0.5 is half way around. (phase) \return The animator. Attach it to a scene node with ISceneNode::addAnimator() and the animator will animate it. If you no longer need the animator, you should call ISceneNodeAnimator::drop(). See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimator* createFlyCircleAnimator( const core::vector3df& center=core::vector3df(0.f,0.f,0.f), f32 radius=100.f, f32 speed=0.001f, const core::vector3df& direction=core::vector3df(0.f, 1.f, 0.f), f32 startPosition = 0.f, f32 radiusEllipsoid = 0.f) = 0; //! Creates a fly straight animator, which lets the attached scene node fly or move along a line between two points. /** \param startPoint: Start point of the line. \param endPoint: End point of the line. \param timeForWay: Time in milli seconds how long the node should need to move from the start point to the end point. \param loop: If set to false, the node stops when the end point is reached. If loop is true, the node begins again at the start. \param pingpong Flag to set whether the animator should fly back from end to start again. \return The animator. Attach it to a scene node with ISceneNode::addAnimator() and the animator will animate it. If you no longer need the animator, you should call ISceneNodeAnimator::drop(). See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimator* createFlyStraightAnimator(const core::vector3df& startPoint, const core::vector3df& endPoint, u32 timeForWay, bool loop=false, bool pingpong = false) = 0; //! Creates a texture animator, which switches the textures of the target scene node based on a list of textures. /** \param textures: List of textures to use. \param timePerFrame: Time in milliseconds, how long any texture in the list should be visible. \param loop: If set to to false, the last texture remains set, and the animation stops. If set to true, the animation restarts with the first texture. \return The animator. Attach it to a scene node with ISceneNode::addAnimator() and the animator will animate it. If you no longer need the animator, you should call ISceneNodeAnimator::drop(). See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimator* createTextureAnimator(const core::array& textures, s32 timePerFrame, bool loop=true) = 0; //! Creates a scene node animator, which deletes the scene node after some time automatically. /** \param timeMs: Time in milliseconds, after when the node will be deleted. \return The animator. Attach it to a scene node with ISceneNode::addAnimator() and the animator will animate it. If you no longer need the animator, you should call ISceneNodeAnimator::drop(). See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimator* createDeleteAnimator(u32 timeMs) = 0; //! Creates a special scene node animator for doing automatic collision detection and response. /** See ISceneNodeAnimatorCollisionResponse for details. \param world: Triangle selector holding all triangles of the world with which the scene node may collide. You can create a triangle selector with ISceneManager::createTriangleSelector(); \param sceneNode: SceneNode which should be manipulated. After you added this animator to the scene node, the scene node will not be able to move through walls and is affected by gravity. If you need to teleport the scene node to a new position without it being effected by the collision geometry, then call sceneNode->setPosition(); then animator->setTargetNode(sceneNode); \param ellipsoidRadius: Radius of the ellipsoid with which collision detection and response is done. If you have got a scene node, and you are unsure about how big the radius should be, you could use the following code to determine it: \code const core::aabbox3d& box = yourSceneNode->getBoundingBox(); core::vector3df radius = box.MaxEdge - box.getCenter(); \endcode \param gravityPerSecond: Sets the gravity of the environment, as an acceleration in units per second per second. If your units are equivalent to metres, then core::vector3df(0,-10.0f,0) would give an approximately realistic gravity. You can disable gravity by setting it to core::vector3df(0,0,0). \param ellipsoidTranslation: By default, the ellipsoid for collision detection is created around the center of the scene node, which means that the ellipsoid surrounds it completely. If this is not what you want, you may specify a translation for the ellipsoid. \param slidingValue: DOCUMENTATION NEEDED. \return The animator. Attach it to a scene node with ISceneNode::addAnimator() and the animator will cause it to do collision detection and response. If you no longer need the animator, you should call ISceneNodeAnimator::drop(). See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimatorCollisionResponse* createCollisionResponseAnimator( ITriangleSelector* world, ISceneNode* sceneNode, const core::vector3df& ellipsoidRadius = core::vector3df(30,60,30), const core::vector3df& gravityPerSecond = core::vector3df(0,-10.0f,0), const core::vector3df& ellipsoidTranslation = core::vector3df(0,0,0), f32 slidingValue = 0.0005f) = 0; //! Creates a follow spline animator. /** The animator modifies the position of the attached scene node to make it follow a hermite spline. It uses a subset of hermite splines: either cardinal splines (tightness != 0.5) or catmull-rom-splines (tightness == 0.5). The animator moves from one control point to the next in 1/speed seconds. This code was sent in by Matthias Gall. If you no longer need the animator, you should call ISceneNodeAnimator::drop(). See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimator* createFollowSplineAnimator(s32 startTime, const core::array< core::vector3df >& points, f32 speed = 1.0f, f32 tightness = 0.5f, bool loop=true, bool pingpong=false) = 0; //! Creates a simple ITriangleSelector, based on a mesh. /** Triangle selectors can be used for doing collision detection. Don't use this selector for a huge amount of triangles like in Quake3 maps. Instead, use for example ISceneManager::createOctreeTriangleSelector(). Please note that the created triangle selector is not automaticly attached to the scene node. You will have to call ISceneNode::setTriangleSelector() for this. To create and attach a triangle selector is done like this: \code ITriangleSelector* s = sceneManager->createTriangleSelector(yourMesh, yourSceneNode); yourSceneNode->setTriangleSelector(s); s->drop(); \endcode \param mesh: Mesh of which the triangles are taken. \param node: Scene node of which visibility and transformation is used. \return The selector, or null if not successful. If you no longer need the selector, you should call ITriangleSelector::drop(). See IReferenceCounted::drop() for more information. */ virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node) = 0; //! Creates a simple ITriangleSelector, based on an animated mesh scene node. /** Details of the mesh associated with the node will be extracted internally. Call ITriangleSelector::update() to have the triangle selector updated based on the current frame of the animated mesh scene node. \param node The animated mesh scene node from which to build the selector */ virtual ITriangleSelector* createTriangleSelector(IAnimatedMeshSceneNode* node) = 0; //! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. /** Triangle selectors can be used for doing collision detection. Every time when triangles are queried, the triangle selector gets the bounding box of the scene node, an creates new triangles. In this way, it works good with animated scene nodes. \param node: Scene node of which the bounding box, visibility and transformation is used. \return The selector, or null if not successful. If you no longer need the selector, you should call ITriangleSelector::drop(). See IReferenceCounted::drop() for more information. */ virtual ITriangleSelector* createTriangleSelectorFromBoundingBox(ISceneNode* node) = 0; //! Creates a Triangle Selector, optimized by an octree. /** Triangle selectors can be used for doing collision detection. This triangle selector is optimized for huge amounts of triangle, it organizes them in an octree. Please note that the created triangle selector is not automaticly attached to the scene node. You will have to call ISceneNode::setTriangleSelector() for this. To create and attach a triangle selector is done like this: \code ITriangleSelector* s = sceneManager->createOctreeTriangleSelector(yourMesh, yourSceneNode); yourSceneNode->setTriangleSelector(s); s->drop(); \endcode For more informations and examples on this, take a look at the collision tutorial in the SDK. \param mesh: Mesh of which the triangles are taken. \param node: Scene node of which visibility and transformation is used. \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. If a node gets less polys the this value, it will not be splitted into smaller nodes. \return The selector, or null if not successful. If you no longer need the selector, you should call ITriangleSelector::drop(). See IReferenceCounted::drop() for more information. */ virtual ITriangleSelector* createOctreeTriangleSelector(IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode=32) = 0; //! //! Creates a Triangle Selector, optimized by an octree. /** \deprecated Use createOctreeTriangleSelector instead. This method may be removed by Irrlicht 1.9. */ _IRR_DEPRECATED_ ITriangleSelector* createOctTreeTriangleSelector(IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode=32) { return createOctreeTriangleSelector(mesh, node, minimalPolysPerNode); } //! Creates a meta triangle selector. /** A meta triangle selector is nothing more than a collection of one or more triangle selectors providing together the interface of one triangle selector. In this way, collision tests can be done with different triangle soups in one pass. \return The selector, or null if not successful. If you no longer need the selector, you should call ITriangleSelector::drop(). See IReferenceCounted::drop() for more information. */ virtual IMetaTriangleSelector* createMetaTriangleSelector() = 0; //! Creates a triangle selector which can select triangles from a terrain scene node. /** \param node: Pointer to the created terrain scene node \param LOD: Level of detail, 0 for highest detail. \return The selector, or null if not successful. If you no longer need the selector, you should call ITriangleSelector::drop(). See IReferenceCounted::drop() for more information. */ virtual ITriangleSelector* createTerrainTriangleSelector( ITerrainSceneNode* node, s32 LOD=0) = 0; //! Adds an external mesh loader for extending the engine with new file formats. /** If you want the engine to be extended with file formats it currently is not able to load (e.g. .cob), just implement the IMeshLoader interface in your loading class and add it with this method. Using this method it is also possible to override built-in mesh loaders with newer or updated versions without the need to recompile the engine. \param externalLoader: Implementation of a new mesh loader. */ virtual void addExternalMeshLoader(IMeshLoader* externalLoader) = 0; //! Returns the number of mesh loaders supported by Irrlicht at this time virtual u32 getMeshLoaderCount() const = 0; //! Retrieve the given mesh loader /** \param index The index of the loader to retrieve. This parameter is an 0-based array index. \return A pointer to the specified loader, 0 if the index is incorrect. */ virtual IMeshLoader* getMeshLoader(u32 index) const = 0; //! Adds an external scene loader for extending the engine with new file formats. /** If you want the engine to be extended with file formats it currently is not able to load (e.g. .vrml), just implement the ISceneLoader interface in your loading class and add it with this method. Using this method it is also possible to override the built-in scene loaders with newer or updated versions without the need to recompile the engine. \param externalLoader: Implementation of a new mesh loader. */ virtual void addExternalSceneLoader(ISceneLoader* externalLoader) = 0; //! Returns the number of scene loaders supported by Irrlicht at this time virtual u32 getSceneLoaderCount() const = 0; //! Retrieve the given scene loader /** \param index The index of the loader to retrieve. This parameter is an 0-based array index. \return A pointer to the specified loader, 0 if the index is incorrect. */ virtual ISceneLoader* getSceneLoader(u32 index) const = 0; //! Get pointer to the scene collision manager. /** \return Pointer to the collision manager This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneCollisionManager* getSceneCollisionManager() = 0; //! Get pointer to the mesh manipulator. /** \return Pointer to the mesh manipulator This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IMeshManipulator* getMeshManipulator() = 0; //! Adds a scene node to the deletion queue. /** The scene node is immediatly deleted when it's secure. Which means when the scene node does not execute animators and things like that. This method is for example used for deleting scene nodes by their scene node animators. In most other cases, a ISceneNode::remove() call is enough, using this deletion queue is not necessary. See ISceneManager::createDeleteAnimator() for details. \param node: Node to detete. */ virtual void addToDeletionQueue(ISceneNode* node) = 0; //! Posts an input event to the environment. /** Usually you do not have to use this method, it is used by the internal engine. */ virtual bool postEventFromUser(const SEvent& event) = 0; //! Clears the whole scene. /** All scene nodes are removed. */ virtual void clear() = 0; //! Get interface to the parameters set in this scene. /** String parameters can be used by plugins and mesh loaders. For example the CMS and LMTS loader want a parameter named 'CSM_TexturePath' and 'LMTS_TexturePath' set to the path were attached textures can be found. See CSM_TEXTURE_PATH, LMTS_TEXTURE_PATH, MY3D_TEXTURE_PATH, COLLADA_CREATE_SCENE_INSTANCES, DMF_TEXTURE_PATH and DMF_USE_MATERIALS_DIRS*/ virtual io::IAttributes* getParameters() = 0; //! Get current render pass. /** All scene nodes are being rendered in a specific order. First lights, cameras, sky boxes, solid geometry, and then transparent stuff. During the rendering process, scene nodes may want to know what the scene manager is rendering currently, because for example they registered for rendering twice, once for transparent geometry and once for solid. When knowing what rendering pass currently is active they can render the correct part of their geometry. */ virtual E_SCENE_NODE_RENDER_PASS getSceneNodeRenderPass() const = 0; //! Get the default scene node factory which can create all built in scene nodes /** \return Pointer to the default scene node factory This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNodeFactory* getDefaultSceneNodeFactory() = 0; //! Adds a scene node factory to the scene manager. /** Use this to extend the scene manager with new scene node types which it should be able to create automaticly, for example when loading data from xml files. */ virtual void registerSceneNodeFactory(ISceneNodeFactory* factoryToAdd) = 0; //! Get amount of registered scene node factories. virtual u32 getRegisteredSceneNodeFactoryCount() const = 0; //! Get a scene node factory by index /** \return Pointer to the requested scene node factory, or 0 if it does not exist. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNodeFactory* getSceneNodeFactory(u32 index) = 0; //! Get the default scene node animator factory which can create all built-in scene node animators /** \return Pointer to the default scene node animator factory This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimatorFactory* getDefaultSceneNodeAnimatorFactory() = 0; //! Adds a scene node animator factory to the scene manager. /** Use this to extend the scene manager with new scene node animator types which it should be able to create automaticly, for example when loading data from xml files. */ virtual void registerSceneNodeAnimatorFactory(ISceneNodeAnimatorFactory* factoryToAdd) = 0; //! Get amount of registered scene node animator factories. virtual u32 getRegisteredSceneNodeAnimatorFactoryCount() const = 0; //! Get scene node animator factory by index /** \return Pointer to the requested scene node animator factory, or 0 if it does not exist. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimatorFactory* getSceneNodeAnimatorFactory(u32 index) = 0; //! Get typename from a scene node type or null if not found virtual const c8* getSceneNodeTypeName(ESCENE_NODE_TYPE type) = 0; //! Returns a typename from a scene node animator type or null if not found virtual const c8* getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) = 0; //! Adds a scene node to the scene by name /** \return Pointer to the scene node added by a factory This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual ISceneNode* addSceneNode(const char* sceneNodeTypeName, ISceneNode* parent=0) = 0; //! creates a scene node animator based on its type name /** \param typeName: Type of the scene node animator to add. \param target: Target scene node of the new animator. \return Returns pointer to the new scene node animator or null if not successful. You need to drop this pointer after calling this, see IReferenceCounted::drop() for details. */ virtual ISceneNodeAnimator* createSceneNodeAnimator(const char* typeName, ISceneNode* target=0) = 0; //! Creates a new scene manager. /** This can be used to easily draw and/or store two independent scenes at the same time. The mesh cache will be shared between all existing scene managers, which means if you load a mesh in the original scene manager using for example getMesh(), the mesh will be available in all other scene managers too, without loading. The original/main scene manager will still be there and accessible via IrrlichtDevice::getSceneManager(). If you need input event in this new scene manager, for example for FPS cameras, you'll need to forward input to this manually: Just implement an IEventReceiver and call yourNewSceneManager->postEventFromUser(), and return true so that the original scene manager doesn't get the event. Otherwise, all input will go to the main scene manager automatically. If you no longer need the new scene manager, you should call ISceneManager::drop(). See IReferenceCounted::drop() for more information. */ virtual ISceneManager* createNewSceneManager(bool cloneContent=false) = 0; //! Saves the current scene into a file. /** Scene nodes with the option isDebugObject set to true are not being saved. The scene is usually written to an .irr file, an xml based format. .irr files can Be edited with the Irrlicht Engine Editor, irrEdit (http://www.ambiera.com/irredit/). To load .irr files again, see ISceneManager::loadScene(). \param filename Name of the file. \param userDataSerializer If you want to save some user data for every scene node into the file, implement the ISceneUserDataSerializer interface and provide it as parameter here. Otherwise, simply specify 0 as this parameter. \param node Node which is taken as the top node of the scene. This node and all of its descendants are saved into the scene file. Pass 0 or the scene manager to save the full scene (which is also the default). \return True if successful. */ virtual bool saveScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0) = 0; //! Saves the current scene into a file. /** Scene nodes with the option isDebugObject set to true are not being saved. The scene is usually written to an .irr file, an xml based format. .irr files can Be edited with the Irrlicht Engine Editor, irrEdit (http://www.ambiera.com/irredit/). To load .irr files again, see ISceneManager::loadScene(). \param file File where the scene is saved into. \param userDataSerializer If you want to save some user data for every scene node into the file, implement the ISceneUserDataSerializer interface and provide it as parameter here. Otherwise, simply specify 0 as this parameter. \param node Node which is taken as the top node of the scene. This node and all of its descendants are saved into the scene file. Pass 0 or the scene manager to save the full scene (which is also the default). \return True if successful. */ virtual bool saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0) = 0; //! Saves the current scene into a file. /** Scene nodes with the option isDebugObject set to true are not being saved. The scene is usually written to an .irr file, an xml based format. .irr files can Be edited with the Irrlicht Engine Editor, irrEdit (http://www.ambiera.com/irredit/). To load .irr files again, see ISceneManager::loadScene(). \param writer XMLWriter with which the scene is saved. \param currentPath Path which is used for relative file names. Usually the directory of the file written into. \param userDataSerializer If you want to save some user data for every scene node into the file, implement the ISceneUserDataSerializer interface and provide it as parameter here. Otherwise, simply specify 0 as this parameter. \param node Node which is taken as the top node of the scene. This node and all of its descendants are saved into the scene file. Pass 0 or the scene manager to save the full scene (which is also the default). \return True if successful. */ virtual bool saveScene(io::IXMLWriter* writer, const io::path& currentPath, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0) = 0; //! Loads a scene. Note that the current scene is not cleared before. /** The scene is usually loaded from an .irr file, an xml based format, but other scene formats can be added to the engine via ISceneManager::addExternalSceneLoader. .irr files can Be edited with the Irrlicht Engine Editor, irrEdit (http://www.ambiera.com/irredit/) or saved directly by the engine using ISceneManager::saveScene(). \param filename Name of the file to load from. \param userDataSerializer If you want to load user data possibily saved in that file for some scene nodes in the file, implement the ISceneUserDataSerializer interface and provide it as parameter here. Otherwise, simply specify 0 as this parameter. \param rootNode Node which is taken as the root node of the scene. Pass 0 to add the scene directly to the scene manager (which is also the default). \return True if successful. */ virtual bool loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* rootNode=0) = 0; //! Loads a scene. Note that the current scene is not cleared before. /** The scene is usually loaded from an .irr file, an xml based format, but other scene formats can be added to the engine via ISceneManager::addExternalSceneLoader. .irr files can Be edited with the Irrlicht Engine Editor, irrEdit (http://www.ambiera.com/irredit/) or saved directly by the engine using ISceneManager::saveScene(). \param file File where the scene is loaded from. \param userDataSerializer If you want to load user data possibily saved in that file for some scene nodes in the file, implement the ISceneUserDataSerializer interface and provide it as parameter here. Otherwise, simply specify 0 as this parameter. \param rootNode Node which is taken as the root node of the scene. Pass 0 to add the scene directly to the scene manager (which is also the default). \return True if successful. */ virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* rootNode=0) = 0; //! Get a mesh writer implementation if available /** Note: You need to drop() the pointer after use again, see IReferenceCounted::drop() for details. */ virtual IMeshWriter* createMeshWriter(EMESH_WRITER_TYPE type) = 0; //! Get a skinned mesh, which is not available as header-only code /** Note: You need to drop() the pointer after use again, see IReferenceCounted::drop() for details. */ virtual ISkinnedMesh* createSkinnedMesh() = 0; //! Sets ambient color of the scene virtual void setAmbientLight(const video::SColorf &ambientColor) = 0; //! Get ambient color of the scene virtual const video::SColorf& getAmbientLight() const = 0; //! Register a custom callbacks manager which gets callbacks during scene rendering. /** \param[in] lightManager: the new callbacks manager. You may pass 0 to remove the current callbacks manager and restore the default behavior. */ virtual void setLightManager(ILightManager* lightManager) = 0; //! Get an instance of a geometry creator. /** The geometry creator provides some helper methods to create various types of basic geometry. This can be useful for custom scene nodes. */ virtual const IGeometryCreator* getGeometryCreator(void) const = 0; //! Check if node is culled in current view frustum /** Please note that depending on the used culling method this check can be rather coarse, or slow. A positive result is correct, though, i.e. if this method returns true the node is positively not visible. The node might still be invisible even if this method returns false. \param node The scene node which is checked for culling. \return True if node is not visible in the current scene, else false. */ virtual bool isCulled(const ISceneNode* node) const =0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ISceneLoader.h0000644000000000000000000000424212574354552016150 0ustar rootroot// Copyright (C) 2010-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_LOADER_H_INCLUDED__ #define __I_SCENE_LOADER_H_INCLUDED__ #include "IReferenceCounted.h" #include "path.h" namespace irr { namespace io { class IReadFile; } // end namespace io namespace scene { class ISceneNode; class ISceneUserDataSerializer; //! Class which can load a scene into the scene manager. /** If you want Irrlicht to be able to load currently unsupported scene file formats (e.g. .vrml), then implement this and add your new Sceneloader to the engine with ISceneManager::addExternalSceneLoader(). */ class ISceneLoader : public virtual IReferenceCounted { public: //! Returns true if the class might be able to load this file. /** This decision should be based on the file extension (e.g. ".vrml") only. \param filename Name of the file to test. \return True if the extension is a recognised type. */ virtual bool isALoadableFileExtension(const io::path& filename) const = 0; //! Returns true if the class might be able to load this file. /** This decision will be based on a quick look at the contents of the file. \param file The file to test. \return True if the extension is a recognised type. */ virtual bool isALoadableFileFormat(io::IReadFile* file) const = 0; //! Loads the scene into the scene manager. /** \param file File which contains the scene. \param userDataSerializer: If you want to load user data which may be attached to some some scene nodes in the file, implement the ISceneUserDataSerializer interface and provide it as parameter here. Otherwise, simply specify 0 as this parameter. \param rootNode The node to load the scene into, if none is provided then the scene will be loaded into the root node. \return Returns true on success, false on failure. Returns 0 if loading failed. */ virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* rootNode=0) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ISceneCollisionManager.h0000644000000000000000000002445212574354552020175 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SCENE_COLLISION_MANAGER_H_INCLUDED__ #define __I_SCENE_COLLISION_MANAGER_H_INCLUDED__ #include "IReferenceCounted.h" #include "vector3d.h" #include "triangle3d.h" #include "position2d.h" #include "line3d.h" namespace irr { namespace scene { class ISceneNode; class ICameraSceneNode; class ITriangleSelector; //! The Scene Collision Manager provides methods for performing collision tests and picking on scene nodes. class ISceneCollisionManager : public virtual IReferenceCounted { public: //! Finds the nearest collision point of a line and lots of triangles, if there is one. /** \param ray: Line with which collisions are tested. \param selector: TriangleSelector containing the triangles. It can be created for example using ISceneManager::createTriangleSelector() or ISceneManager::createTriangleOctreeSelector(). \param outCollisionPoint: If a collision is detected, this will contain the position of the nearest collision to the line-start. \param outTriangle: If a collision is detected, this will contain the triangle with which the ray collided. \param outNode: If a collision is detected, this will contain the scene node associated with the triangle that was hit. \return True if a collision was detected and false if not. */ virtual bool getCollisionPoint(const core::line3d& ray, ITriangleSelector* selector, core::vector3df& outCollisionPoint, core::triangle3df& outTriangle, ISceneNode*& outNode) =0; //! Collides a moving ellipsoid with a 3d world with gravity and returns the resulting new position of the ellipsoid. /** This can be used for moving a character in a 3d world: The character will slide at walls and is able to walk up stairs. The method used how to calculate the collision result position is based on the paper "Improved Collision detection and Response" by Kasper Fauerby. \param selector: TriangleSelector containing the triangles of the world. It can be created for example using ISceneManager::createTriangleSelector() or ISceneManager::createTriangleOctreeSelector(). \param ellipsoidPosition: Position of the ellipsoid. \param ellipsoidRadius: Radius of the ellipsoid. \param ellipsoidDirectionAndSpeed: Direction and speed of the movement of the ellipsoid. \param triout: Optional parameter where the last triangle causing a collision is stored, if there is a collision. \param hitPosition: Return value for the position of the collision \param outFalling: Is set to true if the ellipsoid is falling down, caused by gravity. \param outNode: the node with which the ellipoid collided (if any) \param slidingSpeed: DOCUMENTATION NEEDED. \param gravityDirectionAndSpeed: Direction and force of gravity. \return New position of the ellipsoid. */ virtual core::vector3df getCollisionResultPosition( ITriangleSelector* selector, const core::vector3df &ellipsoidPosition, const core::vector3df& ellipsoidRadius, const core::vector3df& ellipsoidDirectionAndSpeed, core::triangle3df& triout, core::vector3df& hitPosition, bool& outFalling, ISceneNode*& outNode, f32 slidingSpeed = 0.0005f, const core::vector3df& gravityDirectionAndSpeed = core::vector3df(0.0f, 0.0f, 0.0f)) = 0; //! Returns a 3d ray which would go through the 2d screen coodinates. /** \param pos: Screen coordinates in pixels. \param camera: Camera from which the ray starts. If null, the active camera is used. \return Ray starting from the position of the camera and ending at a length of the far value of the camera at a position which would be behind the 2d screen coodinates. */ virtual core::line3d getRayFromScreenCoordinates( const core::position2d& pos, ICameraSceneNode* camera = 0) = 0; //! Calculates 2d screen position from a 3d position. /** \param pos: 3D position in world space to be transformed into 2d. \param camera: Camera to be used. If null, the currently active camera is used. \param useViewPort: Calculate screen coordinates relative to the current view port. Please note that unless the driver does not take care of the view port, it is usually best to get the result in absolute screen coordinates (flag=false). \return 2d screen coordinates which a object in the 3d world would have if it would be rendered to the screen. If the 3d position is behind the camera, it is set to (-1000,-1000). In most cases you can ignore this fact, because if you use this method for drawing a decorator over a 3d object, it will be clipped by the screen borders. */ virtual core::position2d getScreenCoordinatesFrom3DPosition( const core::vector3df& pos, ICameraSceneNode* camera=0, bool useViewPort=false) = 0; //! Gets the scene node, which is currently visible under the given screencoordinates, viewed from the currently active camera. /** The collision tests are done using a bounding box for each scene node. You can limit the recursive search so just all children of the specified root are tested. \param pos: Position in pixel screen coordinates, under which the returned scene node will be. \param idBitMask: Only scene nodes with an id with bits set like in this mask will be tested. If the BitMask is 0, this feature is disabled. Please note that the default node id of -1 will match with every bitmask != 0 \param bNoDebugObjects: Doesn't take debug objects into account when true. These are scene nodes with IsDebugObject() = true. \param root If different from 0, the search is limited to the children of this node. \return Visible scene node under screen coordinates with matching bits in its id. If there is no scene node under this position, 0 is returned. */ virtual ISceneNode* getSceneNodeFromScreenCoordinatesBB(const core::position2d& pos, s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0) =0; //! Returns the nearest scene node which collides with a 3d ray and whose id matches a bitmask. /** The collision tests are done using a bounding box for each scene node. The recursive search can be limited be specifying a scene node. \param ray Line with which collisions are tested. \param idBitMask Only scene nodes with an id which matches at least one of the bits contained in this mask will be tested. However, if this parameter is 0, then all nodes are checked. \param bNoDebugObjects: Doesn't take debug objects into account when true. These are scene nodes with IsDebugObject() = true. \param root If different from 0, the search is limited to the children of this node. \return Scene node nearest to ray.start, which collides with the ray and matches the idBitMask, if the mask is not null. If no scene node is found, 0 is returned. */ virtual ISceneNode* getSceneNodeFromRayBB(const core::line3d& ray, s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0) =0; //! Get the scene node, which the given camera is looking at and whose id matches the bitmask. /** A ray is simply casted from the position of the camera to the view target position, and all scene nodes are tested against this ray. The collision tests are done using a bounding box for each scene node. \param camera: Camera from which the ray is casted. \param idBitMask: Only scene nodes with an id which matches at least one of the bits contained in this mask will be tested. However, if this parameter is 0, then all nodes are checked. feature is disabled. Please note that the default node id of -1 will match with every bitmask != 0 \param bNoDebugObjects: Doesn't take debug objects into account when true. These are scene nodes with IsDebugObject() = true. \return Scene node nearest to the camera, which collides with the ray and matches the idBitMask, if the mask is not null. If no scene node is found, 0 is returned. */ virtual ISceneNode* getSceneNodeFromCameraBB(ICameraSceneNode* camera, s32 idBitMask=0, bool bNoDebugObjects = false) = 0; //! Perform a ray/box and ray/triangle collision check on a heirarchy of scene nodes. /** This checks all scene nodes under the specified one, first by ray/bounding box, and then by accurate ray/triangle collision, finding the nearest collision, and the scene node containg it. It returns the node hit, and (via output parameters) the position of the collision, and the triangle that was hit. All scene nodes in the hierarchy tree under the specified node are checked. Only nodes that are visible, with an ID that matches at least one bit in the supplied bitmask, and which have a triangle selector are considered as candidates for being hit. You do not have to build a meta triangle selector; the individual triangle selectors of each candidate scene node are used automatically. \param ray: Line with which collisions are tested. \param outCollisionPoint: If a collision is detected, this will contain the position of the nearest collision. \param outTriangle: If a collision is detected, this will contain the triangle with which the ray collided. \param idBitMask: Only scene nodes with an id which matches at least one of the bits contained in this mask will be tested. However, if this parameter is 0, then all nodes are checked. \param collisionRootNode: the scene node at which to begin checking. Only this node and its children will be checked. If you want to check the entire scene, pass 0, and the root scene node will be used (this is the default). \param noDebugObjects: when true, debug objects are not considered viable targets. Debug objects are scene nodes with IsDebugObject() = true. \return Returns the scene node containing the hit triangle nearest to ray.start. If no collision is detected, then 0 is returned. */ virtual ISceneNode* getSceneNodeAndCollisionPointFromRay( core::line3df ray, core::vector3df & outCollisionPoint, core::triangle3df & outTriangle, s32 idBitMask = 0, ISceneNode * collisionRootNode = 0, bool noDebugObjects = false) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/irrXML.h0000644000000000000000000006013112574354552015027 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h #ifndef __IRR_XML_H_INCLUDED__ #define __IRR_XML_H_INCLUDED__ #include #include "IrrCompileConfig.h" /** \mainpage irrXML 1.2 API documentation
\section intro Introduction Welcome to the irrXML API documentation. Here you'll find any information you'll need to develop applications with irrXML. If you look for a tutorial on how to start, take a look at the \ref irrxmlexample, at the homepage of irrXML at www.ambiera.com/irrxml/ or into the SDK in the directory example. irrXML is intended to be a high speed and easy-to-use XML Parser for C++, and this documentation is an important part of it. If you have any questions or suggestions, just send a email to the author of the engine, Nikolaus Gebhardt (niko (at) irrlicht3d.org). For more informations about this parser, see \ref history. \section features Features irrXML provides forward-only, read-only access to a stream of non validated XML data. It was fully implemented by Nikolaus Gebhardt. Its current features are: - It it fast as lighting and has very low memory usage. It was developed with the intention of being used in 3D games, as it already has been. - irrXML is very small: It only consists of 60 KB of code and can be added easily to your existing project. - Of course, it is platform independent and works with lots of compilers. - It is able to parse ASCII, UTF-8, UTF-16 and UTF-32 text files, both in little and big endian format. - Independent of the input file format, the parser can return all strings in ASCII, UTF-8, UTF-16 and UTF-32 format. - With its optional file access abstraction it has the advantage that it can read not only from files but from any type of data (memory, network, ...). For example when used with the Irrlicht Engine, it directly reads from compressed .zip files. - Just like the Irrlicht Engine for which it was originally created, it is extremely easy to use. - It has no external dependencies, it does not even need the STL. Although irrXML has some strenghts, it currently also has the following limitations: - The input xml file is not validated and assumed to be correct. \section irrxmlexample Example The following code demonstrates the basic usage of irrXML. A simple xml file like this is parsed: \code Welcome to the Mesh Viewer of the "Irrlicht Engine". \endcode The code for parsing this file would look like this: \code #include using namespace irr; // irrXML is located in the namespace irr::io using namespace io; #include // we use STL strings to store data in this example void main() { // create the reader using one of the factory functions IrrXMLReader* xml = createIrrXMLReader("config.xml"); // strings for storing the data we want to get out of the file std::string modelFile; std::string messageText; std::string caption; // parse the file until end reached while(xml && xml->read()) { switch(xml->getNodeType()) { case EXN_TEXT: // in this xml file, the only text which occurs is the messageText messageText = xml->getNodeData(); break; case EXN_ELEMENT: { if (!strcmp("model", xml->getNodeName())) modelFile = xml->getAttributeValue("file"); else if (!strcmp("messageText", xml->getNodeName())) caption = xml->getAttributeValue("caption"); } break; } } // delete the xml parser after usage delete xml; } \endcode \section howto How to use Simply add the source files in the /src directory of irrXML to your project. Done. \section license License The irrXML license is based on the zlib license. Basicly, this means you can do with irrXML whatever you want: Copyright (C) 2002-2012 Nikolaus Gebhardt This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. \section history History As lots of references in this documentation and the source show, this xml parser has originally been a part of the Irrlicht Engine. But because the parser has become very useful with the latest release, people asked for a separate version of it, to be able to use it in non Irrlicht projects. With irrXML 1.0, this has now been done. */ namespace irr { namespace io { //! Enumeration of all supported source text file formats enum ETEXT_FORMAT { //! ASCII, file without byte order mark, or not a text file ETF_ASCII, //! UTF-8 format ETF_UTF8, //! UTF-16 format, big endian ETF_UTF16_BE, //! UTF-16 format, little endian ETF_UTF16_LE, //! UTF-32 format, big endian ETF_UTF32_BE, //! UTF-32 format, little endian ETF_UTF32_LE }; //! Enumeration for all xml nodes which are parsed by IrrXMLReader enum EXML_NODE { //! No xml node. This is usually the node if you did not read anything yet. EXN_NONE, //! An xml element such as <foo> EXN_ELEMENT, //! End of an xml element such as </foo> EXN_ELEMENT_END, //! Text within an xml element: <foo> this is the text. </foo> //! Also text between 2 xml elements: </foo> this is the text. <foo> EXN_TEXT, //! An xml comment like <!-- I am a comment --> or a DTD definition. EXN_COMMENT, //! An xml cdata section like <![CDATA[ this is some CDATA ]]> EXN_CDATA, //! Unknown element. EXN_UNKNOWN }; //! Callback class for file read abstraction. /** With this, it is possible to make the xml parser read in other things than just files. The Irrlicht engine is using this for example to read xml from compressed .zip files. To make the parser read in any other data, derive a class from this interface, implement the two methods to read your data and give a pointer to an instance of your implementation when calling createIrrXMLReader(), createIrrXMLReaderUTF16() or createIrrXMLReaderUTF32() */ class IFileReadCallBack { public: //! Destructor virtual ~IFileReadCallBack() {} //! Reads an amount of bytes from the file. /** \param buffer: Pointer to buffer where to read bytes will be written to. \param sizeToRead: Amount of bytes to read from the file. \return Returns how much bytes were read. */ virtual int read(void* buffer, int sizeToRead) = 0; //! Returns size of file in bytes virtual long getSize() const = 0; }; //! Empty class to be used as parent class for IrrXMLReader. /** If you need another class as base class for the xml reader, you can do this by creating the reader using for example new CXMLReaderImpl(yourcallback); The Irrlicht Engine for example needs IReferenceCounted as base class for every object to let it automaticly reference countend, hence it replaces IXMLBase with IReferenceCounted. See irrXML.cpp on how this can be done in detail. */ class IXMLBase { }; //! Interface providing easy read access to a XML file. /** You can create an instance of this reader using one of the factory functions createIrrXMLReader(), createIrrXMLReaderUTF16() and createIrrXMLReaderUTF32(). If using the parser from the Irrlicht Engine, please use IFileSystem::createXMLReader() instead. For a detailed intro how to use the parser, see \ref irrxmlexample and \ref features. The typical usage of this parser looks like this: \code #include using namespace irr; // irrXML is located in the namespace irr::io using namespace io; void main() { // create the reader using one of the factory functions IrrXMLReader* xml = createIrrXMLReader("config.xml"); if (xml == 0) return; // file could not be opened // parse the file until end reached while(xml->read()) { // based on xml->getNodeType(), do something. } // delete the xml parser after usage delete xml; } \endcode See \ref irrxmlexample for a more detailed example. */ template class IIrrXMLReader : public super_class { public: //! Destructor virtual ~IIrrXMLReader() {} //! Reads forward to the next xml node. /** \return Returns false, if there was no further node. */ virtual bool read() = 0; //! Returns the type of the current XML node. virtual EXML_NODE getNodeType() const = 0; //! Returns attribute count of the current XML node. /** This is usually non null if the current node is EXN_ELEMENT, and the element has attributes. \return Returns amount of attributes of this xml node. */ virtual unsigned int getAttributeCount() const = 0; //! Returns name of an attribute. /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. \return Name of the attribute, 0 if an attribute with this index does not exist. */ virtual const char_type* getAttributeName(int idx) const = 0; //! Returns the value of an attribute. /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. \return Value of the attribute, 0 if an attribute with this index does not exist. */ virtual const char_type* getAttributeValue(int idx) const = 0; //! Returns the value of an attribute. /** \param name: Name of the attribute. \return Value of the attribute, 0 if an attribute with this name does not exist. */ virtual const char_type* getAttributeValue(const char_type* name) const = 0; //! Returns the value of an attribute in a safe way. /** Like getAttributeValue(), but does not return 0 if the attribute does not exist. An empty string ("") is returned then. \param name: Name of the attribute. \return Value of the attribute, and "" if an attribute with this name does not exist */ virtual const char_type* getAttributeValueSafe(const char_type* name) const = 0; //! Returns the value of an attribute as integer. /** \param name Name of the attribute. \return Value of the attribute as integer, and 0 if an attribute with this name does not exist or the value could not be interpreted as integer. */ virtual int getAttributeValueAsInt(const char_type* name) const = 0; //! Returns the value of an attribute as integer. /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. \return Value of the attribute as integer, and 0 if an attribute with this index does not exist or the value could not be interpreted as integer. */ virtual int getAttributeValueAsInt(int idx) const = 0; //! Returns the value of an attribute as float. /** \param name: Name of the attribute. \return Value of the attribute as float, and 0 if an attribute with this name does not exist or the value could not be interpreted as float. */ virtual float getAttributeValueAsFloat(const char_type* name) const = 0; //! Returns the value of an attribute as float. /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. \return Value of the attribute as float, and 0 if an attribute with this index does not exist or the value could not be interpreted as float. */ virtual float getAttributeValueAsFloat(int idx) const = 0; //! Returns the name of the current node. /** Only valid, if the node type is EXN_ELEMENT. \return Name of the current node or 0 if the node has no name. */ virtual const char_type* getNodeName() const = 0; //! Returns data of the current node. /** Only valid if the node has some data and it is of type EXN_TEXT, EXN_COMMENT, EXN_CDATA or EXN_UNKNOWN. */ virtual const char_type* getNodeData() const = 0; //! Returns if an element is an empty element, like <foo /> virtual bool isEmptyElement() const = 0; //! Returns format of the source xml file. /** It is not necessary to use this method because the parser will convert the input file format to the format wanted by the user when creating the parser. This method is useful to get/display additional informations. */ virtual ETEXT_FORMAT getSourceFormat() const = 0; //! Returns format of the strings returned by the parser. /** This will be UTF8 for example when you created a parser with IrrXMLReaderUTF8() and UTF32 when it has been created using IrrXMLReaderUTF32. It should not be necessary to call this method and only exists for informational purposes. */ virtual ETEXT_FORMAT getParserFormat() const = 0; }; template struct xmlChar { T c; xmlChar() {} xmlChar(char in) : c(static_cast(in)) {} xmlChar(wchar_t in) : c(static_cast(in)) {} #if defined(__BORLANDC__) // Note - removing explicit for borland was to get it to even compile. // There haven't been any kind of tests for that besides that. xmlChar(unsigned char in) : c(static_cast(in)) {} xmlChar(unsigned short in) : c(static_cast(in)) {} xmlChar(unsigned int in) : c(static_cast(in)) {} xmlChar(unsigned long in) : c(static_cast(in)) {} #else explicit xmlChar(unsigned char in) : c(static_cast(in)) {} explicit xmlChar(unsigned short in) : c(static_cast(in)) {} explicit xmlChar(unsigned int in) : c(static_cast(in)) {} explicit xmlChar(unsigned long in) : c(static_cast(in)) {} #endif operator T() const { return c; } void operator=(int t) { c=static_cast(t); } }; //! defines the utf-16 type. /** Not using wchar_t for this because wchar_t has 16 bit on windows and 32 bit on other operating systems. */ typedef xmlChar char16; //! defines the utf-32 type. /** Not using wchar_t for this because wchar_t has 16 bit on windows and 32 bit on other operating systems. */ typedef xmlChar char32; //! A UTF-8 or ASCII character xml parser. /** This means that all character data will be returned in 8 bit ASCII or UTF-8 by this parser. The file to read can be in any format, it will be converted to UTF-8 if it is not in this format. Create an instance of this with createIrrXMLReader(); See IIrrXMLReader for description on how to use it. */ typedef IIrrXMLReader IrrXMLReader; //! A UTF-16 xml parser. /** This means that all character data will be returned in UTF-16 by this parser. The file to read can be in any format, it will be converted to UTF-16 if it is not in this format. Create an instance of this with createIrrXMLReaderUTF16(); See IIrrXMLReader for description on how to use it. */ typedef IIrrXMLReader IrrXMLReaderUTF16; //! A UTF-32 xml parser. /** This means that all character data will be returned in UTF-32 by this parser. The file to read can be in any format, it will be converted to UTF-32 if it is not in this format. Create an instance of this with createIrrXMLReaderUTF32(); See IIrrXMLReader for description on how to use it. */ typedef IIrrXMLReader IrrXMLReaderUTF32; //! Creates an instance of an UFT-8 or ASCII character xml parser. /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can be in any format, it will be converted to UTF-8 if it is not in this format. If you are using the Irrlicht Engine, it is better not to use this function but IFileSystem::createXMLReaderUTF8() instead. \param filename: Name of file to be opened. \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(const char* filename); //! Creates an instance of an UFT-8 or ASCII character xml parser. /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can be in any format, it will be converted to UTF-8 if it is not in this format. If you are using the Irrlicht Engine, it is better not to use this function but IFileSystem::createXMLReaderUTF8() instead. \param file: Pointer to opened file, must have been opened in binary mode, e.g. using fopen("foo.bar", "wb"); The file will not be closed after it has been read. \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(FILE* file); //! Creates an instance of an UFT-8 or ASCII character xml parser. /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can be in any format, it will be converted to UTF-8 if it is not in this format. If you are using the Irrlicht Engine, it is better not to use this function but IFileSystem::createXMLReaderUTF8() instead. \param callback: Callback for file read abstraction. Implement your own callback to make the xml parser read in other things than just files. See IFileReadCallBack for more information about this. \param deleteCallback: if true, the callback will be deleted after the file has been read. Otherwise the caller si responsible for cleaning it up. \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(IFileReadCallBack* callback, bool deleteCallback = false); //! Creates an instance of an UFT-16 xml parser. /** This means that all character data will be returned in UTF-16. The file to read can be in any format, it will be converted to UTF-16 if it is not in this format. If you are using the Irrlicht Engine, it is better not to use this function but IFileSystem::createXMLReader() instead. \param filename: Name of file to be opened. \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(const char* filename); //! Creates an instance of an UFT-16 xml parser. /** This means that all character data will be returned in UTF-16. The file to read can be in any format, it will be converted to UTF-16 if it is not in this format. If you are using the Irrlicht Engine, it is better not to use this function but IFileSystem::createXMLReader() instead. \param file: Pointer to opened file, must have been opened in binary mode, e.g. using fopen("foo.bar", "wb"); The file will not be closed after it has been read. \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(FILE* file); //! Creates an instance of an UFT-16 xml parser. /** This means that all character data will be returned in UTF-16. The file to read can be in any format, it will be converted to UTF-16 if it is not in this format. If you are using the Irrlicht Engine, it is better not to use this function but IFileSystem::createXMLReader() instead. \param callback: Callback for file read abstraction. Implement your own callback to make the xml parser read in other things than just files. See IFileReadCallBack for more information about this. \param deleteCallback: if true, the callback will be deleted after the file has been read. Otherwise the caller si responsible for cleaning it up. \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(IFileReadCallBack* callback, bool deleteCallback = false); //! Creates an instance of an UFT-32 xml parser. /** This means that all character data will be returned in UTF-32. The file to read can be in any format, it will be converted to UTF-32 if it is not in this format. If you are using the Irrlicht Engine, it is better not to use this function but IFileSystem::createXMLReader() instead. \param filename: Name of file to be opened. \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(const char* filename); //! Creates an instance of an UFT-32 xml parser. /** This means that all character data will be returned in UTF-32. The file to read can be in any format, it will be converted to UTF-32 if it is not in this format. if you are using the Irrlicht Engine, it is better not to use this function but IFileSystem::createXMLReader() instead. \param file: Pointer to opened file, must have been opened in binary mode, e.g. using fopen("foo.bar", "wb"); The file will not be closed after it has been read. \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(FILE* file); //! Creates an instance of an UFT-32 xml parser. /** This means that all character data will be returned in UTF-32. The file to read can be in any format, it will be converted to UTF-32 if it is not in this format. If you are using the Irrlicht Engine, it is better not to use this function but IFileSystem::createXMLReader() instead. \param callback: Callback for file read abstraction. Implement your own callback to make the xml parser read in other things than just files. See IFileReadCallBack for more information about this. \param deleteCallback: if true, the callback will be deleted after the file has been read. Otherwise the caller si responsible for cleaning it up. \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(IFileReadCallBack* callback, bool deleteCallback = false); /*! \file irrXML.h \brief Header file of the irrXML, the Irrlicht XML parser. This file includes everything needed for using irrXML, the XML parser of the Irrlicht Engine. To use irrXML, you only need to include this file in your project: \code #include \endcode It is also common to use the two namespaces in which irrXML is included, directly after including irrXML.h: \code #include using namespace irr; using namespace io; \endcode */ } // end namespace io } // end namespace irr #endif // __IRR_XML_H_INCLUDED__ irrlicht-1.8.3/include/irrunpack.h0000644000000000000000000000120212574354552015642 0ustar rootroot// Copyright (C) 2007-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // include this file to switch back to default alignment // file belongs to irrpack.h, see there for more info // Default alignment #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( pop, packing ) #elif defined (__DMC__) # pragma pack( pop ) #elif defined( __GNUC__ ) # if (__GNUC__ > 4 ) || ((__GNUC__ == 4 ) && (__GNUC_MINOR__ >= 7)) # pragma pack( pop, packing ) # endif #endif #undef PACK_STRUCT irrlicht-1.8.3/include/irrTypes.h0000644000000000000000000001767212574354552015507 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_TYPES_H_INCLUDED__ #define __IRR_TYPES_H_INCLUDED__ #include "IrrCompileConfig.h" namespace irr { //! 8 bit unsigned variable. /** This is a typedef for unsigned char, it ensures portability of the engine. */ #if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) typedef unsigned __int8 u8; #else typedef unsigned char u8; #endif //! 8 bit signed variable. /** This is a typedef for signed char, it ensures portability of the engine. */ #if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) typedef __int8 s8; #else typedef signed char s8; #endif //! 8 bit character variable. /** This is a typedef for char, it ensures portability of the engine. */ typedef char c8; //! 16 bit unsigned variable. /** This is a typedef for unsigned short, it ensures portability of the engine. */ #if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) typedef unsigned __int16 u16; #else typedef unsigned short u16; #endif //! 16 bit signed variable. /** This is a typedef for signed short, it ensures portability of the engine. */ #if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) typedef __int16 s16; #else typedef signed short s16; #endif //! 32 bit unsigned variable. /** This is a typedef for unsigned int, it ensures portability of the engine. */ #if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) typedef unsigned __int32 u32; #else typedef unsigned int u32; #endif //! 32 bit signed variable. /** This is a typedef for signed int, it ensures portability of the engine. */ #if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) typedef __int32 s32; #else typedef signed int s32; #endif #ifdef __IRR_HAS_S64 //! 64 bit unsigned variable. /** This is a typedef for 64bit uint, it ensures portability of the engine. */ #if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) typedef unsigned __int64 u64; #elif __GNUC__ #if __WORDSIZE == 64 typedef unsigned long int u64; #else __extension__ typedef unsigned long long u64; #endif #else typedef unsigned long long u64; #endif //! 64 bit signed variable. /** This is a typedef for 64bit int, it ensures portability of the engine. */ #if defined(_MSC_VER) || ((__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) typedef __int64 s64; #elif __GNUC__ #if __WORDSIZE == 64 typedef long int s64; #else __extension__ typedef long long s64; #endif #else typedef long long s64; #endif #endif // __IRR_HAS_S64 //! 32 bit floating point variable. /** This is a typedef for float, it ensures portability of the engine. */ typedef float f32; //! 64 bit floating point variable. /** This is a typedef for double, it ensures portability of the engine. */ typedef double f64; } // end namespace irr #include #ifdef _IRR_WINDOWS_API_ //! Defines for s{w,n}printf because these methods do not match the ISO C //! standard on Windows platforms, but it does on all others. //! These should be int snprintf(char *str, size_t size, const char *format, ...); //! and int swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...); #if defined(_MSC_VER) && _MSC_VER > 1310 && !defined (_WIN32_WCE) #define swprintf swprintf_s #define snprintf sprintf_s #elif !defined(__CYGWIN__) #define swprintf _snwprintf #define snprintf _snprintf #endif // define the wchar_t type if not already built in. #ifdef _MSC_VER #ifndef _WCHAR_T_DEFINED //! A 16 bit wide character type. /** Defines the wchar_t-type. In VS6, its not possible to tell the standard compiler to treat wchar_t as a built-in type, and sometimes we just don't want to include the huge stdlib.h or wchar.h, so we'll use this. */ typedef unsigned short wchar_t; #define _WCHAR_T_DEFINED #endif // wchar is not defined #endif // microsoft compiler #endif // _IRR_WINDOWS_API_ namespace irr { //! Type name for character type used by the file system. /** Should the wide character version of the FileSystem be used it is a 16 bit character variable. Used for unicode Filesystem and unicode strings. Else it is a 8 bit character variable. Used for ansi Filesystem and non-unicode strings */ #if defined(_IRR_WCHAR_FILESYSTEM) typedef wchar_t fschar_t; #define _IRR_TEXT(X) L##X #else typedef char fschar_t; #define _IRR_TEXT(X) X #endif } // end namespace irr //! define a break macro for debugging. #if defined(_DEBUG) #if defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && !defined (_WIN32_WCE) #if defined(WIN64) || defined(_WIN64) // using portable common solution for x64 configuration #include #define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) if (_CONDITION_) {_CrtDbgBreak();} #else #define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) if (_CONDITION_) {_asm int 3} #endif #else #include "assert.h" #define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) assert( !(_CONDITION_) ); #endif #else #define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) #endif //! Defines a deprecated macro which generates a warning at compile time /** The usage is simple For typedef: typedef _IRR_DEPRECATED_ int test1; For classes/structs: class _IRR_DEPRECATED_ test2 { ... }; For methods: class test3 { _IRR_DEPRECATED_ virtual void foo() {} }; For functions: template _IRR_DEPRECATED_ void test4(void) {} **/ #if defined(IGNORE_DEPRECATED_WARNING) #define _IRR_DEPRECATED_ #elif _MSC_VER >= 1310 //vs 2003 or higher #define _IRR_DEPRECATED_ __declspec(deprecated) #elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) // all versions above 3.0 should support this feature #define _IRR_DEPRECATED_ __attribute__ ((deprecated)) #else #define _IRR_DEPRECATED_ #endif //! Defines a small statement to work around a microsoft compiler bug. /** The microsoft compiler 7.0 - 7.1 has a bug: When you call unmanaged code that returns a bool type value of false from managed code, the return value may appear as true. See http://support.microsoft.com/default.aspx?kbid=823071 for details. Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/ #if defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400) #define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX __asm mov eax,100 #else #define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX #endif // _IRR_MANAGED_MARSHALLING_BUGFIX // memory debugging #if defined(_DEBUG) && defined(IRRLICHT_EXPORTS) && defined(_MSC_VER) && \ (_MSC_VER > 1299) && !defined(_IRR_DONT_DO_MEMORY_DEBUGGING_HERE) && !defined(_WIN32_WCE) #define CRTDBG_MAP_ALLOC #define _CRTDBG_MAP_ALLOC #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) #include #include #define new DEBUG_CLIENTBLOCK #endif // disable truncated debug information warning in visual studio 6 by default #if defined(_MSC_VER) && (_MSC_VER < 1300 ) #pragma warning( disable: 4786) #endif // _MSC //! ignore VC8 warning deprecated /** The microsoft compiler */ #if defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && (_MSC_VER >= 1400) //#pragma warning( disable: 4996) //#define _CRT_SECURE_NO_DEPRECATE 1 //#define _CRT_NONSTDC_NO_DEPRECATE 1 #endif //! creates four CC codes used in Irrlicht for simple ids /** some compilers can create those by directly writing the code like 'code', but some generate warnings so we use this macro here */ #define MAKE_IRR_ID(c0, c1, c2, c3) \ ((irr::u32)(irr::u8)(c0) | ((irr::u32)(irr::u8)(c1) << 8) | \ ((irr::u32)(irr::u8)(c2) << 16) | ((irr::u32)(irr::u8)(c3) << 24 )) #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #define _strcmpi(a,b) strcmpi(a,b) #endif #endif // __IRR_TYPES_H_INCLUDED__ irrlicht-1.8.3/include/irrString.h0000644000000000000000000007204612574354552015645 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h #ifndef __IRR_STRING_H_INCLUDED__ #define __IRR_STRING_H_INCLUDED__ #include "irrTypes.h" #include "irrAllocator.h" #include "irrMath.h" #include #include #include namespace irr { namespace core { //! Very simple string class with some useful features. /** string and string both accept Unicode AND ASCII/Latin-1, so you can assign Unicode to string and ASCII/Latin-1 to string (and the other way round) if you want to. However, note that the conversation between both is not done using any encoding. This means that c8 strings are treated as ASCII/Latin-1, not UTF-8, and are simply expanded to the equivalent wchar_t, while Unicode/wchar_t characters are truncated to 8-bit ASCII/Latin-1 characters, discarding all other information in the wchar_t. */ enum eLocaleID { IRR_LOCALE_ANSI = 0, IRR_LOCALE_GERMAN = 1 }; static eLocaleID locale_current = IRR_LOCALE_ANSI; static inline void locale_set ( eLocaleID id ) { locale_current = id; } //! Returns a character converted to lower case static inline u32 locale_lower ( u32 x ) { switch ( locale_current ) { case IRR_LOCALE_GERMAN: case IRR_LOCALE_ANSI: break; } // ansi return x >= 'A' && x <= 'Z' ? x + 0x20 : x; } //! Returns a character converted to upper case static inline u32 locale_upper ( u32 x ) { switch ( locale_current ) { case IRR_LOCALE_GERMAN: case IRR_LOCALE_ANSI: break; } // ansi return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x; } template > class string { public: typedef T char_type; //! Default constructor string() : array(0), allocated(1), used(1) { array = allocator.allocate(1); // new T[1]; array[0] = 0; } //! Constructor string(const string& other) : array(0), allocated(0), used(0) { *this = other; } //! Constructor from other string types template string(const string& other) : array(0), allocated(0), used(0) { *this = other; } //! Constructs a string from a float explicit string(const double number) : array(0), allocated(0), used(0) { c8 tmpbuf[255]; snprintf(tmpbuf, 255, "%0.6f", number); *this = tmpbuf; } //! Constructs a string from an int explicit string(int number) : array(0), allocated(0), used(0) { // store if negative and make positive bool negative = false; if (number < 0) { number *= -1; negative = true; } // temporary buffer for 16 numbers c8 tmpbuf[16]={0}; u32 idx = 15; // special case '0' if (!number) { tmpbuf[14] = '0'; *this = &tmpbuf[14]; return; } // add numbers while(number && idx) { --idx; tmpbuf[idx] = (c8)('0' + (number % 10)); number /= 10; } // add sign if (negative) { --idx; tmpbuf[idx] = '-'; } *this = &tmpbuf[idx]; } //! Constructs a string from an unsigned int explicit string(unsigned int number) : array(0), allocated(0), used(0) { // temporary buffer for 16 numbers c8 tmpbuf[16]={0}; u32 idx = 15; // special case '0' if (!number) { tmpbuf[14] = '0'; *this = &tmpbuf[14]; return; } // add numbers while(number && idx) { --idx; tmpbuf[idx] = (c8)('0' + (number % 10)); number /= 10; } *this = &tmpbuf[idx]; } //! Constructs a string from a long explicit string(long number) : array(0), allocated(0), used(0) { // store if negative and make positive bool negative = false; if (number < 0) { number *= -1; negative = true; } // temporary buffer for 16 numbers c8 tmpbuf[16]={0}; u32 idx = 15; // special case '0' if (!number) { tmpbuf[14] = '0'; *this = &tmpbuf[14]; return; } // add numbers while(number && idx) { --idx; tmpbuf[idx] = (c8)('0' + (number % 10)); number /= 10; } // add sign if (negative) { --idx; tmpbuf[idx] = '-'; } *this = &tmpbuf[idx]; } //! Constructs a string from an unsigned long explicit string(unsigned long number) : array(0), allocated(0), used(0) { // temporary buffer for 16 numbers c8 tmpbuf[16]={0}; u32 idx = 15; // special case '0' if (!number) { tmpbuf[14] = '0'; *this = &tmpbuf[14]; return; } // add numbers while(number && idx) { --idx; tmpbuf[idx] = (c8)('0' + (number % 10)); number /= 10; } *this = &tmpbuf[idx]; } //! Constructor for copying a string from a pointer with a given length template string(const B* const c, u32 length) : array(0), allocated(0), used(0) { if (!c) { // correctly init the string to an empty one *this=""; return; } allocated = used = length+1; array = allocator.allocate(used); // new T[used]; for (u32 l = 0; l string(const B* const c) : array(0), allocated(0), used(0) { *this = c; } //! Destructor ~string() { allocator.deallocate(array); // delete [] array; } //! Assignment operator string& operator=(const string& other) { if (this == &other) return *this; used = other.size()+1; if (used>allocated) { allocator.deallocate(array); // delete [] array; allocated = used; array = allocator.allocate(used); //new T[used]; } const T* p = other.c_str(); for (u32 i=0; i string& operator=(const string& other) { *this = other.c_str(); return *this; } //! Assignment operator for strings, ascii and unicode template string& operator=(const B* const c) { if (!c) { if (!array) { array = allocator.allocate(1); //new T[1]; allocated = 1; } used = 1; array[0] = 0x0; return *this; } if ((void*)c == (void*)array) return *this; u32 len = 0; const B* p = c; do { ++len; } while(*p++); // we'll keep the old string for a while, because the new // string could be a part of the current string. T* oldArray = array; used = len; if (used>allocated) { allocated = used; array = allocator.allocate(used); //new T[used]; } for (u32 l = 0; l operator+(const string& other) const { string str(*this); str.append(other); return str; } //! Append operator for strings, ascii and unicode template string operator+(const B* const c) const { string str(*this); str.append(c); return str; } //! Direct access operator T& operator [](const u32 index) { _IRR_DEBUG_BREAK_IF(index>=used) // bad index return array[index]; } //! Direct access operator const T& operator [](const u32 index) const { _IRR_DEBUG_BREAK_IF(index>=used) // bad index return array[index]; } //! Equality operator bool operator==(const T* const str) const { if (!str) return false; u32 i; for (i=0; array[i] && str[i]; ++i) if (array[i] != str[i]) return false; return (!array[i] && !str[i]); } //! Equality operator bool operator==(const string& other) const { for (u32 i=0; array[i] && other.array[i]; ++i) if (array[i] != other.array[i]) return false; return used == other.used; } //! Is smaller comparator bool operator<(const string& other) const { for (u32 i=0; array[i] && other.array[i]; ++i) { const s32 diff = array[i] - other.array[i]; if (diff) return (diff < 0); } return (used < other.used); } //! Inequality operator bool operator!=(const T* const str) const { return !(*this == str); } //! Inequality operator bool operator!=(const string& other) const { return !(*this == other); } //! Returns length of the string's content /** \return Length of the string's content in characters, excluding the trailing NUL. */ u32 size() const { return used-1; } //! Informs if the string is empty or not. //! \return True if the string is empty, false if not. bool empty() const { return (size() == 0); } //! Returns character string /** \return pointer to C-style NUL terminated string. */ const T* c_str() const { return array; } //! Makes the string lower case. string& make_lower() { for (u32 i=0; array[i]; ++i) array[i] = locale_lower ( array[i] ); return *this; } //! Makes the string upper case. string& make_upper() { for (u32 i=0; array[i]; ++i) array[i] = locale_upper ( array[i] ); return *this; } //! Compares the strings ignoring case. /** \param other: Other string to compare. \return True if the strings are equal ignoring case. */ bool equals_ignore_case(const string& other) const { for(u32 i=0; array[i] && other[i]; ++i) if (locale_lower( array[i]) != locale_lower(other[i])) return false; return used == other.used; } //! Compares the strings ignoring case. /** \param other: Other string to compare. \param sourcePos: where to start to compare in the string \return True if the strings are equal ignoring case. */ bool equals_substring_ignore_case(const string&other, const s32 sourcePos = 0 ) const { if ( (u32) sourcePos >= used ) return false; u32 i; for( i=0; array[sourcePos + i] && other[i]; ++i) if (locale_lower( array[sourcePos + i]) != locale_lower(other[i])) return false; return array[sourcePos + i] == 0 && other[i] == 0; } //! Compares the strings ignoring case. /** \param other: Other string to compare. \return True if this string is smaller ignoring case. */ bool lower_ignore_case(const string& other) const { for(u32 i=0; array[i] && other.array[i]; ++i) { s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] ); if ( diff ) return diff < 0; } return used < other.used; } //! compares the first n characters of the strings /** \param other Other string to compare. \param n Number of characters to compare \return True if the n first characters of both strings are equal. */ bool equalsn(const string& other, u32 n) const { u32 i; for(i=0; array[i] && other[i] && i < n; ++i) if (array[i] != other[i]) return false; // if one (or both) of the strings was smaller then they // are only equal if they have the same length return (i == n) || (used == other.used); } //! compares the first n characters of the strings /** \param str Other string to compare. \param n Number of characters to compare \return True if the n first characters of both strings are equal. */ bool equalsn(const T* const str, u32 n) const { if (!str) return false; u32 i; for(i=0; array[i] && str[i] && i < n; ++i) if (array[i] != str[i]) return false; // if one (or both) of the strings was smaller then they // are only equal if they have the same length return (i == n) || (array[i] == 0 && str[i] == 0); } //! Appends a character to this string /** \param character: Character to append. */ string& append(T character) { if (used + 1 > allocated) reallocate(used + 1); ++used; array[used-2] = character; array[used-1] = 0; return *this; } //! Appends a char string to this string /** \param other: Char string to append. */ /** \param length: The length of the string to append. */ string& append(const T* const other, u32 length=0xffffffff) { if (!other) return *this; u32 len = 0; const T* p = other; while(*p) { ++len; ++p; } if (len > length) len = length; if (used + len > allocated) reallocate(used + len); --used; ++len; for (u32 l=0; l& append(const string& other) { if (other.size() == 0) return *this; --used; u32 len = other.size()+1; if (used + len > allocated) reallocate(used + len); for (u32 l=0; l& append(const string& other, u32 length) { if (other.size() == 0) return *this; if (other.size() < length) { append(other); return *this; } if (used + length > allocated) reallocate(used + length); --used; for (u32 l=0; l s32 findFirstCharNotInList(const B* const c, u32 count=1) const { if (!c || !count) return -1; for (u32 i=0; i s32 findLastCharNotInList(const B* const c, u32 count=1) const { if (!c || !count) return -1; for (s32 i=(s32)(used-2); i>=0; --i) { u32 j; for (j=0; j=0; --i) if (array[i] == c) return i; return -1; } //! finds last occurrence of a character of a list in string /** \param c: List of strings to find. For example if the method should find the last occurrence of 'a' or 'b', this parameter should be "ab". \param count: Amount of characters in the list. Usually, this should be strlen(c) \return Position where one of the characters has been found, or -1 if not found. */ s32 findLastChar(const T* const c, u32 count=1) const { if (!c || !count) return -1; for (s32 i=(s32)used-2; i>=0; --i) for (u32 j=0; j s32 find(const B* const str, const u32 start = 0) const { if (str && *str) { u32 len = 0; while (str[len]) ++len; if (len > used-1) return -1; for (u32 i=start; i subString(u32 begin, s32 length, bool make_lower = false ) const { // if start after string // or no proper substring length if ((length <= 0) || (begin>=size())) return string(""); // clamp length to maximal value if ((length+begin) > size()) length = size()-begin; string o; o.reserve(length+1); s32 i; if ( !make_lower ) { for (i=0; i& operator += (T c) { append(c); return *this; } //! Appends a char string to this string /** \param c Char string to append. */ string& operator += (const T* const c) { append(c); return *this; } //! Appends a string to this string /** \param other String to append. */ string& operator += (const string& other) { append(other); return *this; } //! Appends a string representation of a number to this string /** \param i Number to append. */ string& operator += (const int i) { append(string(i)); return *this; } //! Appends a string representation of a number to this string /** \param i Number to append. */ string& operator += (const unsigned int i) { append(string(i)); return *this; } //! Appends a string representation of a number to this string /** \param i Number to append. */ string& operator += (const long i) { append(string(i)); return *this; } //! Appends a string representation of a number to this string /** \param i Number to append. */ string& operator += (const unsigned long i) { append(string(i)); return *this; } //! Appends a string representation of a number to this string /** \param i Number to append. */ string& operator += (const double i) { append(string(i)); return *this; } //! Appends a string representation of a number to this string /** \param i Number to append. */ string& operator += (const float i) { append(string(i)); return *this; } //! Replaces all characters of a special type with another one /** \param toReplace Character to replace. \param replaceWith Character replacing the old one. */ string& replace(T toReplace, T replaceWith) { for (u32 i=0; i& replace(const string& toReplace, const string& replaceWith) { if (toReplace.size() == 0) return *this; const T* other = toReplace.c_str(); const T* replace = replaceWith.c_str(); const u32 other_size = toReplace.size(); const u32 replace_size = replaceWith.size(); // Determine the delta. The algorithm will change depending on the delta. s32 delta = replace_size - other_size; // A character for character replace. The string will not shrink or grow. if (delta == 0) { s32 pos = 0; while ((pos = find(other, pos)) != -1) { for (u32 i = 0; i < replace_size; ++i) array[pos + i] = replace[i]; ++pos; } return *this; } // We are going to be removing some characters. The string will shrink. if (delta < 0) { u32 i = 0; for (u32 pos = 0; pos < used; ++i, ++pos) { // Is this potentially a match? if (array[pos] == *other) { // Check to see if we have a match. u32 j; for (j = 0; j < other_size; ++j) { if (array[pos + j] != other[j]) break; } // If we have a match, replace characters. if (j == other_size) { for (j = 0; j < replace_size; ++j) array[i + j] = replace[j]; i += replace_size - 1; pos += other_size - 1; continue; } } // No match found, just copy characters. array[i] = array[pos]; } array[i-1] = 0; used = i; return *this; } // We are going to be adding characters, so the string size will increase. // Count the number of times toReplace exists in the string so we can allocate the new size. u32 find_count = 0; s32 pos = 0; while ((pos = find(other, pos)) != -1) { ++find_count; ++pos; } // Re-allocate the string now, if needed. u32 len = delta * find_count; if (used + len > allocated) reallocate(used + len); // Start replacing. pos = 0; while ((pos = find(other, pos)) != -1) { T* start = array + pos + other_size - 1; T* ptr = array + used - 1; T* end = array + delta + used -1; // Shift characters to make room for the string. while (ptr != start) { *end = *ptr; --ptr; --end; } // Add the new string now. for (u32 i = 0; i < replace_size; ++i) array[pos + i] = replace[i]; pos += replace_size; used += delta; } return *this; } //! Removes characters from a string. /** \param c: Character to remove. */ string& remove(T c) { u32 pos = 0; u32 found = 0; for (u32 i=0; i& remove(const string& toRemove) { u32 size = toRemove.size(); if ( size == 0 ) return *this; u32 pos = 0; u32 found = 0; for (u32 i=0; i& removeChars(const string & characters) { if (characters.size() == 0) return *this; u32 pos = 0; u32 found = 0; for (u32 i=0; i& trim(const string & whitespace = " \t\n\r") { // find start and end of the substring without the specified characters const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used); if (begin == -1) return (*this=""); const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.used); return (*this = subString(begin, (end +1) - begin)); } //! Erases a character from the string. /** May be slow, because all elements following after the erased element have to be copied. \param index: Index of element to be erased. */ string& erase(u32 index) { _IRR_DEBUG_BREAK_IF(index>=used) // access violation for (u32 i=index+1; i& validate() { // terminate on existing null for (u32 i=0; i 0 ) { used = allocated; array[used-1] = 0; } else { used = 0; } return *this; } //! gets the last char of a string or null T lastChar() const { return used > 1 ? array[used-2] : 0; } //! split string into parts. /** This method will split a string at certain delimiter characters into the container passed in as reference. The type of the container has to be given as template parameter. It must provide a push_back and a size method. \param ret The result container \param c C-style string of delimiter characters \param count Number of delimiter characters \param ignoreEmptyTokens Flag to avoid empty substrings in the result container. If two delimiters occur without a character in between, an empty substring would be placed in the result. If this flag is set, only non-empty strings are stored. \param keepSeparators Flag which allows to add the separator to the result string. If this flag is true, the concatenation of the substrings results in the original string. Otherwise, only the characters between the delimiters are returned. \return The number of resulting substrings */ template u32 split(container& ret, const T* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const { if (!c) return 0; const u32 oldSize=ret.size(); u32 lastpos = 0; bool lastWasSeparator = false; for (u32 i=0; i(&array[lastpos], i - lastpos)); foundSeparator = true; lastpos = (keepSeparators ? i : i + 1); break; } } lastWasSeparator = foundSeparator; } if ((used - 1) > lastpos) ret.push_back(string(&array[lastpos], (used - 1) - lastpos)); return ret.size()-oldSize; } private: //! Reallocate the array, make it bigger or smaller void reallocate(u32 new_size) { T* old_array = array; array = allocator.allocate(new_size); //new T[new_size]; allocated = new_size; u32 amount = used < new_size ? used : new_size; for (u32 i=0; i stringc; //! Typedef for wide character strings typedef string stringw; } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/irrpack.h0000644000000000000000000000264112574354552015307 0ustar rootroot// Copyright (C) 2007-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // include this file right before the data structures to be 1-aligned // and add to each structure the PACK_STRUCT define just like this: // struct mystruct // { // ... // } PACK_STRUCT; // Always include the irrunpack.h file right after the last type declared // like this, and do not put any other types with different alignment // in between! // byte-align structures #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma warning(disable: 4103) # pragma pack( push, packing ) # pragma pack( 1 ) # define PACK_STRUCT #elif defined( __DMC__ ) # pragma pack( push, 1 ) # define PACK_STRUCT #elif defined( __GNUC__ ) // Using pragma pack might work with earlier gcc versions already, but // it started to be necessary with gcc 4.7 on mingw unless compiled with -mno-ms-bitfields. // And I found some hints on the web that older gcc versions on the other hand had sometimes // trouble with pragma pack while they worked with __attribute__((packed)). # if (__GNUC__ > 4 ) || ((__GNUC__ == 4 ) && (__GNUC_MINOR__ >= 7)) # pragma pack( push, packing ) # pragma pack( 1 ) # define PACK_STRUCT # else # define PACK_STRUCT __attribute__((packed)) #endif #else # error compiler not supported #endif irrlicht-1.8.3/include/irrMath.h0000644000000000000000000004630712574354552015271 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_MATH_H_INCLUDED__ #define __IRR_MATH_H_INCLUDED__ #include "IrrCompileConfig.h" #include "irrTypes.h" #include #include #include // for abs() etc. #include // For INT_MAX / UINT_MAX #if defined(_IRR_SOLARIS_PLATFORM_) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) || defined (_WIN32_WCE) #define sqrtf(X) (irr::f32)sqrt((irr::f64)(X)) #define sinf(X) (irr::f32)sin((irr::f64)(X)) #define cosf(X) (irr::f32)cos((irr::f64)(X)) #define asinf(X) (irr::f32)asin((irr::f64)(X)) #define acosf(X) (irr::f32)acos((irr::f64)(X)) #define atan2f(X,Y) (irr::f32)atan2((irr::f64)(X),(irr::f64)(Y)) #define ceilf(X) (irr::f32)ceil((irr::f64)(X)) #define floorf(X) (irr::f32)floor((irr::f64)(X)) #define powf(X,Y) (irr::f32)pow((irr::f64)(X),(irr::f64)(Y)) #define fmodf(X,Y) (irr::f32)fmod((irr::f64)(X),(irr::f64)(Y)) #define fabsf(X) (irr::f32)fabs((irr::f64)(X)) #define logf(X) (irr::f32)log((irr::f64)(X)) #endif #ifndef FLT_MAX #define FLT_MAX 3.402823466E+38F #endif #ifndef FLT_MIN #define FLT_MIN 1.17549435e-38F #endif namespace irr { namespace core { //! Rounding error constant often used when comparing f32 values. const s32 ROUNDING_ERROR_S32 = 0; #ifdef __IRR_HAS_S64 const s64 ROUNDING_ERROR_S64 = 0; #endif const f32 ROUNDING_ERROR_f32 = 0.000001f; const f64 ROUNDING_ERROR_f64 = 0.00000001; #ifdef PI // make sure we don't collide with a define #undef PI #endif //! Constant for PI. const f32 PI = 3.14159265359f; //! Constant for reciprocal of PI. const f32 RECIPROCAL_PI = 1.0f/PI; //! Constant for half of PI. const f32 HALF_PI = PI/2.0f; #ifdef PI64 // make sure we don't collide with a define #undef PI64 #endif //! Constant for 64bit PI. const f64 PI64 = 3.1415926535897932384626433832795028841971693993751; //! Constant for 64bit reciprocal of PI. const f64 RECIPROCAL_PI64 = 1.0/PI64; //! 32bit Constant for converting from degrees to radians const f32 DEGTORAD = PI / 180.0f; //! 32bit constant for converting from radians to degrees (formally known as GRAD_PI) const f32 RADTODEG = 180.0f / PI; //! 64bit constant for converting from degrees to radians (formally known as GRAD_PI2) const f64 DEGTORAD64 = PI64 / 180.0; //! 64bit constant for converting from radians to degrees const f64 RADTODEG64 = 180.0 / PI64; //! Utility function to convert a radian value to degrees /** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X \param radians The radians value to convert to degrees. */ inline f32 radToDeg(f32 radians) { return RADTODEG * radians; } //! Utility function to convert a radian value to degrees /** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X \param radians The radians value to convert to degrees. */ inline f64 radToDeg(f64 radians) { return RADTODEG64 * radians; } //! Utility function to convert a degrees value to radians /** Provided as it can be clearer to write degToRad(X) than DEGTORAD * X \param degrees The degrees value to convert to radians. */ inline f32 degToRad(f32 degrees) { return DEGTORAD * degrees; } //! Utility function to convert a degrees value to radians /** Provided as it can be clearer to write degToRad(X) than DEGTORAD * X \param degrees The degrees value to convert to radians. */ inline f64 degToRad(f64 degrees) { return DEGTORAD64 * degrees; } //! returns minimum of two values. Own implementation to get rid of the STL (VS6 problems) template inline const T& min_(const T& a, const T& b) { return a < b ? a : b; } //! returns minimum of three values. Own implementation to get rid of the STL (VS6 problems) template inline const T& min_(const T& a, const T& b, const T& c) { return a < b ? min_(a, c) : min_(b, c); } //! returns maximum of two values. Own implementation to get rid of the STL (VS6 problems) template inline const T& max_(const T& a, const T& b) { return a < b ? b : a; } //! returns maximum of three values. Own implementation to get rid of the STL (VS6 problems) template inline const T& max_(const T& a, const T& b, const T& c) { return a < b ? max_(b, c) : max_(a, c); } //! returns abs of two values. Own implementation to get rid of STL (VS6 problems) template inline T abs_(const T& a) { return a < (T)0 ? -a : a; } //! returns linear interpolation of a and b with ratio t //! \return: a if t==0, b if t==1, and the linear interpolation else template inline T lerp(const T& a, const T& b, const f32 t) { return (T)(a*(1.f-t)) + (b*t); } //! clamps a value between low and high template inline const T clamp (const T& value, const T& low, const T& high) { return min_ (max_(value,low), high); } //! swaps the content of the passed parameters // Note: We use the same trick as boost and use two template arguments to // avoid ambiguity when swapping objects of an Irrlicht type that has not // it's own swap overload. Otherwise we get conflicts with some compilers // in combination with stl. template inline void swap(T1& a, T2& b) { T1 c(a); a = b; b = c; } //! returns if a equals b, taking possible rounding errors into account inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64) { return (a + tolerance >= b) && (a - tolerance <= b); } //! returns if a equals b, taking possible rounding errors into account inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32) { return (a + tolerance >= b) && (a - tolerance <= b); } union FloatIntUnion32 { FloatIntUnion32(float f1 = 0.0f) : f(f1) {} // Portable sign-extraction bool sign() const { return (i >> 31) != 0; } irr::s32 i; irr::f32 f; }; //! We compare the difference in ULP's (spacing between floating-point numbers, aka ULP=1 means there exists no float between). //\result true when numbers have a ULP <= maxUlpDiff AND have the same sign. inline bool equalsByUlp(f32 a, f32 b, int maxUlpDiff) { // Based on the ideas and code from Bruce Dawson on // http://www.altdevblogaday.com/2012/02/22/comparing-floating-point-numbers-2012-edition/ // When floats are interpreted as integers the two nearest possible float numbers differ just // by one integer number. Also works the other way round, an integer of 1 interpreted as float // is for example the smallest possible float number. FloatIntUnion32 fa(a); FloatIntUnion32 fb(b); // Different signs, we could maybe get difference to 0, but so close to 0 using epsilons is better. if ( fa.sign() != fb.sign() ) { // Check for equality to make sure +0==-0 if (fa.i == fb.i) return true; return false; } // Find the difference in ULPs. int ulpsDiff = abs_(fa.i- fb.i); if (ulpsDiff <= maxUlpDiff) return true; return false; } #if 0 //! returns if a equals b, not using any rounding tolerance inline bool equals(const s32 a, const s32 b) { return (a == b); } //! returns if a equals b, not using any rounding tolerance inline bool equals(const u32 a, const u32 b) { return (a == b); } #endif //! returns if a equals b, taking an explicit rounding tolerance into account inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32) { return (a + tolerance >= b) && (a - tolerance <= b); } //! returns if a equals b, taking an explicit rounding tolerance into account inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32) { return (a + tolerance >= b) && (a - tolerance <= b); } #ifdef __IRR_HAS_S64 //! returns if a equals b, taking an explicit rounding tolerance into account inline bool equals(const s64 a, const s64 b, const s64 tolerance = ROUNDING_ERROR_S64) { return (a + tolerance >= b) && (a - tolerance <= b); } #endif //! returns if a equals zero, taking rounding errors into account inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64) { return fabs(a) <= tolerance; } //! returns if a equals zero, taking rounding errors into account inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32) { return fabsf(a) <= tolerance; } //! returns if a equals not zero, taking rounding errors into account inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32) { return fabsf(a) > tolerance; } //! returns if a equals zero, taking rounding errors into account inline bool iszero(const s32 a, const s32 tolerance = 0) { return ( a & 0x7ffffff ) <= tolerance; } //! returns if a equals zero, taking rounding errors into account inline bool iszero(const u32 a, const u32 tolerance = 0) { return a <= tolerance; } #ifdef __IRR_HAS_S64 //! returns if a equals zero, taking rounding errors into account inline bool iszero(const s64 a, const s64 tolerance = 0) { return abs_(a) <= tolerance; } #endif inline s32 s32_min(s32 a, s32 b) { const s32 mask = (a - b) >> 31; return (a & mask) | (b & ~mask); } inline s32 s32_max(s32 a, s32 b) { const s32 mask = (a - b) >> 31; return (b & mask) | (a & ~mask); } inline s32 s32_clamp (s32 value, s32 low, s32 high) { return s32_min(s32_max(value,low), high); } /* float IEEE-754 bit represenation 0 0x00000000 1.0 0x3f800000 0.5 0x3f000000 3 0x40400000 +inf 0x7f800000 -inf 0xff800000 +NaN 0x7fc00000 or 0x7ff00000 in general: number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits) */ typedef union { u32 u; s32 s; f32 f; } inttofloat; #define F32_AS_S32(f) (*((s32 *) &(f))) #define F32_AS_U32(f) (*((u32 *) &(f))) #define F32_AS_U32_POINTER(f) ( ((u32 *) &(f))) #define F32_VALUE_0 0x00000000 #define F32_VALUE_1 0x3f800000 #define F32_SIGN_BIT 0x80000000U #define F32_EXPON_MANTISSA 0x7FFFFFFFU //! code is taken from IceFPU //! Integer representation of a floating-point value. #ifdef IRRLICHT_FAST_MATH #define IR(x) ((u32&)(x)) #else inline u32 IR(f32 x) {inttofloat tmp; tmp.f=x; return tmp.u;} #endif //! Absolute integer representation of a floating-point value #define AIR(x) (IR(x)&0x7fffffff) //! Floating-point representation of an integer value. #ifdef IRRLICHT_FAST_MATH #define FR(x) ((f32&)(x)) #else inline f32 FR(u32 x) {inttofloat tmp; tmp.u=x; return tmp.f;} inline f32 FR(s32 x) {inttofloat tmp; tmp.s=x; return tmp.f;} #endif //! integer representation of 1.0 #define IEEE_1_0 0x3f800000 //! integer representation of 255.0 #define IEEE_255_0 0x437f0000 #ifdef IRRLICHT_FAST_MATH #define F32_LOWER_0(f) (F32_AS_U32(f) > F32_SIGN_BIT) #define F32_LOWER_EQUAL_0(f) (F32_AS_S32(f) <= F32_VALUE_0) #define F32_GREATER_0(f) (F32_AS_S32(f) > F32_VALUE_0) #define F32_GREATER_EQUAL_0(f) (F32_AS_U32(f) <= F32_SIGN_BIT) #define F32_EQUAL_1(f) (F32_AS_U32(f) == F32_VALUE_1) #define F32_EQUAL_0(f) ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0) // only same sign #define F32_A_GREATER_B(a,b) (F32_AS_S32((a)) > F32_AS_S32((b))) #else #define F32_LOWER_0(n) ((n) < 0.0f) #define F32_LOWER_EQUAL_0(n) ((n) <= 0.0f) #define F32_GREATER_0(n) ((n) > 0.0f) #define F32_GREATER_EQUAL_0(n) ((n) >= 0.0f) #define F32_EQUAL_1(n) ((n) == 1.0f) #define F32_EQUAL_0(n) ((n) == 0.0f) #define F32_A_GREATER_B(a,b) ((a) > (b)) #endif #ifndef REALINLINE #ifdef _MSC_VER #define REALINLINE __forceinline #else #define REALINLINE inline #endif #endif #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) // 8-bit bools in borland builder //! conditional set based on mask and arithmetic shift REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b ) { return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b; } //! conditional set based on mask and arithmetic shift REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a ) { return ( -condition >> 31 ) & a; } #else //! conditional set based on mask and arithmetic shift REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b ) { return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b; } //! conditional set based on mask and arithmetic shift REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b ) { return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b; } //! conditional set based on mask and arithmetic shift REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a ) { return ( -condition >> 31 ) & a; } #endif /* if (condition) state |= m; else state &= ~m; */ REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask ) { // 0, or any postive to mask //s32 conmask = -condition >> 31; state ^= ( ( -condition >> 31 ) ^ state ) & mask; } inline f32 round_( f32 x ) { return floorf( x + 0.5f ); } REALINLINE void clearFPUException () { #ifdef IRRLICHT_FAST_MATH return; #ifdef feclearexcept feclearexcept(FE_ALL_EXCEPT); #elif defined(_MSC_VER) __asm fnclex; #elif defined(__GNUC__) && defined(__x86__) __asm__ __volatile__ ("fclex \n\t"); #else # warn clearFPUException not supported. #endif #endif } // calculate: sqrt ( x ) REALINLINE f32 squareroot(const f32 f) { return sqrtf(f); } // calculate: sqrt ( x ) REALINLINE f64 squareroot(const f64 f) { return sqrt(f); } // calculate: sqrt ( x ) REALINLINE s32 squareroot(const s32 f) { return static_cast(squareroot(static_cast(f))); } #ifdef __IRR_HAS_S64 // calculate: sqrt ( x ) REALINLINE s64 squareroot(const s64 f) { return static_cast(squareroot(static_cast(f))); } #endif // calculate: 1 / sqrt ( x ) REALINLINE f64 reciprocal_squareroot(const f64 x) { return 1.0 / sqrt(x); } // calculate: 1 / sqrtf ( x ) REALINLINE f32 reciprocal_squareroot(const f32 f) { #if defined ( IRRLICHT_FAST_MATH ) #if defined(_MSC_VER) // SSE reciprocal square root estimate, accurate to 12 significant // bits of the mantissa f32 recsqrt; __asm rsqrtss xmm0, f // xmm0 = rsqrtss(f) __asm movss recsqrt, xmm0 // return xmm0 return recsqrt; /* // comes from Nvidia u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1; f32 y = *(f32*)&tmp; return y * (1.47f - 0.47f * x * y * y); */ #else return 1.f / sqrtf(f); #endif #else // no fast math return 1.f / sqrtf(f); #endif } // calculate: 1 / sqrtf( x ) REALINLINE s32 reciprocal_squareroot(const s32 x) { return static_cast(reciprocal_squareroot(static_cast(x))); } // calculate: 1 / x REALINLINE f32 reciprocal( const f32 f ) { #if defined (IRRLICHT_FAST_MATH) // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant // bi ts of the mantissa // One Newtown-Raphson Iteration: // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f) f32 rec; __asm rcpss xmm0, f // xmm0 = rcpss(f) __asm movss xmm1, f // xmm1 = f __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f) __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f) __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f) __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f) // - f * rcpss(f) * rcpss(f) __asm movss rec, xmm0 // return xmm0 return rec; //! i do not divide through 0.. (fpu expection) // instead set f to a high value to get a return value near zero.. // -1000000000000.f.. is use minus to stay negative.. // must test's here (plane.normal dot anything ) checks on <= 0.f //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5; //return 1.f / FR ( x ); #else // no fast math return 1.f / f; #endif } // calculate: 1 / x REALINLINE f64 reciprocal ( const f64 f ) { return 1.0 / f; } // calculate: 1 / x, low precision allowed REALINLINE f32 reciprocal_approxim ( const f32 f ) { #if defined( IRRLICHT_FAST_MATH) // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant // bi ts of the mantissa // One Newtown-Raphson Iteration: // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f) f32 rec; __asm rcpss xmm0, f // xmm0 = rcpss(f) __asm movss xmm1, f // xmm1 = f __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f) __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f) __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f) __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f) // - f * rcpss(f) * rcpss(f) __asm movss rec, xmm0 // return xmm0 return rec; /* // SSE reciprocal estimate, accurate to 12 significant bits of f32 rec; __asm rcpss xmm0, f // xmm0 = rcpss(f) __asm movss rec , xmm0 // return xmm0 return rec; */ /* register u32 x = 0x7F000000 - IR ( p ); const f32 r = FR ( x ); return r * (2.0f - p * r); */ #else // no fast math return 1.f / f; #endif } REALINLINE s32 floor32(f32 x) { #ifdef IRRLICHT_FAST_MATH const f32 h = 0.5f; s32 t; #if defined(_MSC_VER) __asm { fld x fsub h fistp t } #elif defined(__GNUC__) __asm__ __volatile__ ( "fsub %2 \n\t" "fistpl %0" : "=m" (t) : "t" (x), "f" (h) : "st" ); #else # warn IRRLICHT_FAST_MATH not supported. return (s32) floorf ( x ); #endif return t; #else // no fast math return (s32) floorf ( x ); #endif } REALINLINE s32 ceil32 ( f32 x ) { #ifdef IRRLICHT_FAST_MATH const f32 h = 0.5f; s32 t; #if defined(_MSC_VER) __asm { fld x fadd h fistp t } #elif defined(__GNUC__) __asm__ __volatile__ ( "fadd %2 \n\t" "fistpl %0 \n\t" : "=m"(t) : "t"(x), "f"(h) : "st" ); #else # warn IRRLICHT_FAST_MATH not supported. return (s32) ceilf ( x ); #endif return t; #else // not fast math return (s32) ceilf ( x ); #endif } REALINLINE s32 round32(f32 x) { #if defined(IRRLICHT_FAST_MATH) s32 t; #if defined(_MSC_VER) __asm { fld x fistp t } #elif defined(__GNUC__) __asm__ __volatile__ ( "fistpl %0 \n\t" : "=m"(t) : "t"(x) : "st" ); #else # warn IRRLICHT_FAST_MATH not supported. return (s32) round_(x); #endif return t; #else // no fast math return (s32) round_(x); #endif } inline f32 f32_max3(const f32 a, const f32 b, const f32 c) { return a > b ? (a > c ? a : c) : (b > c ? b : c); } inline f32 f32_min3(const f32 a, const f32 b, const f32 c) { return a < b ? (a < c ? a : c) : (b < c ? b : c); } inline f32 fract ( f32 x ) { return x - floorf ( x ); } } // end namespace core } // end namespace irr #ifndef IRRLICHT_FAST_MATH using irr::core::IR; using irr::core::FR; #endif #endif irrlicht-1.8.3/include/irrMap.h0000644000000000000000000005767512574354552015127 0ustar rootroot// Copyright (C) 2006-2012 by Kat'Oun // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_MAP_H_INCLUDED__ #define __IRR_MAP_H_INCLUDED__ #include "irrTypes.h" #include "irrMath.h" namespace irr { namespace core { //! map template for associative arrays using a red-black tree template class map { //! red/black tree for map template class RBTree { public: RBTree(const KeyTypeRB& k, const ValueTypeRB& v) : LeftChild(0), RightChild(0), Parent(0), Key(k), Value(v), IsRed(true) {} void setLeftChild(RBTree* p) { LeftChild=p; if (p) p->setParent(this); } void setRightChild(RBTree* p) { RightChild=p; if (p) p->setParent(this); } void setParent(RBTree* p) { Parent=p; } void setValue(const ValueTypeRB& v) { Value = v; } void setRed() { IsRed = true; } void setBlack() { IsRed = false; } RBTree* getLeftChild() const { return LeftChild; } RBTree* getRightChild() const { return RightChild; } RBTree* getParent() const { return Parent; } const ValueTypeRB& getValue() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Value; } ValueTypeRB& getValue() { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Value; } const KeyTypeRB& getKey() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Key; } bool isRoot() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Parent==0; } bool isLeftChild() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return (Parent != 0) && (Parent->getLeftChild()==this); } bool isRightChild() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return (Parent!=0) && (Parent->getRightChild()==this); } bool isLeaf() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return (LeftChild==0) && (RightChild==0); } unsigned int getLevel() const { if (isRoot()) return 1; else return getParent()->getLevel() + 1; } bool isRed() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return IsRed; } bool isBlack() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return !IsRed; } private: RBTree(); RBTree* LeftChild; RBTree* RightChild; RBTree* Parent; KeyTypeRB Key; ValueTypeRB Value; bool IsRed; }; // RBTree public: typedef RBTree Node; // We need the forwad declaration for the friend declaration class ConstIterator; //! Normal Iterator class Iterator { friend class ConstIterator; public: Iterator() : Root(0), Cur(0) {} // Constructor(Node*) Iterator(Node* root) : Root(root) { reset(); } // Copy constructor Iterator(const Iterator& src) : Root(src.Root), Cur(src.Cur) {} void reset(bool atLowest=true) { if (atLowest) Cur = getMin(Root); else Cur = getMax(Root); } bool atEnd() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Cur==0; } Node* getNode() const { return Cur; } Iterator& operator=(const Iterator& src) { Root = src.Root; Cur = src.Cur; return (*this); } void operator++(int) { inc(); } void operator--(int) { dec(); } Node* operator->() { return getNode(); } Node& operator*() { _IRR_DEBUG_BREAK_IF(atEnd()) // access violation return *Cur; } private: Node* getMin(Node* n) const { while(n && n->getLeftChild()) n = n->getLeftChild(); return n; } Node* getMax(Node* n) const { while(n && n->getRightChild()) n = n->getRightChild(); return n; } void inc() { // Already at end? if (Cur==0) return; if (Cur->getRightChild()) { // If current node has a right child, the next higher node is the // node with lowest key beneath the right child. Cur = getMin(Cur->getRightChild()); } else if (Cur->isLeftChild()) { // No right child? Well if current node is a left child then // the next higher node is the parent Cur = Cur->getParent(); } else { // Current node neither is left child nor has a right child. // Ie it is either right child or root // The next higher node is the parent of the first non-right // child (ie either a left child or the root) up in the // hierarchy. Root's parent is 0. while(Cur->isRightChild()) Cur = Cur->getParent(); Cur = Cur->getParent(); } } void dec() { // Already at end? if (Cur==0) return; if (Cur->getLeftChild()) { // If current node has a left child, the next lower node is the // node with highest key beneath the left child. Cur = getMax(Cur->getLeftChild()); } else if (Cur->isRightChild()) { // No left child? Well if current node is a right child then // the next lower node is the parent Cur = Cur->getParent(); } else { // Current node neither is right child nor has a left child. // Ie it is either left child or root // The next higher node is the parent of the first non-left // child (ie either a right child or the root) up in the // hierarchy. Root's parent is 0. while(Cur->isLeftChild()) Cur = Cur->getParent(); Cur = Cur->getParent(); } } Node* Root; Node* Cur; }; // Iterator //! Const Iterator class ConstIterator { friend class Iterator; public: ConstIterator() : Root(0), Cur(0) {} // Constructor(Node*) ConstIterator(const Node* root) : Root(root) { reset(); } // Copy constructor ConstIterator(const ConstIterator& src) : Root(src.Root), Cur(src.Cur) {} ConstIterator(const Iterator& src) : Root(src.Root), Cur(src.Cur) {} void reset(bool atLowest=true) { if (atLowest) Cur = getMin(Root); else Cur = getMax(Root); } bool atEnd() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Cur==0; } const Node* getNode() const { return Cur; } ConstIterator& operator=(const ConstIterator& src) { Root = src.Root; Cur = src.Cur; return (*this); } void operator++(int) { inc(); } void operator--(int) { dec(); } const Node* operator->() { return getNode(); } const Node& operator*() { _IRR_DEBUG_BREAK_IF(atEnd()) // access violation return *Cur; } private: const Node* getMin(const Node* n) const { while(n && n->getLeftChild()) n = n->getLeftChild(); return n; } const Node* getMax(const Node* n) const { while(n && n->getRightChild()) n = n->getRightChild(); return n; } void inc() { // Already at end? if (Cur==0) return; if (Cur->getRightChild()) { // If current node has a right child, the next higher node is the // node with lowest key beneath the right child. Cur = getMin(Cur->getRightChild()); } else if (Cur->isLeftChild()) { // No right child? Well if current node is a left child then // the next higher node is the parent Cur = Cur->getParent(); } else { // Current node neither is left child nor has a right child. // Ie it is either right child or root // The next higher node is the parent of the first non-right // child (ie either a left child or the root) up in the // hierarchy. Root's parent is 0. while(Cur->isRightChild()) Cur = Cur->getParent(); Cur = Cur->getParent(); } } void dec() { // Already at end? if (Cur==0) return; if (Cur->getLeftChild()) { // If current node has a left child, the next lower node is the // node with highest key beneath the left child. Cur = getMax(Cur->getLeftChild()); } else if (Cur->isRightChild()) { // No left child? Well if current node is a right child then // the next lower node is the parent Cur = Cur->getParent(); } else { // Current node neither is right child nor has a left child. // Ie it is either left child or root // The next higher node is the parent of the first non-left // child (ie either a right child or the root) up in the // hierarchy. Root's parent is 0. while(Cur->isLeftChild()) Cur = Cur->getParent(); Cur = Cur->getParent(); } } const Node* Root; const Node* Cur; }; // ConstIterator //! Parent First Iterator. /** Traverses the tree from top to bottom. Typical usage is when storing the tree structure, because when reading it later (and inserting elements) the tree structure will be the same. */ class ParentFirstIterator { public: ParentFirstIterator() : Root(0), Cur(0) {} explicit ParentFirstIterator(Node* root) : Root(root), Cur(0) { reset(); } void reset() { Cur = Root; } bool atEnd() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Cur==0; } Node* getNode() { return Cur; } ParentFirstIterator& operator=(const ParentFirstIterator& src) { Root = src.Root; Cur = src.Cur; return (*this); } void operator++(int) { inc(); } Node* operator -> () { return getNode(); } Node& operator* () { _IRR_DEBUG_BREAK_IF(atEnd()) // access violation return *getNode(); } private: void inc() { // Already at end? if (Cur==0) return; // First we try down to the left if (Cur->getLeftChild()) { Cur = Cur->getLeftChild(); } else if (Cur->getRightChild()) { // No left child? The we go down to the right. Cur = Cur->getRightChild(); } else { // No children? Move up in the hierarcy until // we either reach 0 (and are finished) or // find a right uncle. while (Cur!=0) { // But if parent is left child and has a right "uncle" the parent // has already been processed but the uncle hasn't. Move to // the uncle. if (Cur->isLeftChild() && Cur->getParent()->getRightChild()) { Cur = Cur->getParent()->getRightChild(); return; } Cur = Cur->getParent(); } } } Node* Root; Node* Cur; }; // ParentFirstIterator //! Parent Last Iterator /** Traverse the tree from bottom to top. Typical usage is when deleting all elements in the tree because you must delete the children before you delete their parent. */ class ParentLastIterator { public: ParentLastIterator() : Root(0), Cur(0) {} explicit ParentLastIterator(Node* root) : Root(root), Cur(0) { reset(); } void reset() { Cur = getMin(Root); } bool atEnd() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Cur==0; } Node* getNode() { return Cur; } ParentLastIterator& operator=(const ParentLastIterator& src) { Root = src.Root; Cur = src.Cur; return (*this); } void operator++(int) { inc(); } Node* operator -> () { return getNode(); } Node& operator* () { _IRR_DEBUG_BREAK_IF(atEnd()) // access violation return *getNode(); } private: Node* getMin(Node* n) { while(n!=0 && (n->getLeftChild()!=0 || n->getRightChild()!=0)) { if (n->getLeftChild()) n = n->getLeftChild(); else n = n->getRightChild(); } return n; } void inc() { // Already at end? if (Cur==0) return; // Note: Starting point is the node as far down to the left as possible. // If current node has an uncle to the right, go to the // node as far down to the left from the uncle as possible // else just go up a level to the parent. if (Cur->isLeftChild() && Cur->getParent()->getRightChild()) { Cur = getMin(Cur->getParent()->getRightChild()); } else Cur = Cur->getParent(); } Node* Root; Node* Cur; }; // ParentLastIterator // AccessClass is a temporary class used with the [] operator. // It makes it possible to have different behavior in situations like: // myTree["Foo"] = 32; // If "Foo" already exists update its value else insert a new element. // int i = myTree["Foo"] // If "Foo" exists return its value. class AccessClass { // Let map be the only one who can instantiate this class. friend class map; public: // Assignment operator. Handles the myTree["Foo"] = 32; situation void operator=(const ValueType& value) { // Just use the Set method, it handles already exist/not exist situation Tree.set(Key,value); } // ValueType operator operator ValueType() { Node* node = Tree.find(Key); // Not found _IRR_DEBUG_BREAK_IF(node==0) // access violation _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return node->getValue(); } private: AccessClass(map& tree, const KeyType& key) : Tree(tree), Key(key) {} AccessClass(); map& Tree; const KeyType& Key; }; // AccessClass // Constructor. map() : Root(0), Size(0) {} // Destructor ~map() { clear(); } //------------------------------ // Public Commands //------------------------------ //! Inserts a new node into the tree /** \param keyNew: the index for this value \param v: the value to insert \return True if successful, false if it fails (already exists) */ bool insert(const KeyType& keyNew, const ValueType& v) { // First insert node the "usual" way (no fancy balance logic yet) Node* newNode = new Node(keyNew,v); if (!insert(newNode)) { delete newNode; _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } // Then attend a balancing party while (!newNode->isRoot() && (newNode->getParent()->isRed())) { if (newNode->getParent()->isLeftChild()) { // If newNode is a left child, get its right 'uncle' Node* newNodesUncle = newNode->getParent()->getParent()->getRightChild(); if ( newNodesUncle!=0 && newNodesUncle->isRed()) { // case 1 - change the colors newNode->getParent()->setBlack(); newNodesUncle->setBlack(); newNode->getParent()->getParent()->setRed(); // Move newNode up the tree newNode = newNode->getParent()->getParent(); } else { // newNodesUncle is a black node if ( newNode->isRightChild()) { // and newNode is to the right // case 2 - move newNode up and rotate newNode = newNode->getParent(); rotateLeft(newNode); } // case 3 newNode->getParent()->setBlack(); newNode->getParent()->getParent()->setRed(); rotateRight(newNode->getParent()->getParent()); } } else { // If newNode is a right child, get its left 'uncle' Node* newNodesUncle = newNode->getParent()->getParent()->getLeftChild(); if ( newNodesUncle!=0 && newNodesUncle->isRed()) { // case 1 - change the colors newNode->getParent()->setBlack(); newNodesUncle->setBlack(); newNode->getParent()->getParent()->setRed(); // Move newNode up the tree newNode = newNode->getParent()->getParent(); } else { // newNodesUncle is a black node if (newNode->isLeftChild()) { // and newNode is to the left // case 2 - move newNode up and rotate newNode = newNode->getParent(); rotateRight(newNode); } // case 3 newNode->getParent()->setBlack(); newNode->getParent()->getParent()->setRed(); rotateLeft(newNode->getParent()->getParent()); } } } // Color the root black Root->setBlack(); return true; } //! Replaces the value if the key already exists, otherwise inserts a new element. /** \param k The index for this value \param v The new value of */ void set(const KeyType& k, const ValueType& v) { Node* p = find(k); if (p) p->setValue(v); else insert(k,v); } //! Removes a node from the tree and returns it. /** The returned node must be deleted by the user \param k the key to remove \return A pointer to the node, or 0 if not found */ Node* delink(const KeyType& k) { Node* p = find(k); if (p == 0) return 0; // Rotate p down to the left until it has no right child, will get there // sooner or later. while(p->getRightChild()) { // "Pull up my right child and let it knock me down to the left" rotateLeft(p); } // p now has no right child but might have a left child Node* left = p->getLeftChild(); // Let p's parent point to p's child instead of point to p if (p->isLeftChild()) p->getParent()->setLeftChild(left); else if (p->isRightChild()) p->getParent()->setRightChild(left); else { // p has no parent => p is the root. // Let the left child be the new root. setRoot(left); } // p is now gone from the tree in the sense that // no one is pointing at it, so return it. --Size; return p; } //! Removes a node from the tree and deletes it. /** \return True if the node was found and deleted */ bool remove(const KeyType& k) { Node* p = find(k); return remove(p); } //! Removes a node from the tree and deletes it. /** \return True if the node was found and deleted */ bool remove(Node* p) { if (p == 0) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } // Rotate p down to the left until it has no right child, will get there // sooner or later. while(p->getRightChild()) { // "Pull up my right child and let it knock me down to the left" rotateLeft(p); } // p now has no right child but might have a left child Node* left = p->getLeftChild(); // Let p's parent point to p's child instead of point to p if (p->isLeftChild()) p->getParent()->setLeftChild(left); else if (p->isRightChild()) p->getParent()->setRightChild(left); else { // p has no parent => p is the root. // Let the left child be the new root. setRoot(left); } // p is now gone from the tree in the sense that // no one is pointing at it. Let's get rid of it. delete p; --Size; return true; } //! Clear the entire tree void clear() { ParentLastIterator i(getParentLastIterator()); while(!i.atEnd()) { Node* p = i.getNode(); i++; // Increment it before it is deleted // else iterator will get quite confused. delete p; } Root = 0; Size= 0; } //! Is the tree empty? //! \return Returns true if empty, false if not bool empty() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Root == 0; } //! \deprecated Use empty() instead. This method may be removed by Irrlicht 1.9 _IRR_DEPRECATED_ bool isEmpty() const { return empty(); } //! Search for a node with the specified key. //! \param keyToFind: The key to find //! \return Returns 0 if node couldn't be found. Node* find(const KeyType& keyToFind) const { Node* pNode = Root; while(pNode!=0) { const KeyType& key=pNode->getKey(); if (keyToFind == key) return pNode; else if (keyToFind < key) pNode = pNode->getLeftChild(); else //keyToFind > key pNode = pNode->getRightChild(); } return 0; } //! Gets the root element. //! \return Returns a pointer to the root node, or //! 0 if the tree is empty. Node* getRoot() const { return Root; } //! Returns the number of nodes in the tree. u32 size() const { return Size; } //! Swap the content of this map container with the content of another map /** Afterwards this object will contain the content of the other object and the other object will contain the content of this object. Iterators will afterwards be valid for the swapped object. \param other Swap content with this object */ void swap(map& other) { core::swap(Root, other.Root); core::swap(Size, other.Size); } //------------------------------ // Public Iterators //------------------------------ //! Returns an iterator Iterator getIterator() const { Iterator it(getRoot()); return it; } //! Returns a Constiterator ConstIterator getConstIterator() const { Iterator it(getRoot()); return it; } //! Returns a ParentFirstIterator. //! Traverses the tree from top to bottom. Typical usage is //! when storing the tree structure, because when reading it //! later (and inserting elements) the tree structure will //! be the same. ParentFirstIterator getParentFirstIterator() const { ParentFirstIterator it(getRoot()); return it; } //! Returns a ParentLastIterator to traverse the tree from //! bottom to top. //! Typical usage is when deleting all elements in the tree //! because you must delete the children before you delete //! their parent. ParentLastIterator getParentLastIterator() const { ParentLastIterator it(getRoot()); return it; } //------------------------------ // Public Operators //------------------------------ //! operator [] for access to elements /** for example myMap["key"] */ AccessClass operator[](const KeyType& k) { return AccessClass(*this, k); } private: //------------------------------ // Disabled methods //------------------------------ // Copy constructor and assignment operator deliberately // defined but not implemented. The tree should never be // copied, pass along references to it instead. explicit map(const map& src); map& operator = (const map& src); //! Set node as new root. /** The node will be set to black, otherwise core dumps may arise (patch provided by rogerborg). \param newRoot Node which will be the new root */ void setRoot(Node* newRoot) { Root = newRoot; if (Root != 0) { Root->setParent(0); Root->setBlack(); } } //! Insert a node into the tree without using any fancy balancing logic. /** \return false if that key already exist in the tree. */ bool insert(Node* newNode) { bool result=true; // Assume success if (Root==0) { setRoot(newNode); Size = 1; } else { Node* pNode = Root; const KeyType& keyNew = newNode->getKey(); while (pNode) { const KeyType& key=pNode->getKey(); if (keyNew == key) { result = false; pNode = 0; } else if (keyNew < key) { if (pNode->getLeftChild() == 0) { pNode->setLeftChild(newNode); pNode = 0; } else pNode = pNode->getLeftChild(); } else // keyNew > key { if (pNode->getRightChild()==0) { pNode->setRightChild(newNode); pNode = 0; } else { pNode = pNode->getRightChild(); } } } if (result) ++Size; } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return result; } //! Rotate left. //! Pull up node's right child and let it knock node down to the left void rotateLeft(Node* p) { Node* right = p->getRightChild(); p->setRightChild(right->getLeftChild()); if (p->isLeftChild()) p->getParent()->setLeftChild(right); else if (p->isRightChild()) p->getParent()->setRightChild(right); else setRoot(right); right->setLeftChild(p); } //! Rotate right. //! Pull up node's left child and let it knock node down to the right void rotateRight(Node* p) { Node* left = p->getLeftChild(); p->setLeftChild(left->getRightChild()); if (p->isLeftChild()) p->getParent()->setLeftChild(left); else if (p->isRightChild()) p->getParent()->setRightChild(left); else setRoot(left); left->setRightChild(p); } //------------------------------ // Private Members //------------------------------ Node* Root; // The top node. 0 if empty. u32 Size; // Number of nodes in the tree }; } // end namespace core } // end namespace irr #endif // __IRR_MAP_H_INCLUDED__ irrlicht-1.8.3/include/irrList.h0000644000000000000000000002266412574354552015313 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_LIST_H_INCLUDED__ #define __IRR_LIST_H_INCLUDED__ #include "irrTypes.h" #include "irrAllocator.h" #include "irrMath.h" namespace irr { namespace core { //! Doubly linked list template. template class list { private: //! List element node with pointer to previous and next element in the list. struct SKListNode { SKListNode(const T& e) : Next(0), Prev(0), Element(e) {} SKListNode* Next; SKListNode* Prev; T Element; }; public: class ConstIterator; //! List iterator. class Iterator { public: Iterator() : Current(0) {} Iterator& operator ++() { Current = Current->Next; return *this; } Iterator& operator --() { Current = Current->Prev; return *this; } Iterator operator ++(s32) { Iterator tmp = *this; Current = Current->Next; return tmp; } Iterator operator --(s32) { Iterator tmp = *this; Current = Current->Prev; return tmp; } Iterator& operator +=(s32 num) { if(num > 0) { while (num-- && this->Current != 0) ++(*this); } else { while(num++ && this->Current != 0) --(*this); } return *this; } Iterator operator + (s32 num) const { Iterator tmp = *this; return tmp += num; } Iterator& operator -=(s32 num) { return (*this)+=(-num); } Iterator operator - (s32 num) const { return (*this)+ (-num); } bool operator ==(const Iterator& other) const { return Current == other.Current; } bool operator !=(const Iterator& other) const { return Current != other.Current; } bool operator ==(const ConstIterator& other) const { return Current == other.Current; } bool operator !=(const ConstIterator& other) const { return Current != other.Current; } #if defined (_MSC_VER) && (_MSC_VER < 1300) #pragma warning(disable:4284) // infix notation problem when using iterator operator -> #endif T & operator * () { return Current->Element; } T * operator ->() { return &Current->Element; } private: explicit Iterator(SKListNode* begin) : Current(begin) {} SKListNode* Current; friend class list; friend class ConstIterator; }; //! List iterator for const access. class ConstIterator { public: ConstIterator() : Current(0) {} ConstIterator(const Iterator& iter) : Current(iter.Current) {} ConstIterator& operator ++() { Current = Current->Next; return *this; } ConstIterator& operator --() { Current = Current->Prev; return *this; } ConstIterator operator ++(s32) { ConstIterator tmp = *this; Current = Current->Next; return tmp; } ConstIterator operator --(s32) { ConstIterator tmp = *this; Current = Current->Prev; return tmp; } ConstIterator& operator +=(s32 num) { if(num > 0) { while(num-- && this->Current != 0) ++(*this); } else { while(num++ && this->Current != 0) --(*this); } return *this; } ConstIterator operator + (s32 num) const { ConstIterator tmp = *this; return tmp += num; } ConstIterator& operator -=(s32 num) { return (*this)+=(-num); } ConstIterator operator - (s32 num) const { return (*this)+ (-num); } bool operator ==(const ConstIterator& other) const { return Current == other.Current; } bool operator !=(const ConstIterator& other) const { return Current != other.Current; } bool operator ==(const Iterator& other) const { return Current == other.Current; } bool operator !=(const Iterator& other) const { return Current != other.Current; } const T & operator * () { return Current->Element; } const T * operator ->() { return &Current->Element; } ConstIterator & operator =(const Iterator & iterator) { Current = iterator.Current; return *this; } private: explicit ConstIterator(SKListNode* begin) : Current(begin) {} SKListNode* Current; friend class Iterator; friend class list; }; //! Default constructor for empty list. list() : First(0), Last(0), Size(0) {} //! Copy constructor. list(const list& other) : First(0), Last(0), Size(0) { *this = other; } //! Destructor ~list() { clear(); } //! Assignment operator void operator=(const list& other) { if(&other == this) { return; } clear(); SKListNode* node = other.First; while(node) { push_back(node->Element); node = node->Next; } } //! Returns amount of elements in list. /** \return Amount of elements in the list. */ u32 size() const { return Size; } u32 getSize() const { return Size; } //! Clears the list, deletes all elements in the list. /** All existing iterators of this list will be invalid. */ void clear() { while(First) { SKListNode * next = First->Next; allocator.destruct(First); allocator.deallocate(First); First = next; } //First = 0; handled by loop Last = 0; Size = 0; } //! Checks for empty list. /** \return True if the list is empty and false if not. */ bool empty() const { return (First == 0); } //! Adds an element at the end of the list. /** \param element Element to add to the list. */ void push_back(const T& element) { SKListNode* node = allocator.allocate(1); allocator.construct(node, element); ++Size; if (First == 0) First = node; node->Prev = Last; if (Last != 0) Last->Next = node; Last = node; } //! Adds an element at the begin of the list. /** \param element: Element to add to the list. */ void push_front(const T& element) { SKListNode* node = allocator.allocate(1); allocator.construct(node, element); ++Size; if (First == 0) { Last = node; First = node; } else { node->Next = First; First->Prev = node; First = node; } } //! Gets first node. /** \return A list iterator pointing to the beginning of the list. */ Iterator begin() { return Iterator(First); } //! Gets first node. /** \return A const list iterator pointing to the beginning of the list. */ ConstIterator begin() const { return ConstIterator(First); } //! Gets end node. /** \return List iterator pointing to null. */ Iterator end() { return Iterator(0); } //! Gets end node. /** \return Const list iterator pointing to null. */ ConstIterator end() const { return ConstIterator(0); } //! Gets last element. /** \return List iterator pointing to the last element of the list. */ Iterator getLast() { return Iterator(Last); } //! Gets last element. /** \return Const list iterator pointing to the last element of the list. */ ConstIterator getLast() const { return ConstIterator(Last); } //! Inserts an element after an element. /** \param it Iterator pointing to element after which the new element should be inserted. \param element The new element to be inserted into the list. */ void insert_after(const Iterator& it, const T& element) { SKListNode* node = allocator.allocate(1); allocator.construct(node, element); node->Next = it.Current->Next; if (it.Current->Next) it.Current->Next->Prev = node; node->Prev = it.Current; it.Current->Next = node; ++Size; if (it.Current == Last) Last = node; } //! Inserts an element before an element. /** \param it Iterator pointing to element before which the new element should be inserted. \param element The new element to be inserted into the list. */ void insert_before(const Iterator& it, const T& element) { SKListNode* node = allocator.allocate(1); allocator.construct(node, element); node->Prev = it.Current->Prev; if (it.Current->Prev) it.Current->Prev->Next = node; node->Next = it.Current; it.Current->Prev = node; ++Size; if (it.Current == First) First = node; } //! Erases an element. /** \param it Iterator pointing to the element which shall be erased. \return Iterator pointing to next element. */ Iterator erase(Iterator& it) { // suggest changing this to a const Iterator& and // working around line: it.Current = 0 (possibly with a mutable, or just let it be garbage?) Iterator returnIterator(it); ++returnIterator; if(it.Current == First) { First = it.Current->Next; } else { it.Current->Prev->Next = it.Current->Next; } if(it.Current == Last) { Last = it.Current->Prev; } else { it.Current->Next->Prev = it.Current->Prev; } allocator.destruct(it.Current); allocator.deallocate(it.Current); it.Current = 0; --Size; return returnIterator; } //! Swap the content of this list container with the content of another list /** Afterwards this object will contain the content of the other object and the other object will contain the content of this object. Iterators will afterwards be valid for the swapped object. \param other Swap content with this object */ void swap(list& other) { core::swap(First, other.First); core::swap(Last, other.Last); core::swap(Size, other.Size); core::swap(allocator, other.allocator); // memory is still released by the same allocator used for allocation } private: SKListNode* First; SKListNode* Last; u32 Size; irrAllocator allocator; }; } // end namespace core }// end namespace irr #endif irrlicht-1.8.3/include/IrrlichtDevice.h0000644000000000000000000002766012574354552016564 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_IRRLICHT_DEVICE_H_INCLUDED__ #define __I_IRRLICHT_DEVICE_H_INCLUDED__ #include "IReferenceCounted.h" #include "dimension2d.h" #include "IVideoDriver.h" #include "EDriverTypes.h" #include "EDeviceTypes.h" #include "IEventReceiver.h" #include "ICursorControl.h" #include "IVideoModeList.h" #include "ITimer.h" #include "IOSOperator.h" namespace irr { class ILogger; class IEventReceiver; class IRandomizer; namespace io { class IFileSystem; } // end namespace io namespace gui { class IGUIEnvironment; } // end namespace gui namespace scene { class ISceneManager; } // end namespace scene //! The Irrlicht device. You can create it with createDevice() or createDeviceEx(). /** This is the most important class of the Irrlicht Engine. You can access everything in the engine if you have a pointer to an instance of this class. There should be only one instance of this class at any time. */ class IrrlichtDevice : public virtual IReferenceCounted { public: //! Runs the device. /** Also increments the virtual timer by calling ITimer::tick();. You can prevent this by calling ITimer::stop(); before and ITimer::start() after calling IrrlichtDevice::run(). Returns false if device wants to be deleted. Use it in this way: \code while(device->run()) { // draw everything here } \endcode If you want the device to do nothing if the window is inactive (recommended), use the slightly enhanced code shown at isWindowActive(). Note if you are running Irrlicht inside an external, custom created window: Calling Device->run() will cause Irrlicht to dispatch windows messages internally. If you are running Irrlicht in your own custom window, you can also simply use your own message loop using GetMessage, DispatchMessage and whatever and simply don't use this method. But note that Irrlicht will not be able to fetch user input then. See irr::SIrrlichtCreationParameters::WindowId for more informations and example code. */ virtual bool run() = 0; //! Cause the device to temporarily pause execution and let other processes run. /** This should bring down processor usage without major performance loss for Irrlicht */ virtual void yield() = 0; //! Pause execution and let other processes to run for a specified amount of time. /** It may not wait the full given time, as sleep may be interrupted \param timeMs: Time to sleep for in milisecs. \param pauseTimer: If true, pauses the device timer while sleeping */ virtual void sleep(u32 timeMs, bool pauseTimer=false) = 0; //! Provides access to the video driver for drawing 3d and 2d geometry. /** \return Pointer the video driver. */ virtual video::IVideoDriver* getVideoDriver() = 0; //! Provides access to the virtual file system. /** \return Pointer to the file system. */ virtual io::IFileSystem* getFileSystem() = 0; //! Provides access to the 2d user interface environment. /** \return Pointer to the gui environment. */ virtual gui::IGUIEnvironment* getGUIEnvironment() = 0; //! Provides access to the scene manager. /** \return Pointer to the scene manager. */ virtual scene::ISceneManager* getSceneManager() = 0; //! Provides access to the cursor control. /** \return Pointer to the mouse cursor control interface. */ virtual gui::ICursorControl* getCursorControl() = 0; //! Provides access to the message logger. /** \return Pointer to the logger. */ virtual ILogger* getLogger() = 0; //! Gets a list with all video modes available. /** If you are confused now, because you think you have to create an Irrlicht Device with a video mode before being able to get the video mode list, let me tell you that there is no need to start up an Irrlicht Device with EDT_DIRECT3D8, EDT_OPENGL or EDT_SOFTWARE: For this (and for lots of other reasons) the null driver, EDT_NULL exists. \return Pointer to a list with all video modes supported by the gfx adapter. */ virtual video::IVideoModeList* getVideoModeList() = 0; //! Provides access to the operation system operator object. /** The OS operator provides methods for getting system specific informations and doing system specific operations, such as exchanging data with the clipboard or reading the operation system version. \return Pointer to the OS operator. */ virtual IOSOperator* getOSOperator() = 0; //! Provides access to the engine's timer. /** The system time can be retrieved by it as well as the virtual time, which also can be manipulated. \return Pointer to the ITimer object. */ virtual ITimer* getTimer() = 0; //! Provides access to the engine's currently set randomizer. /** \return Pointer to the IRandomizer object. */ virtual IRandomizer* getRandomizer() const =0; //! Sets a new randomizer. /** \param r Pointer to the new IRandomizer object. This object is grab()'ed by the engine and will be released upon the next setRandomizer call or upon device destruction. */ virtual void setRandomizer(IRandomizer* r) =0; //! Creates a new default randomizer. /** The default randomizer provides the random sequence known from previous Irrlicht versions and is the initial randomizer set on device creation. \return Pointer to the default IRandomizer object. */ virtual IRandomizer* createDefaultRandomizer() const =0; //! Sets the caption of the window. /** \param text: New text of the window caption. */ virtual void setWindowCaption(const wchar_t* text) = 0; //! Returns if the window is active. /** If the window is inactive, nothing needs to be drawn. So if you don't want to draw anything when the window is inactive, create your drawing loop this way: \code while(device->run()) { if (device->isWindowActive()) { // draw everything here } else device->yield(); } \endcode \return True if window is active. */ virtual bool isWindowActive() const = 0; //! Checks if the Irrlicht window has focus /** \return True if window has focus. */ virtual bool isWindowFocused() const = 0; //! Checks if the Irrlicht window is minimized /** \return True if window is minimized. */ virtual bool isWindowMinimized() const = 0; //! Checks if the Irrlicht window is running in fullscreen mode /** \return True if window is fullscreen. */ virtual bool isFullscreen() const = 0; //! Get the current color format of the window /** \return Color format of the window. */ virtual video::ECOLOR_FORMAT getColorFormat() const = 0; //! Notifies the device that it should close itself. /** IrrlichtDevice::run() will always return false after closeDevice() was called. */ virtual void closeDevice() = 0; //! Get the version of the engine. /** The returned string will look like this: "1.2.3" or this: "1.2". \return String which contains the version. */ virtual const c8* getVersion() const = 0; //! Sets a new user event receiver which will receive events from the engine. /** Return true in IEventReceiver::OnEvent to prevent the event from continuing along the chain of event receivers. The path that an event takes through the system depends on its type. See irr::EEVENT_TYPE for details. \param receiver New receiver to be used. */ virtual void setEventReceiver(IEventReceiver* receiver) = 0; //! Provides access to the current event receiver. /** \return Pointer to the current event receiver. Returns 0 if there is none. */ virtual IEventReceiver* getEventReceiver() = 0; //! Sends a user created event to the engine. /** Is is usually not necessary to use this. However, if you are using an own input library for example for doing joystick input, you can use this to post key or mouse input events to the engine. Internally, this method only delegates the events further to the scene manager and the GUI environment. */ virtual bool postEventFromUser(const SEvent& event) = 0; //! Sets the input receiving scene manager. /** If set to null, the main scene manager (returned by GetSceneManager()) will receive the input \param sceneManager New scene manager to be used. */ virtual void setInputReceivingSceneManager(scene::ISceneManager* sceneManager) = 0; //! Sets if the window should be resizable in windowed mode. /** The default is false. This method only works in windowed mode. \param resize Flag whether the window should be resizable. */ virtual void setResizable(bool resize=false) = 0; //! Minimizes the window if possible. virtual void minimizeWindow() =0; //! Maximizes the window if possible. virtual void maximizeWindow() =0; //! Restore the window to normal size if possible. virtual void restoreWindow() =0; //! Activate any joysticks, and generate events for them. /** Irrlicht contains support for joysticks, but does not generate joystick events by default, as this would consume joystick info that 3rd party libraries might rely on. Call this method to activate joystick support in Irrlicht and to receive irr::SJoystickEvent events. \param joystickInfo On return, this will contain an array of each joystick that was found and activated. \return true if joysticks are supported on this device and _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ is defined, false if joysticks are not supported or support is compiled out. */ virtual bool activateJoysticks(core::array& joystickInfo) =0; //! Set the current Gamma Value for the Display virtual bool setGammaRamp(f32 red, f32 green, f32 blue, f32 relativebrightness, f32 relativecontrast) =0; //! Get the current Gamma Value for the Display virtual bool getGammaRamp(f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast) =0; //! Remove messages pending in the system message loop /** This function is usually used after messages have been buffered for a longer time, for example when loading a large scene. Clearing the message loop prevents that mouse- or buttonclicks which users have pressed in the meantime will now trigger unexpected actions in the gui.
So far the following messages are cleared:
Win32: All keyboard and mouse messages
Linux: All keyboard and mouse messages
All other devices are not yet supported here.
The function is still somewhat experimental, as the kind of messages we clear is based on just a few use-cases. If you think further messages should be cleared, or some messages should not be cleared here, then please tell us. */ virtual void clearSystemMessages() = 0; //! Get the type of the device. /** This allows the user to check which windowing system is currently being used. */ virtual E_DEVICE_TYPE getType() const = 0; //! Check if a driver type is supported by the engine. /** Even if true is returned the driver may not be available for a configuration requested when creating the device. */ static bool isDriverSupported(video::E_DRIVER_TYPE driver) { switch (driver) { case video::EDT_NULL: return true; case video::EDT_SOFTWARE: #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return true; #else return false; #endif case video::EDT_BURNINGSVIDEO: #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ return true; #else return false; #endif case video::EDT_DIRECT3D8: #ifdef _IRR_COMPILE_WITH_DIRECT3D_8_ return true; #else return false; #endif case video::EDT_DIRECT3D9: #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ return true; #else return false; #endif case video::EDT_OPENGL: #ifdef _IRR_COMPILE_WITH_OPENGL_ return true; #else return false; #endif default: return false; } } }; } // end namespace irr #endif irrlicht-1.8.3/include/irrlicht.h0000644000000000000000000003311112574354552015470 0ustar rootroot/* irrlicht.h -- interface of the 'Irrlicht Engine' Copyright (C) 2002-2012 Nikolaus Gebhardt This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Please note that the Irrlicht Engine is based in part on the work of the Independent JPEG Group, the zlib and the libPng. This means that if you use the Irrlicht Engine in your product, you must acknowledge somewhere in your documentation that you've used the IJG code. It would also be nice to mention that you use the Irrlicht Engine, the zlib and libPng. See the README files in the jpeglib, the zlib and libPng for further informations. */ #ifndef __IRRLICHT_H_INCLUDED__ #define __IRRLICHT_H_INCLUDED__ #include "IrrCompileConfig.h" #include "aabbox3d.h" #include "CDynamicMeshBuffer.h" #include "CIndexBuffer.h" #include "CMeshBuffer.h" #include "coreutil.h" #include "CVertexBuffer.h" #include "dimension2d.h" #include "ECullingTypes.h" #include "EDebugSceneTypes.h" #include "EDriverFeatures.h" #include "EDriverTypes.h" #include "EGUIAlignment.h" #include "EGUIElementTypes.h" #include "EHardwareBufferFlags.h" #include "EMaterialFlags.h" #include "EMaterialTypes.h" #include "EMeshWriterEnums.h" #include "EMessageBoxFlags.h" #include "ESceneNodeAnimatorTypes.h" #include "ESceneNodeTypes.h" #include "ETerrainElements.h" #include "fast_atof.h" #include "heapsort.h" #include "IAnimatedMesh.h" #include "IAnimatedMeshMD2.h" #include "IAnimatedMeshMD3.h" #include "IAnimatedMeshSceneNode.h" #include "IAttributeExchangingObject.h" #include "IAttributes.h" #include "IBillboardSceneNode.h" #include "IBillboardTextSceneNode.h" #include "IBoneSceneNode.h" #include "ICameraSceneNode.h" #include "ICursorControl.h" #include "IDummyTransformationSceneNode.h" #include "IDynamicMeshBuffer.h" #include "IEventReceiver.h" #include "IFileList.h" #include "IFileSystem.h" #include "IGeometryCreator.h" #include "IGPUProgrammingServices.h" #include "IGUIButton.h" #include "IGUICheckBox.h" #include "IGUIColorSelectDialog.h" #include "IGUIComboBox.h" #include "IGUIContextMenu.h" #include "IGUIEditBox.h" #include "IGUIElement.h" #include "IGUIElementFactory.h" #include "IGUIEnvironment.h" #include "IGUIFileOpenDialog.h" #include "IGUIFont.h" #include "IGUIFontBitmap.h" #include "IGUIImage.h" #include "IGUIInOutFader.h" #include "IGUIListBox.h" #include "IGUIMeshViewer.h" #include "IGUIScrollBar.h" #include "IGUISkin.h" #include "IGUISpinBox.h" #include "IGUISpriteBank.h" #include "IGUIStaticText.h" #include "IGUITabControl.h" #include "IGUITable.h" #include "IGUIToolbar.h" #include "IGUIWindow.h" #include "IGUITreeView.h" #include "IImage.h" #include "IImageLoader.h" #include "IImageWriter.h" #include "IIndexBuffer.h" #include "ILightSceneNode.h" #include "ILogger.h" #include "IMaterialRenderer.h" #include "IMaterialRendererServices.h" #include "IMesh.h" #include "IMeshBuffer.h" #include "IMeshCache.h" #include "IMeshLoader.h" #include "IMeshManipulator.h" #include "IMeshSceneNode.h" #include "IMeshWriter.h" #include "IColladaMeshWriter.h" #include "IMetaTriangleSelector.h" #include "IOSOperator.h" #include "IParticleSystemSceneNode.h" // also includes all emitters and attractors #include "IQ3LevelMesh.h" #include "IQ3Shader.h" #include "IReadFile.h" #include "IReferenceCounted.h" #include "irrArray.h" #include "IRandomizer.h" #include "IrrlichtDevice.h" #include "irrList.h" #include "irrMap.h" #include "irrMath.h" #include "irrString.h" #include "irrTypes.h" #include "path.h" #include "irrXML.h" #include "ISceneCollisionManager.h" #include "ISceneLoader.h" #include "ISceneManager.h" #include "ISceneNode.h" #include "ISceneNodeAnimator.h" #include "ISceneNodeAnimatorCameraFPS.h" #include "ISceneNodeAnimatorCameraMaya.h" #include "ISceneNodeAnimatorCollisionResponse.h" #include "ISceneNodeAnimatorFactory.h" #include "ISceneNodeFactory.h" #include "ISceneUserDataSerializer.h" #include "IShaderConstantSetCallBack.h" #include "IShadowVolumeSceneNode.h" #include "ISkinnedMesh.h" #include "ITerrainSceneNode.h" #include "ITextSceneNode.h" #include "ITexture.h" #include "ITimer.h" #include "ITriangleSelector.h" #include "IVertexBuffer.h" #include "IVideoDriver.h" #include "IVideoModeList.h" #include "IVolumeLightSceneNode.h" #include "IWriteFile.h" #include "IXMLReader.h" #include "IXMLWriter.h" #include "ILightManager.h" #include "Keycodes.h" #include "line2d.h" #include "line3d.h" #include "matrix4.h" #include "plane3d.h" #include "position2d.h" #include "quaternion.h" #include "rect.h" #include "S3DVertex.h" #include "SAnimatedMesh.h" #include "SceneParameters.h" #include "SColor.h" #include "SExposedVideoData.h" #include "SIrrCreationParameters.h" #include "SKeyMap.h" #include "SLight.h" #include "SMaterial.h" #include "SMesh.h" #include "SMeshBuffer.h" #include "SMeshBufferLightMap.h" #include "SMeshBufferTangents.h" #include "SParticle.h" #include "SSharedMeshBuffer.h" #include "SSkinMeshBuffer.h" #include "SVertexIndex.h" #include "SViewFrustum.h" #include "triangle3d.h" #include "vector2d.h" #include "vector3d.h" /*! \mainpage Irrlicht Engine 1.8 API documentation * *
* * \section intro Introduction * * Welcome to the Irrlicht Engine API documentation. * Here you'll find any information you'll need to develop applications with * the Irrlicht Engine. If you are looking for a tutorial on how to start, you'll * find some on the homepage of the Irrlicht Engine at * irrlicht.sourceforge.net * or inside the SDK in the examples directory. * * The Irrlicht Engine is intended to be an easy-to-use 3d engine, so * this documentation is an important part of it. If you have any questions or * suggestions, just send a email to the author of the engine, Nikolaus Gebhardt * (niko (at) irrlicht3d.org). * * * \section links Links * * Namespaces: A very good place to start reading * the documentation.
* Class list: List of all classes with descriptions.
* Class members: Good place to find forgotten features.
* * \section irrexample Short example * * A simple application, starting up the engine, loading a Quake 2 animated * model file and the corresponding texture, animating and displaying it * in front of a blue background and placing a user controlable 3d camera * would look like the following code. I think this example shows the usage * of the engine quite well: * * \code * #include * using namespace irr; * * int main() * { * // start up the engine * IrrlichtDevice *device = createDevice(video::EDT_DIRECT3D8, * core::dimension2d(640,480)); * * video::IVideoDriver* driver = device->getVideoDriver(); * scene::ISceneManager* scenemgr = device->getSceneManager(); * * device->setWindowCaption(L"Hello World!"); * * // load and show quake2 .md2 model * scene::ISceneNode* node = scenemgr->addAnimatedMeshSceneNode( * scenemgr->getMesh("quake2model.md2")); * * // if everything worked, add a texture and disable lighting * if (node) * { * node->setMaterialTexture(0, driver->getTexture("texture.bmp")); * node->setMaterialFlag(video::EMF_LIGHTING, false); * } * * // add a first person shooter style user controlled camera * scenemgr->addCameraSceneNodeFPS(); * * // draw everything * while(device->run() && driver) * { * driver->beginScene(true, true, video::SColor(255,0,0,255)); * scenemgr->drawAll(); * driver->endScene(); * } * * // delete device * device->drop(); * return 0; * } * \endcode * * Irrlicht can load a lot of file formats automaticly, see irr::scene::ISceneManager::getMesh() * for a detailed list. So if you would like to replace the simple blue screen background by * a cool Quake 3 Map, optimized by an octree, just insert this code * somewhere before the while loop: * * \code * // add .pk3 archive to the file system * device->getFileSystem()->addZipFileArchive("quake3map.pk3"); * * // load .bsp file and show it using an octree * scenemgr->addOctreeSceneNode( * scenemgr->getMesh("quake3map.bsp")); * \endcode * * As you can see, the engine uses namespaces. Everything in the engine is * placed into the namespace 'irr', but there are also 5 sub namespaces. * You can find a list of all namespaces with descriptions at the * namespaces page. * This is also a good place to start reading the documentation. If you * don't want to write the namespace names all the time, just use all namespaces like * this: * \code * using namespace core; * using namespace scene; * using namespace video; * using namespace io; * using namespace gui; * \endcode * * There is a lot more the engine can do, but I hope this gave a short * overview over the basic features of the engine. For more examples, please take * a look into the examples directory of the SDK. */ #include "SIrrCreationParameters.h" //! Everything in the Irrlicht Engine can be found in this namespace. namespace irr { //! Creates an Irrlicht device. The Irrlicht device is the root object for using the engine. /** If you need more parameters to be passed to the creation of the Irrlicht Engine device, use the createDeviceEx() function. \param deviceType: Type of the device. This can currently be video::EDT_NULL, video::EDT_SOFTWARE, video::EDT_BURNINGSVIDEO, video::EDT_DIRECT3D8, video::EDT_DIRECT3D9 and video::EDT_OPENGL. \param windowSize: Size of the window or the video mode in fullscreen mode. \param bits: Bits per pixel in fullscreen mode. Ignored if windowed mode. \param fullscreen: Should be set to true if the device should run in fullscreen. Otherwise the device runs in windowed mode. \param stencilbuffer: Specifies if the stencil buffer should be enabled. Set this to true, if you want the engine be able to draw stencil buffer shadows. Note that not all devices are able to use the stencil buffer. If they don't no shadows will be drawn. \param vsync: Specifies vertical syncronisation: If set to true, the driver will wait for the vertical retrace period, otherwise not. \param receiver: A user created event receiver. \return Returns pointer to the created IrrlichtDevice or null if the device could not be created. */ extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDevice( video::E_DRIVER_TYPE deviceType = video::EDT_SOFTWARE, // parantheses are necessary for some compilers const core::dimension2d& windowSize = (core::dimension2d(640,480)), u32 bits = 16, bool fullscreen = false, bool stencilbuffer = false, bool vsync = false, IEventReceiver* receiver = 0); //! typedef for Function Pointer typedef IrrlichtDevice* (IRRCALLCONV *funcptr_createDevice )( video::E_DRIVER_TYPE deviceType, const core::dimension2d& windowSize, u32 bits, bool fullscreen, bool stencilbuffer, bool vsync, IEventReceiver* receiver); //! Creates an Irrlicht device with the option to specify advanced parameters. /** Usually you should used createDevice() for creating an Irrlicht Engine device. Use this function only if you wish to specify advanced parameters like a window handle in which the device should be created. \param parameters: Structure containing advanced parameters for the creation of the device. See irr::SIrrlichtCreationParameters for details. \return Returns pointer to the created IrrlichtDevice or null if the device could not be created. */ extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx( const SIrrlichtCreationParameters& parameters); //! typedef for Function Pointer typedef IrrlichtDevice* (IRRCALLCONV *funcptr_createDeviceEx )( const SIrrlichtCreationParameters& parameters ); // THE FOLLOWING IS AN EMPTY LIST OF ALL SUB NAMESPACES // EXISTING ONLY FOR THE DOCUMENTATION SOFTWARE DOXYGEN. //! Basic classes such as vectors, planes, arrays, lists, and so on can be found in this namespace. namespace core { } //! The gui namespace contains useful classes for easy creation of a graphical user interface. namespace gui { } //! This namespace provides interfaces for input/output: Reading and writing files, accessing zip archives, xml files, ... namespace io { } //! All scene management can be found in this namespace: Mesh loading, special scene nodes like octrees and billboards, ... namespace scene { } //! The video namespace contains classes for accessing the video driver. All 2d and 3d rendering is done here. namespace video { } } /*! \file irrlicht.h \brief Main header file of the irrlicht, the only file needed to include. */ #endif irrlicht-1.8.3/include/IrrCompileConfig.h0000644000000000000000000010162612574354552017052 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_COMPILE_CONFIG_H_INCLUDED__ #define __IRR_COMPILE_CONFIG_H_INCLUDED__ //! Irrlicht SDK Version #define IRRLICHT_VERSION_MAJOR 1 #define IRRLICHT_VERSION_MINOR 8 #define IRRLICHT_VERSION_REVISION 3 // This flag will be defined only in SVN, the official release code will have // it undefined //#define IRRLICHT_VERSION_SVN -alpha #define IRRLICHT_SDK_VERSION "1.8.3" #include // TODO: Although included elsewhere this is required at least for mingw //! The defines for different operating system are: //! _IRR_XBOX_PLATFORM_ for XBox //! _IRR_WINDOWS_ for all irrlicht supported Windows versions //! _IRR_WINDOWS_CE_PLATFORM_ for Windows CE //! _IRR_WINDOWS_API_ for Windows or XBox //! _IRR_LINUX_PLATFORM_ for Linux (it is defined here if no other os is defined) //! _IRR_SOLARIS_PLATFORM_ for Solaris //! _IRR_OSX_PLATFORM_ for Apple systems running OSX //! _IRR_POSIX_API_ for Posix compatible systems //! Note: PLATFORM defines the OS specific layer, API can group several platforms //! DEVICE is the windowing system used, several PLATFORMs support more than one DEVICE //! Irrlicht can be compiled with more than one device //! _IRR_COMPILE_WITH_WINDOWS_DEVICE_ for Windows API based device //! _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ for Windows CE API based device //! _IRR_COMPILE_WITH_OSX_DEVICE_ for Cocoa native windowing on OSX //! _IRR_COMPILE_WITH_X11_DEVICE_ for Linux X11 based device //! _IRR_COMPILE_WITH_SDL_DEVICE_ for platform independent SDL framework //! _IRR_COMPILE_WITH_CONSOLE_DEVICE_ for no windowing system, used as a fallback //! _IRR_COMPILE_WITH_FB_DEVICE_ for framebuffer systems //! Passing defines to the compiler which have NO in front of the _IRR definename is an alternative //! way which can be used to disable defines (instead of outcommenting them in this header). //! So defines can be controlled from Makefiles or Projectfiles which allows building //! different library versions without having to change the sources. //! Example: NO_IRR_COMPILE_WITH_X11_ would disable X11 //! Uncomment this line to compile with the SDL device //#define _IRR_COMPILE_WITH_SDL_DEVICE_ #ifdef NO_IRR_COMPILE_WITH_SDL_DEVICE_ #undef _IRR_COMPILE_WITH_SDL_DEVICE_ #endif //! Comment this line to compile without the fallback console device. #define _IRR_COMPILE_WITH_CONSOLE_DEVICE_ #ifdef NO_IRR_COMPILE_WITH_CONSOLE_DEVICE_ #undef _IRR_COMPILE_WITH_CONSOLE_DEVICE_ #endif //! WIN32 for Windows32 //! WIN64 for Windows64 // The windows platform and API support SDL and WINDOW device #if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) #define _IRR_WINDOWS_ #define _IRR_WINDOWS_API_ #define _IRR_COMPILE_WITH_WINDOWS_DEVICE_ #endif //! WINCE is a very restricted environment for mobile devices #if defined(_WIN32_WCE) #define _IRR_WINDOWS_ #define _IRR_WINDOWS_API_ #define _IRR_WINDOWS_CE_PLATFORM_ #define _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ #endif #if defined(_MSC_VER) && (_MSC_VER < 1300) # error "Only Microsoft Visual Studio 7.0 and later are supported." #endif // XBox only suppots the native Window stuff #if defined(_XBOX) #undef _IRR_WINDOWS_ #define _IRR_XBOX_PLATFORM_ #define _IRR_WINDOWS_API_ //#define _IRR_COMPILE_WITH_WINDOWS_DEVICE_ #undef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ //#define _IRR_COMPILE_WITH_SDL_DEVICE_ #include #endif #if defined(__APPLE__) || defined(MACOSX) #if !defined(MACOSX) #define MACOSX // legacy support #endif #define _IRR_OSX_PLATFORM_ #define _IRR_COMPILE_WITH_OSX_DEVICE_ #endif #if !defined(_IRR_WINDOWS_API_) && !defined(_IRR_OSX_PLATFORM_) #ifndef _IRR_SOLARIS_PLATFORM_ #define _IRR_LINUX_PLATFORM_ #endif #define _IRR_POSIX_API_ #define _IRR_COMPILE_WITH_X11_DEVICE_ #endif //! Define _IRR_COMPILE_WITH_JOYSTICK_SUPPORT_ if you want joystick events. #define _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ #ifdef NO_IRR_COMPILE_WITH_JOYSTICK_EVENTS_ #undef _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ #endif //! Maximum number of texture an SMaterial can have, up to 8 are supported by Irrlicht. #define _IRR_MATERIAL_MAX_TEXTURES_ 4 //! Define _IRR_COMPILE_WITH_DIRECT3D_8_ and _IRR_COMPILE_WITH_DIRECT3D_9_ to //! compile the Irrlicht engine with Direct3D8 and/or DIRECT3D9. /** If you only want to use the software device or opengl you can disable those defines. This switch is mostly disabled because people do not get the g++ compiler compile directX header files, and directX is only available on Windows platforms. If you are using Dev-Cpp, and want to compile this using a DX dev pack, you can define _IRR_COMPILE_WITH_DX9_DEV_PACK_. So you simply need to add something like this to the compiler settings: -DIRR_COMPILE_WITH_DX9_DEV_PACK and this to the linker settings: -ld3dx9 -ld3dx8 Microsoft have chosen to remove D3D8 headers from their recent DXSDKs, and so D3D8 support is now disabled by default. If you really want to build with D3D8 support, then you will have to source a DXSDK with the appropriate headers, e.g. Summer 2004. This is a Microsoft issue, not an Irrlicht one. */ #if defined(_IRR_WINDOWS_API_) && (!defined(__GNUC__) || defined(IRR_COMPILE_WITH_DX9_DEV_PACK)) //! Define _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ if you want to use DirectInput for joystick handling. /** This only applies to Windows devices, currently only supported under Win32 device. If not defined, Windows Multimedia library is used, which offers also broad support for joystick devices. */ #define _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ #ifdef NO_IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ #undef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ #endif // can't get this to compile currently under borland, can be removed if someone has a better solution #if defined(__BORLANDC__) #undef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_ #endif //! Only define _IRR_COMPILE_WITH_DIRECT3D_8_ if you have an appropriate DXSDK, e.g. Summer 2004 // #define _IRR_COMPILE_WITH_DIRECT3D_8_ #define _IRR_COMPILE_WITH_DIRECT3D_9_ #ifdef NO_IRR_COMPILE_WITH_DIRECT3D_8_ #undef _IRR_COMPILE_WITH_DIRECT3D_8_ #endif #ifdef NO_IRR_COMPILE_WITH_DIRECT3D_9_ #undef _IRR_COMPILE_WITH_DIRECT3D_9_ #endif #endif //! Define _IRR_COMPILE_WITH_OPENGL_ to compile the Irrlicht engine with OpenGL. /** If you do not wish the engine to be compiled with OpenGL, comment this define out. */ #define _IRR_COMPILE_WITH_OPENGL_ #ifdef NO_IRR_COMPILE_WITH_OPENGL_ #undef _IRR_COMPILE_WITH_OPENGL_ #endif //! Define _IRR_COMPILE_WITH_SOFTWARE_ to compile the Irrlicht engine with software driver /** If you do not need the software driver, or want to use Burning's Video instead, comment this define out */ #define _IRR_COMPILE_WITH_SOFTWARE_ #ifdef NO_IRR_COMPILE_WITH_SOFTWARE_ #undef _IRR_COMPILE_WITH_SOFTWARE_ #endif //! Define _IRR_COMPILE_WITH_BURNINGSVIDEO_ to compile the Irrlicht engine with Burning's video driver /** If you do not need this software driver, you can comment this define out. */ #define _IRR_COMPILE_WITH_BURNINGSVIDEO_ #ifdef NO_IRR_COMPILE_WITH_BURNINGSVIDEO_ #undef _IRR_COMPILE_WITH_BURNINGSVIDEO_ #endif //! Define _IRR_COMPILE_WITH_X11_ to compile the Irrlicht engine with X11 support. /** If you do not wish the engine to be compiled with X11, comment this define out. */ // Only used in LinuxDevice. #define _IRR_COMPILE_WITH_X11_ #ifdef NO_IRR_COMPILE_WITH_X11_ #undef _IRR_COMPILE_WITH_X11_ #endif //! Define _IRR_OPENGL_USE_EXTPOINTER_ if the OpenGL renderer should use OpenGL extensions via function pointers. /** On some systems there is no support for the dynamic extension of OpenGL via function pointers such that this has to be undef'ed. */ #if !defined(_IRR_OSX_PLATFORM_) && !defined(_IRR_SOLARIS_PLATFORM_) #define _IRR_OPENGL_USE_EXTPOINTER_ #endif //! On some Linux systems the XF86 vidmode extension or X11 RandR are missing. Use these flags //! to remove the dependencies such that Irrlicht will compile on those systems, too. //! If you don't need colored cursors you can also disable the Xcursor extension #if defined(_IRR_LINUX_PLATFORM_) && defined(_IRR_COMPILE_WITH_X11_) #define _IRR_LINUX_X11_VIDMODE_ //#define _IRR_LINUX_X11_RANDR_ #ifdef NO_IRR_LINUX_X11_VIDMODE_ #undef _IRR_LINUX_X11_VIDMODE_ #endif #ifdef NO_IRR_LINUX_X11_RANDR_ #undef _IRR_LINUX_X11_RANDR_ #endif //! X11 has by default only monochrome cursors, but using the Xcursor library we can also get color cursor support. //! If you have the need for custom color cursors on X11 then enable this and make sure you also link //! to the Xcursor library in your Makefile/Projectfile. //#define _IRR_LINUX_XCURSOR_ #ifdef NO_IRR_LINUX_XCURSOR_ #undef _IRR_LINUX_XCURSOR_ #endif #endif //! Define _IRR_COMPILE_WITH_GUI_ to compile the engine with the built-in GUI /** Disable this if you are using an external library to draw the GUI. If you disable this then you will not be able to use anything provided by the GUI Environment, including loading fonts. */ #define _IRR_COMPILE_WITH_GUI_ #ifdef NO_IRR_COMPILE_WITH_GUI_ #undef _IRR_COMPILE_WITH_GUI_ #endif //! Define _IRR_WCHAR_FILESYSTEM to enable unicode filesystem support for the engine. /** This enables the engine to read/write from unicode filesystem. If you disable this feature, the engine behave as before (ansi). This is currently only supported for Windows based systems. You also have to set #define UNICODE for this to compile. */ //#define _IRR_WCHAR_FILESYSTEM #ifdef NO_IRR_WCHAR_FILESYSTEM #undef _IRR_WCHAR_FILESYSTEM #endif //! Define _IRR_COMPILE_WITH_JPEGLIB_ to enable compiling the engine using libjpeg. /** This enables the engine to read jpeg images. If you comment this out, the engine will no longer read .jpeg images. */ #define _IRR_COMPILE_WITH_LIBJPEG_ #ifdef NO_IRR_COMPILE_WITH_LIBJPEG_ #undef _IRR_COMPILE_WITH_LIBJPEG_ #endif //! Define _IRR_USE_NON_SYSTEM_JPEG_LIB_ to let irrlicht use the jpeglib which comes with irrlicht. /** If this is commented out, Irrlicht will try to compile using the jpeg lib installed in the system. This is only used when _IRR_COMPILE_WITH_LIBJPEG_ is defined. */ #define _IRR_USE_NON_SYSTEM_JPEG_LIB_ #ifdef NO_IRR_USE_NON_SYSTEM_JPEG_LIB_ #undef _IRR_USE_NON_SYSTEM_JPEG_LIB_ #endif //! Define _IRR_COMPILE_WITH_LIBPNG_ to enable compiling the engine using libpng. /** This enables the engine to read png images. If you comment this out, the engine will no longer read .png images. */ #define _IRR_COMPILE_WITH_LIBPNG_ #ifdef NO_IRR_COMPILE_WITH_LIBPNG_ #undef _IRR_COMPILE_WITH_LIBPNG_ #endif //! Define _IRR_USE_NON_SYSTEM_LIBPNG_ to let irrlicht use the libpng which comes with irrlicht. /** If this is commented out, Irrlicht will try to compile using the libpng installed in the system. This is only used when _IRR_COMPILE_WITH_LIBPNG_ is defined. */ #define _IRR_USE_NON_SYSTEM_LIB_PNG_ #ifdef NO_IRR_USE_NON_SYSTEM_LIB_PNG_ #undef _IRR_USE_NON_SYSTEM_LIB_PNG_ #endif //! Define _IRR_D3D_NO_SHADER_DEBUGGING to disable shader debugging in D3D9 /** If _IRR_D3D_NO_SHADER_DEBUGGING is undefined in IrrCompileConfig.h, it is possible to debug all D3D9 shaders in VisualStudio. All shaders (which have been generated in memory or read from archives for example) will be emitted into a temporary file at runtime for this purpose. To debug your shaders, choose Debug->Direct3D->StartWithDirect3DDebugging in Visual Studio, and for every shader a file named 'irr_dbg_shader_%%.vsh' or 'irr_dbg_shader_%%.psh' will be created. Drag'n'drop the file you want to debug into visual studio. That's it. You can now set breakpoints and watch registers, variables etc. This works with ASM, HLSL, and both with pixel and vertex shaders. Note that the engine will run in D3D REF for this, which is a lot slower than HAL. */ #define _IRR_D3D_NO_SHADER_DEBUGGING #ifdef NO_IRR_D3D_NO_SHADER_DEBUGGING #undef _IRR_D3D_NO_SHADER_DEBUGGING #endif //! Define _IRR_D3D_USE_LEGACY_HLSL_COMPILER to enable the old HLSL compiler in recent DX SDKs /** This enables support for ps_1_x shaders for recent DX SDKs. Otherwise, support for this shader model is not available anymore in SDKs after Oct2006. You need to distribute the OCT2006_d3dx9_31_x86.cab or OCT2006_d3dx9_31_x64.cab though, in order to provide the user with the proper DLL. That's why it's disabled by default. */ //#define _IRR_D3D_USE_LEGACY_HLSL_COMPILER #ifdef NO_IRR_D3D_USE_LEGACY_HLSL_COMPILER #undef _IRR_D3D_USE_LEGACY_HLSL_COMPILER #endif //! Define _IRR_COMPILE_WITH_CG_ to enable Cg Shading Language support //#define _IRR_COMPILE_WITH_CG_ #ifdef NO_IRR_COMPILE_WITH_CG_ #undef _IRR_COMPILE_WITH_CG_ #endif #if !defined(_IRR_COMPILE_WITH_OPENGL_) && !defined(_IRR_COMPILE_WITH_DIRECT3D_9_) #undef _IRR_COMPILE_WITH_CG_ #endif //! Define _IRR_USE_NVIDIA_PERFHUD_ to opt-in to using the nVidia PerHUD tool /** Enable, by opting-in, to use the nVidia PerfHUD performance analysis driver tool . */ #undef _IRR_USE_NVIDIA_PERFHUD_ //! Define one of the three setting for Burning's Video Software Rasterizer /** So if we were marketing guys we could say Irrlicht has 4 Software-Rasterizers. In a Nutshell: All Burnings Rasterizers use 32 Bit Backbuffer, 32Bit Texture & 32 Bit Z or WBuffer, 16 Bit/32 Bit can be adjusted on a global flag. BURNINGVIDEO_RENDERER_BEAUTIFUL 32 Bit + Vertexcolor + Lighting + Per Pixel Perspective Correct + SubPixel/SubTexel Correct + Bilinear Texturefiltering + WBuffer BURNINGVIDEO_RENDERER_FAST 32 Bit + Per Pixel Perspective Correct + SubPixel/SubTexel Correct + WBuffer + Bilinear Dithering TextureFiltering + WBuffer BURNINGVIDEO_RENDERER_ULTRA_FAST 16Bit + SubPixel/SubTexel Correct + ZBuffer */ #define BURNINGVIDEO_RENDERER_BEAUTIFUL //#define BURNINGVIDEO_RENDERER_FAST //#define BURNINGVIDEO_RENDERER_ULTRA_FAST //#define BURNINGVIDEO_RENDERER_CE //! Uncomment the following line if you want to ignore the deprecated warnings //#define IGNORE_DEPRECATED_WARNING //! Define _IRR_COMPILE_WITH_IRR_SCENE_LOADER_ if you want to be able to load /** .irr scenes using ISceneManager::loadScene */ #define _IRR_COMPILE_WITH_IRR_SCENE_LOADER_ #ifdef NO_IRR_COMPILE_WITH_IRR_SCENE_LOADER_ #undef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_ #endif //! Define _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ if you want to use bone based /** animated meshes. If you compile without this, you will be unable to load B3D, MS3D or X meshes */ #define _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ #ifdef NO_IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ #undef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ #endif #ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ //! Define _IRR_COMPILE_WITH_B3D_LOADER_ if you want to use Blitz3D files #define _IRR_COMPILE_WITH_B3D_LOADER_ #ifdef NO_IRR_COMPILE_WITH_B3D_LOADER_ #undef _IRR_COMPILE_WITH_B3D_LOADER_ #endif //! Define _IRR_COMPILE_WITH_MS3D_LOADER_ if you want to Milkshape files #define _IRR_COMPILE_WITH_MS3D_LOADER_ #ifdef NO_IRR_COMPILE_WITH_MS3D_LOADER_ #undef _IRR_COMPILE_WITH_MS3D_LOADER_ #endif //! Define _IRR_COMPILE_WITH_X_LOADER_ if you want to use Microsoft X files #define _IRR_COMPILE_WITH_X_LOADER_ #ifdef NO_IRR_COMPILE_WITH_X_LOADER_ #undef _IRR_COMPILE_WITH_X_LOADER_ #endif //! Define _IRR_COMPILE_WITH_OGRE_LOADER_ if you want to load Ogre 3D files #define _IRR_COMPILE_WITH_OGRE_LOADER_ #ifdef NO_IRR_COMPILE_WITH_OGRE_LOADER_ #undef _IRR_COMPILE_WITH_OGRE_LOADER_ #endif #endif // _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ //! Define _IRR_COMPILE_WITH_IRR_MESH_LOADER_ if you want to load Irrlicht Engine .irrmesh files #define _IRR_COMPILE_WITH_IRR_MESH_LOADER_ #ifdef NO_IRR_COMPILE_WITH_IRR_MESH_LOADER_ #undef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ #endif //! Define _IRR_COMPILE_WITH_HALFLIFE_LOADER_ if you want to load Halflife animated files #define _IRR_COMPILE_WITH_HALFLIFE_LOADER_ #ifdef NO_IRR_COMPILE_WITH_HALFLIFE_LOADER_ #undef _IRR_COMPILE_WITH_HALFLIFE_LOADER_ #endif //! Define _IRR_COMPILE_WITH_MD2_LOADER_ if you want to load Quake 2 animated files #define _IRR_COMPILE_WITH_MD2_LOADER_ #ifdef NO_IRR_COMPILE_WITH_MD2_LOADER_ #undef _IRR_COMPILE_WITH_MD2_LOADER_ #endif //! Define _IRR_COMPILE_WITH_MD3_LOADER_ if you want to load Quake 3 animated files #define _IRR_COMPILE_WITH_MD3_LOADER_ #ifdef NO_IRR_COMPILE_WITH_MD3_LOADER_ #undef _IRR_COMPILE_WITH_MD3_LOADER_ #endif //! Define _IRR_COMPILE_WITH_3DS_LOADER_ if you want to load 3D Studio Max files #define _IRR_COMPILE_WITH_3DS_LOADER_ #ifdef NO_IRR_COMPILE_WITH_3DS_LOADER_ #undef _IRR_COMPILE_WITH_3DS_LOADER_ #endif //! Define _IRR_COMPILE_WITH_COLLADA_LOADER_ if you want to load Collada files #define _IRR_COMPILE_WITH_COLLADA_LOADER_ #ifdef NO_IRR_COMPILE_WITH_COLLADA_LOADER_ #undef _IRR_COMPILE_WITH_COLLADA_LOADER_ #endif //! Define _IRR_COMPILE_WITH_CSM_LOADER_ if you want to load Cartography Shop files #define _IRR_COMPILE_WITH_CSM_LOADER_ #ifdef NO_IRR_COMPILE_WITH_CSM_LOADER_ #undef _IRR_COMPILE_WITH_CSM_LOADER_ #endif //! Define _IRR_COMPILE_WITH_BSP_LOADER_ if you want to load Quake 3 BSP files #define _IRR_COMPILE_WITH_BSP_LOADER_ #ifdef NO_IRR_COMPILE_WITH_BSP_LOADER_ #undef _IRR_COMPILE_WITH_BSP_LOADER_ #endif //! Define _IRR_COMPILE_WITH_DMF_LOADER_ if you want to load DeleD files #define _IRR_COMPILE_WITH_DMF_LOADER_ #ifdef NO_IRR_COMPILE_WITH_DMF_LOADER_ #undef _IRR_COMPILE_WITH_DMF_LOADER_ #endif //! Define _IRR_COMPILE_WITH_LMTS_LOADER_ if you want to load LMTools files #define _IRR_COMPILE_WITH_LMTS_LOADER_ #ifdef NO_IRR_COMPILE_WITH_LMTS_LOADER_ #undef _IRR_COMPILE_WITH_LMTS_LOADER_ #endif //! Define _IRR_COMPILE_WITH_MY3D_LOADER_ if you want to load MY3D files #define _IRR_COMPILE_WITH_MY3D_LOADER_ #ifdef NO_IRR_COMPILE_WITH_MY3D_LOADER_ #undef _IRR_COMPILE_WITH_MY3D_LOADER_ #endif //! Define _IRR_COMPILE_WITH_OBJ_LOADER_ if you want to load Wavefront OBJ files #define _IRR_COMPILE_WITH_OBJ_LOADER_ #ifdef NO_IRR_COMPILE_WITH_OBJ_LOADER_ #undef _IRR_COMPILE_WITH_OBJ_LOADER_ #endif //! Define _IRR_COMPILE_WITH_OCT_LOADER_ if you want to load FSRad OCT files #define _IRR_COMPILE_WITH_OCT_LOADER_ #ifdef NO_IRR_COMPILE_WITH_OCT_LOADER_ #undef _IRR_COMPILE_WITH_OCT_LOADER_ #endif //! Define _IRR_COMPILE_WITH_LWO_LOADER_ if you want to load Lightwave3D files #define _IRR_COMPILE_WITH_LWO_LOADER_ #ifdef NO_IRR_COMPILE_WITH_LWO_LOADER_ #undef _IRR_COMPILE_WITH_LWO_LOADER_ #endif //! Define _IRR_COMPILE_WITH_STL_LOADER_ if you want to load stereolithography files #define _IRR_COMPILE_WITH_STL_LOADER_ #ifdef NO_IRR_COMPILE_WITH_STL_LOADER_ #undef _IRR_COMPILE_WITH_STL_LOADER_ #endif //! Define _IRR_COMPILE_WITH_PLY_LOADER_ if you want to load Polygon (Stanford Triangle) files #define _IRR_COMPILE_WITH_PLY_LOADER_ #ifdef NO_IRR_COMPILE_WITH_PLY_LOADER_ #undef _IRR_COMPILE_WITH_PLY_LOADER_ #endif //! Define _IRR_COMPILE_WITH_SMF_LOADER_ if you want to load 3D World Studio mesh files #define _IRR_COMPILE_WITH_SMF_LOADER_ #ifdef NO_IRR_COMPILE_WITH_SMF_LOADER_ #undef _IRR_COMPILE_WITH_SMF_LOADER_ #endif //! Define _IRR_COMPILE_WITH_IRR_WRITER_ if you want to write static .irrMesh files #define _IRR_COMPILE_WITH_IRR_WRITER_ #ifdef NO_IRR_COMPILE_WITH_IRR_WRITER_ #undef _IRR_COMPILE_WITH_IRR_WRITER_ #endif //! Define _IRR_COMPILE_WITH_COLLADA_WRITER_ if you want to write Collada files #define _IRR_COMPILE_WITH_COLLADA_WRITER_ #ifdef NO_IRR_COMPILE_WITH_COLLADA_WRITER_ #undef _IRR_COMPILE_WITH_COLLADA_WRITER_ #endif //! Define _IRR_COMPILE_WITH_STL_WRITER_ if you want to write .stl files #define _IRR_COMPILE_WITH_STL_WRITER_ #ifdef NO_IRR_COMPILE_WITH_STL_WRITER_ #undef _IRR_COMPILE_WITH_STL_WRITER_ #endif //! Define _IRR_COMPILE_WITH_OBJ_WRITER_ if you want to write .obj files #define _IRR_COMPILE_WITH_OBJ_WRITER_ #ifdef NO_IRR_COMPILE_WITH_OBJ_WRITER_ #undef _IRR_COMPILE_WITH_OBJ_WRITER_ #endif //! Define _IRR_COMPILE_WITH_PLY_WRITER_ if you want to write .ply files #define _IRR_COMPILE_WITH_PLY_WRITER_ #ifdef NO_IRR_COMPILE_WITH_PLY_WRITER_ #undef _IRR_COMPILE_WITH_PLY_WRITER_ #endif //! Define _IRR_COMPILE_WITH_BMP_LOADER_ if you want to load .bmp files //! Disabling this loader will also disable the built-in font #define _IRR_COMPILE_WITH_BMP_LOADER_ #ifdef NO_IRR_COMPILE_WITH_BMP_LOADER_ #undef _IRR_COMPILE_WITH_BMP_LOADER_ #endif //! Define _IRR_COMPILE_WITH_JPG_LOADER_ if you want to load .jpg files #define _IRR_COMPILE_WITH_JPG_LOADER_ #ifdef NO_IRR_COMPILE_WITH_JPG_LOADER_ #undef _IRR_COMPILE_WITH_JPG_LOADER_ #endif //! Define _IRR_COMPILE_WITH_PCX_LOADER_ if you want to load .pcx files #define _IRR_COMPILE_WITH_PCX_LOADER_ #ifdef NO_IRR_COMPILE_WITH_PCX_LOADER_ #undef _IRR_COMPILE_WITH_PCX_LOADER_ #endif //! Define _IRR_COMPILE_WITH_PNG_LOADER_ if you want to load .png files #define _IRR_COMPILE_WITH_PNG_LOADER_ #ifdef NO_IRR_COMPILE_WITH_PNG_LOADER_ #undef _IRR_COMPILE_WITH_PNG_LOADER_ #endif //! Define _IRR_COMPILE_WITH_PPM_LOADER_ if you want to load .ppm/.pgm/.pbm files #define _IRR_COMPILE_WITH_PPM_LOADER_ #ifdef NO_IRR_COMPILE_WITH_PPM_LOADER_ #undef _IRR_COMPILE_WITH_PPM_LOADER_ #endif //! Define _IRR_COMPILE_WITH_PSD_LOADER_ if you want to load .psd files #define _IRR_COMPILE_WITH_PSD_LOADER_ #ifdef NO_IRR_COMPILE_WITH_PSD_LOADER_ #undef _IRR_COMPILE_WITH_PSD_LOADER_ #endif //! Define _IRR_COMPILE_WITH_DDS_LOADER_ if you want to load .dds files // Outcommented because // a) it doesn't compile on 64-bit currently // b) anyone enabling it should be aware that S3TC compression algorithm which might be used in that loader // is patented in the US by S3 and they do collect license fees when it's used in applications. // So if you are unfortunate enough to develop applications for US market and their broken patent system be careful. // #define _IRR_COMPILE_WITH_DDS_LOADER_ #ifdef NO_IRR_COMPILE_WITH_DDS_LOADER_ #undef _IRR_COMPILE_WITH_DDS_LOADER_ #endif //! Define _IRR_COMPILE_WITH_TGA_LOADER_ if you want to load .tga files #define _IRR_COMPILE_WITH_TGA_LOADER_ #ifdef NO_IRR_COMPILE_WITH_TGA_LOADER_ #undef _IRR_COMPILE_WITH_TGA_LOADER_ #endif //! Define _IRR_COMPILE_WITH_WAL_LOADER_ if you want to load .wal files #define _IRR_COMPILE_WITH_WAL_LOADER_ #ifdef NO_IRR_COMPILE_WITH_WAL_LOADER_ #undef _IRR_COMPILE_WITH_WAL_LOADER_ #endif //! Define _IRR_COMPILE_WITH_LMP_LOADER_ if you want to load .lmp files #define _IRR_COMPILE_WITH_LMP_LOADER_ #ifdef NO_IRR_COMPILE_WITH_LMP_LOADER_ #undef _IRR_COMPILE_WITH_LMP_LOADER_ #endif //! Define _IRR_COMPILE_WITH_RGB_LOADER_ if you want to load Silicon Graphics .rgb/.rgba/.sgi/.int/.inta/.bw files #define _IRR_COMPILE_WITH_RGB_LOADER_ #ifdef NO_IRR_COMPILE_WITH_RGB_LOADER_ #undef _IRR_COMPILE_WITH_RGB_LOADER_ #endif //! Define _IRR_COMPILE_WITH_BMP_WRITER_ if you want to write .bmp files #define _IRR_COMPILE_WITH_BMP_WRITER_ #ifdef NO_IRR_COMPILE_WITH_BMP_WRITER_ #undef _IRR_COMPILE_WITH_BMP_WRITER_ #endif //! Define _IRR_COMPILE_WITH_JPG_WRITER_ if you want to write .jpg files #define _IRR_COMPILE_WITH_JPG_WRITER_ #ifdef NO_IRR_COMPILE_WITH_JPG_WRITER_ #undef _IRR_COMPILE_WITH_JPG_WRITER_ #endif //! Define _IRR_COMPILE_WITH_PCX_WRITER_ if you want to write .pcx files #define _IRR_COMPILE_WITH_PCX_WRITER_ #ifdef NO_IRR_COMPILE_WITH_PCX_WRITER_ #undef _IRR_COMPILE_WITH_PCX_WRITER_ #endif //! Define _IRR_COMPILE_WITH_PNG_WRITER_ if you want to write .png files #define _IRR_COMPILE_WITH_PNG_WRITER_ #ifdef NO_IRR_COMPILE_WITH_PNG_WRITER_ #undef _IRR_COMPILE_WITH_PNG_WRITER_ #endif //! Define _IRR_COMPILE_WITH_PPM_WRITER_ if you want to write .ppm files #define _IRR_COMPILE_WITH_PPM_WRITER_ #ifdef NO_IRR_COMPILE_WITH_PPM_WRITER_ #undef _IRR_COMPILE_WITH_PPM_WRITER_ #endif //! Define _IRR_COMPILE_WITH_PSD_WRITER_ if you want to write .psd files #define _IRR_COMPILE_WITH_PSD_WRITER_ #ifdef NO_IRR_COMPILE_WITH_PSD_WRITER_ #undef _IRR_COMPILE_WITH_PSD_WRITER_ #endif //! Define _IRR_COMPILE_WITH_TGA_WRITER_ if you want to write .tga files #define _IRR_COMPILE_WITH_TGA_WRITER_ #ifdef NO_IRR_COMPILE_WITH_TGA_WRITER_ #undef _IRR_COMPILE_WITH_TGA_WRITER_ #endif //! Define __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ if you want to open ZIP and GZIP archives /** ZIP reading has several more options below to configure. */ #define __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ #ifdef NO__IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ #undef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ #endif #ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ //! Define _IRR_COMPILE_WITH_ZLIB_ to enable compiling the engine using zlib. /** This enables the engine to read from compressed .zip archives. If you disable this feature, the engine can still read archives, but only uncompressed ones. */ #define _IRR_COMPILE_WITH_ZLIB_ #ifdef NO_IRR_COMPILE_WITH_ZLIB_ #undef _IRR_COMPILE_WITH_ZLIB_ #endif //! Define _IRR_USE_NON_SYSTEM_ZLIB_ to let irrlicht use the zlib which comes with irrlicht. /** If this is commented out, Irrlicht will try to compile using the zlib installed on the system. This is only used when _IRR_COMPILE_WITH_ZLIB_ is defined. */ #define _IRR_USE_NON_SYSTEM_ZLIB_ #ifdef NO_IRR_USE_NON_SYSTEM_ZLIB_ #undef _IRR_USE_NON_SYSTEM_ZLIB_ #endif //! Define _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ if you want to read AES-encrypted ZIP archives #define _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ #ifdef NO_IRR_COMPILE_WITH_ZIP_ENCRYPTION_ #undef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ #endif //! Define _IRR_COMPILE_WITH_BZIP2_ if you want to support bzip2 compressed zip archives /** bzip2 is superior to the original zip file compression modes, but requires a certain amount of memory for decompression and adds several files to the library. */ #define _IRR_COMPILE_WITH_BZIP2_ #ifdef NO_IRR_COMPILE_WITH_BZIP2_ #undef _IRR_COMPILE_WITH_BZIP2_ #endif //! Define _IRR_USE_NON_SYSTEM_BZLIB_ to let irrlicht use the bzlib which comes with irrlicht. /** If this is commented out, Irrlicht will try to compile using the bzlib installed on the system. This is only used when _IRR_COMPILE_WITH_BZLIB_ is defined. */ #define _IRR_USE_NON_SYSTEM_BZLIB_ #ifdef NO_IRR_USE_NON_SYSTEM_BZLIB_ #undef _IRR_USE_NON_SYSTEM_BZLIB_ #endif //! Define _IRR_COMPILE_WITH_LZMA_ if you want to use LZMA compressed zip files. /** LZMA is a very efficient compression code, known from 7zip. Irrlicht currently only supports zip archives, though. */ #define _IRR_COMPILE_WITH_LZMA_ #ifdef NO_IRR_COMPILE_WITH_LZMA_ #undef _IRR_COMPILE_WITH_LZMA_ #endif #endif //! Define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ if you want to mount folders as archives #define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ #ifdef NO__IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ #undef __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ #endif //! Define __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ if you want to open ID software PAK archives #define __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ #ifdef NO__IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ #undef __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ #endif //! Define __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ if you want to open Nebula Device NPK archives #define __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ #ifdef NO__IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ #undef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ #endif //! Define __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ if you want to open TAR archives #define __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ #ifdef NO__IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ #undef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ #endif //! Define __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ if you want to open WAD archives #define __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ #ifdef NO__IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ #undef __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ #endif //! Set FPU settings /** Irrlicht should use approximate float and integer fpu techniques precision will be lower but speed higher. currently X86 only */ #if !defined(_IRR_OSX_PLATFORM_) && !defined(_IRR_SOLARIS_PLATFORM_) //#define IRRLICHT_FAST_MATH #ifdef NO_IRRLICHT_FAST_MATH #undef IRRLICHT_FAST_MATH #endif #endif // Some cleanup and standard stuff #ifdef _IRR_WINDOWS_API_ // To build Irrlicht as a static library, you must define _IRR_STATIC_LIB_ in both the // Irrlicht build, *and* in the user application, before #including #ifndef _IRR_STATIC_LIB_ #ifdef IRRLICHT_EXPORTS #define IRRLICHT_API __declspec(dllexport) #else #define IRRLICHT_API __declspec(dllimport) #endif // IRRLICHT_EXPORT #else #define IRRLICHT_API #endif // _IRR_STATIC_LIB_ // Declare the calling convention. #if defined(_STDCALL_SUPPORTED) #define IRRCALLCONV __stdcall #else #define IRRCALLCONV __cdecl #endif // STDCALL_SUPPORTED #else // _IRR_WINDOWS_API_ // Force symbol export in shared libraries built with gcc. #if (__GNUC__ >= 4) && !defined(_IRR_STATIC_LIB_) && defined(IRRLICHT_EXPORTS) #define IRRLICHT_API __attribute__ ((visibility("default"))) #else #define IRRLICHT_API #endif #define IRRCALLCONV #endif // _IRR_WINDOWS_API_ // We need to disable DIRECT3D9 support for Visual Studio 6.0 because // those $%&$!! disabled support for it since Dec. 2004 and users are complaining // about linker errors. Comment this out only if you are knowing what you are // doing. (Which means you have an old DX9 SDK and VisualStudio6). #ifdef _MSC_VER #if (_MSC_VER < 1300 && !defined(__GNUC__)) #undef _IRR_COMPILE_WITH_DIRECT3D_9_ #pragma message("Compiling Irrlicht with Visual Studio 6.0, support for DX9 is disabled.") #endif #endif // XBox does not have OpenGL or DirectX9 #if defined(_IRR_XBOX_PLATFORM_) #undef _IRR_COMPILE_WITH_OPENGL_ #undef _IRR_COMPILE_WITH_DIRECT3D_9_ #endif //! WinCE does not have OpenGL or DirectX9. use minimal loaders #if defined(_WIN32_WCE) #undef _IRR_COMPILE_WITH_OPENGL_ #undef _IRR_COMPILE_WITH_DIRECT3D_8_ #undef _IRR_COMPILE_WITH_DIRECT3D_9_ #undef BURNINGVIDEO_RENDERER_BEAUTIFUL #undef BURNINGVIDEO_RENDERER_FAST #undef BURNINGVIDEO_RENDERER_ULTRA_FAST #define BURNINGVIDEO_RENDERER_CE #undef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ #define _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ //#define _IRR_WCHAR_FILESYSTEM #undef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ //#undef _IRR_COMPILE_WITH_MD2_LOADER_ #undef _IRR_COMPILE_WITH_MD3_LOADER_ #undef _IRR_COMPILE_WITH_3DS_LOADER_ #undef _IRR_COMPILE_WITH_COLLADA_LOADER_ #undef _IRR_COMPILE_WITH_CSM_LOADER_ #undef _IRR_COMPILE_WITH_BSP_LOADER_ #undef _IRR_COMPILE_WITH_DMF_LOADER_ #undef _IRR_COMPILE_WITH_LMTS_LOADER_ #undef _IRR_COMPILE_WITH_MY3D_LOADER_ #undef _IRR_COMPILE_WITH_OBJ_LOADER_ #undef _IRR_COMPILE_WITH_OCT_LOADER_ #undef _IRR_COMPILE_WITH_OGRE_LOADER_ #undef _IRR_COMPILE_WITH_LWO_LOADER_ #undef _IRR_COMPILE_WITH_STL_LOADER_ #undef _IRR_COMPILE_WITH_IRR_WRITER_ #undef _IRR_COMPILE_WITH_COLLADA_WRITER_ #undef _IRR_COMPILE_WITH_STL_WRITER_ #undef _IRR_COMPILE_WITH_OBJ_WRITER_ //#undef _IRR_COMPILE_WITH_BMP_LOADER_ //#undef _IRR_COMPILE_WITH_JPG_LOADER_ #undef _IRR_COMPILE_WITH_PCX_LOADER_ //#undef _IRR_COMPILE_WITH_PNG_LOADER_ #undef _IRR_COMPILE_WITH_PPM_LOADER_ #undef _IRR_COMPILE_WITH_PSD_LOADER_ //#undef _IRR_COMPILE_WITH_TGA_LOADER_ #undef _IRR_COMPILE_WITH_WAL_LOADER_ #undef _IRR_COMPILE_WITH_BMP_WRITER_ #undef _IRR_COMPILE_WITH_JPG_WRITER_ #undef _IRR_COMPILE_WITH_PCX_WRITER_ #undef _IRR_COMPILE_WITH_PNG_WRITER_ #undef _IRR_COMPILE_WITH_PPM_WRITER_ #undef _IRR_COMPILE_WITH_PSD_WRITER_ #undef _IRR_COMPILE_WITH_TGA_WRITER_ #endif #ifndef _IRR_WINDOWS_API_ #undef _IRR_WCHAR_FILESYSTEM #endif #if defined(__sparc__) || defined(__sun__) #define __BIG_ENDIAN__ #endif #if defined(_IRR_SOLARIS_PLATFORM_) #undef _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ #endif //! Define __IRR_HAS_S64 if the irr::s64 type should be enable (needs long long, available on most platforms, but not part of ISO C++ 98) #define __IRR_HAS_S64 #ifdef NO__IRR_HAS_S64 #undef __IRR_HAS_S64 #endif #if defined(__BORLANDC__) #include // Borland 5.5.1 does not have _strcmpi defined #if __BORLANDC__ == 0x551 // #define _strcmpi strcmpi #undef _tfinddata_t #undef _tfindfirst #undef _tfindnext #define _tfinddata_t __tfinddata_t #define _tfindfirst __tfindfirst #define _tfindnext __tfindnext typedef long intptr_t; #endif #endif #ifdef _DEBUG //! A few attributes are written in CSceneManager when _IRR_SCENEMANAGER_DEBUG is enabled // NOTE: Those attributes were used always until 1.8.0 and became a global define for 1.8.1 // which is only enabled in debug because it had a large (sometimes >5%) impact on speed. // A better solution in the long run is to break the interface and remove _all_ attribute // access in functions like CSceneManager::drawAll and instead put that information in some // own struct/class or in CSceneManager. // See http://irrlicht.sourceforge.net/forum/viewtopic.php?f=2&t=48211 for the discussion. #define _IRR_SCENEMANAGER_DEBUG #ifdef NO_IRR_SCENEMANAGER_DEBUG #undef _IRR_SCENEMANAGER_DEBUG #endif #endif #endif // __IRR_COMPILE_CONFIG_H_INCLUDED__ irrlicht-1.8.3/include/irrArray.h0000644000000000000000000003754712574354552015464 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h #ifndef __IRR_ARRAY_H_INCLUDED__ #define __IRR_ARRAY_H_INCLUDED__ #include "irrTypes.h" #include "heapsort.h" #include "irrAllocator.h" #include "irrMath.h" namespace irr { namespace core { //! Self reallocating template array (like stl vector) with additional features. /** Some features are: Heap sorting, binary search methods, easier debugging. */ template > class array { public: //! Default constructor for empty array. array() : data(0), allocated(0), used(0), strategy(ALLOC_STRATEGY_DOUBLE), free_when_destroyed(true), is_sorted(true) { } //! Constructs an array and allocates an initial chunk of memory. /** \param start_count Amount of elements to pre-allocate. */ array(u32 start_count) : data(0), allocated(0), used(0), strategy(ALLOC_STRATEGY_DOUBLE), free_when_destroyed(true), is_sorted(true) { reallocate(start_count); } //! Copy constructor array(const array& other) : data(0) { *this = other; } //! Destructor. /** Frees allocated memory, if set_free_when_destroyed was not set to false by the user before. */ ~array() { clear(); } //! Reallocates the array, make it bigger or smaller. /** \param new_size New size of array. \param canShrink Specifies whether the array is reallocated even if enough space is available. Setting this flag to false can speed up array usage, but may use more memory than required by the data. */ void reallocate(u32 new_size, bool canShrink=true) { if (allocated==new_size) return; if (!canShrink && (new_size < allocated)) return; T* old_data = data; data = allocator.allocate(new_size); //new T[new_size]; allocated = new_size; // copy old data s32 end = used < new_size ? used : new_size; for (s32 i=0; iused) // access violation if (used + 1 > allocated) { // this doesn't work if the element is in the same // array. So we'll copy the element first to be sure // we'll get no data corruption const T e(element); // increase data block u32 newAlloc; switch ( strategy ) { case ALLOC_STRATEGY_DOUBLE: newAlloc = used + 1 + (allocated < 500 ? (allocated < 5 ? 5 : used) : used >> 2); break; default: case ALLOC_STRATEGY_SAFE: newAlloc = used + 1; break; } reallocate( newAlloc); // move array content and construct new element // first move end one up for (u32 i=used; i>index; --i) { if (i index) allocator.destruct(&data[index]); allocator.construct(&data[index], e); // data[index] = e; } else { // element inserted not at end if ( used > index ) { // create one new element at the end allocator.construct(&data[used], data[used-1]); // move the rest of the array content for (u32 i=used-1; i>index; --i) { data[i] = data[i-1]; } // insert the new element data[index] = element; } else { // insert the new element to the end allocator.construct(&data[index], element); } } // set to false as we don't know if we have the comparison operators is_sorted = false; ++used; } //! Clears the array and deletes all allocated memory. void clear() { if (free_when_destroyed) { for (u32 i=0; i& operator=(const array& other) { if (this == &other) return *this; strategy = other.strategy; if (data) clear(); //if (allocated < other.allocated) if (other.allocated == 0) data = 0; else data = allocator.allocate(other.allocated); // new T[other.allocated]; used = other.used; free_when_destroyed = true; is_sorted = other.is_sorted; allocated = other.allocated; for (u32 i=0; i& other) const { if (used != other.used) return false; for (u32 i=0; i& other) const { return !(*this==other); } //! Direct access operator T& operator [](u32 index) { _IRR_DEBUG_BREAK_IF(index>=used) // access violation return data[index]; } //! Direct const access operator const T& operator [](u32 index) const { _IRR_DEBUG_BREAK_IF(index>=used) // access violation return data[index]; } //! Gets last element. T& getLast() { _IRR_DEBUG_BREAK_IF(!used) // access violation return data[used-1]; } //! Gets last element const T& getLast() const { _IRR_DEBUG_BREAK_IF(!used) // access violation return data[used-1]; } //! Gets a pointer to the array. /** \return Pointer to the array. */ T* pointer() { return data; } //! Gets a const pointer to the array. /** \return Pointer to the array. */ const T* const_pointer() const { return data; } //! Get number of occupied elements of the array. /** \return Size of elements in the array which are actually occupied. */ u32 size() const { return used; } //! Get amount of memory allocated. /** \return Amount of memory allocated. The amount of bytes allocated would be allocated_size() * sizeof(ElementTypeUsed); */ u32 allocated_size() const { return allocated; } //! Check if array is empty. /** \return True if the array is empty false if not. */ bool empty() const { return used == 0; } //! Sorts the array using heapsort. /** There is no additional memory waste and the algorithm performs O(n*log n) in worst case. */ void sort() { if (!is_sorted && used>1) heapsort(data, used); is_sorted = true; } //! Performs a binary search for an element, returns -1 if not found. /** The array will be sorted before the binary search if it is not already sorted. Caution is advised! Be careful not to call this on unsorted const arrays, or the slower method will be used. \param element Element to search for. \return Position of the searched element if it was found, otherwise -1 is returned. */ s32 binary_search(const T& element) { sort(); return binary_search(element, 0, used-1); } //! Performs a binary search for an element if possible, returns -1 if not found. /** This method is for const arrays and so cannot call sort(), if the array is not sorted then linear_search will be used instead. Potentially very slow! \param element Element to search for. \return Position of the searched element if it was found, otherwise -1 is returned. */ s32 binary_search(const T& element) const { if (is_sorted) return binary_search(element, 0, used-1); else return linear_search(element); } //! Performs a binary search for an element, returns -1 if not found. /** \param element: Element to search for. \param left First left index \param right Last right index. \return Position of the searched element if it was found, otherwise -1 is returned. */ s32 binary_search(const T& element, s32 left, s32 right) const { if (!used) return -1; s32 m; do { m = (left+right)>>1; if (element < data[m]) right = m - 1; else left = m + 1; } while((element < data[m] || data[m] < element) && left<=right); // this last line equals to: // " while((element != array[m]) && left<=right);" // but we only want to use the '<' operator. // the same in next line, it is "(element == array[m])" if (!(element < data[m]) && !(data[m] < element)) return m; return -1; } //! Performs a binary search for an element, returns -1 if not found. //! it is used for searching a multiset /** The array will be sorted before the binary search if it is not already sorted. \param element Element to search for. \param &last return lastIndex of equal elements \return Position of the first searched element if it was found, otherwise -1 is returned. */ s32 binary_search_multi(const T& element, s32 &last) { sort(); s32 index = binary_search(element, 0, used-1); if ( index < 0 ) return index; // The search can be somewhere in the middle of the set // look linear previous and past the index last = index; while ( index > 0 && !(element < data[index - 1]) && !(data[index - 1] < element) ) { index -= 1; } // look linear up while ( last < (s32) used - 1 && !(element < data[last + 1]) && !(data[last + 1] < element) ) { last += 1; } return index; } //! Finds an element in linear time, which is very slow. /** Use binary_search for faster finding. Only works if ==operator is implemented. \param element Element to search for. \return Position of the searched element if it was found, otherwise -1 is returned. */ s32 linear_search(const T& element) const { for (u32 i=0; i=0; --i) if (data[i] == element) return i; return -1; } //! Erases an element from the array. /** May be slow, because all elements following after the erased element have to be copied. \param index: Index of element to be erased. */ void erase(u32 index) { _IRR_DEBUG_BREAK_IF(index>=used) // access violation for (u32 i=index+1; i=used || count<1) return; if (index+count>used) count = used-index; u32 i; for (i=index; i= index+count) // not already destructed before loop allocator.destruct(&data[i-count]); allocator.construct(&data[i-count], data[i]); // data[i-count] = data[i]; if (i >= used-count) // those which are not overwritten allocator.destruct(&data[i]); } used-= count; } //! Sets if the array is sorted void set_sorted(bool _is_sorted) { is_sorted = _is_sorted; } //! Swap the content of this array container with the content of another array /** Afterwards this object will contain the content of the other object and the other object will contain the content of this object. \param other Swap content with this object */ void swap(array& other) { core::swap(data, other.data); core::swap(allocated, other.allocated); core::swap(used, other.used); core::swap(allocator, other.allocator); // memory is still released by the same allocator used for allocation eAllocStrategy helper_strategy(strategy); // can't use core::swap with bitfields strategy = other.strategy; other.strategy = helper_strategy; bool helper_free_when_destroyed(free_when_destroyed); free_when_destroyed = other.free_when_destroyed; other.free_when_destroyed = helper_free_when_destroyed; bool helper_is_sorted(is_sorted); is_sorted = other.is_sorted; other.is_sorted = helper_is_sorted; } private: T* data; u32 allocated; u32 used; TAlloc allocator; eAllocStrategy strategy:4; bool free_when_destroyed:1; bool is_sorted:1; }; } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/irrAllocator.h0000644000000000000000000000451112574354552016307 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h #ifndef __IRR_ALLOCATOR_H_INCLUDED__ #define __IRR_ALLOCATOR_H_INCLUDED__ #include "irrTypes.h" #include // necessary for older compilers #include namespace irr { namespace core { #ifdef DEBUG_CLIENTBLOCK #undef DEBUG_CLIENTBLOCK #define DEBUG_CLIENTBLOCK new #endif //! Very simple allocator implementation, containers using it can be used across dll boundaries template class irrAllocator { public: //! Destructor virtual ~irrAllocator() {} //! Allocate memory for an array of objects T* allocate(size_t cnt) { return (T*)internal_new(cnt* sizeof(T)); } //! Deallocate memory for an array of objects void deallocate(T* ptr) { internal_delete(ptr); } //! Construct an element void construct(T* ptr, const T&e) { new ((void*)ptr) T(e); } //! Destruct an element void destruct(T* ptr) { ptr->~T(); } protected: virtual void* internal_new(size_t cnt) { return operator new(cnt); } virtual void internal_delete(void* ptr) { operator delete(ptr); } }; //! Fast allocator, only to be used in containers inside the same memory heap. /** Containers using it are NOT able to be used it across dll boundaries. Use this when using in an internal class or function or when compiled into a static lib */ template class irrAllocatorFast { public: //! Allocate memory for an array of objects T* allocate(size_t cnt) { return (T*)operator new(cnt* sizeof(T)); } //! Deallocate memory for an array of objects void deallocate(T* ptr) { operator delete(ptr); } //! Construct an element void construct(T* ptr, const T&e) { new ((void*)ptr) T(e); } //! Destruct an element void destruct(T* ptr) { ptr->~T(); } }; #ifdef DEBUG_CLIENTBLOCK #undef DEBUG_CLIENTBLOCK #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) #endif //! defines an allocation strategy enum eAllocStrategy { ALLOC_STRATEGY_SAFE = 0, ALLOC_STRATEGY_DOUBLE = 1, ALLOC_STRATEGY_SQRT = 2 }; } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/IReferenceCounted.h0000644000000000000000000001414512574354552017207 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_IREFERENCE_COUNTED_H_INCLUDED__ #define __I_IREFERENCE_COUNTED_H_INCLUDED__ #include "irrTypes.h" namespace irr { //! Base class of most objects of the Irrlicht Engine. /** This class provides reference counting through the methods grab() and drop(). It also is able to store a debug string for every instance of an object. Most objects of the Irrlicht Engine are derived from IReferenceCounted, and so they are reference counted. When you create an object in the Irrlicht engine, calling a method which starts with 'create', an object is created, and you get a pointer to the new object. If you no longer need the object, you have to call drop(). This will destroy the object, if grab() was not called in another part of you program, because this part still needs the object. Note, that you only need to call drop() to the object, if you created it, and the method had a 'create' in it. A simple example: If you want to create a texture, you may want to call an imaginable method IDriver::createTexture. You call ITexture* texture = driver->createTexture(dimension2d(128, 128)); If you no longer need the texture, call texture->drop(). If you want to load a texture, you may want to call imaginable method IDriver::loadTexture. You do this like ITexture* texture = driver->loadTexture("example.jpg"); You will not have to drop the pointer to the loaded texture, because the name of the method does not start with 'create'. The texture is stored somewhere by the driver. */ class IReferenceCounted { public: //! Constructor. IReferenceCounted() : DebugName(0), ReferenceCounter(1) { } //! Destructor. virtual ~IReferenceCounted() { } //! Grabs the object. Increments the reference counter by one. /** Someone who calls grab() to an object, should later also call drop() to it. If an object never gets as much drop() as grab() calls, it will never be destroyed. The IReferenceCounted class provides a basic reference counting mechanism with its methods grab() and drop(). Most objects of the Irrlicht Engine are derived from IReferenceCounted, and so they are reference counted. When you create an object in the Irrlicht engine, calling a method which starts with 'create', an object is created, and you get a pointer to the new object. If you no longer need the object, you have to call drop(). This will destroy the object, if grab() was not called in another part of you program, because this part still needs the object. Note, that you only need to call drop() to the object, if you created it, and the method had a 'create' in it. A simple example: If you want to create a texture, you may want to call an imaginable method IDriver::createTexture. You call ITexture* texture = driver->createTexture(dimension2d(128, 128)); If you no longer need the texture, call texture->drop(). If you want to load a texture, you may want to call imaginable method IDriver::loadTexture. You do this like ITexture* texture = driver->loadTexture("example.jpg"); You will not have to drop the pointer to the loaded texture, because the name of the method does not start with 'create'. The texture is stored somewhere by the driver. */ void grab() const { ++ReferenceCounter; } //! Drops the object. Decrements the reference counter by one. /** The IReferenceCounted class provides a basic reference counting mechanism with its methods grab() and drop(). Most objects of the Irrlicht Engine are derived from IReferenceCounted, and so they are reference counted. When you create an object in the Irrlicht engine, calling a method which starts with 'create', an object is created, and you get a pointer to the new object. If you no longer need the object, you have to call drop(). This will destroy the object, if grab() was not called in another part of you program, because this part still needs the object. Note, that you only need to call drop() to the object, if you created it, and the method had a 'create' in it. A simple example: If you want to create a texture, you may want to call an imaginable method IDriver::createTexture. You call ITexture* texture = driver->createTexture(dimension2d(128, 128)); If you no longer need the texture, call texture->drop(). If you want to load a texture, you may want to call imaginable method IDriver::loadTexture. You do this like ITexture* texture = driver->loadTexture("example.jpg"); You will not have to drop the pointer to the loaded texture, because the name of the method does not start with 'create'. The texture is stored somewhere by the driver. \return True, if the object was deleted. */ bool drop() const { // someone is doing bad reference counting. _IRR_DEBUG_BREAK_IF(ReferenceCounter <= 0) --ReferenceCounter; if (!ReferenceCounter) { delete this; return true; } return false; } //! Get the reference count. /** \return Current value of the reference counter. */ s32 getReferenceCount() const { return ReferenceCounter; } //! Returns the debug name of the object. /** The Debugname may only be set and changed by the object itself. This method should only be used in Debug mode. \return Returns a string, previously set by setDebugName(); */ const c8* getDebugName() const { return DebugName; } protected: //! Sets the debug name of the object. /** The Debugname may only be set and changed by the object itself. This method should only be used in Debug mode. \param newName: New debug name to set. */ void setDebugName(const c8* newName) { DebugName = newName; } private: //! The debug name. const c8* DebugName; //! The reference counter. Mutable to do reference counting on const objects. mutable s32 ReferenceCounter; }; } // end namespace irr #endif irrlicht-1.8.3/include/IReadFile.h0000644000000000000000000000371612574354552015444 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_READ_FILE_H_INCLUDED__ #define __I_READ_FILE_H_INCLUDED__ #include "IReferenceCounted.h" #include "coreutil.h" namespace irr { namespace io { //! Interface providing read acess to a file. class IReadFile : public virtual IReferenceCounted { public: //! Reads an amount of bytes from the file. /** \param buffer Pointer to buffer where read bytes are written to. \param sizeToRead Amount of bytes to read from the file. \return How many bytes were read. */ virtual s32 read(void* buffer, u32 sizeToRead) = 0; //! Changes position in file /** \param finalPos Destination position in the file. \param relativeMovement If set to true, the position in the file is changed relative to current position. Otherwise the position is changed from beginning of file. \return True if successful, otherwise false. */ virtual bool seek(long finalPos, bool relativeMovement = false) = 0; //! Get size of file. /** \return Size of the file in bytes. */ virtual long getSize() const = 0; //! Get the current position in the file. /** \return Current position in the file in bytes. */ virtual long getPos() const = 0; //! Get name of file. /** \return File name as zero terminated character string. */ virtual const io::path& getFileName() const = 0; }; //! Internal function, please do not use. IReadFile* createReadFile(const io::path& fileName); //! Internal function, please do not use. IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize); //! Internal function, please do not use. IReadFile* createMemoryReadFile(void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped); } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/include/IRandomizer.h0000644000000000000000000000152412574354552016076 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_RANDOMIZER_H_INCLUDED__ #define __I_RANDOMIZER_H_INCLUDED__ #include "IReferenceCounted.h" namespace irr { //! Interface for generating random numbers class IRandomizer : public virtual IReferenceCounted { public: //! resets the randomizer /** \param value Initialization value (seed) */ virtual void reset(s32 value=0x0f0f0f0f) =0; //! generates a pseudo random number in the range 0..randMax() virtual s32 rand() const =0; //! generates a pseudo random number in the range 0..1 virtual f32 frand() const =0; //! get maxmimum number generated by rand() virtual s32 randMax() const =0; }; } // end namespace irr #endif irrlicht-1.8.3/include/IQ3Shader.h0000644000000000000000000004745612574354552015414 0ustar rootroot// Copyright (C) 2006-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_Q3_LEVEL_SHADER_H_INCLUDED__ #define __I_Q3_LEVEL_SHADER_H_INCLUDED__ #include "irrArray.h" #include "fast_atof.h" #include "IFileSystem.h" #include "IVideoDriver.h" #include "coreutil.h" namespace irr { namespace scene { namespace quake3 { static core::stringc irrEmptyStringc(""); //! Hold the different Mesh Types used for getMesh enum eQ3MeshIndex { E_Q3_MESH_GEOMETRY = 0, E_Q3_MESH_ITEMS, E_Q3_MESH_BILLBOARD, E_Q3_MESH_FOG, E_Q3_MESH_UNRESOLVED, E_Q3_MESH_SIZE }; /*! used to customize Quake3 BSP Loader */ struct Q3LevelLoadParameter { Q3LevelLoadParameter () :defaultLightMapMaterial ( video::EMT_LIGHTMAP_M4 ), defaultModulate ( video::EMFN_MODULATE_4X ), defaultFilter ( video::EMF_BILINEAR_FILTER ), patchTesselation ( 8 ), verbose ( 0 ), startTime ( 0 ), endTime ( 0 ), mergeShaderBuffer ( 1 ), cleanUnResolvedMeshes ( 1 ), loadAllShaders ( 0 ), loadSkyShader ( 0 ), alpharef ( 1 ), swapLump ( 0 ), #ifdef __BIG_ENDIAN__ swapHeader ( 1 ) #else swapHeader ( 0 ) #endif { memcpy ( scriptDir, "scripts\x0", 8 ); } video::E_MATERIAL_TYPE defaultLightMapMaterial; video::E_MODULATE_FUNC defaultModulate; video::E_MATERIAL_FLAG defaultFilter; s32 patchTesselation; s32 verbose; u32 startTime; u32 endTime; s32 mergeShaderBuffer; s32 cleanUnResolvedMeshes; s32 loadAllShaders; s32 loadSkyShader; s32 alpharef; s32 swapLump; s32 swapHeader; c8 scriptDir [ 64 ]; }; // some useful typedefs typedef core::array< core::stringc > tStringList; typedef core::array< video::ITexture* > tTexArray; // string helper.. TODO: move to generic files inline s16 isEqual ( const core::stringc &string, u32 &pos, const c8 *list[], u16 listSize ) { const char * in = string.c_str () + pos; for ( u16 i = 0; i != listSize; ++i ) { if (string.size() < pos) return -2; u32 len = (u32) strlen ( list[i] ); if (string.size() < pos+len) continue; if ( in [len] != 0 && in [len] != ' ' ) continue; if ( strncmp ( in, list[i], len ) ) continue; pos += len + 1; return (s16) i; } return -2; } inline f32 getAsFloat ( const core::stringc &string, u32 &pos ) { const char * in = string.c_str () + pos; f32 value = 0.f; pos += (u32) ( core::fast_atof_move ( in, value ) - in ) + 1; return value; } //! get a quake3 vector translated to irrlicht position (x,-z,y ) inline core::vector3df getAsVector3df ( const core::stringc &string, u32 &pos ) { core::vector3df v; v.X = getAsFloat ( string, pos ); v.Z = getAsFloat ( string, pos ); v.Y = getAsFloat ( string, pos ); return v; } /* extract substrings */ inline void getAsStringList ( tStringList &list, s32 max, const core::stringc &string, u32 &startPos ) { list.clear (); s32 finish = 0; s32 endPos; do { endPos = string.findNext ( ' ', startPos ); if ( endPos == -1 ) { finish = 1; endPos = string.size(); } list.push_back ( string.subString ( startPos, endPos - startPos ) ); startPos = endPos + 1; if ( list.size() >= (u32) max ) finish = 1; } while ( !finish ); } //! A blend function for a q3 shader. struct SBlendFunc { SBlendFunc ( video::E_MODULATE_FUNC mod ) : type ( video::EMT_SOLID ), modulate ( mod ), param0( 0.f ), isTransparent ( 0 ) {} video::E_MATERIAL_TYPE type; video::E_MODULATE_FUNC modulate; f32 param0; u32 isTransparent; }; // parses the content of Variable cull inline bool getCullingFunction ( const core::stringc &cull ) { if ( cull.size() == 0 ) return true; bool ret = true; static const c8 * funclist[] = { "none", "disable", "twosided" }; u32 pos = 0; switch ( isEqual ( cull, pos, funclist, 3 ) ) { case 0: case 1: case 2: ret = false; break; } return ret; } // parses the content of Variable depthfunc // return a z-test inline u8 getDepthFunction ( const core::stringc &string ) { u8 ret = video::ECFN_LESSEQUAL; if ( string.size() == 0 ) return ret; static const c8 * funclist[] = { "lequal","equal" }; u32 pos = 0; switch ( isEqual ( string, pos, funclist, 2 ) ) { case 0: ret = video::ECFN_LESSEQUAL; break; case 1: ret = video::ECFN_EQUAL; break; } return ret; } /*! parses the content of Variable blendfunc,alphafunc it also make a hint for rendering as transparent or solid node. we assume a typical quake scene would look like this.. 1) Big Static Mesh ( solid ) 2) static scene item ( may use transparency ) but rendered in the solid pass 3) additional transparency item in the transparent pass it's not 100% accurate! it just empirical.. */ inline static void getBlendFunc ( const core::stringc &string, SBlendFunc &blendfunc ) { if ( string.size() == 0 ) return; // maps to E_BLEND_FACTOR static const c8 * funclist[] = { "gl_zero", "gl_one", "gl_dst_color", "gl_one_minus_dst_color", "gl_src_color", "gl_one_minus_src_color", "gl_src_alpha", "gl_one_minus_src_alpha", "gl_dst_alpha", "gl_one_minus_dst_alpha", "gl_src_alpha_sat", "add", "filter", "blend", "ge128", "gt0", }; u32 pos = 0; s32 srcFact = isEqual ( string, pos, funclist, 16 ); if ( srcFact < 0 ) return; u32 resolved = 0; s32 dstFact = isEqual ( string, pos, funclist, 16 ); switch ( srcFact ) { case video::EBF_ZERO: switch ( dstFact ) { // gl_zero gl_src_color == gl_dst_color gl_zero case video::EBF_SRC_COLOR: blendfunc.type = video::EMT_ONETEXTURE_BLEND; blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate ); blendfunc.isTransparent = 1; resolved = 1; break; } break; case video::EBF_ONE: switch ( dstFact ) { // gl_one gl_zero case video::EBF_ZERO: blendfunc.type = video::EMT_SOLID; blendfunc.isTransparent = 0; resolved = 1; break; // gl_one gl_one case video::EBF_ONE: blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR; blendfunc.isTransparent = 1; resolved = 1; break; } break; case video::EBF_SRC_ALPHA: switch ( dstFact ) { // gl_src_alpha gl_one_minus_src_alpha case video::EBF_ONE_MINUS_SRC_ALPHA: blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; blendfunc.param0 = 1.f/255.f; blendfunc.isTransparent = 1; resolved = 1; break; } break; case 11: // add blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR; blendfunc.isTransparent = 1; resolved = 1; break; case 12: // filter = gl_dst_color gl_zero or gl_zero gl_src_color blendfunc.type = video::EMT_ONETEXTURE_BLEND; blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate ); blendfunc.isTransparent = 1; resolved = 1; break; case 13: // blend = gl_src_alpha gl_one_minus_src_alpha blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; blendfunc.param0 = 1.f/255.f; blendfunc.isTransparent = 1; resolved = 1; break; case 14: // alphafunc ge128 blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; blendfunc.param0 = 0.5f; blendfunc.isTransparent = 1; resolved = 1; break; case 15: // alphafunc gt0 blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; blendfunc.param0 = 1.f / 255.f; blendfunc.isTransparent = 1; resolved = 1; break; } // use the generic blender if ( 0 == resolved ) { blendfunc.type = video::EMT_ONETEXTURE_BLEND; blendfunc.param0 = video::pack_textureBlendFunc ( (video::E_BLEND_FACTOR) srcFact, (video::E_BLEND_FACTOR) dstFact, blendfunc.modulate); blendfunc.isTransparent = 1; } } // random noise [-1;1] struct Noiser { static f32 get () { static u32 RandomSeed = 0x69666966; RandomSeed = (RandomSeed * 3631 + 1); f32 value = ( (f32) (RandomSeed & 0x7FFF ) * (1.0f / (f32)(0x7FFF >> 1) ) ) - 1.f; return value; } }; enum eQ3ModifierFunction { TCMOD = 0, DEFORMVERTEXES = 1, RGBGEN = 2, TCGEN = 3, MAP = 4, ALPHAGEN = 5, FUNCTION2 = 0x10, SCROLL = FUNCTION2 + 1, SCALE = FUNCTION2 + 2, ROTATE = FUNCTION2 + 3, STRETCH = FUNCTION2 + 4, TURBULENCE = FUNCTION2 + 5, WAVE = FUNCTION2 + 6, IDENTITY = FUNCTION2 + 7, VERTEX = FUNCTION2 + 8, TEXTURE = FUNCTION2 + 9, LIGHTMAP = FUNCTION2 + 10, ENVIRONMENT = FUNCTION2 + 11, DOLLAR_LIGHTMAP = FUNCTION2 + 12, BULGE = FUNCTION2 + 13, AUTOSPRITE = FUNCTION2 + 14, AUTOSPRITE2 = FUNCTION2 + 15, TRANSFORM = FUNCTION2 + 16, EXACTVERTEX = FUNCTION2 + 17, CONSTANT = FUNCTION2 + 18, LIGHTINGSPECULAR = FUNCTION2 + 19, MOVE = FUNCTION2 + 20, NORMAL = FUNCTION2 + 21, IDENTITYLIGHTING = FUNCTION2 + 22, WAVE_MODIFIER_FUNCTION = 0x30, SINUS = WAVE_MODIFIER_FUNCTION + 1, COSINUS = WAVE_MODIFIER_FUNCTION + 2, SQUARE = WAVE_MODIFIER_FUNCTION + 3, TRIANGLE = WAVE_MODIFIER_FUNCTION + 4, SAWTOOTH = WAVE_MODIFIER_FUNCTION + 5, SAWTOOTH_INVERSE = WAVE_MODIFIER_FUNCTION + 6, NOISE = WAVE_MODIFIER_FUNCTION + 7, UNKNOWN = -2 }; struct SModifierFunction { SModifierFunction () : masterfunc0 ( UNKNOWN ), masterfunc1( UNKNOWN ), func ( SINUS ), tcgen( TEXTURE ), rgbgen ( IDENTITY ), alphagen ( UNKNOWN ), base ( 0 ), amp ( 1 ), phase ( 0 ), frequency ( 1 ), wave ( 1 ), x ( 0 ), y ( 0 ), z( 0 ), count( 0 ) {} // "tcmod","deformvertexes","rgbgen", "tcgen" eQ3ModifierFunction masterfunc0; // depends eQ3ModifierFunction masterfunc1; // depends eQ3ModifierFunction func; eQ3ModifierFunction tcgen; eQ3ModifierFunction rgbgen; eQ3ModifierFunction alphagen; union { f32 base; f32 bulgewidth; }; union { f32 amp; f32 bulgeheight; }; f32 phase; union { f32 frequency; f32 bulgespeed; }; union { f32 wave; f32 div; }; f32 x; f32 y; f32 z; u32 count; f32 evaluate ( f32 dt ) const { // phase in 0 and 1.. f32 x = core::fract( (dt + phase ) * frequency ); f32 y = 0.f; switch ( func ) { case SINUS: y = sinf ( x * core::PI * 2.f ); break; case COSINUS: y = cosf ( x * core::PI * 2.f ); break; case SQUARE: y = x < 0.5f ? 1.f : -1.f; break; case TRIANGLE: y = x < 0.5f ? ( 4.f * x ) - 1.f : ( -4.f * x ) + 3.f; break; case SAWTOOTH: y = x; break; case SAWTOOTH_INVERSE: y = 1.f - x; break; case NOISE: y = Noiser::get(); break; default: break; } return base + ( y * amp ); } }; inline core::vector3df getMD3Normal ( u32 i, u32 j ) { const f32 lng = i * 2.0f * core::PI / 255.0f; const f32 lat = j * 2.0f * core::PI / 255.0f; return core::vector3df(cosf ( lat ) * sinf ( lng ), sinf ( lat ) * sinf ( lng ), cosf ( lng )); } // inline void getModifierFunc ( SModifierFunction& fill, const core::stringc &string, u32 &pos ) { if ( string.size() == 0 ) return; static const c8 * funclist[] = { "sin","cos","square", "triangle", "sawtooth","inversesawtooth", "noise" }; fill.func = (eQ3ModifierFunction) isEqual ( string,pos, funclist,7 ); fill.func = fill.func == UNKNOWN ? SINUS : (eQ3ModifierFunction) ((u32) fill.func + WAVE_MODIFIER_FUNCTION + 1); fill.base = getAsFloat ( string, pos ); fill.amp = getAsFloat ( string, pos ); fill.phase = getAsFloat ( string, pos ); fill.frequency = getAsFloat ( string, pos ); } // name = "a b c .." struct SVariable { core::stringc name; core::stringc content; SVariable ( const c8 * n, const c8 *c = 0 ) : name ( n ), content (c) {} virtual ~SVariable () {} void clear () { name = ""; content = ""; } s32 isValid () const { return name.size(); } bool operator == ( const SVariable &other ) const { return 0 == strcmp ( name.c_str(), other.name.c_str () ); } bool operator < ( const SVariable &other ) const { return 0 > strcmp ( name.c_str(), other.name.c_str () ); } }; // string database. "a" = "Hello", "b" = "1234.6" struct SVarGroup { SVarGroup () { Variable.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); } virtual ~SVarGroup () {} u32 isDefined ( const c8 * name, const c8 * content = 0 ) const { for ( u32 i = 0; i != Variable.size (); ++i ) { if ( 0 == strcmp ( Variable[i].name.c_str(), name ) && ( 0 == content || strstr ( Variable[i].content.c_str(), content ) ) ) { return i + 1; } } return 0; } // searches for Variable name and returns is content // if Variable is not found a reference to an Empty String is returned const core::stringc &get( const c8 * name ) const { SVariable search ( name ); s32 index = Variable.linear_search ( search ); if ( index < 0 ) return irrEmptyStringc; return Variable [ index ].content; } // set the Variable name void set ( const c8 * name, const c8 * content = 0 ) { u32 index = isDefined ( name, 0 ); if ( 0 == index ) { Variable.push_back ( SVariable ( name, content ) ); } else { Variable [ index ].content = content; } } core::array < SVariable > Variable; }; //! holding a group a variable struct SVarGroupList: public IReferenceCounted { SVarGroupList () { VariableGroup.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); } virtual ~SVarGroupList () {} core::array < SVarGroup > VariableGroup; }; //! A Parsed Shader Holding Variables ordered in Groups struct IShader { IShader () : ID ( 0 ), VarGroup ( 0 ) {} virtual ~IShader () {} void operator = (const IShader &other ) { ID = other.ID; VarGroup = other.VarGroup; name = other.name; } bool operator == (const IShader &other ) const { return 0 == strcmp ( name.c_str(), other.name.c_str () ); //return name == other.name; } bool operator < (const IShader &other ) const { return strcmp ( name.c_str(), other.name.c_str () ) < 0; //return name < other.name; } u32 getGroupSize () const { if ( 0 == VarGroup ) return 0; return VarGroup->VariableGroup.size (); } const SVarGroup * getGroup ( u32 stage ) const { if ( 0 == VarGroup || stage >= VarGroup->VariableGroup.size () ) return 0; return &VarGroup->VariableGroup [ stage ]; } // id s32 ID; SVarGroupList *VarGroup; // reference // Shader: shader name ( also first variable in first Vargroup ) // Entity: classname ( variable in Group(1) ) core::stringc name; }; typedef IShader IEntity; typedef core::array < IEntity > tQ3EntityList; /* dump shader like original layout, regardless of internal data holding no recursive folding.. */ inline void dumpVarGroup ( core::stringc &dest, const SVarGroup * group, s32 stack ) { core::stringc buf; s32 i; if ( stack > 0 ) { buf = ""; for ( i = 0; i < stack - 1; ++i ) buf += '\t'; buf += "{\n"; dest.append ( buf ); } for ( u32 g = 0; g != group->Variable.size(); ++g ) { buf = ""; for ( i = 0; i < stack; ++i ) buf += '\t'; buf += group->Variable[g].name; buf += " "; buf += group->Variable[g].content; buf += "\n"; dest.append ( buf ); } if ( stack > 1 ) { buf = ""; for ( i = 0; i < stack - 1; ++i ) buf += '\t'; buf += "}\n"; dest.append ( buf ); } } /*! dump a Shader or an Entity */ inline core::stringc & dumpShader ( core::stringc &dest, const IShader * shader, bool entity = false ) { if ( 0 == shader ) return dest; const SVarGroup * group; const u32 size = shader->VarGroup->VariableGroup.size (); for ( u32 i = 0; i != size; ++i ) { group = &shader->VarGroup->VariableGroup[ i ]; dumpVarGroup ( dest, group, core::clamp( (int)i, 0, 2 ) ); } if ( !entity ) { if ( size <= 1 ) { dest.append ( "{\n" ); } dest.append ( "}\n" ); } return dest; } /* quake3 doesn't care much about tga & jpg load one or multiple files stored in name started at startPos to the texture array textures if texture is not loaded 0 will be added ( to find missing textures easier) */ inline void getTextures(tTexArray &textures, const core::stringc &name, u32 &startPos, io::IFileSystem *fileSystem, video::IVideoDriver* driver) { static const char* extension[] = { ".jpg", ".jpeg", ".png", ".dds", ".tga", ".bmp", ".pcx" }; tStringList stringList; getAsStringList(stringList, -1, name, startPos); textures.clear(); io::path loadFile; for ( u32 i = 0; i!= stringList.size (); ++i ) { video::ITexture* texture = 0; for (u32 g = 0; g != 7 ; ++g) { core::cutFilenameExtension ( loadFile, stringList[i] ); if ( loadFile == "$whiteimage" ) { texture = driver->getTexture( "$whiteimage" ); if ( 0 == texture ) { core::dimension2du s ( 2, 2 ); u32 image[4] = { 0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }; video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); texture = driver->addTexture( "$whiteimage", w ); w->drop (); } } else if ( loadFile == "$redimage" ) { texture = driver->getTexture( "$redimage" ); if ( 0 == texture ) { core::dimension2du s ( 2, 2 ); u32 image[4] = { 0xFFFF0000, 0xFFFF0000,0xFFFF0000,0xFFFF0000 }; video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); texture = driver->addTexture( "$redimage", w ); w->drop (); } } else if ( loadFile == "$blueimage" ) { texture = driver->getTexture( "$blueimage" ); if ( 0 == texture ) { core::dimension2du s ( 2, 2 ); u32 image[4] = { 0xFF0000FF, 0xFF0000FF,0xFF0000FF,0xFF0000FF }; video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); texture = driver->addTexture( "$blueimage", w ); w->drop (); } } else if ( loadFile == "$checkerimage" ) { texture = driver->getTexture( "$checkerimage" ); if ( 0 == texture ) { core::dimension2du s ( 2, 2 ); u32 image[4] = { 0xFFFFFFFF, 0xFF000000,0xFF000000,0xFFFFFFFF }; video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); texture = driver->addTexture( "$checkerimage", w ); w->drop (); } } else if ( loadFile == "$lightmap" ) { texture = 0; } else { loadFile.append ( extension[g] ); } if ( fileSystem->existFile ( loadFile ) ) { texture = driver->getTexture( loadFile ); if ( texture ) break; texture = 0; } } // take 0 Texture textures.push_back(texture); } } //! Manages various Quake3 Shader Styles class IShaderManager : public IReferenceCounted { }; } // end namespace quake3 } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IQ3LevelMesh.h0000644000000000000000000000273012574354552016054 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_Q3_LEVEL_MESH_H_INCLUDED__ #define __I_Q3_LEVEL_MESH_H_INCLUDED__ #include "IAnimatedMesh.h" #include "IQ3Shader.h" namespace irr { namespace scene { //! Interface for a Mesh which can be loaded directly from a Quake3 .bsp-file. /** The Mesh tries to load all textures of the map.*/ class IQ3LevelMesh : public IAnimatedMesh { public: //! loads the shader definition from file /** \param filename Name of the shaderfile, defaults to /scripts if fileNameIsValid is false. \param fileNameIsValid Specifies whether the filename is valid in the current situation. */ virtual const quake3::IShader* getShader( const c8* filename, bool fileNameIsValid=true ) = 0; //! returns a already loaded Shader virtual const quake3::IShader* getShader(u32 index) const = 0; //! get's an interface to the entities virtual quake3::tQ3EntityList& getEntityList() = 0; //! returns the requested brush entity /** \param num The number from the model key of the entity. Use this interface if you parse the entities yourself.*/ virtual IMesh* getBrushEntityMesh(s32 num) const = 0; //! returns the requested brush entity virtual IMesh* getBrushEntityMesh(quake3::IEntity &ent) const = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IParticleSystemSceneNode.h0000644000000000000000000006511312574354552020524 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_SYSTEM_SCENE_NODE_H_INCLUDED__ #define __I_PARTICLE_SYSTEM_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" #include "IParticleAnimatedMeshSceneNodeEmitter.h" #include "IParticleBoxEmitter.h" #include "IParticleCylinderEmitter.h" #include "IParticleMeshEmitter.h" #include "IParticleRingEmitter.h" #include "IParticleSphereEmitter.h" #include "IParticleAttractionAffector.h" #include "IParticleFadeOutAffector.h" #include "IParticleGravityAffector.h" #include "IParticleRotationAffector.h" #include "dimension2d.h" namespace irr { namespace scene { //! A particle system scene node for creating snow, fire, exlosions, smoke... /** A scene node controlling a particle System. The behavior of the particles can be controlled by setting the right particle emitters and affectors. You can for example easily create a campfire by doing this: \code scene::IParticleSystemSceneNode* p = scenemgr->addParticleSystemSceneNode(); p->setParticleSize(core::dimension2d(20.0f, 10.0f)); scene::IParticleEmitter* em = p->createBoxEmitter( core::aabbox3d(-5,0,-5,5,1,5), core::vector3df(0.0f,0.03f,0.0f), 40,80, video::SColor(0,255,255,255),video::SColor(0,255,255,255), 1100,2000); p->setEmitter(em); em->drop(); scene::IParticleAffector* paf = p->createFadeOutParticleAffector(); p->addAffector(paf); paf->drop(); \endcode */ class IParticleSystemSceneNode : public ISceneNode { public: //! Constructor IParticleSystemSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) : ISceneNode(parent, mgr, id, position, rotation, scale) {} //! Sets the size of all particles. virtual void setParticleSize( const core::dimension2d &size = core::dimension2d(5.0f, 5.0f)) = 0; //! Sets if the particles should be global. /** If they are, the particles are affected by the movement of the particle system scene node too, otherwise they completely ignore it. Default is true. */ virtual void setParticlesAreGlobal(bool global=true) = 0; //! Remove all currently visible particles virtual void clearParticles() = 0; //! Do manually update the particles. //! This should only be called when you want to render the node outside the scenegraph, //! as the node will care about this otherwise automatically. virtual void doParticleSystem(u32 time) = 0; //! Gets the particle emitter, which creates the particles. /** \return The particle emitter. Can be 0 if none is set. */ virtual IParticleEmitter* getEmitter() =0; //! Sets the particle emitter, which creates the particles. /** A particle emitter can be created using one of the createEmitter methods. For example to create and use a simple PointEmitter, call IParticleEmitter* p = createPointEmitter(); setEmitter(p); p->drop(); \param emitter: Sets the particle emitter. You can set this to 0 for removing the current emitter and stopping the particle system emitting new particles. */ virtual void setEmitter(IParticleEmitter* emitter) = 0; //! Adds new particle effector to the particle system. /** A particle affector modifies the particles. For example, the FadeOut affector lets all particles fade out after some time. It is created and used in this way: \code IParticleAffector* p = createFadeOutParticleAffector(); addAffector(p); p->drop(); \endcode Please note that an affector is not necessary for the particle system to work. \param affector: New affector. */ virtual void addAffector(IParticleAffector* affector) = 0; //! Get a list of all particle affectors. /** \return The list of particle affectors attached to this node. */ virtual const core::list& getAffectors() const = 0; //! Removes all particle affectors in the particle system. virtual void removeAllAffectors() = 0; //! Creates a particle emitter for an animated mesh scene node /** \param node: Pointer to the animated mesh scene node to emit particles from \param useNormalDirection: If true, the direction of each particle created will be the normal of the vertex that it's emitting from. The normal is divided by the normalDirectionModifier parameter, which defaults to 100.0f. \param direction: Direction and speed of particle emission. \param normalDirectionModifier: If the emitter is using the normal direction then the normal of the vertex that is being emitted from is divided by this number. \param mbNumber: This allows you to specify a specific meshBuffer for the IMesh* to emit particles from. The default value is -1, which means a random meshBuffer picked from all of the meshes meshBuffers will be selected to pick a random vertex from. If the value is 0 or greater, it will only pick random vertices from the meshBuffer specified by this value. \param everyMeshVertex: If true, the emitter will emit between min/max particles every second, for every vertex in the mesh, if false, it will emit between min/max particles from random vertices in the mesh. \param minParticlesPerSecond: Minimal amount of particles emitted per second. \param maxParticlesPerSecond: Maximal amount of particles emitted per second. \param minStartColor: Minimal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param maxStartColor: Maximal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. \param maxAngleDegrees: Maximal angle in degrees, the emitting direction of the particle will differ from the original direction. \param minStartSize: Minimal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \param maxStartSize: Maximal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \return Pointer to the created particle emitter. To set this emitter as new emitter of this particle system, just call setEmitter(). Note that you'll have to drop() the returned pointer, after you don't need it any more, see IReferenceCounted::drop() for more informations. */ virtual IParticleAnimatedMeshSceneNodeEmitter* createAnimatedMeshSceneNodeEmitter( scene::IAnimatedMeshSceneNode* node, bool useNormalDirection = true, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), f32 normalDirectionModifier = 100.0f, s32 mbNumber = -1, bool everyMeshVertex = false, u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin = 2000, u32 lifeTimeMax = 4000, s32 maxAngleDegrees = 0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; //! Creates a box particle emitter. /** \param box: The box for the emitter. \param direction: Direction and speed of particle emission. \param minParticlesPerSecond: Minimal amount of particles emitted per second. \param maxParticlesPerSecond: Maximal amount of particles emitted per second. \param minStartColor: Minimal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param maxStartColor: Maximal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. \param maxAngleDegrees: Maximal angle in degrees, the emitting direction of the particle will differ from the original direction. \param minStartSize: Minimal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \param maxStartSize: Maximal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \return Pointer to the created particle emitter. To set this emitter as new emitter of this particle system, just call setEmitter(). Note that you'll have to drop() the returned pointer, after you don't need it any more, see IReferenceCounted::drop() for more informations. */ virtual IParticleBoxEmitter* createBoxEmitter( const core::aabbox3df& box = core::aabbox3df(-10,28,-10,10,30,10), const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; //! Creates a particle emitter for emitting from a cylinder /** \param center: The center of the circle at the base of the cylinder \param radius: The thickness of the cylinder \param normal: Direction of the length of the cylinder \param length: The length of the the cylinder \param outlineOnly: Whether or not to put points inside the cylinder or on the outline only \param direction: Direction and speed of particle emission. \param minParticlesPerSecond: Minimal amount of particles emitted per second. \param maxParticlesPerSecond: Maximal amount of particles emitted per second. \param minStartColor: Minimal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param maxStartColor: Maximal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. \param maxAngleDegrees: Maximal angle in degrees, the emitting direction of the particle will differ from the original direction. \param minStartSize: Minimal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \param maxStartSize: Maximal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \return Pointer to the created particle emitter. To set this emitter as new emitter of this particle system, just call setEmitter(). Note that you'll have to drop() the returned pointer, after you don't need it any more, see IReferenceCounted::drop() for more informations. */ virtual IParticleCylinderEmitter* createCylinderEmitter( const core::vector3df& center, f32 radius, const core::vector3df& normal, f32 length, bool outlineOnly = false, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin = 2000, u32 lifeTimeMax = 4000, s32 maxAngleDegrees = 0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; //! Creates a mesh particle emitter. /** \param mesh: Pointer to mesh to emit particles from \param useNormalDirection: If true, the direction of each particle created will be the normal of the vertex that it's emitting from. The normal is divided by the normalDirectionModifier parameter, which defaults to 100.0f. \param direction: Direction and speed of particle emission. \param normalDirectionModifier: If the emitter is using the normal direction then the normal of the vertex that is being emitted from is divided by this number. \param mbNumber: This allows you to specify a specific meshBuffer for the IMesh* to emit particles from. The default value is -1, which means a random meshBuffer picked from all of the meshes meshBuffers will be selected to pick a random vertex from. If the value is 0 or greater, it will only pick random vertices from the meshBuffer specified by this value. \param everyMeshVertex: If true, the emitter will emit between min/max particles every second, for every vertex in the mesh, if false, it will emit between min/max particles from random vertices in the mesh. \param minParticlesPerSecond: Minimal amount of particles emitted per second. \param maxParticlesPerSecond: Maximal amount of particles emitted per second. \param minStartColor: Minimal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param maxStartColor: Maximal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. \param maxAngleDegrees: Maximal angle in degrees, the emitting direction of the particle will differ from the original direction. \param minStartSize: Minimal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \param maxStartSize: Maximal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \return Pointer to the created particle emitter. To set this emitter as new emitter of this particle system, just call setEmitter(). Note that you'll have to drop() the returned pointer, after you don't need it any more, see IReferenceCounted::drop() for more informations. */ virtual IParticleMeshEmitter* createMeshEmitter( scene::IMesh* mesh, bool useNormalDirection = true, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), f32 normalDirectionModifier = 100.0f, s32 mbNumber = -1, bool everyMeshVertex = false, u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin = 2000, u32 lifeTimeMax = 4000, s32 maxAngleDegrees = 0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; //! Creates a point particle emitter. /** \param direction: Direction and speed of particle emission. \param minParticlesPerSecond: Minimal amount of particles emitted per second. \param maxParticlesPerSecond: Maximal amount of particles emitted per second. \param minStartColor: Minimal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param maxStartColor: Maximal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. \param maxAngleDegrees: Maximal angle in degrees, the emitting direction of the particle will differ from the original direction. \param minStartSize: Minimal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \param maxStartSize: Maximal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \return Pointer to the created particle emitter. To set this emitter as new emitter of this particle system, just call setEmitter(). Note that you'll have to drop() the returned pointer, after you don't need it any more, see IReferenceCounted::drop() for more informations. */ virtual IParticlePointEmitter* createPointEmitter( const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; //! Creates a ring particle emitter. /** \param center: Center of ring \param radius: Distance of points from center, points will be rotated around the Y axis at a random 360 degrees and will then be shifted by the provided ringThickness values in each axis. \param ringThickness : thickness of the ring or how wide the ring is \param direction: Direction and speed of particle emission. \param minParticlesPerSecond: Minimal amount of particles emitted per second. \param maxParticlesPerSecond: Maximal amount of particles emitted per second. \param minStartColor: Minimal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param maxStartColor: Maximal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. \param maxAngleDegrees: Maximal angle in degrees, the emitting direction of the particle will differ from the original direction. \param minStartSize: Minimal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \param maxStartSize: Maximal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \return Pointer to the created particle emitter. To set this emitter as new emitter of this particle system, just call setEmitter(). Note that you'll have to drop() the returned pointer, after you don't need it any more, see IReferenceCounted::drop() for more informations. */ virtual IParticleRingEmitter* createRingEmitter( const core::vector3df& center, f32 radius, f32 ringThickness, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; //! Creates a sphere particle emitter. /** \param center: Center of sphere \param radius: Radius of sphere \param direction: Direction and speed of particle emission. \param minParticlesPerSecond: Minimal amount of particles emitted per second. \param maxParticlesPerSecond: Maximal amount of particles emitted per second. \param minStartColor: Minimal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param maxStartColor: Maximal initial start color of a particle. The real color of every particle is calculated as random interpolation between minStartColor and maxStartColor. \param lifeTimeMin: Minimal lifetime of a particle, in milliseconds. \param lifeTimeMax: Maximal lifetime of a particle, in milliseconds. \param maxAngleDegrees: Maximal angle in degrees, the emitting direction of the particle will differ from the original direction. \param minStartSize: Minimal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \param maxStartSize: Maximal initial start size of a particle. The real size of every particle is calculated as random interpolation between minStartSize and maxStartSize. \return Pointer to the created particle emitter. To set this emitter as new emitter of this particle system, just call setEmitter(). Note that you'll have to drop() the returned pointer, after you don't need it any more, see IReferenceCounted::drop() for more informations. */ virtual IParticleSphereEmitter* createSphereEmitter( const core::vector3df& center, f32 radius, const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0, const core::dimension2df& minStartSize = core::dimension2df(5.0f,5.0f), const core::dimension2df& maxStartSize = core::dimension2df(5.0f,5.0f) ) = 0; //! Creates a point attraction affector. /** This affector modifies the positions of the particles and attracts them to a specified point at a specified speed per second. \param point: Point to attract particles to. \param speed: Speed in units per second, to attract to the specified point. \param attract: Whether the particles attract or detract from this point. \param affectX: Whether or not this will affect the X position of the particle. \param affectY: Whether or not this will affect the Y position of the particle. \param affectZ: Whether or not this will affect the Z position of the particle. \return Pointer to the created particle affector. To add this affector as new affector of this particle system, just call addAffector(). Note that you'll have to drop() the returned pointer, after you don't need it any more, see IReferenceCounted::drop() for more informations. */ virtual IParticleAttractionAffector* createAttractionAffector( const core::vector3df& point, f32 speed = 1.0f, bool attract = true, bool affectX = true, bool affectY = true, bool affectZ = true) = 0; //! Creates a scale particle affector. /** This affector scales the particle to the a multiple of its size defined by the scaleTo variable. \param scaleTo: multiple of the size which the particle will be scaled to until deletion \return Pointer to the created particle affector. To add this affector as new affector of this particle system, just call addAffector(). Note that you'll have to drop() the returned pointer, after you don't need it any more, see IReferenceCounted::drop() for more information. */ virtual IParticleAffector* createScaleParticleAffector(const core::dimension2df& scaleTo = core::dimension2df(1.0f, 1.0f)) = 0; //! Creates a fade out particle affector. /** This affector modifies the color of every particle and and reaches the final color when the particle dies. This affector looks really good, if the EMT_TRANSPARENT_ADD_COLOR material is used and the targetColor is video::SColor(0,0,0,0): Particles are fading out into void with this setting. \param targetColor: Color whereto the color of the particle is changed. \param timeNeededToFadeOut: How much time in milli seconds should the affector need to change the color to the targetColor. \return Pointer to the created particle affector. To add this affector as new affector of this particle system, just call addAffector(). Note that you'll have to drop() the returned pointer, after you don't need it any more, see IReferenceCounted::drop() for more informations. */ virtual IParticleFadeOutAffector* createFadeOutParticleAffector( const video::SColor& targetColor = video::SColor(0,0,0,0), u32 timeNeededToFadeOut = 1000) = 0; //! Creates a gravity affector. /** This affector modifies the direction of the particle. It assumes that the particle is fired out of the emitter with huge force, but is loosing this after some time and is catched by the gravity then. This affector is ideal for creating things like fountains. \param gravity: Direction and force of gravity. \param timeForceLost: Time in milli seconds when the force of the emitter is totally lost and the particle does not move any more. This is the time where gravity fully affects the particle. \return Pointer to the created particle affector. To add this affector as new affector of this particle system, just call addAffector(). Note that you'll have to drop() the returned pointer, after you don't need it any more, see IReferenceCounted::drop() for more informations. */ virtual IParticleGravityAffector* createGravityAffector( const core::vector3df& gravity = core::vector3df(0.0f,-0.03f,0.0f), u32 timeForceLost = 1000) = 0; //! Creates a rotation affector. /** This affector modifies the positions of the particles and attracts them to a specified point at a specified speed per second. \param speed: Rotation in degrees per second \param pivotPoint: Point to rotate the particles around \return Pointer to the created particle affector. To add this affector as new affector of this particle system, just call addAffector(). Note that you'll have to drop() the returned pointer, after you don't need it any more, see IReferenceCounted::drop() for more informations. */ virtual IParticleRotationAffector* createRotationAffector( const core::vector3df& speed = core::vector3df(5.0f,5.0f,5.0f), const core::vector3df& pivotPoint = core::vector3df(0.0f,0.0f,0.0f) ) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IParticleSphereEmitter.h0000644000000000000000000000207712574354552020234 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_SPHERE_EMITTER_H_INCLUDED__ #define __I_PARTICLE_SPHERE_EMITTER_H_INCLUDED__ #include "IParticleEmitter.h" namespace irr { namespace scene { //! A particle emitter which emits from a spherical space. class IParticleSphereEmitter : public IParticleEmitter { public: //! Set the center of the sphere for particle emissions virtual void setCenter( const core::vector3df& center ) = 0; //! Set the radius of the sphere for particle emissions virtual void setRadius( f32 radius ) = 0; //! Get the center of the sphere for particle emissions virtual const core::vector3df& getCenter() const = 0; //! Get the radius of the sphere for particle emissions virtual f32 getRadius() const = 0; //! Get emitter type virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_SPHERE; } }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IParticleRotationAffector.h0000644000000000000000000000224212574354552020717 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_ROTATION_AFFECTOR_H_INCLUDED__ #define __I_PARTICLE_ROTATION_AFFECTOR_H_INCLUDED__ #include "IParticleAffector.h" namespace irr { namespace scene { //! A particle affector which rotates the particle system. class IParticleRotationAffector : public IParticleAffector { public: //! Set the point that particles will rotate around virtual void setPivotPoint( const core::vector3df& point ) = 0; //! Set the speed in degrees per second in all 3 dimensions virtual void setSpeed( const core::vector3df& speed ) = 0; //! Get the point that particles are attracted to virtual const core::vector3df& getPivotPoint() const = 0; //! Get the speed in degrees per second in all 3 dimensions virtual const core::vector3df& getSpeed() const = 0; //! Get emitter type virtual E_PARTICLE_AFFECTOR_TYPE getType() const { return EPAT_ROTATE; } }; } // end namespace scene } // end namespace irr #endif // __I_PARTICLE_ROTATION_AFFECTOR_H_INCLUDED__ irrlicht-1.8.3/include/IParticleRingEmitter.h0000644000000000000000000000222112574354552017674 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_RING_EMITTER_H_INCLUDED__ #define __I_PARTICLE_RING_EMITTER_H_INCLUDED__ #include "IParticleEmitter.h" namespace irr { namespace scene { //! A particle emitter which emits particles along a ring shaped area. class IParticleRingEmitter : public IParticleEmitter { public: //! Set the center of the ring virtual void setCenter( const core::vector3df& center ) = 0; //! Set the radius of the ring virtual void setRadius( f32 radius ) = 0; //! Set the thickness of the ring virtual void setRingThickness( f32 ringThickness ) = 0; //! Get the center of the ring virtual const core::vector3df& getCenter() const = 0; //! Get the radius of the ring virtual f32 getRadius() const = 0; //! Get the thickness of the ring virtual f32 getRingThickness() const = 0; //! Get emitter type virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_RING; } }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IParticleMeshEmitter.h0000644000000000000000000000330512574354552017675 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_MESH_EMITTER_H_INCLUDED__ #define __I_PARTICLE_MESH_EMITTER_H_INCLUDED__ #include "IParticleEmitter.h" #include "IMesh.h" namespace irr { namespace scene { //! A particle emitter which emits from vertices of a mesh class IParticleMeshEmitter : public IParticleEmitter { public: //! Set Mesh to emit particles from virtual void setMesh( IMesh* mesh ) = 0; //! Set whether to use vertex normal for direction, or direction specified virtual void setUseNormalDirection( bool useNormalDirection = true ) = 0; //! Set the amount that the normal is divided by for getting a particles direction virtual void setNormalDirectionModifier( f32 normalDirectionModifier ) = 0; //! Sets whether to emit min<->max particles for every vertex or to pick min<->max vertices virtual void setEveryMeshVertex( bool everyMeshVertex = true ) = 0; //! Get Mesh we're emitting particles from virtual const IMesh* getMesh() const = 0; //! Get whether to use vertex normal for direction, or direction specified virtual bool isUsingNormalDirection() const = 0; //! Get the amount that the normal is divided by for getting a particles direction virtual f32 getNormalDirectionModifier() const = 0; //! Gets whether to emit min<->max particles for every vertex or to pick min<->max vertices virtual bool getEveryMeshVertex() const = 0; //! Get emitter type virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_MESH; } }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IParticleGravityAffector.h0000644000000000000000000000235012574354552020545 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_GRAVITY_AFFECTOR_H_INCLUDED__ #define __I_PARTICLE_GRAVITY_AFFECTOR_H_INCLUDED__ #include "IParticleAffector.h" namespace irr { namespace scene { //! A particle affector which applies gravity to particles. class IParticleGravityAffector : public IParticleAffector { public: //! Set the time in milliseconds when the gravity force is totally lost /** At that point the particle does not move any more. */ virtual void setTimeForceLost( f32 timeForceLost ) = 0; //! Set the direction and force of gravity in all 3 dimensions. virtual void setGravity( const core::vector3df& gravity ) = 0; //! Get the time in milliseconds when the gravity force is totally lost virtual f32 getTimeForceLost() const = 0; //! Get the direction and force of gravity. virtual const core::vector3df& getGravity() const = 0; //! Get emitter type virtual E_PARTICLE_AFFECTOR_TYPE getType() const { return EPAT_GRAVITY; } }; } // end namespace scene } // end namespace irr #endif // __I_PARTICLE_GRAVITY_AFFECTOR_H_INCLUDED__ irrlicht-1.8.3/include/IParticleFadeOutAffector.h0000644000000000000000000000237712574354552020460 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_FADE_OUT_AFFECTOR_H_INCLUDED__ #define __I_PARTICLE_FADE_OUT_AFFECTOR_H_INCLUDED__ #include "IParticleAffector.h" namespace irr { namespace scene { //! A particle affector which fades out the particles. class IParticleFadeOutAffector : public IParticleAffector { public: //! Sets the targetColor, i.e. the color the particles will interpolate to over time. virtual void setTargetColor( const video::SColor& targetColor ) = 0; //! Sets the time in milliseconds it takes for each particle to fade out (minimal 1 ms) virtual void setFadeOutTime( u32 fadeOutTime ) = 0; //! Gets the targetColor, i.e. the color the particles will interpolate to over time. virtual const video::SColor& getTargetColor() const = 0; //! Gets the time in milliseconds it takes for each particle to fade out. virtual u32 getFadeOutTime() const = 0; //! Get emitter type virtual E_PARTICLE_AFFECTOR_TYPE getType() const { return EPAT_FADE_OUT; } }; } // end namespace scene } // end namespace irr #endif // __I_PARTICLE_FADE_OUT_AFFECTOR_H_INCLUDED__ irrlicht-1.8.3/include/IParticleEmitter.h0000644000000000000000000000754212574354552017067 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_EMITTER_H_INCLUDED__ #define __I_PARTICLE_EMITTER_H_INCLUDED__ #include "IAttributeExchangingObject.h" #include "SParticle.h" namespace irr { namespace scene { //! Types of built in particle emitters enum E_PARTICLE_EMITTER_TYPE { EPET_POINT = 0, EPET_ANIMATED_MESH, EPET_BOX, EPET_CYLINDER, EPET_MESH, EPET_RING, EPET_SPHERE, EPET_COUNT }; //! Names for built in particle emitters const c8* const ParticleEmitterTypeNames[] = { "Point", "AnimatedMesh", "Box", "Cylinder", "Mesh", "Ring", "Sphere", 0 }; //! A particle emitter for using with particle systems. /** A Particle emitter emitts new particles into a particle system. */ class IParticleEmitter : public virtual io::IAttributeExchangingObject { public: //! Prepares an array with new particles to emitt into the system /** \param now Current time. \param timeSinceLastCall Time elapsed since last call, in milliseconds. \param outArray Pointer which will point to the array with the new particles to add into the system. \return Amount of new particles in the array. Can be 0. */ virtual s32 emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray) = 0; //! Set direction the emitter emits particles virtual void setDirection( const core::vector3df& newDirection ) = 0; //! Set minimum number of particles the emitter emits per second virtual void setMinParticlesPerSecond( u32 minPPS ) = 0; //! Set maximum number of particles the emitter emits per second virtual void setMaxParticlesPerSecond( u32 maxPPS ) = 0; //! Set minimum starting color for particles virtual void setMinStartColor( const video::SColor& color ) = 0; //! Set maximum starting color for particles virtual void setMaxStartColor( const video::SColor& color ) = 0; //! Set the maximum starting size for particles virtual void setMaxStartSize( const core::dimension2df& size ) = 0; //! Set the minimum starting size for particles virtual void setMinStartSize( const core::dimension2df& size ) = 0; //! Set the minimum particle life-time in milliseconds virtual void setMinLifeTime( u32 lifeTimeMin ) = 0; //! Set the maximum particle life-time in milliseconds virtual void setMaxLifeTime( u32 lifeTimeMax ) = 0; //! Set maximal random derivation from the direction virtual void setMaxAngleDegrees( s32 maxAngleDegrees ) = 0; //! Get direction the emitter emits particles virtual const core::vector3df& getDirection() const = 0; //! Get the minimum number of particles the emitter emits per second virtual u32 getMinParticlesPerSecond() const = 0; //! Get the maximum number of particles the emitter emits per second virtual u32 getMaxParticlesPerSecond() const = 0; //! Get the minimum starting color for particles virtual const video::SColor& getMinStartColor() const = 0; //! Get the maximum starting color for particles virtual const video::SColor& getMaxStartColor() const = 0; //! Get the maximum starting size for particles virtual const core::dimension2df& getMaxStartSize() const = 0; //! Get the minimum starting size for particles virtual const core::dimension2df& getMinStartSize() const = 0; //! Get the minimum particle life-time in milliseconds virtual u32 getMinLifeTime() const = 0; //! Get the maximum particle life-time in milliseconds virtual u32 getMaxLifeTime() const = 0; //! Get maximal random derivation from the direction virtual s32 getMaxAngleDegrees() const = 0; //! Get emitter type virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_POINT; } }; typedef IParticleEmitter IParticlePointEmitter; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IParticleCylinderEmitter.h0000644000000000000000000000316212574354552020553 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_CYLINDER_EMITTER_H_INCLUDED__ #define __I_PARTICLE_CYLINDER_EMITTER_H_INCLUDED__ #include "IParticleEmitter.h" namespace irr { namespace scene { //! A particle emitter which emits from a cylindrically shaped space. class IParticleCylinderEmitter : public IParticleEmitter { public: //! Set the center of the radius for the cylinder, at one end of the cylinder virtual void setCenter( const core::vector3df& center ) = 0; //! Set the normal of the cylinder virtual void setNormal( const core::vector3df& normal ) = 0; //! Set the radius of the cylinder virtual void setRadius( f32 radius ) = 0; //! Set the length of the cylinder virtual void setLength( f32 length ) = 0; //! Set whether or not to draw points inside the cylinder virtual void setOutlineOnly( bool outlineOnly = true ) = 0; //! Get the center of the cylinder virtual const core::vector3df& getCenter() const = 0; //! Get the normal of the cylinder virtual const core::vector3df& getNormal() const = 0; //! Get the radius of the cylinder virtual f32 getRadius() const = 0; //! Get the center of the cylinder virtual f32 getLength() const = 0; //! Get whether or not to draw points inside the cylinder virtual bool getOutlineOnly() const = 0; //! Get emitter type virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_CYLINDER; } }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IParticleBoxEmitter.h0000644000000000000000000000150212574354552017526 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_BOX_EMITTER_H_INCLUDED__ #define __I_PARTICLE_BOX_EMITTER_H_INCLUDED__ #include "IParticleEmitter.h" #include "aabbox3d.h" namespace irr { namespace scene { //! A particle emitter which emits particles from a box shaped space class IParticleBoxEmitter : public IParticleEmitter { public: //! Set the box shape virtual void setBox( const core::aabbox3df& box ) = 0; //! Get the box shape set virtual const core::aabbox3df& getBox() const = 0; //! Get emitter type virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_BOX; } }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IParticleAttractionAffector.h0000644000000000000000000000345412574354552021236 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_ATTRACTION_AFFECTOR_H_INCLUDED__ #define __I_PARTICLE_ATTRACTION_AFFECTOR_H_INCLUDED__ #include "IParticleAffector.h" namespace irr { namespace scene { //! A particle affector which attracts or detracts particles. class IParticleAttractionAffector : public IParticleAffector { public: //! Set the point that particles will attract to virtual void setPoint( const core::vector3df& point ) = 0; //! Set whether or not the particles are attracting or detracting virtual void setAttract( bool attract ) = 0; //! Set whether or not this will affect particles in the X direction virtual void setAffectX( bool affect ) = 0; //! Set whether or not this will affect particles in the Y direction virtual void setAffectY( bool affect ) = 0; //! Set whether or not this will affect particles in the Z direction virtual void setAffectZ( bool affect ) = 0; //! Get the point that particles are attracted to virtual const core::vector3df& getPoint() const = 0; //! Get whether or not the particles are attracting or detracting virtual bool getAttract() const = 0; //! Get whether or not the particles X position are affected virtual bool getAffectX() const = 0; //! Get whether or not the particles Y position are affected virtual bool getAffectY() const = 0; //! Get whether or not the particles Z position are affected virtual bool getAffectZ() const = 0; //! Get emitter type virtual E_PARTICLE_AFFECTOR_TYPE getType() const { return EPAT_ATTRACT; } }; } // end namespace scene } // end namespace irr #endif // __I_PARTICLE_ATTRACTION_AFFECTOR_H_INCLUDED__ irrlicht-1.8.3/include/IParticleAnimatedMeshSceneNodeEmitter.h0000644000000000000000000000364012574354552023126 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_ANIMATED_MESH_SCENE_NODE_EMITTER_H_INCLUDED__ #define __I_PARTICLE_ANIMATED_MESH_SCENE_NODE_EMITTER_H_INCLUDED__ #include "IParticleEmitter.h" #include "IAnimatedMeshSceneNode.h" namespace irr { namespace scene { //! A particle emitter which emits particles from mesh vertices. class IParticleAnimatedMeshSceneNodeEmitter : public IParticleEmitter { public: //! Set Mesh to emit particles from virtual void setAnimatedMeshSceneNode( IAnimatedMeshSceneNode* node ) = 0; //! Set whether to use vertex normal for direction, or direction specified virtual void setUseNormalDirection( bool useNormalDirection = true ) = 0; //! Set the amount that the normal is divided by for getting a particles direction virtual void setNormalDirectionModifier( f32 normalDirectionModifier ) = 0; //! Sets whether to emit min<->max particles for every vertex or to pick min<->max vertices virtual void setEveryMeshVertex( bool everyMeshVertex = true ) = 0; //! Get mesh we're emitting particles from virtual const IAnimatedMeshSceneNode* getAnimatedMeshSceneNode() const = 0; //! Get whether to use vertex normal for direction, or direction specified virtual bool isUsingNormalDirection() const = 0; //! Get the amount that the normal is divided by for getting a particles direction virtual f32 getNormalDirectionModifier() const = 0; //! Gets whether to emit min<->max particles for every vertex or to pick min<->max vertices virtual bool getEveryMeshVertex() const = 0; //! Get emitter type virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_ANIMATED_MESH; } }; } // end namespace scene } // end namespace irr #endif // __I_PARTICLE_ANIMATED_MESH_SCENE_NODE_EMITTER_H_INCLUDED__ irrlicht-1.8.3/include/IParticleAffector.h0000644000000000000000000000313312574354552017177 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_PARTICLE_AFFECTOR_H_INCLUDED__ #define __I_PARTICLE_AFFECTOR_H_INCLUDED__ #include "IAttributeExchangingObject.h" #include "SParticle.h" namespace irr { namespace scene { //! Types of built in particle affectors enum E_PARTICLE_AFFECTOR_TYPE { EPAT_NONE = 0, EPAT_ATTRACT, EPAT_FADE_OUT, EPAT_GRAVITY, EPAT_ROTATE, EPAT_SCALE, EPAT_COUNT }; //! Names for built in particle affectors const c8* const ParticleAffectorTypeNames[] = { "None", "Attract", "FadeOut", "Gravity", "Rotate", "Scale", 0 }; //! A particle affector modifies particles. class IParticleAffector : public virtual io::IAttributeExchangingObject { public: //! constructor IParticleAffector() : Enabled(true) {} //! Affects an array of particles. /** \param now Current time. (Same as ITimer::getTime() would return) \param particlearray Array of particles. \param count Amount of particles in array. */ virtual void affect(u32 now, SParticle* particlearray, u32 count) = 0; //! Sets whether or not the affector is currently enabled. virtual void setEnabled(bool enabled) { Enabled = enabled; } //! Gets whether or not the affector is currently enabled. virtual bool getEnabled() const { return Enabled; } //! Get emitter type virtual E_PARTICLE_AFFECTOR_TYPE getType() const = 0; protected: bool Enabled; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IOSOperator.h0000644000000000000000000000321312574354552016016 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_OS_OPERATOR_H_INCLUDED__ #define __I_OS_OPERATOR_H_INCLUDED__ #include "IReferenceCounted.h" #include "irrString.h" namespace irr { //! The Operating system operator provides operation system specific methods and informations. class IOSOperator : public virtual IReferenceCounted { public: //! Get the current operation system version as string. virtual const core::stringc& getOperatingSystemVersion() const = 0; //! Get the current operation system version as string. /** \deprecated Use getOperatingSystemVersion instead. This method will be removed in Irrlicht 1.9. */ _IRR_DEPRECATED_ const wchar_t* getOperationSystemVersion() const { return core::stringw(getOperatingSystemVersion()).c_str(); } //! Copies text to the clipboard virtual void copyToClipboard(const c8* text) const = 0; //! Get text from the clipboard /** \return Returns 0 if no string is in there. */ virtual const c8* getTextFromClipboard() const = 0; //! Get the processor speed in megahertz /** \param MHz The integer variable to store the speed in. \return True if successful, false if not */ virtual bool getProcessorSpeedMHz(u32* MHz) const = 0; //! Get the total and available system RAM /** \param Total: will contain the total system memory \param Avail: will contain the available memory \return True if successful, false if not */ virtual bool getSystemMemory(u32* Total, u32* Avail) const = 0; }; } // end namespace #endif irrlicht-1.8.3/include/IMetaTriangleSelector.h0000644000000000000000000000257212574354552020045 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_META_TRIANGLE_SELECTOR_H_INCLUDED__ #define __I_META_TRIANGLE_SELECTOR_H_INCLUDED__ #include "ITriangleSelector.h" namespace irr { namespace scene { //! Interface for making multiple triangle selectors work as one big selector. /** This is nothing more than a collection of one or more triangle selectors providing together the interface of one triangle selector. In this way, collision tests can be done with different triangle soups in one pass. */ class IMetaTriangleSelector : public ITriangleSelector { public: //! Adds a triangle selector to the collection of triangle selectors. /** \param toAdd: Pointer to an triangle selector to add to the list. */ virtual void addTriangleSelector(ITriangleSelector* toAdd) = 0; //! Removes a specific triangle selector from the collection. /** \param toRemove: Pointer to an triangle selector which is in the list but will be removed. \return True if successful, false if not. */ virtual bool removeTriangleSelector(ITriangleSelector* toRemove) = 0; //! Removes all triangle selectors from the collection. virtual void removeAllTriangleSelectors() = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IMeshWriter.h0000644000000000000000000000277012574354552016061 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_I_MESH_WRITER_H_INCLUDED__ #define __IRR_I_MESH_WRITER_H_INCLUDED__ #include "IReferenceCounted.h" #include "EMeshWriterEnums.h" namespace irr { namespace io { class IWriteFile; } // end namespace io namespace scene { class IMesh; //! Interface for writing meshes class IMeshWriter : public virtual IReferenceCounted { public: //! Destructor virtual ~IMeshWriter() {} //! Get the type of the mesh writer /** For own implementations, use MAKE_IRR_ID as shown in the EMESH_WRITER_TYPE enumeration to return your own unique mesh type id. \return Type of the mesh writer. */ virtual EMESH_WRITER_TYPE getType() const = 0; //! Write a static mesh. /** \param file File handle to write the mesh to. \param mesh Pointer to mesh to be written. \param flags Optional flags to set properties of the writer. \return True if sucessful */ virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE) = 0; // Writes an animated mesh // for future use, no writer is able to write animated meshes currently /* \return Returns true if sucessful */ //virtual bool writeAnimatedMesh(io::IWriteFile* file, // scene::IAnimatedMesh* mesh, // s32 flags=EMWF_NONE) = 0; }; } // end namespace } // end namespace #endif irrlicht-1.8.3/include/IMeshSceneNode.h0000644000000000000000000000564212574354552016451 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_MESH_SCENE_NODE_H_INCLUDED__ #define __I_MESH_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" namespace irr { namespace scene { class IShadowVolumeSceneNode; class IMesh; //! A scene node displaying a static mesh class IMeshSceneNode : public ISceneNode { public: //! Constructor /** Use setMesh() to set the mesh to display. */ IMeshSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1,1,1)) : ISceneNode(parent, mgr, id, position, rotation, scale) {} //! Sets a new mesh to display /** \param mesh Mesh to display. */ virtual void setMesh(IMesh* mesh) = 0; //! Get the currently defined mesh for display. /** \return Pointer to mesh which is displayed by this node. */ virtual IMesh* getMesh(void) = 0; //! Creates shadow volume scene node as child of this node. /** The shadow can be rendered using the ZPass or the zfail method. ZPass is a little bit faster because the shadow volume creation is easier, but with this method there occur ugly looking artifacs when the camera is inside the shadow volume. These error do not occur with the ZFail method. \param shadowMesh: Optional custom mesh for shadow volume. \param id: Id of the shadow scene node. This id can be used to identify the node later. \param zfailmethod: If set to true, the shadow will use the zfail method, if not, zpass is used. \param infinity: Value used by the shadow volume algorithm to scale the shadow volume (for zfail shadow volume we support only finite shadows, so camera zfar must be larger than shadow back cap, which is depend on infinity parameter). \return Pointer to the created shadow scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh=0, s32 id=-1, bool zfailmethod=true, f32 infinity=1000.0f) = 0; //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. /** In this way it is possible to change the materials of a mesh causing all mesh scene nodes referencing this mesh to change, too. \param readonly Flag if the materials shall be read-only. */ virtual void setReadOnlyMaterials(bool readonly) = 0; //! Check if the scene node should not copy the materials of the mesh but use them in a read only style /** This flag can be set by setReadOnlyMaterials(). \return Whether the materials are read-only. */ virtual bool isReadOnlyMaterials() const = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IMeshManipulator.h0000644000000000000000000004163112574354552017077 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_MESH_MANIPULATOR_H_INCLUDED__ #define __I_MESH_MANIPULATOR_H_INCLUDED__ #include "IReferenceCounted.h" #include "vector3d.h" #include "aabbox3d.h" #include "matrix4.h" #include "IAnimatedMesh.h" #include "IMeshBuffer.h" #include "SVertexManipulator.h" namespace irr { namespace scene { struct SMesh; //! An interface for easy manipulation of meshes. /** Scale, set alpha value, flip surfaces, and so on. This exists for fixing problems with wrong imported or exported meshes quickly after loading. It is not intended for doing mesh modifications and/or animations during runtime. */ class IMeshManipulator : public virtual IReferenceCounted { public: //! Flips the direction of surfaces. /** Changes backfacing triangles to frontfacing triangles and vice versa. \param mesh Mesh on which the operation is performed. */ virtual void flipSurfaces(IMesh* mesh) const = 0; //! Sets the alpha vertex color value of the whole mesh to a new value. /** \param mesh Mesh on which the operation is performed. \param alpha New alpha value. Must be a value between 0 and 255. */ void setVertexColorAlpha(IMesh* mesh, s32 alpha) const { apply(scene::SVertexColorSetAlphaManipulator(alpha), mesh); } //! Sets the alpha vertex color value of the whole mesh to a new value. /** \param buffer Meshbuffer on which the operation is performed. \param alpha New alpha value. Must be a value between 0 and 255. */ void setVertexColorAlpha(IMeshBuffer* buffer, s32 alpha) const { apply(scene::SVertexColorSetAlphaManipulator(alpha), buffer); } //! Sets the colors of all vertices to one color /** \param mesh Mesh on which the operation is performed. \param color New color. */ void setVertexColors(IMesh* mesh, video::SColor color) const { apply(scene::SVertexColorSetManipulator(color), mesh); } //! Sets the colors of all vertices to one color /** \param buffer Meshbuffer on which the operation is performed. \param color New color. */ void setVertexColors(IMeshBuffer* buffer, video::SColor color) const { apply(scene::SVertexColorSetManipulator(color), buffer); } //! Recalculates all normals of the mesh. /** \param mesh: Mesh on which the operation is performed. \param smooth: If the normals shall be smoothed. \param angleWeighted: If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. */ virtual void recalculateNormals(IMesh* mesh, bool smooth = false, bool angleWeighted = false) const=0; //! Recalculates all normals of the mesh buffer. /** \param buffer: Mesh buffer on which the operation is performed. \param smooth: If the normals shall be smoothed. \param angleWeighted: If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. */ virtual void recalculateNormals(IMeshBuffer* buffer, bool smooth = false, bool angleWeighted = false) const=0; //! Recalculates tangents, requires a tangent mesh /** \param mesh Mesh on which the operation is performed. \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the mesh are used unchanged. \param smooth If the normals shall be smoothed. \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. */ virtual void recalculateTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false) const=0; //! Recalculates tangents, requires a tangent mesh buffer /** \param buffer Meshbuffer on which the operation is performed. \param recalculateNormals If the normals shall be recalculated, otherwise original normals of the buffer are used unchanged. \param smooth If the normals shall be smoothed. \param angleWeighted If the normals shall be smoothed in relation to their angles. More expensive, but also higher precision. */ virtual void recalculateTangents(IMeshBuffer* buffer, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false) const=0; //! Scales the actual mesh, not a scene node. /** \param mesh Mesh on which the operation is performed. \param factor Scale factor for each axis. */ void scale(IMesh* mesh, const core::vector3df& factor) const { apply(SVertexPositionScaleManipulator(factor), mesh, true); } //! Scales the actual meshbuffer, not a scene node. /** \param buffer Meshbuffer on which the operation is performed. \param factor Scale factor for each axis. */ void scale(IMeshBuffer* buffer, const core::vector3df& factor) const { apply(SVertexPositionScaleManipulator(factor), buffer, true); } //! Scales the actual mesh, not a scene node. /** \deprecated Use scale() instead. This method may be removed by Irrlicht 1.9 \param mesh Mesh on which the operation is performed. \param factor Scale factor for each axis. */ _IRR_DEPRECATED_ void scaleMesh(IMesh* mesh, const core::vector3df& factor) const {return scale(mesh,factor);} //! Scale the texture coords of a mesh. /** \param mesh Mesh on which the operation is performed. \param factor Vector which defines the scale for each axis. \param level Number of texture coord, starting from 1. Support for level 2 exists for LightMap buffers. */ void scaleTCoords(scene::IMesh* mesh, const core::vector2df& factor, u32 level=1) const { apply(SVertexTCoordsScaleManipulator(factor, level), mesh); } //! Scale the texture coords of a meshbuffer. /** \param buffer Meshbuffer on which the operation is performed. \param factor Vector which defines the scale for each axis. \param level Number of texture coord, starting from 1. Support for level 2 exists for LightMap buffers. */ void scaleTCoords(scene::IMeshBuffer* buffer, const core::vector2df& factor, u32 level=1) const { apply(SVertexTCoordsScaleManipulator(factor, level), buffer); } //! Applies a transformation to a mesh /** \param mesh Mesh on which the operation is performed. \param m transformation matrix. */ void transform(IMesh* mesh, const core::matrix4& m) const { apply(SVertexPositionTransformManipulator(m), mesh, true); } //! Applies a transformation to a meshbuffer /** \param buffer Meshbuffer on which the operation is performed. \param m transformation matrix. */ void transform(IMeshBuffer* buffer, const core::matrix4& m) const { apply(SVertexPositionTransformManipulator(m), buffer, true); } //! Applies a transformation to a mesh /** \deprecated Use transform() instead. This method may be removed by Irrlicht 1.9 \param mesh Mesh on which the operation is performed. \param m transformation matrix. */ _IRR_DEPRECATED_ virtual void transformMesh(IMesh* mesh, const core::matrix4& m) const {return transform(mesh,m);} //! Creates a planar texture mapping on the mesh /** \param mesh: Mesh on which the operation is performed. \param resolution: resolution of the planar mapping. This is the value specifying which is the relation between world space and texture coordinate space. */ virtual void makePlanarTextureMapping(IMesh* mesh, f32 resolution=0.001f) const=0; //! Creates a planar texture mapping on the meshbuffer /** \param meshbuffer: Buffer on which the operation is performed. \param resolution: resolution of the planar mapping. This is the value specifying which is the relation between world space and texture coordinate space. */ virtual void makePlanarTextureMapping(scene::IMeshBuffer* meshbuffer, f32 resolution=0.001f) const=0; //! Creates a planar texture mapping on the buffer /** This method is currently implemented towards the LWO planar mapping. A more general biasing might be required. \param mesh Mesh on which the operation is performed. \param resolutionS Resolution of the planar mapping in horizontal direction. This is the ratio between object space and texture space. \param resolutionT Resolution of the planar mapping in vertical direction. This is the ratio between object space and texture space. \param axis The axis along which the texture is projected. The allowed values are 0 (X), 1(Y), and 2(Z). \param offset Vector added to the vertex positions (in object coordinates). */ virtual void makePlanarTextureMapping(scene::IMesh* mesh, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const=0; //! Creates a planar texture mapping on the meshbuffer /** This method is currently implemented towards the LWO planar mapping. A more general biasing might be required. \param buffer Buffer on which the operation is performed. \param resolutionS Resolution of the planar mapping in horizontal direction. This is the ratio between object space and texture space. \param resolutionT Resolution of the planar mapping in vertical direction. This is the ratio between object space and texture space. \param axis The axis along which the texture is projected. The allowed values are 0 (X), 1(Y), and 2(Z). \param offset Vector added to the vertex positions (in object coordinates). */ virtual void makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const=0; //! Clones a static IMesh into a modifiable SMesh. /** All meshbuffers in the returned SMesh are of type SMeshBuffer or SMeshBufferLightMap. \param mesh Mesh to copy. \return Cloned mesh. If you no longer need the cloned mesh, you should call SMesh::drop(). See IReferenceCounted::drop() for more information. */ virtual SMesh* createMeshCopy(IMesh* mesh) const = 0; //! Creates a copy of the mesh, which will only consist of S3DVertexTangents vertices. /** This is useful if you want to draw tangent space normal mapped geometry because it calculates the tangent and binormal data which is needed there. \param mesh Input mesh \param recalculateNormals The normals are recalculated if set, otherwise the original ones are kept. Note that keeping the normals may introduce inaccurate tangents if the normals are very different to those calculated from the faces. \param smooth The normals/tangents are smoothed across the meshbuffer's faces if this flag is set. \param angleWeighted Improved smoothing calculation used \param recalculateTangents Whether are actually calculated, or just the mesh with proper type is created. \return Mesh consisting only of S3DVertexTangents vertices. If you no longer need the cloned mesh, you should call IMesh::drop(). See IReferenceCounted::drop() for more information. */ virtual IMesh* createMeshWithTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false, bool recalculateTangents=true) const=0; //! Creates a copy of the mesh, which will only consist of S3DVertex2TCoord vertices. /** \param mesh Input mesh \return Mesh consisting only of S3DVertex2TCoord vertices. If you no longer need the cloned mesh, you should call IMesh::drop(). See IReferenceCounted::drop() for more information. */ virtual IMesh* createMeshWith2TCoords(IMesh* mesh) const = 0; //! Creates a copy of the mesh, which will only consist of S3DVertex vertices. /** \param mesh Input mesh \return Mesh consisting only of S3DVertex vertices. If you no longer need the cloned mesh, you should call IMesh::drop(). See IReferenceCounted::drop() for more information. */ virtual IMesh* createMeshWith1TCoords(IMesh* mesh) const = 0; //! Creates a copy of a mesh with all vertices unwelded /** \param mesh Input mesh \return Mesh consisting only of unique faces. All vertices which were previously shared are now duplicated. If you no longer need the cloned mesh, you should call IMesh::drop(). See IReferenceCounted::drop() for more information. */ virtual IMesh* createMeshUniquePrimitives(IMesh* mesh) const = 0; //! Creates a copy of a mesh with vertices welded /** \param mesh Input mesh \param tolerance The threshold for vertex comparisons. \return Mesh without redundant vertices. If you no longer need the cloned mesh, you should call IMesh::drop(). See IReferenceCounted::drop() for more information. */ virtual IMesh* createMeshWelded(IMesh* mesh, f32 tolerance=core::ROUNDING_ERROR_f32) const = 0; //! Get amount of polygons in mesh. /** \param mesh Input mesh \return Number of polygons in mesh. */ virtual s32 getPolyCount(IMesh* mesh) const = 0; //! Get amount of polygons in mesh. /** \param mesh Input mesh \return Number of polygons in mesh. */ virtual s32 getPolyCount(IAnimatedMesh* mesh) const = 0; //! Create a new AnimatedMesh and adds the mesh to it /** \param mesh Input mesh \param type The type of the animated mesh to create. \return Newly created animated mesh with mesh as its only content. When you don't need the animated mesh anymore, you should call IAnimatedMesh::drop(). See IReferenceCounted::drop() for more information. */ virtual IAnimatedMesh * createAnimatedMesh(IMesh* mesh, scene::E_ANIMATED_MESH_TYPE type = scene::EAMT_UNKNOWN) const = 0; //! Vertex cache optimization according to the Forsyth paper /** More information can be found at http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html The function is thread-safe (read: you can optimize several meshes in different threads). \param mesh Source mesh for the operation. \return A new mesh optimized for the vertex cache. */ virtual IMesh* createForsythOptimizedMesh(const IMesh *mesh) const = 0; //! Apply a manipulator on the Meshbuffer /** \param func A functor defining the mesh manipulation. \param buffer The Meshbuffer to apply the manipulator to. \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation. \return True if the functor was successfully applied, else false. */ template bool apply(const Functor& func, IMeshBuffer* buffer, bool boundingBoxUpdate=false) const { return apply_(func, buffer, boundingBoxUpdate, func); } //! Apply a manipulator on the Mesh /** \param func A functor defining the mesh manipulation. \param mesh The Mesh to apply the manipulator to. \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation. \return True if the functor was successfully applied, else false. */ template bool apply(const Functor& func, IMesh* mesh, bool boundingBoxUpdate=false) const { if (!mesh) return true; bool result = true; core::aabbox3df bufferbox; for (u32 i=0; igetMeshBufferCount(); ++i) { result &= apply(func, mesh->getMeshBuffer(i), boundingBoxUpdate); if (boundingBoxUpdate) { if (0==i) bufferbox.reset(mesh->getMeshBuffer(i)->getBoundingBox()); else bufferbox.addInternalBox(mesh->getMeshBuffer(i)->getBoundingBox()); } } if (boundingBoxUpdate) mesh->setBoundingBox(bufferbox); return result; } protected: //! Apply a manipulator based on the type of the functor /** \param func A functor defining the mesh manipulation. \param buffer The Meshbuffer to apply the manipulator to. \param boundingBoxUpdate Specifies if the bounding box should be updated during manipulation. \param typeTest Unused parameter, which handles the proper call selection based on the type of the Functor which is passed in two times. \return True if the functor was successfully applied, else false. */ template bool apply_(const Functor& func, IMeshBuffer* buffer, bool boundingBoxUpdate, const IVertexManipulator& typeTest) const { if (!buffer) return true; core::aabbox3df bufferbox; for (u32 i=0; igetVertexCount(); ++i) { switch (buffer->getVertexType()) { case video::EVT_STANDARD: { video::S3DVertex* verts = (video::S3DVertex*)buffer->getVertices(); func(verts[i]); } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* verts = (video::S3DVertex2TCoords*)buffer->getVertices(); func(verts[i]); } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* verts = (video::S3DVertexTangents*)buffer->getVertices(); func(verts[i]); } break; } if (boundingBoxUpdate) { if (0==i) bufferbox.reset(buffer->getPosition(0)); else bufferbox.addInternalPoint(buffer->getPosition(i)); } } if (boundingBoxUpdate) buffer->setBoundingBox(bufferbox); return true; } }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IMeshLoader.h0000644000000000000000000000305512574354552016010 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_MESH_LOADER_H_INCLUDED__ #define __I_MESH_LOADER_H_INCLUDED__ #include "IReferenceCounted.h" #include "path.h" namespace irr { namespace io { class IReadFile; } // end namespace io namespace scene { class IAnimatedMesh; //! Class which is able to load an animated mesh from a file. /** If you want Irrlicht be able to load meshes of currently unsupported file formats (e.g. .cob), then implement this and add your new Meshloader with ISceneManager::addExternalMeshLoader() to the engine. */ class IMeshLoader : public virtual IReferenceCounted { public: //! Destructor virtual ~IMeshLoader() {} //! Returns true if the file might be loaded by this class. /** This decision should be based on the file extension (e.g. ".cob") only. \param filename Name of the file to test. \return True if the file might be loaded by this class. */ virtual bool isALoadableFileExtension(const io::path& filename) const = 0; //! Creates/loads an animated mesh from the file. /** \param file File handler to load the file from. \return Pointer to the created mesh. Returns 0 if loading failed. If you no longer need the mesh, you should call IAnimatedMesh::drop(). See IReferenceCounted::drop() for more information. */ virtual IAnimatedMesh* createMesh(io::IReadFile* file) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IMeshCache.h0000644000000000000000000001604712574354552015612 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_MESH_CACHE_H_INCLUDED__ #define __I_MESH_CACHE_H_INCLUDED__ #include "IReferenceCounted.h" #include "path.h" namespace irr { namespace scene { class IMesh; class IAnimatedMesh; class IAnimatedMeshSceneNode; class IMeshLoader; //! The mesh cache stores already loaded meshes and provides an interface to them. /** You can access it using ISceneManager::getMeshCache(). All existing scene managers will return a pointer to the same mesh cache, because it is shared between them. With this interface, it is possible to manually add new loaded meshes (if ISceneManager::getMesh() is not sufficient), to remove them and to iterate through already loaded meshes. */ class IMeshCache : public virtual IReferenceCounted { public: //! Destructor virtual ~IMeshCache() {} //! Adds a mesh to the internal list of loaded meshes. /** Usually, ISceneManager::getMesh() is called to load a mesh from a file. That method searches the list of loaded meshes if a mesh has already been loaded and returns a pointer to if it is in that list and already in memory. Otherwise it loads the mesh. With IMeshCache::addMesh(), it is possible to pretend that a mesh already has been loaded. This method can be used for example by mesh loaders who need to load more than one mesh with one call. They can add additional meshes with this method to the scene manager. The COLLADA loader for example uses this method. \param name Name of the mesh. When calling ISceneManager::getMesh() with this name it will return the mesh set by this method. \param mesh Pointer to a mesh which will now be referenced by this name. */ virtual void addMesh(const io::path& name, IAnimatedMesh* mesh) = 0; //! Removes the mesh from the cache. /** After loading a mesh with getMesh(), the mesh can be removed from the cache using this method, freeing a lot of memory. \param mesh Pointer to the mesh which shall be removed. */ virtual void removeMesh(const IMesh* const mesh) = 0; //! Returns amount of loaded meshes in the cache. /** You can load new meshes into the cache using getMesh() and addMesh(). If you ever need to access the internal mesh cache, you can do this using removeMesh(), getMeshNumber(), getMeshByIndex() and getMeshName(). \return Number of meshes in cache. */ virtual u32 getMeshCount() const = 0; //! Returns current index number of the mesh or -1 when not found. /** \param mesh Pointer to the mesh to search for. \return Index of the mesh in the cache, or -1 if not found. */ virtual s32 getMeshIndex(const IMesh* const mesh) const = 0; //! Returns a mesh based on its index number. /** \param index: Index of the mesh, number between 0 and getMeshCount()-1. Note that this number is only valid until a new mesh is loaded or removed. \return Pointer to the mesh or 0 if there is none with this number. */ virtual IAnimatedMesh* getMeshByIndex(u32 index) = 0; //! Returns a mesh based on its name (often a filename). /** \deprecated Use getMeshByName() instead. This method may be removed by Irrlicht 1.9 */ _IRR_DEPRECATED_ IAnimatedMesh* getMeshByFilename(const io::path& filename) { return getMeshByName(filename); } //! Get the name of a loaded mesh, based on its index. (Name is often identical to the filename). /** \deprecated Use getMeshName() instead. This method may be removed by Irrlicht 1.9 */ _IRR_DEPRECATED_ const io::path& getMeshFilename(u32 index) const { return getMeshName(index).getInternalName(); } //! Get the name of a loaded mesh, if there is any. (Name is often identical to the filename). /** \deprecated Use getMeshName() instead. This method may be removed by Irrlicht 1.9 */ _IRR_DEPRECATED_ const io::path& getMeshFilename(const IMesh* const mesh) const { return getMeshName(mesh).getInternalName(); } //! Renames a loaded mesh. /** \deprecated Use renameMesh() instead. This method may be removed by Irrlicht 1.9 */ _IRR_DEPRECATED_ bool setMeshFilename(u32 index, const io::path& filename) { return renameMesh(index, filename); } //! Renames a loaded mesh. /** \deprecated Use renameMesh() instead. This method may be removed by Irrlicht 1.9 */ _IRR_DEPRECATED_ bool setMeshFilename(const IMesh* const mesh, const io::path& filename) { return renameMesh(mesh, filename); } //! Returns a mesh based on its name. /** \param name Name of the mesh. Usually a filename. \return Pointer to the mesh or 0 if there is none with this number. */ virtual IAnimatedMesh* getMeshByName(const io::path& name) = 0; //! Get the name of a loaded mesh, based on its index. /** \param index: Index of the mesh, number between 0 and getMeshCount()-1. \return The name if mesh was found and has a name, else the path is empty. */ virtual const io::SNamedPath& getMeshName(u32 index) const = 0; //! Get the name of the loaded mesh if there is any. /** \param mesh Pointer to mesh to query. \return The name if mesh was found and has a name, else the path is empty. */ virtual const io::SNamedPath& getMeshName(const IMesh* const mesh) const = 0; //! Renames a loaded mesh. /** Note that renaming meshes might change the ordering of the meshes, and so the index of the meshes as returned by getMeshIndex() or taken by some methods will change. \param index The index of the mesh in the cache. \param name New name for the mesh. \return True if mesh was renamed. */ virtual bool renameMesh(u32 index, const io::path& name) = 0; //! Renames the loaded mesh /** Note that renaming meshes might change the ordering of the meshes, and so the index of the meshes as returned by getMeshIndex() or taken by some methods will change. \param mesh Mesh to be renamed. \param name New name for the mesh. \return True if mesh was renamed. */ virtual bool renameMesh(const IMesh* const mesh, const io::path& name) = 0; //! Check if a mesh was already loaded. /** \param name Name of the mesh. Usually a filename. \return True if the mesh has been loaded, else false. */ virtual bool isMeshLoaded(const io::path& name) = 0; //! Clears the whole mesh cache, removing all meshes. /** All meshes will be reloaded completely when using ISceneManager::getMesh() after calling this method. Warning: If you have pointers to meshes that were loaded with ISceneManager::getMesh() and you did not grab them, then they may become invalid. */ virtual void clear() = 0; //! Clears all meshes that are held in the mesh cache but not used anywhere else. /** Warning: If you have pointers to meshes that were loaded with ISceneManager::getMesh() and you did not grab them, then they may become invalid. */ virtual void clearUnusedMeshes() = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IMeshBuffer.h0000644000000000000000000001341612574354552016015 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_MESH_BUFFER_H_INCLUDED__ #define __I_MESH_BUFFER_H_INCLUDED__ #include "IReferenceCounted.h" #include "SMaterial.h" #include "aabbox3d.h" #include "S3DVertex.h" #include "SVertexIndex.h" #include "EHardwareBufferFlags.h" #include "EPrimitiveTypes.h" namespace irr { namespace scene { //! Struct for holding a mesh with a single material. /** A part of an IMesh which has the same material on each face of that group. Logical groups of an IMesh need not be put into separate mesh buffers, but can be. Separately animated parts of the mesh must be put into separate mesh buffers. Some mesh buffer implementations have limitations on the number of vertices the buffer can hold. In that case, logical grouping can help. Moreover, the number of vertices should be optimized for the GPU upload, which often depends on the type of gfx card. Typial figures are 1000-10000 vertices per buffer. SMeshBuffer is a simple implementation of a MeshBuffer, which supports up to 65535 vertices. Since meshbuffers are used for drawing, and hence will be exposed to the driver, chances are high that they are grab()'ed from somewhere. It's therefore required to dynamically allocate meshbuffers which are passed to a video driver and only drop the buffer once it's not used in the current code block anymore. */ class IMeshBuffer : public virtual IReferenceCounted { public: //! Get the material of this meshbuffer /** \return Material of this buffer. */ virtual video::SMaterial& getMaterial() = 0; //! Get the material of this meshbuffer /** \return Material of this buffer. */ virtual const video::SMaterial& getMaterial() const = 0; //! Get type of vertex data which is stored in this meshbuffer. /** \return Vertex type of this buffer. */ virtual video::E_VERTEX_TYPE getVertexType() const = 0; //! Get access to vertex data. The data is an array of vertices. /** Which vertex type is used can be determined by getVertexType(). \return Pointer to array of vertices. */ virtual const void* getVertices() const = 0; //! Get access to vertex data. The data is an array of vertices. /** Which vertex type is used can be determined by getVertexType(). \return Pointer to array of vertices. */ virtual void* getVertices() = 0; //! Get amount of vertices in meshbuffer. /** \return Number of vertices in this buffer. */ virtual u32 getVertexCount() const = 0; //! Get type of index data which is stored in this meshbuffer. /** \return Index type of this buffer. */ virtual video::E_INDEX_TYPE getIndexType() const =0; //! Get access to Indices. /** \return Pointer to indices array. */ virtual const u16* getIndices() const = 0; //! Get access to Indices. /** \return Pointer to indices array. */ virtual u16* getIndices() = 0; //! Get amount of indices in this meshbuffer. /** \return Number of indices in this buffer. */ virtual u32 getIndexCount() const = 0; //! Get the axis aligned bounding box of this meshbuffer. /** \return Axis aligned bounding box of this buffer. */ virtual const core::aabbox3df& getBoundingBox() const = 0; //! Set axis aligned bounding box /** \param box User defined axis aligned bounding box to use for this buffer. */ virtual void setBoundingBox(const core::aabbox3df& box) = 0; //! Recalculates the bounding box. Should be called if the mesh changed. virtual void recalculateBoundingBox() = 0; //! returns position of vertex i virtual const core::vector3df& getPosition(u32 i) const = 0; //! returns position of vertex i virtual core::vector3df& getPosition(u32 i) = 0; //! returns normal of vertex i virtual const core::vector3df& getNormal(u32 i) const = 0; //! returns normal of vertex i virtual core::vector3df& getNormal(u32 i) = 0; //! returns texture coord of vertex i virtual const core::vector2df& getTCoords(u32 i) const = 0; //! returns texture coord of vertex i virtual core::vector2df& getTCoords(u32 i) = 0; //! Append the vertices and indices to the current buffer /** Only works for compatible vertex types. \param vertices Pointer to a vertex array. \param numVertices Number of vertices in the array. \param indices Pointer to index array. \param numIndices Number of indices in array. */ virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) = 0; //! Append the meshbuffer to the current buffer /** Only works for compatible vertex types \param other Buffer to append to this one. */ virtual void append(const IMeshBuffer* const other) = 0; //! get the current hardware mapping hint virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const = 0; //! get the current hardware mapping hint virtual E_HARDWARE_MAPPING getHardwareMappingHint_Index() const = 0; //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint( E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX ) = 0; //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) = 0; //! Get the currently used ID for identification of changes. /** This shouldn't be used for anything outside the VideoDriver. */ virtual u32 getChangedID_Vertex() const = 0; //! Get the currently used ID for identification of changes. /** This shouldn't be used for anything outside the VideoDriver. */ virtual u32 getChangedID_Index() const = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IMesh.h0000644000000000000000000000533512574354552014664 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_MESH_H_INCLUDED__ #define __I_MESH_H_INCLUDED__ #include "IReferenceCounted.h" #include "SMaterial.h" #include "EHardwareBufferFlags.h" namespace irr { namespace scene { class IMeshBuffer; //! Class which holds the geometry of an object. /** An IMesh is nothing more than a collection of some mesh buffers (IMeshBuffer). SMesh is a simple implementation of an IMesh. A mesh is usually added to an IMeshSceneNode in order to be rendered. */ class IMesh : public virtual IReferenceCounted { public: //! Get the amount of mesh buffers. /** \return Amount of mesh buffers (IMeshBuffer) in this mesh. */ virtual u32 getMeshBufferCount() const = 0; //! Get pointer to a mesh buffer. /** \param nr: Zero based index of the mesh buffer. The maximum value is getMeshBufferCount() - 1; \return Pointer to the mesh buffer or 0 if there is no such mesh buffer. */ virtual IMeshBuffer* getMeshBuffer(u32 nr) const = 0; //! Get pointer to a mesh buffer which fits a material /** \param material: material to search for \return Pointer to the mesh buffer or 0 if there is no such mesh buffer. */ virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const = 0; //! Get an axis aligned bounding box of the mesh. /** \return Bounding box of this mesh. */ virtual const core::aabbox3d& getBoundingBox() const = 0; //! Set user-defined axis aligned bounding box /** \param box New bounding box to use for the mesh. */ virtual void setBoundingBox( const core::aabbox3df& box) = 0; //! Sets a flag of all contained materials to a new value. /** \param flag: Flag to set in all materials. \param newvalue: New value to set in all materials. */ virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) = 0; //! Set the hardware mapping hint /** This methods allows to define optimization hints for the hardware. This enables, e.g., the use of hardware buffers on pltforms that support this feature. This can lead to noticeable performance gains. */ virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) = 0; //! Flag the meshbuffer as changed, reloads hardware buffers /** This method has to be called every time the vertices or indices have changed. Otherwise, changes won't be updated on the GPU in the next render cycle. */ virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IMaterialRendererServices.h0000644000000000000000000001102712574354552020714 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_MATERIAL_RENDERER_SERVICES_H_INCLUDED__ #define __I_MATERIAL_RENDERER_SERVICES_H_INCLUDED__ #include "SMaterial.h" #include "S3DVertex.h" namespace irr { namespace video { class IVideoDriver; //! Interface providing some methods for changing advanced, internal states of a IVideoDriver. class IMaterialRendererServices { public: //! Destructor virtual ~IMaterialRendererServices() {} //! Can be called by an IMaterialRenderer to make its work easier. /** Sets all basic renderstates if needed. Basic render states are diffuse, ambient, specular, and emissive color, specular power, bilinear and trilinear filtering, wireframe mode, grouraudshading, lighting, zbuffer, zwriteenable, backfaceculling and fog enabling. \param material The new material to be used. \param lastMaterial The material used until now. \param resetAllRenderstates Set to true if all renderstates should be set, regardless of their current state. */ virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) = 0; //! Sets a constant for the vertex shader based on a name. /** This can be used if you used a high level shader language like GLSL or HLSL to create a shader. Example: If you created a shader which has variables named 'mWorldViewProj' (containing the WorldViewProjection matrix) and another one named 'fTime' containing one float, you can set them in your IShaderConstantSetCallBack derived class like this: \code virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData) { video::IVideoDriver* driver = services->getVideoDriver(); f32 time = (f32)os::Timer::getTime()/100000.0f; services->setVertexShaderConstant("fTime", &time, 1); core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION)); worldViewProj *= driver->getTransform(video::ETS_VIEW); worldViewProj *= driver->getTransform(video::ETS_WORLD); services->setVertexShaderConstant("mWorldViewProj", worldViewProj.M, 16); } \endcode \param name Name of the variable \param floats Pointer to array of floats \param count Amount of floats in array. \return True if successful. */ virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count) = 0; //! Bool interface for the above. virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count) = 0; //! Int interface for the above. virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count) = 0; //! Sets a vertex shader constant. /** Can be used if you created a shader using pixel/vertex shader assembler or ARB_fragment_program or ARB_vertex_program. \param data: Data to be set in the constants \param startRegister: First register to be set \param constantAmount: Amount of registers to be set. One register consists of 4 floats. */ virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1) = 0; //! Sets a constant for the pixel shader based on a name. /** This can be used if you used a high level shader language like GLSL or HLSL to create a shader. See setVertexShaderConstant() for an example on how to use this. \param name Name of the variable \param floats Pointer to array of floats \param count Amount of floats in array. \return True if successful. */ virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count) = 0; //! Bool interface for the above. virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count) = 0; //! Int interface for the above. virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count) = 0; //! Sets a pixel shader constant. /** Can be used if you created a shader using pixel/vertex shader assembler or ARB_fragment_program or ARB_vertex_program. \param data Data to be set in the constants \param startRegister First register to be set. \param constantAmount Amount of registers to be set. One register consists of 4 floats. */ virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1) = 0; //! Get pointer to the IVideoDriver interface /** \return Pointer to the IVideoDriver interface */ virtual IVideoDriver* getVideoDriver() = 0; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/IMaterialRenderer.h0000644000000000000000000001132312574354552017207 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_MATERIAL_RENDERER_H_INCLUDED__ #define __I_MATERIAL_RENDERER_H_INCLUDED__ #include "IReferenceCounted.h" #include "SMaterial.h" #include "S3DVertex.h" namespace irr { namespace video { class IVideoDriver; class IMaterialRendererServices; //! Interface for material rendering. /** Can be used to extend the engine with new materials. Refer to IVideoDriver::addMaterialRenderer() for more informations on how to extend the engine with new materials. */ class IMaterialRenderer : public virtual IReferenceCounted { public: //! Called by the IVideoDriver implementation the let the renderer set its needed render states. /** This is called during the IVideoDriver::setMaterial() call. When overriding this, you can set some renderstates or for example a vertex or pixel shader if you like. \param material: The new material parameters to be set. The renderer may change the material flags in this material. For example if this material does not accept the zbuffer = true, it can set it to false. This is useful, because in the next lastMaterial will be just the material in this call. \param lastMaterial: The material parameters which have been set before this material. \param resetAllRenderstates: True if all renderstates should really be reset. This is usually true if the last rendering mode was not a usual 3d rendering mode, but for example a 2d rendering mode. You should reset really all renderstates if this is true, no matter if the lastMaterial had some similar settings. This is used because in most cases, some common renderstates are not changed if they are already there, for example bilinear filtering, wireframe, gouraudshading, lighting, zbuffer, zwriteenable, backfaceculling and fogenable. \param services: Interface providing some methods for changing advanced, internal states of a IVideoDriver. */ virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) {} //! Called every time before a new bunch of geometry is being drawn using this material with for example drawIndexedTriangleList() call. /** OnSetMaterial should normally only be called if the renderer decides that the renderstates should be changed, it won't be called if for example two drawIndexedTriangleList() will be called with the same material set. This method will be called every time. This is useful for example for materials with shaders, which don't only set new renderstates but also shader constants. \param service: Pointer to interface providing methos for setting constants and other things. \param vtxtype: Vertex type with which the next rendering will be done. This can be used by the material renderer to set some specific optimized shaders or if this is an incompatible vertex type for this renderer, to refuse rendering for example. \return Returns true if everything is ok, and false if nothing should be rendered. The material renderer can choose to return false for example if he doesn't support the specified vertex type. This is actually done in D3D8 and D3D9 when using a normal mapped material with a vertex type other than EVT_TANGENTS. */ virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { return true; } //! Called by the IVideoDriver to unset this material. /** Called during the IVideoDriver::setMaterial() call before the new material will get the OnSetMaterial() call. */ virtual void OnUnsetMaterial() {} //! Returns if the material is transparent. /** The scene managment needs to know this for being able to sort the materials by opaque and transparent. */ virtual bool isTransparent() const { return false; } //! Returns the render capability of the material. /** Because some more complex materials are implemented in multiple ways and need special hardware capabilities, it is possible to query how the current material renderer is performing on the current hardware with this function. \return Returns 0 if everything is running fine. Any other value is material renderer specific and means for example that the renderer switched back to a fall back material because it cannot use the latest shaders. More specific examples: Fixed function pipeline materials should return 0 in most cases, parallax mapped material will only return 0 when at least pixel shader 1.4 is available on that machine. */ virtual s32 getRenderCapability() const { return 0; } }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/ILogger.h0000644000000000000000000000761212574354552015207 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_LOGGER_H_INCLUDED__ #define __I_LOGGER_H_INCLUDED__ #include "IReferenceCounted.h" namespace irr { //! Possible log levels. //! When used has filter ELL_DEBUG means => log everything and ELL_NONE means => log (nearly) nothing. //! When used to print logging information ELL_DEBUG will have lowest priority while ELL_NONE //! messages are never filtered and always printed. enum ELOG_LEVEL { //! Used for printing information helpful in debugging ELL_DEBUG, //! Useful information to print. For example hardware infos or something started/stopped. ELL_INFORMATION, //! Warnings that something isn't as expected and can cause oddities ELL_WARNING, //! Something did go wrong. ELL_ERROR, //! Logs with ELL_NONE will never be filtered. //! And used as filter it will remove all logging except ELL_NONE messages. ELL_NONE }; //! Interface for logging messages, warnings and errors class ILogger : public virtual IReferenceCounted { public: //! Destructor virtual ~ILogger() {} //! Returns the current set log level. virtual ELOG_LEVEL getLogLevel() const = 0; //! Sets a new log level. /** With this value, texts which are sent to the logger are filtered out. For example setting this value to ELL_WARNING, only warnings and errors are printed out. Setting it to ELL_INFORMATION, which is the default setting, warnings, errors and informational texts are printed out. \param ll: new log level filter value. */ virtual void setLogLevel(ELOG_LEVEL ll) = 0; //! Prints out a text into the log /** \param text: Text to print out. \param ll: Log level of the text. If the text is an error, set it to ELL_ERROR, if it is warning set it to ELL_WARNING, and if it is just an informational text, set it to ELL_INFORMATION. Texts are filtered with these levels. If you want to be a text displayed, independent on what level filter is set, use ELL_NONE. */ virtual void log(const c8* text, ELOG_LEVEL ll=ELL_INFORMATION) = 0; //! Prints out a text into the log /** \param text: Text to print out. \param hint: Additional info. This string is added after a " :" to the string. \param ll: Log level of the text. If the text is an error, set it to ELL_ERROR, if it is warning set it to ELL_WARNING, and if it is just an informational text, set it to ELL_INFORMATION. Texts are filtered with these levels. If you want to be a text displayed, independent on what level filter is set, use ELL_NONE. */ virtual void log(const c8* text, const c8* hint, ELOG_LEVEL ll=ELL_INFORMATION) = 0; virtual void log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION) = 0; //! Prints out a text into the log /** \param text: Text to print out. \param hint: Additional info. This string is added after a " :" to the string. \param ll: Log level of the text. If the text is an error, set it to ELL_ERROR, if it is warning set it to ELL_WARNING, and if it is just an informational text, set it to ELL_INFORMATION. Texts are filtered with these levels. If you want to be a text displayed, independent on what level filter is set, use ELL_NONE. */ virtual void log(const wchar_t* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION) = 0; //! Prints out a text into the log /** \param text: Text to print out. \param ll: Log level of the text. If the text is an error, set it to ELL_ERROR, if it is warning set it to ELL_WARNING, and if it is just an informational text, set it to ELL_INFORMATION. Texts are filtered with these levels. If you want to be a text displayed, independent on what level filter is set, use ELL_NONE. */ virtual void log(const wchar_t* text, ELOG_LEVEL ll=ELL_INFORMATION) = 0; }; } // end namespace #endif irrlicht-1.8.3/include/ILightSceneNode.h0000644000000000000000000000563612574354552016627 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_LIGHT_SCENE_NODE_H_INCLUDED__ #define __I_LIGHT_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" #include "SLight.h" namespace irr { namespace scene { //! Scene node which is a dynamic light. /** You can switch the light on and off by making it visible or not. It can be animated by ordinary scene node animators. If the light type is directional or spot, the direction of the light source is defined by the rotation of the scene node (assuming (0,0,1) as the local direction of the light). */ class ILightSceneNode : public ISceneNode { public: //! constructor ILightSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0)) : ISceneNode(parent, mgr, id, position) {} //! Sets the light data associated with this ILightSceneNode /** \param light The new light data. */ virtual void setLightData(const video::SLight& light) = 0; //! Gets the light data associated with this ILightSceneNode /** \return The light data. */ virtual const video::SLight& getLightData() const = 0; //! Gets the light data associated with this ILightSceneNode /** \return The light data. */ virtual video::SLight& getLightData() = 0; //! Sets if the node should be visible or not. /** All children of this node won't be visible either, when set to true. \param isVisible If the node shall be visible. */ virtual void setVisible(bool isVisible) = 0; //! Sets the light's radius of influence. /** Outside this radius the light won't lighten geometry and cast no shadows. Setting the radius will also influence the attenuation, setting it to (0,1/radius,0). If you want to override this behavior, set the attenuation after the radius. \param radius The new radius. */ virtual void setRadius(f32 radius) = 0; //! Gets the light's radius of influence. /** \return The current radius. */ virtual f32 getRadius() const = 0; //! Sets the light type. /** \param type The new type. */ virtual void setLightType(video::E_LIGHT_TYPE type) = 0; //! Gets the light type. /** \return The current light type. */ virtual video::E_LIGHT_TYPE getLightType() const = 0; //! Sets whether this light casts shadows. /** Enabling this flag won't automatically cast shadows, the meshes will still need shadow scene nodes attached. But one can enable or disable distinct lights for shadow casting for performance reasons. \param shadow True if this light shall cast shadows. */ virtual void enableCastShadow(bool shadow=true) = 0; //! Check whether this light casts shadows. /** \return True if light would cast shadows, else false. */ virtual bool getCastShadow() const = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ILightManager.h0000644000000000000000000000516012574354552016326 0ustar rootroot// Written by Colin MacDonald - all rights assigned to Nikolaus Gebhardt // Copyright (C) 2008-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_LIGHT_MANAGER_H_INCLUDED__ #define __I_LIGHT_MANAGER_H_INCLUDED__ #include "IReferenceCounted.h" #include "irrArray.h" namespace irr { namespace scene { class ILightSceneNode; //! ILightManager provides an interface for user applications to manipulate the list of lights in the scene. /** The light list can be trimmed or re-ordered before device/ hardware lights are created, and/or individual lights can be switched on and off before or after each scene node is rendered. It is assumed that the ILightManager implementation will store any data that it wishes to retain, i.e. the ISceneManager to which it is assigned, the lightList, the current render pass, and the current scene node. */ class ILightManager : public IReferenceCounted { public: //! Called after the scene's light list has been built, but before rendering has begun. /** As actual device/hardware lights are not created until the ESNRP_LIGHT render pass, this provides an opportunity for the light manager to trim or re-order the light list, before any device/hardware lights have actually been created. \param lightList: the Scene Manager's light list, which the light manager may modify. This reference will remain valid until OnPostRender(). */ virtual void OnPreRender(core::array & lightList) = 0; //! Called after the last scene node is rendered. /** After this call returns, the lightList passed to OnPreRender() becomes invalid. */ virtual void OnPostRender(void) = 0; //! Called before a render pass begins /** \param renderPass: the render pass that's about to begin */ virtual void OnRenderPassPreRender(E_SCENE_NODE_RENDER_PASS renderPass) = 0; //! Called after the render pass specified in OnRenderPassPreRender() ends /** \param[in] renderPass: the render pass that has finished */ virtual void OnRenderPassPostRender(E_SCENE_NODE_RENDER_PASS renderPass) = 0; //! Called before the given scene node is rendered /** \param[in] node: the scene node that's about to be rendered */ virtual void OnNodePreRender(ISceneNode* node) = 0; //! Called after the the node specified in OnNodePreRender() has been rendered /** \param[in] node: the scene node that has just been rendered */ virtual void OnNodePostRender(ISceneNode* node) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IIndexBuffer.h0000644000000000000000000000313212574354552016162 0ustar rootroot// Copyright (C) 2008-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_INDEX_BUFFER_H_INCLUDED__ #define __I_INDEX_BUFFER_H_INCLUDED__ #include "IReferenceCounted.h" #include "irrArray.h" #include "SVertexIndex.h" namespace irr { namespace video { } namespace scene { class IIndexBuffer : public virtual IReferenceCounted { public: virtual void* getData() =0; virtual video::E_INDEX_TYPE getType() const =0; virtual void setType(video::E_INDEX_TYPE IndexType) =0; virtual u32 stride() const =0; virtual u32 size() const =0; virtual void push_back (const u32 &element) =0; virtual u32 operator [](u32 index) const =0; virtual u32 getLast() =0; virtual void setValue(u32 index, u32 value) =0; virtual void set_used(u32 usedNow) =0; virtual void reallocate(u32 new_size) =0; virtual u32 allocated_size() const=0; virtual void* pointer() =0; //! get the current hardware mapping hint virtual E_HARDWARE_MAPPING getHardwareMappingHint() const =0; //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint ) =0; //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty() = 0; //! Get the currently used ID for identification of changes. /** This shouldn't be used for anything outside the VideoDriver. */ virtual u32 getChangedID() const = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IImageWriter.h0000644000000000000000000000232212574354552016200 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef _I_IMAGE_WRITER_H_INCLUDED__ #define _I_IMAGE_WRITER_H_INCLUDED__ #include "IReferenceCounted.h" #include "irrString.h" #include "coreutil.h" namespace irr { namespace io { class IWriteFile; } // end namespace io namespace video { class IImage; //! Interface for writing software image data. class IImageWriter : public IReferenceCounted { public: //! Check if this writer can write a file with the given extension /** \param filename Name of the file to check. \return True if file extension specifies a writable type. */ virtual bool isAWriteableFileExtension(const io::path& filename) const = 0; //! Write image to file /** \param file File handle to write to. \param image Image to write into file. \param param Writer specific parameter, influencing e.g. quality. \return True if image was successfully written. */ virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param = 0) const = 0; }; } // namespace video } // namespace irr #endif // _I_IMAGE_WRITER_H_INCLUDED__ irrlicht-1.8.3/include/IImageLoader.h0000644000000000000000000000305612574354552016137 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_SURFACE_LOADER_H_INCLUDED__ #define __I_SURFACE_LOADER_H_INCLUDED__ #include "IReferenceCounted.h" #include "IImage.h" #include "path.h" namespace irr { namespace io { class IReadFile; } // end namespace io namespace video { //! Class which is able to create a image from a file. /** If you want the Irrlicht Engine be able to load textures of currently unsupported file formats (e.g .gif), then implement this and add your new Surface loader with IVideoDriver::addExternalImageLoader() to the engine. */ class IImageLoader : public virtual IReferenceCounted { public: //! Check if the file might be loaded by this class /** Check is based on the file extension (e.g. ".tga") \param filename Name of file to check. \return True if file seems to be loadable. */ virtual bool isALoadableFileExtension(const io::path& filename) const = 0; //! Check if the file might be loaded by this class /** Check might look into the file. \param file File handle to check. \return True if file seems to be loadable. */ virtual bool isALoadableFileFormat(io::IReadFile* file) const = 0; //! Creates a surface from the file /** \param file File handle to check. \return Pointer to newly created image, or 0 upon error. */ virtual IImage* loadImage(io::IReadFile* file) const = 0; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/IImage.h0000644000000000000000000001077512574354552015016 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_IMAGE_H_INCLUDED__ #define __I_IMAGE_H_INCLUDED__ #include "IReferenceCounted.h" #include "position2d.h" #include "rect.h" #include "SColor.h" namespace irr { namespace video { //! Interface for software image data. /** Image loaders create these images from files. IVideoDrivers convert these images into their (hardware) textures. */ class IImage : public virtual IReferenceCounted { public: //! Lock function. Use this to get a pointer to the image data. /** After you don't need the pointer anymore, you must call unlock(). \return Pointer to the image data. What type of data is pointed to depends on the color format of the image. For example if the color format is ECF_A8R8G8B8, it is of u32. Be sure to call unlock() after you don't need the pointer any more. */ virtual void* lock() = 0; //! Unlock function. /** Should be called after the pointer received by lock() is not needed anymore. */ virtual void unlock() = 0; //! Returns width and height of image data. virtual const core::dimension2d& getDimension() const = 0; //! Returns bits per pixel. virtual u32 getBitsPerPixel() const = 0; //! Returns bytes per pixel virtual u32 getBytesPerPixel() const = 0; //! Returns image data size in bytes virtual u32 getImageDataSizeInBytes() const = 0; //! Returns image data size in pixels virtual u32 getImageDataSizeInPixels() const = 0; //! Returns a pixel virtual SColor getPixel(u32 x, u32 y) const = 0; //! Sets a pixel virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ) = 0; //! Returns the color format virtual ECOLOR_FORMAT getColorFormat() const = 0; //! Returns mask for red value of a pixel virtual u32 getRedMask() const = 0; //! Returns mask for green value of a pixel virtual u32 getGreenMask() const = 0; //! Returns mask for blue value of a pixel virtual u32 getBlueMask() const = 0; //! Returns mask for alpha value of a pixel virtual u32 getAlphaMask() const = 0; //! Returns pitch of image virtual u32 getPitch() const =0; //! Copies the image into the target, scaling the image to fit virtual void copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format=ECF_A8R8G8B8, u32 pitch=0) =0; //! Copies the image into the target, scaling the image to fit virtual void copyToScaling(IImage* target) =0; //! copies this surface into another virtual void copyTo(IImage* target, const core::position2d& pos=core::position2d(0,0)) =0; //! copies this surface into another virtual void copyTo(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect=0) =0; //! copies this surface into another, using the alpha mask and cliprect and a color to add with virtual void copyToWithAlpha(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const SColor &color, const core::rect* clipRect = 0) =0; //! copies this surface into another, scaling it to fit, appyling a box filter virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) = 0; //! fills the surface with given color virtual void fill(const SColor &color) =0; //! get the amount of Bits per Pixel of the given color format static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format) { switch(format) { case ECF_A1R5G5B5: return 16; case ECF_R5G6B5: return 16; case ECF_R8G8B8: return 24; case ECF_A8R8G8B8: return 32; case ECF_R16F: return 16; case ECF_G16R16F: return 32; case ECF_A16B16G16R16F: return 64; case ECF_R32F: return 32; case ECF_G32R32F: return 64; case ECF_A32B32G32R32F: return 128; default: return 0; } } //! test if the color format is only viable for RenderTarget textures /** Since we don't have support for e.g. floating point IImage formats one should test if the color format can be used for arbitrary usage, or if it is restricted to RTTs. */ static bool isRenderTargetOnlyFormat(const ECOLOR_FORMAT format) { switch(format) { case ECF_A1R5G5B5: case ECF_R5G6B5: case ECF_R8G8B8: case ECF_A8R8G8B8: return false; default: return true; } } }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/IGUIWindow.h0000644000000000000000000000533212574354552015601 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_WINDOW_H_INCLUDED__ #define __I_GUI_WINDOW_H_INCLUDED__ #include "IGUIElement.h" #include "EMessageBoxFlags.h" namespace irr { namespace gui { class IGUIButton; //! Default moveable window GUI element with border, caption and close icons. /** \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_ELEMENT_CLOSED */ class IGUIWindow : public IGUIElement { public: //! constructor IGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_WINDOW, environment, parent, id, rectangle) {} //! Returns pointer to the close button /** You can hide the button by calling setVisible(false) on the result. */ virtual IGUIButton* getCloseButton() const = 0; //! Returns pointer to the minimize button /** You can hide the button by calling setVisible(false) on the result. */ virtual IGUIButton* getMinimizeButton() const = 0; //! Returns pointer to the maximize button /** You can hide the button by calling setVisible(false) on the result. */ virtual IGUIButton* getMaximizeButton() const = 0; //! Returns true if the window can be dragged with the mouse, false if not virtual bool isDraggable() const = 0; //! Sets whether the window can be dragged by the mouse virtual void setDraggable(bool draggable) = 0; //! Set if the window background will be drawn virtual void setDrawBackground(bool draw) = 0; //! Get if the window background will be drawn virtual bool getDrawBackground() const = 0; //! Set if the window titlebar will be drawn //! Note: If the background is not drawn, then the titlebar is automatically also not drawn virtual void setDrawTitlebar(bool draw) = 0; //! Get if the window titlebar will be drawn virtual bool getDrawTitlebar() const = 0; //! Returns the rectangle of the drawable area (without border and without titlebar) /** The coordinates are given relative to the top-left position of the gui element.
So to get absolute positions you have to add the resulting rectangle to getAbsolutePosition().UpperLeftCorner.
To get it relative to the parent element you have to add the resulting rectangle to getRelativePosition().UpperLeftCorner. Beware that adding a menu will not change the clientRect as menus are own gui elements, so in that case you might want to subtract the menu area additionally. */ virtual core::rect getClientRect() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUITreeView.h0000644000000000000000000002427712574354552016075 0ustar rootroot// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_TREE_VIEW_H_INCLUDED__ #define __I_GUI_TREE_VIEW_H_INCLUDED__ #include "IGUIElement.h" #include "IGUIImageList.h" #include "irrTypes.h" namespace irr { namespace gui { class IGUIFont; class IGUITreeView; //! Node for gui tree view /** \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_TREEVIEW_NODE_EXPAND \li EGET_TREEVIEW_NODE_COLLAPS \li EGET_TREEVIEW_NODE_DESELECT \li EGET_TREEVIEW_NODE_SELECT */ class IGUITreeViewNode : public IReferenceCounted { public: //! returns the owner (tree view) of this node virtual IGUITreeView* getOwner() const = 0; //! Returns the parent node of this node. /** For the root node this will return 0. */ virtual IGUITreeViewNode* getParent() const = 0; //! returns the text of the node virtual const wchar_t* getText() const = 0; //! sets the text of the node virtual void setText( const wchar_t* text ) = 0; //! returns the icon text of the node virtual const wchar_t* getIcon() const = 0; //! sets the icon text of the node virtual void setIcon( const wchar_t* icon ) = 0; //! returns the image index of the node virtual u32 getImageIndex() const = 0; //! sets the image index of the node virtual void setImageIndex( u32 imageIndex ) = 0; //! returns the image index of the node virtual u32 getSelectedImageIndex() const = 0; //! sets the image index of the node virtual void setSelectedImageIndex( u32 imageIndex ) = 0; //! returns the user data (void*) of this node virtual void* getData() const = 0; //! sets the user data (void*) of this node virtual void setData( void* data ) = 0; //! returns the user data2 (IReferenceCounted) of this node virtual IReferenceCounted* getData2() const = 0; //! sets the user data2 (IReferenceCounted) of this node virtual void setData2( IReferenceCounted* data ) = 0; //! returns the child item count virtual u32 getChildCount() const = 0; //! removes all children (recursive) from this node virtual void clearChildren() = 0; //! removes all children (recursive) from this node /** \deprecated Deprecated in 1.8, use clearChildren() instead. This method may be removed by Irrlicht 1.9 */ _IRR_DEPRECATED_ void clearChilds() { return clearChildren(); } //! returns true if this node has child nodes virtual bool hasChildren() const = 0; //! returns true if this node has child nodes /** \deprecated Deprecated in 1.8, use hasChildren() instead. This method may be removed by Irrlicht 1.9 */ _IRR_DEPRECATED_ bool hasChilds() const { return hasChildren(); } //! Adds a new node behind the last child node. /** \param text text of the new node \param icon icon text of the new node \param imageIndex index of the image for the new node (-1 = none) \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) \param data user data (void*) of the new node \param data2 user data2 (IReferenceCounted*) of the new node \return The new node */ virtual IGUITreeViewNode* addChildBack( const wchar_t* text, const wchar_t* icon = 0, s32 imageIndex=-1, s32 selectedImageIndex=-1, void* data=0, IReferenceCounted* data2=0) =0; //! Adds a new node before the first child node. /** \param text text of the new node \param icon icon text of the new node \param imageIndex index of the image for the new node (-1 = none) \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) \param data user data (void*) of the new node \param data2 user data2 (IReferenceCounted*) of the new node \return The new node */ virtual IGUITreeViewNode* addChildFront( const wchar_t* text, const wchar_t* icon = 0, s32 imageIndex=-1, s32 selectedImageIndex=-1, void* data=0, IReferenceCounted* data2=0 ) =0; //! Adds a new node behind the other node. /** The other node has also te be a child node from this node. \param other Node to insert after \param text text of the new node \param icon icon text of the new node \param imageIndex index of the image for the new node (-1 = none) \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) \param data user data (void*) of the new node \param data2 user data2 (IReferenceCounted*) of the new node \return The new node or 0 if other is no child node from this */ virtual IGUITreeViewNode* insertChildAfter( IGUITreeViewNode* other, const wchar_t* text, const wchar_t* icon = 0, s32 imageIndex=-1, s32 selectedImageIndex=-1, void* data=0, IReferenceCounted* data2=0) =0; //! Adds a new node before the other node. /** The other node has also te be a child node from this node. \param other Node to insert before \param text text of the new node \param icon icon text of the new node \param imageIndex index of the image for the new node (-1 = none) \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) \param data user data (void*) of the new node \param data2 user data2 (IReferenceCounted*) of the new node \return The new node or 0 if other is no child node from this */ virtual IGUITreeViewNode* insertChildBefore( IGUITreeViewNode* other, const wchar_t* text, const wchar_t* icon = 0, s32 imageIndex=-1, s32 selectedImageIndex=-1, void* data=0, IReferenceCounted* data2=0) = 0; //! Return the first child node from this node. /** \return The first child node or 0 if this node has no children. */ virtual IGUITreeViewNode* getFirstChild() const = 0; //! Return the last child node from this node. /** \return The last child node or 0 if this node has no children. */ virtual IGUITreeViewNode* getLastChild() const = 0; //! Returns the previous sibling node from this node. /** \return The previous sibling node from this node or 0 if this is the first node from the parent node. */ virtual IGUITreeViewNode* getPrevSibling() const = 0; //! Returns the next sibling node from this node. /** \return The next sibling node from this node or 0 if this is the last node from the parent node. */ virtual IGUITreeViewNode* getNextSibling() const = 0; //! Returns the next visible (expanded, may be out of scrolling) node from this node. /** \return The next visible node from this node or 0 if this is the last visible node. */ virtual IGUITreeViewNode* getNextVisible() const = 0; //! Deletes a child node. /** \return Returns true if the node was found as a child and is deleted. */ virtual bool deleteChild( IGUITreeViewNode* child ) = 0; //! Moves a child node one position up. /** \return True if the node was found as achild node and was not already the first child. */ virtual bool moveChildUp( IGUITreeViewNode* child ) = 0; //! Moves a child node one position down. /** \return True if the node was found as achild node and was not already the last child. */ virtual bool moveChildDown( IGUITreeViewNode* child ) = 0; //! Returns true if the node is expanded (children are visible). virtual bool getExpanded() const = 0; //! Sets if the node is expanded. virtual void setExpanded( bool expanded ) = 0; //! Returns true if the node is currently selected. virtual bool getSelected() const = 0; //! Sets this node as selected. virtual void setSelected( bool selected ) = 0; //! Returns true if this node is the root node. virtual bool isRoot() const = 0; //! Returns the level of this node. /** The root node has level 0. Direct children of the root has level 1 ... */ virtual s32 getLevel() const = 0; //! Returns true if this node is visible (all parents are expanded). virtual bool isVisible() const = 0; }; //! Default tree view GUI element. /** Displays a windows like tree buttons to expand/collaps the child nodes of an node and optional tree lines. Each node consits of an text, an icon text and a void pointer for user data. */ class IGUITreeView : public IGUIElement { public: //! constructor IGUITreeView(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement( EGUIET_TREE_VIEW, environment, parent, id, rectangle ) {} //! returns the root node (not visible) from the tree. virtual IGUITreeViewNode* getRoot() const = 0; //! returns the selected node of the tree or 0 if none is selected virtual IGUITreeViewNode* getSelected() const = 0; //! returns true if the tree lines are visible virtual bool getLinesVisible() const = 0; //! sets if the tree lines are visible /** \param visible true for visible, false for invisible */ virtual void setLinesVisible( bool visible ) = 0; //! Sets the font which should be used as icon font. /** This font is set to the Irrlicht engine built-in-font by default. Icons can be displayed in front of every list item. An icon is a string, displayed with the icon font. When using the build-in-font of the Irrlicht engine as icon font, the icon strings defined in GUIIcons.h can be used. */ virtual void setIconFont( IGUIFont* font ) = 0; //! Sets the image list which should be used for the image and selected image of every node. /** The default is 0 (no images). */ virtual void setImageList( IGUIImageList* imageList ) = 0; //! Returns the image list which is used for the nodes. virtual IGUIImageList* getImageList() const = 0; //! Sets if the image is left of the icon. Default is true. virtual void setImageLeftOfIcon( bool bLeftOf ) = 0; //! Returns if the Image is left of the icon. Default is true. virtual bool getImageLeftOfIcon() const = 0; //! Returns the node which is associated to the last event. /** This pointer is only valid inside the OnEvent call! */ virtual IGUITreeViewNode* getLastEventNode() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIToolbar.h0000644000000000000000000000204612574354552015733 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_TOOL_BAR_H_INCLUDED__ #define __I_GUI_TOOL_BAR_H_INCLUDED__ #include "IGUIElement.h" namespace irr { namespace video { class ITexture; } // end namespace video namespace gui { class IGUIButton; //! Stays at the top of its parent like the menu bar and contains tool buttons class IGUIToolBar : public IGUIElement { public: //! constructor IGUIToolBar(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_TOOL_BAR, environment, parent, id, rectangle) {} //! Adds a button to the tool bar virtual IGUIButton* addButton(s32 id=-1, const wchar_t* text=0,const wchar_t* tooltiptext=0, video::ITexture* img=0, video::ITexture* pressedimg=0, bool isPushButton=false, bool useAlphaChannel=false) = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUITable.h0000644000000000000000000001447312574354552015367 0ustar rootroot// Copyright (C) 2003-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_TABLE_H_INCLUDED__ #define __I_GUI_TABLE_H_INCLUDED__ #include "IGUIElement.h" #include "irrTypes.h" #include "SColor.h" #include "IGUISkin.h" namespace irr { namespace gui { //! modes for ordering used when a column header is clicked enum EGUI_COLUMN_ORDERING { //! Do not use ordering EGCO_NONE, //! Send a EGET_TABLE_HEADER_CHANGED message when a column header is clicked. EGCO_CUSTOM, //! Sort it ascending by it's ascii value like: a,b,c,... EGCO_ASCENDING, //! Sort it descending by it's ascii value like: z,x,y,... EGCO_DESCENDING, //! Sort it ascending on first click, descending on next, etc EGCO_FLIP_ASCENDING_DESCENDING, //! Not used as mode, only to get maximum value for this enum EGCO_COUNT }; //! Names for EGUI_COLUMN_ORDERING types const c8* const GUIColumnOrderingNames[] = { "none", "custom", "ascend", "descend", "ascend_descend", 0, }; enum EGUI_ORDERING_MODE { //! No element ordering EGOM_NONE, //! Elements are ordered from the smallest to the largest. EGOM_ASCENDING, //! Elements are ordered from the largest to the smallest. EGOM_DESCENDING, //! this value is not used, it only specifies the amount of default ordering types //! available. EGOM_COUNT }; const c8* const GUIOrderingModeNames[] = { "none", "ascending", "descending", 0 }; enum EGUI_TABLE_DRAW_FLAGS { EGTDF_ROWS = 1, EGTDF_COLUMNS = 2, EGTDF_ACTIVE_ROW = 4, EGTDF_COUNT }; //! Default list box GUI element. /** \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_TABLE_CHANGED \li EGET_TABLE_SELECTED_AGAIN \li EGET_TABLE_HEADER_CHANGED */ class IGUITable : public IGUIElement { public: //! constructor IGUITable(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_TABLE, environment, parent, id, rectangle) {} //! Adds a column /** If columnIndex is outside the current range, do push new colum at the end */ virtual void addColumn(const wchar_t* caption, s32 columnIndex=-1) = 0; //! remove a column from the table virtual void removeColumn(u32 columnIndex) = 0; //! Returns the number of columns in the table control virtual s32 getColumnCount() const = 0; //! Makes a column active. This will trigger an ordering process. /** \param idx: The id of the column to make active. \param doOrder: Do also the ordering which depending on mode for active column \return True if successful. */ virtual bool setActiveColumn(s32 idx, bool doOrder=false) = 0; //! Returns which header is currently active virtual s32 getActiveColumn() const = 0; //! Returns the ordering used by the currently active column virtual EGUI_ORDERING_MODE getActiveColumnOrdering() const = 0; //! Set the width of a column virtual void setColumnWidth(u32 columnIndex, u32 width) = 0; //! Get the width of a column virtual u32 getColumnWidth(u32 columnIndex) const = 0; //! columns can be resized by drag 'n drop virtual void setResizableColumns(bool resizable) = 0; //! can columns be resized by dran 'n drop? virtual bool hasResizableColumns() const = 0; //! This tells the table control which ordering mode should be used when a column header is clicked. /** \param columnIndex The index of the column header. \param mode: One of the modes defined in EGUI_COLUMN_ORDERING */ virtual void setColumnOrdering(u32 columnIndex, EGUI_COLUMN_ORDERING mode) = 0; //! Returns which row is currently selected virtual s32 getSelected() const = 0; //! set wich row is currently selected virtual void setSelected( s32 index ) = 0; //! Get amount of rows in the tabcontrol virtual s32 getRowCount() const = 0; //! adds a row to the table /** \param rowIndex Zero based index of rows. The row will be inserted at this position, if a row already exist there, it will be placed after it. If the row is larger than the actual number of row by more than one, it won't be created. Note that if you create a row that's not at the end, there might be performance issues. \return index of inserted row. */ virtual u32 addRow(u32 rowIndex) = 0; //! Remove a row from the table virtual void removeRow(u32 rowIndex) = 0; //! clears the table rows, but keeps the columns intact virtual void clearRows() = 0; //! Swap two row positions. virtual void swapRows(u32 rowIndexA, u32 rowIndexB) = 0; //! This tells the table to start ordering all the rows. /** You need to explicitly tell the table to re order the rows when a new row is added or the cells data is changed. This makes the system more flexible and doesn't make you pay the cost of ordering when adding a lot of rows. \param columnIndex: When set to -1 the active column is used. \param mode Ordering mode of the rows. */ virtual void orderRows(s32 columnIndex=-1, EGUI_ORDERING_MODE mode=EGOM_NONE) = 0; //! Set the text of a cell virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text) = 0; //! Set the text of a cell, and set a color of this cell. virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color) = 0; //! Set the data of a cell virtual void setCellData(u32 rowIndex, u32 columnIndex, void *data) = 0; //! Set the color of a cell text virtual void setCellColor(u32 rowIndex, u32 columnIndex, video::SColor color) = 0; //! Get the text of a cell virtual const wchar_t* getCellText(u32 rowIndex, u32 columnIndex ) const = 0; //! Get the data of a cell virtual void* getCellData(u32 rowIndex, u32 columnIndex ) const = 0; //! clears the table, deletes all items in the table virtual void clear() = 0; //! Set flags, as defined in EGUI_TABLE_DRAW_FLAGS, which influence the layout virtual void setDrawFlags(s32 flags) = 0; //! Get the flags, as defined in EGUI_TABLE_DRAW_FLAGS, which influence the layout virtual s32 getDrawFlags() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUITabControl.h0000644000000000000000000001073612574354552016405 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_TAB_CONTROL_H_INCLUDED__ #define __I_GUI_TAB_CONTROL_H_INCLUDED__ #include "IGUIElement.h" #include "SColor.h" #include "IGUISkin.h" namespace irr { namespace gui { //! A tab-page, onto which other gui elements could be added. /** IGUITab refers to the page itself, not to the tab in the tabbar of an IGUITabControl. */ class IGUITab : public IGUIElement { public: //! constructor IGUITab(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_TAB, environment, parent, id, rectangle) {} //! Returns zero based index of tab if in tabcontrol. /** Can be accessed later IGUITabControl::getTab() by this number. Note that this number can change when other tabs are inserted or removed . */ virtual s32 getNumber() const = 0; //! sets if the tab should draw its background virtual void setDrawBackground(bool draw=true) = 0; //! sets the color of the background, if it should be drawn. virtual void setBackgroundColor(video::SColor c) = 0; //! returns true if the tab is drawing its background, false if not virtual bool isDrawingBackground() const = 0; //! returns the color of the background virtual video::SColor getBackgroundColor() const = 0; //! sets the color of the text virtual void setTextColor(video::SColor c) = 0; //! gets the color of the text virtual video::SColor getTextColor() const = 0; }; //! A standard tab control /** \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_TAB_CHANGED */ class IGUITabControl : public IGUIElement { public: //! constructor IGUITabControl(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_TAB_CONTROL, environment, parent, id, rectangle) {} //! Adds a tab virtual IGUITab* addTab(const wchar_t* caption, s32 id=-1) = 0; //! Insert the tab at the given index /** \return The tab on success or NULL on failure. */ virtual IGUITab* insertTab(s32 idx, const wchar_t* caption, s32 id=-1) = 0; //! Removes a tab from the tabcontrol virtual void removeTab(s32 idx) = 0; //! Clears the tabcontrol removing all tabs virtual void clear() = 0; //! Returns amount of tabs in the tabcontrol virtual s32 getTabCount() const = 0; //! Returns a tab based on zero based index /** \param idx: zero based index of tab. Is a value betwenn 0 and getTabcount()-1; \return Returns pointer to the Tab. Returns 0 if no tab is corresponding to this tab. */ virtual IGUITab* getTab(s32 idx) const = 0; //! Brings a tab to front. /** \param idx: number of the tab. \return Returns true if successful. */ virtual bool setActiveTab(s32 idx) = 0; //! Brings a tab to front. /** \param tab: pointer to the tab. \return Returns true if successful. */ virtual bool setActiveTab(IGUITab *tab) = 0; //! Returns which tab is currently active virtual s32 getActiveTab() const = 0; //! get the the id of the tab at the given absolute coordinates /** \return The id of the tab or -1 when no tab is at those coordinates*/ virtual s32 getTabAt(s32 xpos, s32 ypos) const = 0; //! Set the height of the tabs virtual void setTabHeight( s32 height ) = 0; //! Get the height of the tabs /** return Returns the height of the tabs */ virtual s32 getTabHeight() const = 0; //! set the maximal width of a tab. Per default width is 0 which means "no width restriction". virtual void setTabMaxWidth(s32 width ) = 0; //! get the maximal width of a tab virtual s32 getTabMaxWidth() const = 0; //! Set the alignment of the tabs /** Use EGUIA_UPPERLEFT or EGUIA_LOWERRIGHT */ virtual void setTabVerticalAlignment( gui::EGUI_ALIGNMENT alignment ) = 0; //! Get the alignment of the tabs /** return Returns the alignment of the tabs */ virtual gui::EGUI_ALIGNMENT getTabVerticalAlignment() const = 0; //! Set the extra width added to tabs on each side of the text virtual void setTabExtraWidth( s32 extraWidth ) = 0; //! Get the extra width added to tabs on each side of the text /** return Returns the extra width of the tabs */ virtual s32 getTabExtraWidth() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIStaticText.h0000644000000000000000000001241012574354552016421 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_STATIC_TEXT_H_INCLUDED__ #define __I_GUI_STATIC_TEXT_H_INCLUDED__ #include "IGUIElement.h" #include "SColor.h" namespace irr { namespace gui { class IGUIFont; //! Multi or single line text label. class IGUIStaticText : public IGUIElement { public: //! constructor IGUIStaticText(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_STATIC_TEXT, environment, parent, id, rectangle) {} //! Sets another skin independent font. /** If this is set to zero, the button uses the font of the skin. \param font: New font to set. */ virtual void setOverrideFont(IGUIFont* font=0) = 0; //! Gets the override font (if any) /** \return The override font (may be 0) */ virtual IGUIFont* getOverrideFont(void) const = 0; //! Get the font which is used right now for drawing /** Currently this is the override font when one is set and the font of the active skin otherwise */ virtual IGUIFont* getActiveFont() const = 0; //! Sets another color for the text. /** If set, the static text does not use the EGDC_BUTTON_TEXT color defined in the skin, but the set color instead. You don't need to call IGUIStaticText::enableOverrrideColor(true) after this, this is done by this function. If you set a color, and you want the text displayed with the color of the skin again, call IGUIStaticText::enableOverrideColor(false); \param color: New color of the text. */ virtual void setOverrideColor(video::SColor color) = 0; //! Gets the override color /** \return: The override color */ virtual video::SColor getOverrideColor(void) const = 0; //! Sets if the static text should use the overide color or the color in the gui skin. /** \param enable: If set to true, the override color, which can be set with IGUIStaticText::setOverrideColor is used, otherwise the EGDC_BUTTON_TEXT color of the skin. */ virtual void enableOverrideColor(bool enable) = 0; //! Checks if an override color is enabled /** \return true if the override color is enabled, false otherwise */ virtual bool isOverrideColorEnabled(void) const = 0; //! Sets another color for the background. virtual void setBackgroundColor(video::SColor color) = 0; //! Sets whether to draw the background virtual void setDrawBackground(bool draw) = 0; //! Gets the background color /** \return: The background color */ virtual video::SColor getBackgroundColor() const = 0; //! Checks if background drawing is enabled /** \return true if background drawing is enabled, false otherwise */ virtual bool isDrawBackgroundEnabled() const = 0; //! Sets whether to draw the border virtual void setDrawBorder(bool draw) = 0; //! Checks if border drawing is enabled /** \return true if border drawing is enabled, false otherwise */ virtual bool isDrawBorderEnabled() const = 0; //! Sets text justification mode /** \param horizontal: EGUIA_UPPERLEFT for left justified (default), EGUIA_LOWEERRIGHT for right justified, or EGUIA_CENTER for centered text. \param vertical: EGUIA_UPPERLEFT to align with top edge, EGUIA_LOWEERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */ virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0; //! Enables or disables word wrap for using the static text as multiline text control. /** \param enable: If set to true, words going over one line are broken on to the next line. */ virtual void setWordWrap(bool enable) = 0; //! Checks if word wrap is enabled /** \return true if word wrap is enabled, false otherwise */ virtual bool isWordWrapEnabled(void) const = 0; //! Returns the height of the text in pixels when it is drawn. /** This is useful for adjusting the layout of gui elements based on the height of the multiline text in this element. \return Height of text in pixels. */ virtual s32 getTextHeight() const = 0; //! Returns the width of the current text, in the current font /** If the text is broken, this returns the width of the widest line \return The width of the text, or the widest broken line. */ virtual s32 getTextWidth(void) const = 0; //! Set whether the text in this label should be clipped if it goes outside bounds virtual void setTextRestrainedInside(bool restrainedInside) = 0; //! Checks if the text in this label should be clipped if it goes outside bounds virtual bool isTextRestrainedInside() const = 0; //! Set whether the string should be interpreted as right-to-left (RTL) text /** \note This component does not implement the Unicode bidi standard, the text of the component should be already RTL if you call this. The main difference when RTL is enabled is that the linebreaks for multiline elements are performed starting from the end. */ virtual void setRightToLeft(bool rtl) = 0; //! Checks whether the text in this element should be interpreted as right-to-left virtual bool isRightToLeft() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUISpriteBank.h0000644000000000000000000000537412574354552016402 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_SPRITE_BANK_H_INCLUDED__ #define __I_GUI_SPRITE_BANK_H_INCLUDED__ #include "IReferenceCounted.h" #include "irrArray.h" #include "SColor.h" #include "rect.h" namespace irr { namespace video { class ITexture; } // end namespace video namespace gui { //! A single sprite frame. struct SGUISpriteFrame { u32 textureNumber; u32 rectNumber; }; //! A sprite composed of several frames. struct SGUISprite { SGUISprite() : Frames(), frameTime(0) {} core::array Frames; u32 frameTime; }; //! Sprite bank interface. /** See http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=25742&highlight=spritebank * for more information how to use the spritebank. */ class IGUISpriteBank : public virtual IReferenceCounted { public: //! Returns the list of rectangles held by the sprite bank virtual core::array< core::rect >& getPositions() = 0; //! Returns the array of animated sprites within the sprite bank virtual core::array< SGUISprite >& getSprites() = 0; //! Returns the number of textures held by the sprite bank virtual u32 getTextureCount() const = 0; //! Gets the texture with the specified index virtual video::ITexture* getTexture(u32 index) const = 0; //! Adds a texture to the sprite bank virtual void addTexture(video::ITexture* texture) = 0; //! Changes one of the textures in the sprite bank virtual void setTexture(u32 index, video::ITexture* texture) = 0; //! Add the texture and use it for a single non-animated sprite. //! The texture and the corresponding rectangle and sprite will all be added to the end of each array. //! returns the index of the sprite or -1 on failure virtual s32 addTextureAsSprite(video::ITexture* texture) = 0; //! clears sprites, rectangles and textures virtual void clear() = 0; //! Draws a sprite in 2d with position and color virtual void draw2DSprite(u32 index, const core::position2di& pos, const core::rect* clip=0, const video::SColor& color= video::SColor(255,255,255,255), u32 starttime=0, u32 currenttime=0, bool loop=true, bool center=false) = 0; //! Draws a sprite batch in 2d using an array of positions and a color virtual void draw2DSpriteBatch(const core::array& indices, const core::array& pos, const core::rect* clip=0, const video::SColor& color= video::SColor(255,255,255,255), u32 starttime=0, u32 currenttime=0, bool loop=true, bool center=false) = 0; }; } // end namespace gui } // end namespace irr #endif // __I_GUI_SPRITE_BANK_H_INCLUDED__ irrlicht-1.8.3/include/IGUISpinBox.h0000644000000000000000000000420312574354552015710 0ustar rootroot// Copyright (C) 2006-2012 Michael Zeilfelder // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_SPIN_BOX_H_INCLUDED__ #define __I_GUI_SPIN_BOX_H_INCLUDED__ #include "IGUIElement.h" namespace irr { namespace gui { class IGUIEditBox; //! Single line edit box + spin buttons /** \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_SPINBOX_CHANGED */ class IGUISpinBox : public IGUIElement { public: //! constructor IGUISpinBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_SPIN_BOX, environment, parent, id, rectangle) {} //! Access the edit box used in the spin control virtual IGUIEditBox* getEditBox() const = 0; //! set the current value of the spinbox /** \param val: value to be set in the spinbox */ virtual void setValue(f32 val) = 0; //! Get the current value of the spinbox virtual f32 getValue() const = 0; //! set the range of values which can be used in the spinbox /** \param min: minimum value \param max: maximum value */ virtual void setRange(f32 min, f32 max) = 0; //! get the minimum value which can be used in the spinbox virtual f32 getMin() const = 0; //! get the maximum value which can be used in the spinbox virtual f32 getMax() const = 0; //! Step size by which values are changed when pressing the spinbuttons /** The step size also determines the number of decimal places to display \param step: stepsize used for value changes when pressing spinbuttons */ virtual void setStepSize(f32 step=1.f) = 0; //! Sets the number of decimal places to display. //! Note that this also rounds the range to the same number of decimal places. /** \param places: The number of decimal places to display, use -1 to reset */ virtual void setDecimalPlaces(s32 places) = 0; //! get the current step size virtual f32 getStepSize() const = 0; }; } // end namespace gui } // end namespace irr #endif // __I_GUI_SPIN_BOX_H_INCLUDED__ irrlicht-1.8.3/include/IGUISkin.h0000644000000000000000000004622212574354552015241 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_SKIN_H_INCLUDED__ #define __I_GUI_SKIN_H_INCLUDED__ #include "IAttributeExchangingObject.h" #include "EGUIAlignment.h" #include "SColor.h" #include "rect.h" namespace irr { namespace gui { class IGUIFont; class IGUISpriteBank; class IGUIElement; //! Enumeration of available default skins. /** To set one of the skins, use the following code, for example to set the Windows classic skin: \code gui::IGUISkin* newskin = environment->createSkin(gui::EGST_WINDOWS_CLASSIC); environment->setSkin(newskin); newskin->drop(); \endcode */ enum EGUI_SKIN_TYPE { //! Default windows look and feel EGST_WINDOWS_CLASSIC=0, //! Like EGST_WINDOWS_CLASSIC, but with metallic shaded windows and buttons EGST_WINDOWS_METALLIC, //! Burning's skin EGST_BURNING_SKIN, //! An unknown skin, not serializable at present EGST_UNKNOWN, //! this value is not used, it only specifies the number of skin types EGST_COUNT }; //! Names for gui element types const c8* const GUISkinTypeNames[EGST_COUNT+1] = { "windowsClassic", "windowsMetallic", "burning", "unknown", 0, }; //! Enumeration for skin colors enum EGUI_DEFAULT_COLOR { //! Dark shadow for three-dimensional display elements. EGDC_3D_DARK_SHADOW = 0, //! Shadow color for three-dimensional display elements (for edges facing away from the light source). EGDC_3D_SHADOW, //! Face color for three-dimensional display elements and for dialog box backgrounds. EGDC_3D_FACE, //! Highlight color for three-dimensional display elements (for edges facing the light source.) EGDC_3D_HIGH_LIGHT, //! Light color for three-dimensional display elements (for edges facing the light source.) EGDC_3D_LIGHT, //! Active window border. EGDC_ACTIVE_BORDER, //! Active window title bar text. EGDC_ACTIVE_CAPTION, //! Background color of multiple document interface (MDI) applications. EGDC_APP_WORKSPACE, //! Text on a button EGDC_BUTTON_TEXT, //! Grayed (disabled) text. EGDC_GRAY_TEXT, //! Item(s) selected in a control. EGDC_HIGH_LIGHT, //! Text of item(s) selected in a control. EGDC_HIGH_LIGHT_TEXT, //! Inactive window border. EGDC_INACTIVE_BORDER, //! Inactive window caption. EGDC_INACTIVE_CAPTION, //! Tool tip text color EGDC_TOOLTIP, //! Tool tip background color EGDC_TOOLTIP_BACKGROUND, //! Scrollbar gray area EGDC_SCROLLBAR, //! Window background EGDC_WINDOW, //! Window symbols like on close buttons, scroll bars and check boxes EGDC_WINDOW_SYMBOL, //! Icons in a list or tree EGDC_ICON, //! Selected icons in a list or tree EGDC_ICON_HIGH_LIGHT, //! Grayed (disabled) window symbols like on close buttons, scroll bars and check boxes EGDC_GRAY_WINDOW_SYMBOL, //! Window background for editable field (editbox, checkbox-field) EGDC_EDITABLE, //! Grayed (disabled) window background for editable field (editbox, checkbox-field) EGDC_GRAY_EDITABLE, //! Show focus of window background for editable field (editbox or when checkbox-field is pressed) EGDC_FOCUSED_EDITABLE, //! this value is not used, it only specifies the amount of default colors //! available. EGDC_COUNT }; //! Names for default skin colors const c8* const GUISkinColorNames[EGDC_COUNT+1] = { "3DDarkShadow", "3DShadow", "3DFace", "3DHighlight", "3DLight", "ActiveBorder", "ActiveCaption", "AppWorkspace", "ButtonText", "GrayText", "Highlight", "HighlightText", "InactiveBorder", "InactiveCaption", "ToolTip", "ToolTipBackground", "ScrollBar", "Window", "WindowSymbol", "Icon", "IconHighlight", "GrayWindowSymbol", "Editable", "GrayEditable", "FocusedEditable", 0, }; //! Enumeration for default sizes. enum EGUI_DEFAULT_SIZE { //! default with / height of scrollbar EGDS_SCROLLBAR_SIZE = 0, //! height of menu EGDS_MENU_HEIGHT, //! width of a window button EGDS_WINDOW_BUTTON_WIDTH, //! width of a checkbox check EGDS_CHECK_BOX_WIDTH, //! \deprecated This may be removed by Irrlicht 1.9 EGDS_MESSAGE_BOX_WIDTH, //! \deprecated This may be removed by Irrlicht 1.9 EGDS_MESSAGE_BOX_HEIGHT, //! width of a default button EGDS_BUTTON_WIDTH, //! height of a default button EGDS_BUTTON_HEIGHT, //! distance for text from background EGDS_TEXT_DISTANCE_X, //! distance for text from background EGDS_TEXT_DISTANCE_Y, //! distance for text in the title bar, from the left of the window rect EGDS_TITLEBARTEXT_DISTANCE_X, //! distance for text in the title bar, from the top of the window rect EGDS_TITLEBARTEXT_DISTANCE_Y, //! free space in a messagebox between borders and contents on all sides EGDS_MESSAGE_BOX_GAP_SPACE, //! minimal space to reserve for messagebox text-width EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH, //! maximal space to reserve for messagebox text-width EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH, //! minimal space to reserve for messagebox text-height EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT, //! maximal space to reserve for messagebox text-height EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT, //! pixels to move the button image to the right when a pushbutton is pressed EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X, //! pixels to move the button image down when a pushbutton is pressed EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y, //! pixels to move the button text to the right when a pushbutton is pressed EGDS_BUTTON_PRESSED_TEXT_OFFSET_X, //! pixels to move the button text down when a pushbutton is pressed EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y, //! this value is not used, it only specifies the amount of default sizes //! available. EGDS_COUNT }; //! Names for default skin sizes const c8* const GUISkinSizeNames[EGDS_COUNT+1] = { "ScrollBarSize", "MenuHeight", "WindowButtonWidth", "CheckBoxWidth", "MessageBoxWidth", "MessageBoxHeight", "ButtonWidth", "ButtonHeight", "TextDistanceX", "TextDistanceY", "TitleBarTextX", "TitleBarTextY", "MessageBoxGapSpace", "MessageBoxMinTextWidth", "MessageBoxMaxTextWidth", "MessageBoxMinTextHeight", "MessageBoxMaxTextHeight", "ButtonPressedImageOffsetX", "ButtonPressedImageOffsetY", "ButtonPressedTextOffsetX", "ButtonPressedTextOffsetY", 0 }; enum EGUI_DEFAULT_TEXT { //! Text for the OK button on a message box EGDT_MSG_BOX_OK = 0, //! Text for the Cancel button on a message box EGDT_MSG_BOX_CANCEL, //! Text for the Yes button on a message box EGDT_MSG_BOX_YES, //! Text for the No button on a message box EGDT_MSG_BOX_NO, //! Tooltip text for window close button EGDT_WINDOW_CLOSE, //! Tooltip text for window maximize button EGDT_WINDOW_MAXIMIZE, //! Tooltip text for window minimize button EGDT_WINDOW_MINIMIZE, //! Tooltip text for window restore button EGDT_WINDOW_RESTORE, //! this value is not used, it only specifies the number of default texts EGDT_COUNT }; //! Names for default skin sizes const c8* const GUISkinTextNames[EGDT_COUNT+1] = { "MessageBoxOkay", "MessageBoxCancel", "MessageBoxYes", "MessageBoxNo", "WindowButtonClose", "WindowButtonMaximize", "WindowButtonMinimize", "WindowButtonRestore", 0 }; //! Customizable symbols for GUI enum EGUI_DEFAULT_ICON { //! maximize window button EGDI_WINDOW_MAXIMIZE = 0, //! restore window button EGDI_WINDOW_RESTORE, //! close window button EGDI_WINDOW_CLOSE, //! minimize window button EGDI_WINDOW_MINIMIZE, //! resize icon for bottom right corner of a window EGDI_WINDOW_RESIZE, //! scroll bar up button EGDI_CURSOR_UP, //! scroll bar down button EGDI_CURSOR_DOWN, //! scroll bar left button EGDI_CURSOR_LEFT, //! scroll bar right button EGDI_CURSOR_RIGHT, //! icon for menu children EGDI_MENU_MORE, //! tick for checkbox EGDI_CHECK_BOX_CHECKED, //! down arrow for dropdown menus EGDI_DROP_DOWN, //! smaller up arrow EGDI_SMALL_CURSOR_UP, //! smaller down arrow EGDI_SMALL_CURSOR_DOWN, //! selection dot in a radio button EGDI_RADIO_BUTTON_CHECKED, //! << icon indicating there is more content to the left EGDI_MORE_LEFT, //! >> icon indicating that there is more content to the right EGDI_MORE_RIGHT, //! icon indicating that there is more content above EGDI_MORE_UP, //! icon indicating that there is more content below EGDI_MORE_DOWN, //! plus icon for trees EGDI_EXPAND, //! minus icon for trees EGDI_COLLAPSE, //! file icon for file selection EGDI_FILE, //! folder icon for file selection EGDI_DIRECTORY, //! value not used, it only specifies the number of icons EGDI_COUNT }; const c8* const GUISkinIconNames[EGDI_COUNT+1] = { "windowMaximize", "windowRestore", "windowClose", "windowMinimize", "windowResize", "cursorUp", "cursorDown", "cursorLeft", "cursorRight", "menuMore", "checkBoxChecked", "dropDown", "smallCursorUp", "smallCursorDown", "radioButtonChecked", "moreLeft", "moreRight", "moreUp", "moreDown", "expand", "collapse", "file", "directory", 0 }; // Customizable fonts enum EGUI_DEFAULT_FONT { //! For static text, edit boxes, lists and most other places EGDF_DEFAULT=0, //! Font for buttons EGDF_BUTTON, //! Font for window title bars EGDF_WINDOW, //! Font for menu items EGDF_MENU, //! Font for tooltips EGDF_TOOLTIP, //! this value is not used, it only specifies the amount of default fonts //! available. EGDF_COUNT }; const c8* const GUISkinFontNames[EGDF_COUNT+1] = { "defaultFont", "buttonFont", "windowFont", "menuFont", "tooltipFont", 0 }; //! A skin modifies the look of the GUI elements. class IGUISkin : public virtual io::IAttributeExchangingObject { public: //! returns default color virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const = 0; //! sets a default color virtual void setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor) = 0; //! returns size for the given size type virtual s32 getSize(EGUI_DEFAULT_SIZE size) const = 0; //! Returns a default text. /** For example for Message box button captions: "OK", "Cancel", "Yes", "No" and so on. */ virtual const wchar_t* getDefaultText(EGUI_DEFAULT_TEXT text) const = 0; //! Sets a default text. /** For example for Message box button captions: "OK", "Cancel", "Yes", "No" and so on. */ virtual void setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText) = 0; //! sets a default size virtual void setSize(EGUI_DEFAULT_SIZE which, s32 size) = 0; //! returns the default font virtual IGUIFont* getFont(EGUI_DEFAULT_FONT which=EGDF_DEFAULT) const = 0; //! sets a default font virtual void setFont(IGUIFont* font, EGUI_DEFAULT_FONT which=EGDF_DEFAULT) = 0; //! returns the sprite bank virtual IGUISpriteBank* getSpriteBank() const = 0; //! sets the sprite bank virtual void setSpriteBank(IGUISpriteBank* bank) = 0; //! Returns a default icon /** Returns the sprite index within the sprite bank */ virtual u32 getIcon(EGUI_DEFAULT_ICON icon) const = 0; //! Sets a default icon /** Sets the sprite index used for drawing icons like arrows, close buttons and ticks in checkboxes \param icon: Enum specifying which icon to change \param index: The sprite index used to draw this icon */ virtual void setIcon(EGUI_DEFAULT_ICON icon, u32 index) = 0; //! draws a standard 3d button pane /** Used for drawing for example buttons in normal state. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DButtonPaneStandard(IGUIElement* element, const core::rect& rect, const core::rect* clip=0) = 0; //! draws a pressed 3d button pane /** Used for drawing for example buttons in pressed state. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DButtonPanePressed(IGUIElement* element, const core::rect& rect, const core::rect* clip=0) = 0; //! draws a sunken 3d pane /** Used for drawing the background of edit, combo or check boxes. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param bgcolor: Background color. \param flat: Specifies if the sunken pane should be flat or displayed as sunken deep into the ground. \param fillBackGround: Specifies if the background should be filled with the background color or not be drawn at all. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DSunkenPane(IGUIElement* element, video::SColor bgcolor, bool flat, bool fillBackGround, const core::rect& rect, const core::rect* clip=0) = 0; //! draws a window background /** Used for drawing the background of dialogs and windows. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param titleBarColor: Title color. \param drawTitleBar: True to enable title drawing. \param rect: Defining area where to draw. \param clip: Clip area. \param checkClientArea: When set to non-null the function will not draw anything, but will instead return the clientArea which can be used for drawing by the calling window. That is the area without borders and without titlebar. \return Returns rect where it would be good to draw title bar text. This will work even when checkClientArea is set to a non-null value.*/ virtual core::rect draw3DWindowBackground(IGUIElement* element, bool drawTitleBar, video::SColor titleBarColor, const core::rect& rect, const core::rect* clip=0, core::rect* checkClientArea=0) = 0; //! draws a standard 3d menu pane /** Used for drawing for menus and context menus. It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DMenuPane(IGUIElement* element, const core::rect& rect, const core::rect* clip=0) = 0; //! draws a standard 3d tool bar /** Used for drawing for toolbars and menus. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param rect: Defining area where to draw. \param clip: Clip area. */ virtual void draw3DToolBar(IGUIElement* element, const core::rect& rect, const core::rect* clip=0) = 0; //! draws a tab button /** Used for drawing for tab buttons on top of tabs. \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param active: Specifies if the tab is currently active. \param rect: Defining area where to draw. \param clip: Clip area. \param alignment Alignment of GUI element. */ virtual void draw3DTabButton(IGUIElement* element, bool active, const core::rect& rect, const core::rect* clip=0, gui::EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT) = 0; //! draws a tab control body /** \param element: Pointer to the element which wishes to draw this. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param border: Specifies if the border should be drawn. \param background: Specifies if the background should be drawn. \param rect: Defining area where to draw. \param clip: Clip area. \param tabHeight Height of tab. \param alignment Alignment of GUI element. */ virtual void draw3DTabBody(IGUIElement* element, bool border, bool background, const core::rect& rect, const core::rect* clip=0, s32 tabHeight=-1, gui::EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT ) = 0; //! draws an icon, usually from the skin's sprite bank /** \param element: Pointer to the element which wishes to draw this icon. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param icon: Specifies the icon to be drawn. \param position: The position to draw the icon \param starttime: The time at the start of the animation \param currenttime: The present time, used to calculate the frame number \param loop: Whether the animation should loop or not \param clip: Clip area. */ virtual void drawIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon, const core::position2di position, u32 starttime=0, u32 currenttime=0, bool loop=false, const core::rect* clip=0) = 0; //! draws a 2d rectangle. /** \param element: Pointer to the element which wishes to draw this icon. This parameter is usually not used by IGUISkin, but can be used for example by more complex implementations to find out how to draw the part exactly. \param color: Color of the rectangle to draw. The alpha component specifies how transparent the rectangle will be. \param pos: Position of the rectangle. \param clip: Pointer to rectangle against which the rectangle will be clipped. If the pointer is null, no clipping will be performed. */ virtual void draw2DRectangle(IGUIElement* element, const video::SColor &color, const core::rect& pos, const core::rect* clip = 0) = 0; //! get the type of this skin virtual EGUI_SKIN_TYPE getType() const { return EGST_UNKNOWN; } }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIScrollBar.h0000644000000000000000000000350212574354552016212 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_SCROLL_BAR_H_INCLUDED__ #define __I_GUI_SCROLL_BAR_H_INCLUDED__ #include "IGUIElement.h" namespace irr { namespace gui { //! Default scroll bar GUI element. /** \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_SCROLL_BAR_CHANGED */ class IGUIScrollBar : public IGUIElement { public: //! constructor IGUIScrollBar(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_SCROLL_BAR, environment, parent, id, rectangle) {} //! sets the maximum value of the scrollbar. virtual void setMax(s32 max) = 0; //! gets the maximum value of the scrollbar. virtual s32 getMax() const = 0; //! sets the minimum value of the scrollbar. virtual void setMin(s32 min) = 0; //! gets the minimum value of the scrollbar. virtual s32 getMin() const = 0; //! gets the small step value virtual s32 getSmallStep() const = 0; //! Sets the small step /** That is the amount that the value changes by when clicking on the buttons or using the cursor keys. */ virtual void setSmallStep(s32 step) = 0; //! gets the large step value virtual s32 getLargeStep() const = 0; //! Sets the large step /** That is the amount that the value changes by when clicking in the tray, or using the page up and page down keys. */ virtual void setLargeStep(s32 step) = 0; //! gets the current position of the scrollbar virtual s32 getPos() const = 0; //! sets the current position of the scrollbar virtual void setPos(s32 pos) = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIMeshViewer.h0000644000000000000000000000224712574354552016412 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_MESH_VIEWER_H_INCLUDED__ #define __I_GUI_MESH_VIEWER_H_INCLUDED__ #include "IGUIElement.h" namespace irr { namespace video { class SMaterial; } // end namespace video namespace scene { class IAnimatedMesh; } // end namespace scene namespace gui { //! 3d mesh viewing GUI element. class IGUIMeshViewer : public IGUIElement { public: //! constructor IGUIMeshViewer(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_MESH_VIEWER, environment, parent, id, rectangle) {} //! Sets the mesh to be shown virtual void setMesh(scene::IAnimatedMesh* mesh) = 0; //! Gets the displayed mesh virtual scene::IAnimatedMesh* getMesh() const = 0; //! Sets the material virtual void setMaterial(const video::SMaterial& material) = 0; //! Gets the material virtual const video::SMaterial& getMaterial() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIListBox.h0000644000000000000000000001133712574354552015720 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_LIST_BOX_H_INCLUDED__ #define __I_GUI_LIST_BOX_H_INCLUDED__ #include "IGUIElement.h" #include "SColor.h" namespace irr { namespace gui { class IGUISpriteBank; //! Enumeration for listbox colors enum EGUI_LISTBOX_COLOR { //! Color of text EGUI_LBC_TEXT=0, //! Color of selected text EGUI_LBC_TEXT_HIGHLIGHT, //! Color of icon EGUI_LBC_ICON, //! Color of selected icon EGUI_LBC_ICON_HIGHLIGHT, //! Not used, just counts the number of available colors EGUI_LBC_COUNT }; //! Default list box GUI element. /** \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_LISTBOX_CHANGED \li EGET_LISTBOX_SELECTED_AGAIN */ class IGUIListBox : public IGUIElement { public: //! constructor IGUIListBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_LIST_BOX, environment, parent, id, rectangle) {} //! returns amount of list items virtual u32 getItemCount() const = 0; //! returns string of a list item. the may id be a value from 0 to itemCount-1 virtual const wchar_t* getListItem(u32 id) const = 0; //! adds an list item, returns id of item virtual u32 addItem(const wchar_t* text) = 0; //! adds an list item with an icon /** \param text Text of list entry \param icon Sprite index of the Icon within the current sprite bank. Set it to -1 if you want no icon \return The id of the new created item */ virtual u32 addItem(const wchar_t* text, s32 icon) = 0; //! Removes an item from the list virtual void removeItem(u32 index) = 0; //! get the the id of the item at the given absolute coordinates /** \return The id of the listitem or -1 when no item is at those coordinates*/ virtual s32 getItemAt(s32 xpos, s32 ypos) const = 0; //! Returns the icon of an item virtual s32 getIcon(u32 index) const = 0; //! Sets the sprite bank which should be used to draw list icons. /** This font is set to the sprite bank of the built-in-font by default. A sprite can be displayed in front of every list item. An icon is an index within the icon sprite bank. Several default icons are available in the skin through getIcon. */ virtual void setSpriteBank(IGUISpriteBank* bank) = 0; //! clears the list, deletes all items in the listbox virtual void clear() = 0; //! returns id of selected item. returns -1 if no item is selected. virtual s32 getSelected() const = 0; //! sets the selected item. Set this to -1 if no item should be selected virtual void setSelected(s32 index) = 0; //! sets the selected item. Set this to 0 if no item should be selected virtual void setSelected(const wchar_t *item) = 0; //! set whether the listbox should scroll to newly selected items virtual void setAutoScrollEnabled(bool scroll) = 0; //! returns true if automatic scrolling is enabled, false if not. virtual bool isAutoScrollEnabled() const = 0; //! set all item colors at given index to color virtual void setItemOverrideColor(u32 index, video::SColor color) = 0; //! set all item colors of specified type at given index to color virtual void setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color) = 0; //! clear all item colors at index virtual void clearItemOverrideColor(u32 index) = 0; //! clear item color at index for given colortype virtual void clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) = 0; //! has the item at index its color overwritten? virtual bool hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const = 0; //! return the overwrite color at given item index. virtual video::SColor getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const = 0; //! return the default color which is used for the given colorType virtual video::SColor getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const = 0; //! set the item at the given index virtual void setItem(u32 index, const wchar_t* text, s32 icon) = 0; //! Insert the item at the given index /** \return The index on success or -1 on failure. */ virtual s32 insertItem(u32 index, const wchar_t* text, s32 icon) = 0; //! Swap the items at the given indices virtual void swapItems(u32 index1, u32 index2) = 0; //! set global itemHeight virtual void setItemHeight( s32 height ) = 0; //! Sets whether to draw the background virtual void setDrawBackground(bool draw) = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIInOutFader.h0000644000000000000000000000431712574354552016334 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_IN_OUT_FADER_H_INCLUDED__ #define __I_GUI_IN_OUT_FADER_H_INCLUDED__ #include "IGUIElement.h" #include "SColor.h" namespace irr { namespace gui { //! Element for fading out or in /** Here is a small example on how the class is used. In this example we fade in from a total red screen in the beginning. As you can see, the fader is not only useful for dramatic in and out fading, but also to show that the player is hit in a first person shooter game for example. \code gui::IGUIInOutFader* fader = device->getGUIEnvironment()->addInOutFader(); fader->setColor(video::SColor(0,255,0,0)); fader->fadeIn(4000); \endcode */ class IGUIInOutFader : public IGUIElement { public: //! constructor IGUIInOutFader(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_IN_OUT_FADER, environment, parent, id, rectangle) {} //! Gets the color to fade out to or to fade in from. virtual video::SColor getColor() const = 0; //! Sets the color to fade out to or to fade in from. /** \param color: Color to where it is faded out od from it is faded in. */ virtual void setColor(video::SColor color) = 0; virtual void setColor(video::SColor source, video::SColor dest) = 0; //! Starts the fade in process. /** In the beginning the whole rect is drawn by the set color (black by default) and at the end of the overgiven time the color has faded out. \param time: Time specifying how long it should need to fade in, in milliseconds. */ virtual void fadeIn(u32 time) = 0; //! Starts the fade out process. /** In the beginning everything is visible, and at the end of the time only the set color (black by the fault) will be drawn. \param time: Time specifying how long it should need to fade out, in milliseconds. */ virtual void fadeOut(u32 time) = 0; //! Returns if the fade in or out process is done. virtual bool isReady() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIImageList.h0000644000000000000000000000234212574354552016206 0ustar rootroot// This file is part of the "Irrlicht Engine". // written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de #ifndef __I_GUI_IMAGE_LIST_H_INCLUDED__ #define __I_GUI_IMAGE_LIST_H_INCLUDED__ #include "IGUIElement.h" #include "rect.h" #include "irrTypes.h" namespace irr { namespace gui { //! Font interface. class IGUIImageList : public virtual IReferenceCounted { public: //! Destructor virtual ~IGUIImageList() {}; //! Draws an image and clips it to the specified rectangle if wanted //! \param index: Index of the image //! \param destPos: Position of the image to draw //! \param clip: Optional pointer to a rectalgle against which the text will be clipped. //! If the pointer is null, no clipping will be done. virtual void draw(s32 index, const core::position2d& destPos, const core::rect* clip = 0) = 0; //! Returns the count of Images in the list. //! \return Returns the count of Images in the list. virtual s32 getImageCount() const = 0; //! Returns the size of the images in the list. //! \return Returns the size of the images in the list. virtual core::dimension2d getImageSize() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIImage.h0000644000000000000000000000274312574354552015357 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_IMAGE_H_INCLUDED__ #define __I_GUI_IMAGE_H_INCLUDED__ #include "IGUIElement.h" namespace irr { namespace video { class ITexture; } namespace gui { //! GUI element displaying an image. class IGUIImage : public IGUIElement { public: //! constructor IGUIImage(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_IMAGE, environment, parent, id, rectangle) {} //! Sets an image texture virtual void setImage(video::ITexture* image) = 0; //! Gets the image texture virtual video::ITexture* getImage() const = 0; //! Sets the color of the image virtual void setColor(video::SColor color) = 0; //! Sets if the image should scale to fit the element virtual void setScaleImage(bool scale) = 0; //! Sets if the image should use its alpha channel to draw itself virtual void setUseAlphaChannel(bool use) = 0; //! Gets the color of the image virtual video::SColor getColor() const = 0; //! Returns true if the image is scaled to fit, false if not virtual bool isImageScaled() const = 0; //! Returns true if the image is using the alpha channel, false if not virtual bool isAlphaChannelUsed() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIFontBitmap.h0000644000000000000000000000302712574354552016374 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_FONT_BITMAP_H_INCLUDED__ #define __I_GUI_FONT_BITMAP_H_INCLUDED__ #include "IGUIFont.h" namespace irr { namespace gui { class IGUISpriteBank; //! Font interface. class IGUIFontBitmap : public IGUIFont { public: //! Returns the type of this font virtual EGUI_FONT_TYPE getType() const { return EGFT_BITMAP; } //! returns the parsed Symbol Information virtual IGUISpriteBank* getSpriteBank() const = 0; //! returns the sprite number from a given character virtual u32 getSpriteNoFromChar(const wchar_t *c) const = 0; //! Gets kerning values (distance between letters) for the font. If no parameters are provided, /** the global kerning distance is returned. \param thisLetter: If this parameter is provided, the left side kerning for this letter is added to the global kerning value. For example, a space might only be one pixel wide, but it may be displayed as several pixels. \param previousLetter: If provided, kerning is calculated for both letters and added to the global kerning value. For example, EGFT_BITMAP will add the right kerning value of previousLetter to the left side kerning value of thisLetter, then add the global value. */ virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIFont.h0000644000000000000000000000751712574354552015247 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_FONT_H_INCLUDED__ #define __I_GUI_FONT_H_INCLUDED__ #include "IReferenceCounted.h" #include "SColor.h" #include "rect.h" #include "irrString.h" namespace irr { namespace gui { //! An enum for the different types of GUI font. enum EGUI_FONT_TYPE { //! Bitmap fonts loaded from an XML file or a texture. EGFT_BITMAP = 0, //! Scalable vector fonts loaded from an XML file. /** These fonts reside in system memory and use no video memory until they are displayed. These are slower than bitmap fonts but can be easily scaled and rotated. */ EGFT_VECTOR, //! A font which uses a the native API provided by the operating system. /** Currently not used. */ EGFT_OS, //! An external font type provided by the user. EGFT_CUSTOM }; //! Font interface. class IGUIFont : public virtual IReferenceCounted { public: //! Draws some text and clips it to the specified rectangle if wanted. /** \param text: Text to draw \param position: Rectangle specifying position where to draw the text. \param color: Color of the text \param hcenter: Specifies if the text should be centered horizontally into the rectangle. \param vcenter: Specifies if the text should be centered vertically into the rectangle. \param clip: Optional pointer to a rectangle against which the text will be clipped. If the pointer is null, no clipping will be done. */ virtual void draw(const core::stringw& text, const core::rect& position, video::SColor color, bool hcenter=false, bool vcenter=false, const core::rect* clip=0) = 0; //! Calculates the width and height of a given string of text. /** \return Returns width and height of the area covered by the text if it would be drawn. */ virtual core::dimension2d getDimension(const wchar_t* text) const = 0; //! Calculates the index of the character in the text which is on a specific position. /** \param text: Text string. \param pixel_x: X pixel position of which the index of the character will be returned. \return Returns zero based index of the character in the text, and -1 if no no character is on this position. (=the text is too short). */ virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const = 0; //! Returns the type of this font virtual EGUI_FONT_TYPE getType() const { return EGFT_CUSTOM; } //! Sets global kerning width for the font. virtual void setKerningWidth (s32 kerning) = 0; //! Sets global kerning height for the font. virtual void setKerningHeight (s32 kerning) = 0; //! Gets kerning values (distance between letters) for the font. If no parameters are provided, /** the global kerning distance is returned. \param thisLetter: If this parameter is provided, the left side kerning for this letter is added to the global kerning value. For example, a space might only be one pixel wide, but it may be displayed as several pixels. \param previousLetter: If provided, kerning is calculated for both letters and added to the global kerning value. For example, in a font which supports kerning pairs a string such as 'Wo' may have the 'o' tucked neatly under the 'W'. */ virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const = 0; //! Returns the distance between letters virtual s32 getKerningHeight() const = 0; //! Define which characters should not be drawn by the font. /** For example " " would not draw any space which is usually blank in most fonts. \param s String of symbols which are not send down to the videodriver */ virtual void setInvisibleCharacters( const wchar_t *s ) = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIFileOpenDialog.h0000644000000000000000000000242012574354552017146 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_FILE_OPEN_DIALOG_H_INCLUDED__ #define __I_GUI_FILE_OPEN_DIALOG_H_INCLUDED__ #include "IGUIElement.h" #include "path.h" namespace irr { namespace gui { //! Standard file chooser dialog. /** \warning When the user selects a folder this does change the current working directory \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_DIRECTORY_SELECTED \li EGET_FILE_SELECTED \li EGET_FILE_CHOOSE_DIALOG_CANCELLED */ class IGUIFileOpenDialog : public IGUIElement { public: //! constructor IGUIFileOpenDialog(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_FILE_OPEN_DIALOG, environment, parent, id, rectangle) {} //! Returns the filename of the selected file. Returns NULL, if no file was selected. virtual const wchar_t* getFileName() const = 0; //! Returns the directory of the selected file. Returns NULL, if no directory was selected. virtual const io::path& getDirectoryName() = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIEnvironment.h0000644000000000000000000007027512574354552016646 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_ENVIRONMENT_H_INCLUDED__ #define __I_GUI_ENVIRONMENT_H_INCLUDED__ #include "IReferenceCounted.h" #include "IGUISkin.h" #include "rect.h" #include "EMessageBoxFlags.h" #include "IEventReceiver.h" #include "IXMLReader.h" #include "path.h" namespace irr { class IOSOperator; class IEventReceiver; namespace io { class IXMLWriter; class IReadFile; class IWriteFile; class IFileSystem; } // end namespace io namespace video { class IVideoDriver; class ITexture; } // end namespace video namespace gui { class IGUIElement; class IGUIFont; class IGUISpriteBank; class IGUIScrollBar; class IGUIImage; class IGUIMeshViewer; class IGUICheckBox; class IGUIListBox; class IGUITreeView; class IGUIImageList; class IGUIFileOpenDialog; class IGUIColorSelectDialog; class IGUIInOutFader; class IGUIStaticText; class IGUIEditBox; class IGUISpinBox; class IGUITabControl; class IGUITab; class IGUITable; class IGUIContextMenu; class IGUIComboBox; class IGUIToolBar; class IGUIButton; class IGUIWindow; class IGUIElementFactory; //! GUI Environment. Used as factory and manager of all other GUI elements. /** \par This element can create the following events of type EGUI_EVENT_TYPE (which are passed on to focused sub-elements): \li EGET_ELEMENT_FOCUS_LOST \li EGET_ELEMENT_FOCUSED \li EGET_ELEMENT_LEFT \li EGET_ELEMENT_HOVERED */ class IGUIEnvironment : public virtual IReferenceCounted { public: //! Draws all gui elements by traversing the GUI environment starting at the root node. virtual void drawAll() = 0; //! Sets the focus to an element. /** Causes a EGET_ELEMENT_FOCUS_LOST event followed by a EGET_ELEMENT_FOCUSED event. If someone absorbed either of the events, then the focus will not be changed. \param element Pointer to the element which shall get the focus. \return True on success, false on failure */ virtual bool setFocus(IGUIElement* element) = 0; //! Returns the element which holds the focus. /** \return Pointer to the element with focus. */ virtual IGUIElement* getFocus() const = 0; //! Returns the element which was last under the mouse cursor /** NOTE: This information is updated _after_ the user-eventreceiver received it's mouse-events. To find the hovered element while catching mouse events you have to use instead: IGUIEnvironment::getRootGUIElement()->getElementFromPoint(mousePos); \return Pointer to the element under the mouse. */ virtual IGUIElement* getHovered() const = 0; //! Removes the focus from an element. /** Causes a EGET_ELEMENT_FOCUS_LOST event. If the event is absorbed then the focus will not be changed. \param element Pointer to the element which shall lose the focus. \return True on success, false on failure */ virtual bool removeFocus(IGUIElement* element) = 0; //! Returns whether the element has focus /** \param element Pointer to the element which is tested. \return True if the element has focus, else false. */ virtual bool hasFocus(IGUIElement* element) const = 0; //! Returns the current video driver. /** \return Pointer to the video driver. */ virtual video::IVideoDriver* getVideoDriver() const = 0; //! Returns the file system. /** \return Pointer to the file system. */ virtual io::IFileSystem* getFileSystem() const = 0; //! returns a pointer to the OS operator /** \return Pointer to the OS operator. */ virtual IOSOperator* getOSOperator() const = 0; //! Removes all elements from the environment. virtual void clear() = 0; //! Posts an input event to the environment. /** Usually you do not have to use this method, it is used by the engine internally. \param event The event to post. \return True if succeeded, else false. */ virtual bool postEventFromUser(const SEvent& event) = 0; //! This sets a new event receiver for gui events. /** Usually you do not have to use this method, it is used by the engine internally. \param evr Pointer to the new receiver. */ virtual void setUserEventReceiver(IEventReceiver* evr) = 0; //! Returns pointer to the current gui skin. /** \return Pointer to the GUI skin. */ virtual IGUISkin* getSkin() const = 0; //! Sets a new GUI Skin /** You can use this to change the appearance of the whole GUI Environment. You can set one of the built-in skins or implement your own class derived from IGUISkin and enable it using this method. To set for example the built-in Windows classic skin, use the following code: \code gui::IGUISkin* newskin = environment->createSkin(gui::EGST_WINDOWS_CLASSIC); environment->setSkin(newskin); newskin->drop(); \endcode \param skin New skin to use. */ virtual void setSkin(IGUISkin* skin) = 0; //! Creates a new GUI Skin based on a template. /** Use setSkin() to set the created skin. \param type The type of the new skin. \return Pointer to the created skin. If you no longer need it, you should call IGUISkin::drop(). See IReferenceCounted::drop() for more information. */ virtual IGUISkin* createSkin(EGUI_SKIN_TYPE type) = 0; //! Creates the image list from the given texture. /** \param texture Texture to split into images \param imageSize Dimension of each image \param useAlphaChannel Flag whether alpha channel of the texture should be honored. \return Pointer to the font. Returns 0 if the font could not be loaded. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIImageList* createImageList( video::ITexture* texture, core::dimension2d imageSize, bool useAlphaChannel ) = 0; //! Returns pointer to the font with the specified filename. /** Loads the font if it was not loaded before. \param filename Filename of the Font. \return Pointer to the font. Returns 0 if the font could not be loaded. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIFont* getFont(const io::path& filename) = 0; //! Adds an externally loaded font to the font list. /** This method allows to attach an already loaded font to the list of existing fonts. The font is grabbed if non-null and adding was successful. \param name Name the font should be stored as. \param font Pointer to font to add. \return Pointer to the font stored. This can differ from given parameter if the name previously existed. */ virtual IGUIFont* addFont(const io::path& name, IGUIFont* font) = 0; //! remove loaded font virtual void removeFont(IGUIFont* font) = 0; //! Returns the default built-in font. /** \return Pointer to the default built-in font. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIFont* getBuiltInFont() const = 0; //! Returns pointer to the sprite bank with the specified file name. /** Loads the bank if it was not loaded before. \param filename Filename of the sprite bank's origin. \return Pointer to the sprite bank. Returns 0 if it could not be loaded. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUISpriteBank* getSpriteBank(const io::path& filename) = 0; //! Adds an empty sprite bank to the manager /** \param name Name of the new sprite bank. \return Pointer to the sprite bank. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUISpriteBank* addEmptySpriteBank(const io::path& name) = 0; //! Returns the root gui element. /** This is the first gui element, the (direct or indirect) parent of all other gui elements. It is a valid IGUIElement, with dimensions the same size as the screen. \return Pointer to the root element of the GUI. The returned pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIElement* getRootGUIElement() = 0; //! Adds a button element. /** \param rectangle Rectangle specifying the borders of the button. \param parent Parent gui element of the button. \param id Id with which the gui element can be identified. \param text Text displayed on the button. \param tooltiptext Text displayed in the tooltip. \return Pointer to the created button. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIButton* addButton(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0, const wchar_t* tooltiptext = 0) = 0; //! Adds an empty window element. /** \param rectangle Rectangle specifying the borders of the window. \param modal Defines if the dialog is modal. This means, that all other gui elements which were created before the window cannot be used until it is removed. \param text Text displayed as the window title. \param parent Parent gui element of the window. \param id Id with which the gui element can be identified. \return Pointer to the created window. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIWindow* addWindow(const core::rect& rectangle, bool modal = false, const wchar_t* text=0, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a modal screen. /** This control stops its parent's members from being able to receive input until its last child is removed, it then deletes itself. \param parent Parent gui element of the modal. \return Pointer to the created modal. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIElement* addModalScreen(IGUIElement* parent) = 0; //! Adds a message box. /** \param caption Text to be displayed the title of the message box. \param text Text to be displayed in the body of the message box. \param modal Defines if the dialog is modal. This means, that all other gui elements which were created before the message box cannot be used until this messagebox is removed. \param flags Flags specifying the layout of the message box. For example to create a message box with an OK and a CANCEL button on it, set this to (EMBF_OK | EMBF_CANCEL). \param parent Parent gui element of the message box. \param id Id with which the gui element can be identified. \param image Optional texture which will be displayed beside the text as an image \return Pointer to the created message box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIWindow* addMessageBox(const wchar_t* caption, const wchar_t* text=0, bool modal = true, s32 flags = EMBF_OK, IGUIElement* parent=0, s32 id=-1, video::ITexture* image=0) = 0; //! Adds a scrollbar. /** \param horizontal Specifies if the scroll bar is drawn horizontal or vertical. \param rectangle Rectangle specifying the borders of the scrollbar. \param parent Parent gui element of the scroll bar. \param id Id to identify the gui element. \return Pointer to the created scrollbar. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds an image element. /** \param image Image to be displayed. \param pos Position of the image. The width and height of the image is taken from the image. \param useAlphaChannel Sets if the image should use the alpha channel of the texture to draw itself. \param parent Parent gui element of the image. \param id Id to identify the gui element. \param text Title text of the image. \return Pointer to the created image element. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIImage* addImage(video::ITexture* image, core::position2d pos, bool useAlphaChannel=true, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; //! Adds an image element. /** Use IGUIImage::setImage later to set the image to be displayed. \param rectangle Rectangle specifying the borders of the image. \param parent Parent gui element of the image. \param id Id to identify the gui element. \param text Title text of the image. \param useAlphaChannel Sets if the image should use the alpha channel of the texture to draw itself. \return Pointer to the created image element. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIImage* addImage(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0, bool useAlphaChannel=true) = 0; //! Adds a checkbox element. /** \param checked Define the initial state of the check box. \param rectangle Rectangle specifying the borders of the check box. \param parent Parent gui element of the check box. \param id Id to identify the gui element. \param text Title text of the check box. \return Pointer to the created check box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUICheckBox* addCheckBox(bool checked, const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; //! Adds a list box element. /** \param rectangle Rectangle specifying the borders of the list box. \param parent Parent gui element of the list box. \param id Id to identify the gui element. \param drawBackground Flag whether the background should be drawn. \return Pointer to the created list box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIListBox* addListBox(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, bool drawBackground=false) = 0; //! Adds a tree view element. /** \param rectangle Position and dimension of list box. \param parent Parent gui element of the list box. \param id Id to identify the gui element. \param drawBackground Flag whether the background should be drawn. \param scrollBarVertical Flag whether a vertical scrollbar should be used \param scrollBarHorizontal Flag whether a horizontal scrollbar should be used \return Pointer to the created list box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUITreeView* addTreeView(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, bool drawBackground=false, bool scrollBarVertical = true, bool scrollBarHorizontal = false) = 0; //! Adds a mesh viewer. Not 100% implemented yet. /** \param rectangle Rectangle specifying the borders of the mesh viewer. \param parent Parent gui element of the mesh viewer. \param id Id to identify the gui element. \param text Title text of the mesh viewer. \return Pointer to the created mesh viewer. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIMeshViewer* addMeshViewer(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; //! Adds a file open dialog. /** \param title Text to be displayed as the title of the dialog. \param modal Defines if the dialog is modal. This means, that all other gui elements which were created before the message box cannot be used until this messagebox is removed. \param parent Parent gui element of the dialog. \param id Id to identify the gui element. \param restoreCWD If set to true, the current workingn directory will be restored after the dialog is closed in some way. Otherwise the working directory will be the one that the file dialog was last showing. \param startDir Optional path for which the file dialog will be opened. \return Pointer to the created file open dialog. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIFileOpenDialog* addFileOpenDialog(const wchar_t* title=0, bool modal=true, IGUIElement* parent=0, s32 id=-1, bool restoreCWD=false, io::path::char_type* startDir=0) = 0; //! Adds a color select dialog. /** \param title The title of the dialog. \param modal Defines if the dialog is modal. This means, that all other gui elements which were created before the dialog cannot be used until it is removed. \param parent The parent of the dialog. \param id The ID of the dialog. \return Pointer to the created file open dialog. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIColorSelectDialog* addColorSelectDialog(const wchar_t* title = 0, bool modal=true, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a static text. /** \param text Text to be displayed. Can be altered after creation by SetText(). \param rectangle Rectangle specifying the borders of the static text \param border Set to true if the static text should have a 3d border. \param wordWrap Enable if the text should wrap into multiple lines. \param parent Parent item of the element, e.g. a window. \param id The ID of the element. \param fillBackground Enable if the background shall be filled. Defaults to false. \return Pointer to the created static text. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIStaticText* addStaticText(const wchar_t* text, const core::rect& rectangle, bool border=false, bool wordWrap=true, IGUIElement* parent=0, s32 id=-1, bool fillBackground = false) = 0; //! Adds an edit box. /** Supports unicode input from every keyboard around the world, scrolling, copying and pasting (exchanging data with the clipboard directly), maximum character amount, marking, and all shortcuts like ctrl+X, ctrl+V, ctrl+C, shift+Left, shift+Right, Home, End, and so on. \param text Text to be displayed. Can be altered after creation by setText(). \param rectangle Rectangle specifying the borders of the edit box. \param border Set to true if the edit box should have a 3d border. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the edit box directly in the environment. \param id The ID of the element. \return Pointer to the created edit box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIEditBox* addEditBox(const wchar_t* text, const core::rect& rectangle, bool border=true, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a spin box. /** An edit box with up and down buttons \param text Text to be displayed. Can be altered after creation by setText(). \param rectangle Rectangle specifying the borders of the spin box. \param border Set to true if the spin box should have a 3d border. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the spin box directly in the environment. \param id The ID of the element. \return Pointer to the created spin box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect& rectangle, bool border=true,IGUIElement* parent=0, s32 id=-1) = 0; //! Adds an element for fading in or out. /** \param rectangle Rectangle specifying the borders of the fader. If the pointer is NULL, the whole screen is used. \param parent Parent item of the element, e.g. a window. \param id An identifier for the fader. \return Pointer to the created in-out-fader. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIInOutFader* addInOutFader(const core::rect* rectangle=0, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a tab control to the environment. /** \param rectangle Rectangle specifying the borders of the tab control. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the tab control directly in the environment. \param fillbackground Specifies if the background of the tab control should be drawn. \param border Specifies if a flat 3d border should be drawn. This is usually not necessary unless you place the control directly into the environment without a window as parent. \param id An identifier for the tab control. \return Pointer to the created tab control element. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUITabControl* addTabControl(const core::rect& rectangle, IGUIElement* parent=0, bool fillbackground=false, bool border=true, s32 id=-1) = 0; //! Adds tab to the environment. /** You can use this element to group other elements. This is not used for creating tabs on tab controls, please use IGUITabControl::addTab() for this instead. \param rectangle Rectangle specifying the borders of the tab. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the tab directly in the environment. \param id An identifier for the tab. \return Pointer to the created tab. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUITab* addTab(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a context menu to the environment. /** \param rectangle Rectangle specifying the borders of the menu. Note that the menu is resizing itself based on what items you add. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the menu directly in the environment. \param id An identifier for the menu. \return Pointer to the created context menu. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIContextMenu* addContextMenu(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a menu to the environment. /** This is like the menu you can find on top of most windows in modern graphical user interfaces. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the menu directly in the environment. \param id An identifier for the menu. \return Pointer to the created menu. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIContextMenu* addMenu(IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a toolbar to the environment. /** It is like a menu that is always placed on top of its parent, and contains buttons. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the tool bar directly in the environment. \param id An identifier for the tool bar. \return Pointer to the created tool bar. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIToolBar* addToolBar(IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a combo box to the environment. /** \param rectangle Rectangle specifying the borders of the combo box. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the combo box directly in the environment. \param id An identifier for the combo box. \return Pointer to the created combo box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIComboBox* addComboBox(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1) = 0; //! Adds a table to the environment /** \param rectangle Rectangle specifying the borders of the table. \param parent Parent item of the element, e.g. a window. Set it to 0 to place the element directly in the environment. \param id An identifier for the table. \param drawBackground Flag whether the background should be drawn. \return Pointer to the created table. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUITable* addTable(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, bool drawBackground=false) =0; //! Get the default element factory which can create all built-in elements /** \return Pointer to the factory. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIElementFactory* getDefaultGUIElementFactory() const = 0; //! Adds an element factory to the gui environment. /** Use this to extend the gui environment with new element types which it should be able to create automatically, for example when loading data from xml files. \param factoryToAdd Pointer to new factory. */ virtual void registerGUIElementFactory(IGUIElementFactory* factoryToAdd) = 0; //! Get amount of registered gui element factories. /** \return Amount of registered gui element factories. */ virtual u32 getRegisteredGUIElementFactoryCount() const = 0; //! Get a gui element factory by index /** \param index Index of the factory. \return Factory at given index, or 0 if no such factory exists. */ virtual IGUIElementFactory* getGUIElementFactory(u32 index) const = 0; //! Adds a GUI element by its name /** Each factory is checked if it can create an element of the given name. The first match will be created. \param elementName Name of the element to be created. \param parent Parent of the new element, if not 0. \return New GUI element, or 0 if no such element exists. */ virtual IGUIElement* addGUIElement(const c8* elementName, IGUIElement* parent=0) = 0; //! Saves the current gui into a file. /** \param filename Name of the file. \param start The GUIElement to start with. Root if 0. \return True if saving succeeded, else false. */ virtual bool saveGUI(const io::path& filename, IGUIElement* start=0) = 0; //! Saves the current gui into a file. /** \param file The file to write to. \param start The GUIElement to start with. Root if 0. \return True if saving succeeded, else false. */ virtual bool saveGUI(io::IWriteFile* file, IGUIElement* start=0) = 0; //! Loads the gui. Note that the current gui is not cleared before. /** When a parent is set the elements will be added below the parent, the parent itself does not deserialize. When the file contains skin-settings from the gui-environment those are always serialized into the guienvironment independent of the parent setting. \param filename Name of the file. \param parent Parent for the loaded GUI, root if 0. \return True if loading succeeded, else false. */ virtual bool loadGUI(const io::path& filename, IGUIElement* parent=0) = 0; //! Loads the gui. Note that the current gui is not cleared before. /** When a parent is set the elements will be added below the parent, the parent itself does not deserialize. When the file contains skin-settings from the gui-environment those are always serialized into the guienvironment independent of the parent setting. \param file The file to load from. \param parent Parent for the loaded GUI, root if 0. \return True if loading succeeded, else false. */ virtual bool loadGUI(io::IReadFile* file, IGUIElement* parent=0) = 0; //! Writes attributes of the gui environment virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const =0; //! Reads attributes of the gui environment virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)=0; //! writes an element virtual void writeGUIElement(io::IXMLWriter* writer, IGUIElement* node) =0; //! reads an element virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* node) =0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIElementFactory.h0000644000000000000000000000540112574354552017250 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_ELEMENT_FACTORY_H_INCLUDED__ #define __I_GUI_ELEMENT_FACTORY_H_INCLUDED__ #include "IReferenceCounted.h" #include "EGUIElementTypes.h" namespace irr { namespace gui { class IGUIElement; //! Interface making it possible to dynamically create GUI elements /** To be able to add custom elements to Irrlicht and to make it possible for the scene manager to save and load them, simply implement this interface and register it in your gui environment via IGUIEnvironment::registerGUIElementFactory. Note: When implementing your own element factory, don't call IGUIEnvironment::grab() to increase the reference counter of the environment. This is not necessary because the it will grab() the factory anyway, and otherwise cyclic references will be created. */ class IGUIElementFactory : public virtual IReferenceCounted { public: //! adds an element to the gui environment based on its type id /** \param type: Type of the element to add. \param parent: Parent scene node of the new element, can be null to add to the root. \return Pointer to the new element or null if not successful. */ virtual IGUIElement* addGUIElement(EGUI_ELEMENT_TYPE type, IGUIElement* parent=0) = 0; //! adds a GUI element to the GUI Environment based on its type name /** \param typeName: Type name of the element to add. \param parent: Parent scene node of the new element, can be null to add it to the root. \return Pointer to the new element or null if not successful. */ virtual IGUIElement* addGUIElement(const c8* typeName, IGUIElement* parent=0) = 0; //! Get amount of GUI element types this factory is able to create virtual s32 getCreatableGUIElementTypeCount() const = 0; //! Get type of a createable element type /** \param idx: Index of the element type in this factory. Must be a value between 0 and getCreatableGUIElementTypeCount() */ virtual EGUI_ELEMENT_TYPE getCreateableGUIElementType(s32 idx) const = 0; //! Get type name of a createable GUI element type by index /** \param idx: Index of the type in this factory. Must be a value between 0 and getCreatableGUIElementTypeCount() */ virtual const c8* getCreateableGUIElementTypeName(s32 idx) const = 0; //! returns type name of a createable GUI element /** \param type: Type of GUI element. \return Name of the type if this factory can create the type, otherwise 0. */ virtual const c8* getCreateableGUIElementTypeName(EGUI_ELEMENT_TYPE type) const = 0; }; } // end namespace gui } // end namespace irr #endif // __I_GUI_ELEMENT_FACTORY_H_INCLUDED__ irrlicht-1.8.3/include/IGUIElement.h0000644000000000000000000006732412574354552015734 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_ELEMENT_H_INCLUDED__ #define __I_GUI_ELEMENT_H_INCLUDED__ #include "IAttributeExchangingObject.h" #include "irrList.h" #include "rect.h" #include "irrString.h" #include "IEventReceiver.h" #include "EGUIElementTypes.h" #include "EGUIAlignment.h" #include "IAttributes.h" namespace irr { namespace gui { class IGUIEnvironment; //! Base class of all GUI elements. class IGUIElement : public virtual io::IAttributeExchangingObject, public IEventReceiver { public: //! Constructor IGUIElement(EGUI_ELEMENT_TYPE type, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle) : Parent(0), RelativeRect(rectangle), AbsoluteRect(rectangle), AbsoluteClippingRect(rectangle), DesiredRect(rectangle), MaxSize(0,0), MinSize(1,1), IsVisible(true), IsEnabled(true), IsSubElement(false), NoClip(false), ID(id), IsTabStop(false), TabOrder(-1), IsTabGroup(false), AlignLeft(EGUIA_UPPERLEFT), AlignRight(EGUIA_UPPERLEFT), AlignTop(EGUIA_UPPERLEFT), AlignBottom(EGUIA_UPPERLEFT), Environment(environment), Type(type) { #ifdef _DEBUG setDebugName("IGUIElement"); #endif // if we were given a parent to attach to if (parent) { parent->addChildToEnd(this); recalculateAbsolutePosition(true); } } //! Destructor virtual ~IGUIElement() { // delete all children core::list::Iterator it = Children.begin(); for (; it != Children.end(); ++it) { (*it)->Parent = 0; (*it)->drop(); } } //! Returns parent of this element. IGUIElement* getParent() const { return Parent; } //! Returns the relative rectangle of this element. core::rect getRelativePosition() const { return RelativeRect; } //! Sets the relative rectangle of this element. /** \param r The absolute position to set */ void setRelativePosition(const core::rect& r) { if (Parent) { const core::rect& r2 = Parent->getAbsolutePosition(); core::dimension2df d((f32)(r2.getSize().Width), (f32)(r2.getSize().Height)); if (AlignLeft == EGUIA_SCALE) ScaleRect.UpperLeftCorner.X = (f32)r.UpperLeftCorner.X / d.Width; if (AlignRight == EGUIA_SCALE) ScaleRect.LowerRightCorner.X = (f32)r.LowerRightCorner.X / d.Width; if (AlignTop == EGUIA_SCALE) ScaleRect.UpperLeftCorner.Y = (f32)r.UpperLeftCorner.Y / d.Height; if (AlignBottom == EGUIA_SCALE) ScaleRect.LowerRightCorner.Y = (f32)r.LowerRightCorner.Y / d.Height; } DesiredRect = r; updateAbsolutePosition(); } //! Sets the relative rectangle of this element, maintaining its current width and height /** \param position The new relative position to set. Width and height will not be changed. */ void setRelativePosition(const core::position2di & position) { const core::dimension2di mySize = RelativeRect.getSize(); const core::rect rectangle(position.X, position.Y, position.X + mySize.Width, position.Y + mySize.Height); setRelativePosition(rectangle); } //! Sets the relative rectangle of this element as a proportion of its parent's area. /** \note This method used to be 'void setRelativePosition(const core::rect& r)' \param r The rectangle to set, interpreted as a proportion of the parent's area. Meaningful values are in the range [0...1], unless you intend this element to spill outside its parent. */ void setRelativePositionProportional(const core::rect& r) { if (!Parent) return; const core::dimension2di& d = Parent->getAbsolutePosition().getSize(); DesiredRect = core::rect( core::floor32((f32)d.Width * r.UpperLeftCorner.X), core::floor32((f32)d.Height * r.UpperLeftCorner.Y), core::floor32((f32)d.Width * r.LowerRightCorner.X), core::floor32((f32)d.Height * r.LowerRightCorner.Y)); ScaleRect = r; updateAbsolutePosition(); } //! Gets the absolute rectangle of this element core::rect getAbsolutePosition() const { return AbsoluteRect; } //! Returns the visible area of the element. core::rect getAbsoluteClippingRect() const { return AbsoluteClippingRect; } //! Sets whether the element will ignore its parent's clipping rectangle /** \param noClip If true, the element will not be clipped by its parent's clipping rectangle. */ void setNotClipped(bool noClip) { NoClip = noClip; updateAbsolutePosition(); } //! Gets whether the element will ignore its parent's clipping rectangle /** \return true if the element is not clipped by its parent's clipping rectangle. */ bool isNotClipped() const { return NoClip; } //! Sets the maximum size allowed for this element /** If set to 0,0, there is no maximum size */ void setMaxSize(core::dimension2du size) { MaxSize = size; updateAbsolutePosition(); } //! Sets the minimum size allowed for this element void setMinSize(core::dimension2du size) { MinSize = size; if (MinSize.Width < 1) MinSize.Width = 1; if (MinSize.Height < 1) MinSize.Height = 1; updateAbsolutePosition(); } //! The alignment defines how the borders of this element will be positioned when the parent element is resized. void setAlignment(EGUI_ALIGNMENT left, EGUI_ALIGNMENT right, EGUI_ALIGNMENT top, EGUI_ALIGNMENT bottom) { AlignLeft = left; AlignRight = right; AlignTop = top; AlignBottom = bottom; if (Parent) { core::rect r(Parent->getAbsolutePosition()); core::dimension2df d((f32)r.getSize().Width, (f32)r.getSize().Height); if (AlignLeft == EGUIA_SCALE) ScaleRect.UpperLeftCorner.X = (f32)DesiredRect.UpperLeftCorner.X / d.Width; if (AlignRight == EGUIA_SCALE) ScaleRect.LowerRightCorner.X = (f32)DesiredRect.LowerRightCorner.X / d.Width; if (AlignTop == EGUIA_SCALE) ScaleRect.UpperLeftCorner.Y = (f32)DesiredRect.UpperLeftCorner.Y / d.Height; if (AlignBottom == EGUIA_SCALE) ScaleRect.LowerRightCorner.Y = (f32)DesiredRect.LowerRightCorner.Y / d.Height; } } //! Updates the absolute position. virtual void updateAbsolutePosition() { recalculateAbsolutePosition(false); // update all children core::list::Iterator it = Children.begin(); for (; it != Children.end(); ++it) { (*it)->updateAbsolutePosition(); } } //! Returns the topmost GUI element at the specific position. /** This will check this GUI element and all of its descendants, so it may return this GUI element. To check all GUI elements, call this function on device->getGUIEnvironment()->getRootGUIElement(). Note that the root element is the size of the screen, so doing so (with an on-screen point) will always return the root element if no other element is above it at that point. \param point: The point at which to find a GUI element. \return The topmost GUI element at that point, or 0 if there are no candidate elements at this point. */ IGUIElement* getElementFromPoint(const core::position2d& point) { IGUIElement* target = 0; // we have to search from back to front, because later children // might be drawn over the top of earlier ones. core::list::Iterator it = Children.getLast(); if (isVisible()) { while(it != Children.end()) { target = (*it)->getElementFromPoint(point); if (target) return target; --it; } } if (isVisible() && isPointInside(point)) target = this; return target; } //! Returns true if a point is within this element. /** Elements with a shape other than a rectangle should override this method */ virtual bool isPointInside(const core::position2d& point) const { return AbsoluteClippingRect.isPointInside(point); } //! Adds a GUI element as new child of this element. virtual void addChild(IGUIElement* child) { addChildToEnd(child); if (child) { child->updateAbsolutePosition(); } } //! Removes a child. virtual void removeChild(IGUIElement* child) { core::list::Iterator it = Children.begin(); for (; it != Children.end(); ++it) if ((*it) == child) { (*it)->Parent = 0; (*it)->drop(); Children.erase(it); return; } } //! Removes this element from its parent. virtual void remove() { if (Parent) Parent->removeChild(this); } //! Draws the element and its children. virtual void draw() { if ( isVisible() ) { core::list::Iterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->draw(); } } //! animate the element and its children. virtual void OnPostRender(u32 timeMs) { if ( isVisible() ) { core::list::Iterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->OnPostRender( timeMs ); } } //! Moves this element. virtual void move(core::position2d absoluteMovement) { setRelativePosition(DesiredRect + absoluteMovement); } //! Returns true if element is visible. virtual bool isVisible() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return IsVisible; } //! Sets the visible state of this element. virtual void setVisible(bool visible) { IsVisible = visible; } //! Returns true if this element was created as part of its parent control virtual bool isSubElement() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return IsSubElement; } //! Sets whether this control was created as part of its parent. /** For example, it is true when a scrollbar is part of a listbox. SubElements are not saved to disk when calling guiEnvironment->saveGUI() */ virtual void setSubElement(bool subElement) { IsSubElement = subElement; } //! If set to true, the focus will visit this element when using the tab key to cycle through elements. /** If this element is a tab group (see isTabGroup/setTabGroup) then ctrl+tab will be used instead. */ void setTabStop(bool enable) { IsTabStop = enable; } //! Returns true if this element can be focused by navigating with the tab key bool isTabStop() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return IsTabStop; } //! Sets the priority of focus when using the tab key to navigate between a group of elements. /** See setTabGroup, isTabGroup and getTabGroup for information on tab groups. Elements with a lower number are focused first */ void setTabOrder(s32 index) { // negative = autonumber if (index < 0) { TabOrder = 0; IGUIElement *el = getTabGroup(); while (IsTabGroup && el && el->Parent) el = el->Parent; IGUIElement *first=0, *closest=0; if (el) { // find the highest element number el->getNextElement(-1, true, IsTabGroup, first, closest, true); if (first) { TabOrder = first->getTabOrder() + 1; } } } else TabOrder = index; } //! Returns the number in the tab order sequence s32 getTabOrder() const { return TabOrder; } //! Sets whether this element is a container for a group of elements which can be navigated using the tab key. /** For example, windows are tab groups. Groups can be navigated using ctrl+tab, providing isTabStop is true. */ void setTabGroup(bool isGroup) { IsTabGroup = isGroup; } //! Returns true if this element is a tab group. bool isTabGroup() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return IsTabGroup; } //! Returns the container element which holds all elements in this element's tab group. IGUIElement* getTabGroup() { IGUIElement *ret=this; while (ret && !ret->isTabGroup()) ret = ret->getParent(); return ret; } //! Returns true if element is enabled /** Currently elements do _not_ care about parent-states. So if you want to affect childs you have to enable/disable them all. The only exception to this are sub-elements which also check their parent. */ virtual bool isEnabled() const { if ( isSubElement() && IsEnabled && getParent() ) return getParent()->isEnabled(); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return IsEnabled; } //! Sets the enabled state of this element. virtual void setEnabled(bool enabled) { IsEnabled = enabled; } //! Sets the new caption of this element. virtual void setText(const wchar_t* text) { Text = text; } //! Returns caption of this element. virtual const wchar_t* getText() const { return Text.c_str(); } //! Sets the new caption of this element. virtual void setToolTipText(const wchar_t* text) { ToolTipText = text; } //! Returns caption of this element. virtual const core::stringw& getToolTipText() const { return ToolTipText; } //! Returns id. Can be used to identify the element. virtual s32 getID() const { return ID; } //! Sets the id of this element virtual void setID(s32 id) { ID = id; } //! Called if an event happened. virtual bool OnEvent(const SEvent& event) { return Parent ? Parent->OnEvent(event) : false; } //! Brings a child to front /** \return True if successful, false if not. */ virtual bool bringToFront(IGUIElement* element) { core::list::Iterator it = Children.begin(); for (; it != Children.end(); ++it) { if (element == (*it)) { Children.erase(it); Children.push_back(element); return true; } } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } //! Moves a child to the back, so it's siblings are drawn on top of it /** \return True if successful, false if not. */ virtual bool sendToBack(IGUIElement* child) { core::list::Iterator it = Children.begin(); if (child == (*it)) // already there return true; for (; it != Children.end(); ++it) { if (child == (*it)) { Children.erase(it); Children.push_front(child); return true; } } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } //! Returns list with children of this element virtual const core::list& getChildren() const { return Children; } //! Finds the first element with the given id. /** \param id: Id to search for. \param searchchildren: Set this to true, if also children of this element may contain the element with the searched id and they should be searched too. \return Returns the first element with the given id. If no element with this id was found, 0 is returned. */ virtual IGUIElement* getElementFromId(s32 id, bool searchchildren=false) const { IGUIElement* e = 0; core::list::ConstIterator it = Children.begin(); for (; it != Children.end(); ++it) { if ((*it)->getID() == id) return (*it); if (searchchildren) e = (*it)->getElementFromId(id, true); if (e) return e; } return e; } //! returns true if the given element is a child of this one. //! \param child: The child element to check bool isMyChild(IGUIElement* child) const { if (!child) return false; do { if (child->Parent) child = child->Parent; } while (child->Parent && child != this); _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return child == this; } //! searches elements to find the closest next element to tab to /** \param startOrder: The TabOrder of the current element, -1 if none \param reverse: true if searching for a lower number \param group: true if searching for a higher one \param first: element with the highest/lowest known tab order depending on search direction \param closest: the closest match, depending on tab order and direction \param includeInvisible: includes invisible elements in the search (default=false) \return true if successfully found an element, false to continue searching/fail */ bool getNextElement(s32 startOrder, bool reverse, bool group, IGUIElement*& first, IGUIElement*& closest, bool includeInvisible=false) const { // we'll stop searching if we find this number s32 wanted = startOrder + ( reverse ? -1 : 1 ); if (wanted==-2) wanted = 1073741824; // maximum s32 core::list::ConstIterator it = Children.begin(); s32 closestOrder, currentOrder; while(it != Children.end()) { // ignore invisible elements and their children if ( ( (*it)->isVisible() || includeInvisible ) && (group == true || (*it)->isTabGroup() == false) ) { // only check tab stops and those with the same group status if ((*it)->isTabStop() && ((*it)->isTabGroup() == group)) { currentOrder = (*it)->getTabOrder(); // is this what we're looking for? if (currentOrder == wanted) { closest = *it; return true; } // is it closer than the current closest? if (closest) { closestOrder = closest->getTabOrder(); if ( ( reverse && currentOrder > closestOrder && currentOrder < startOrder) ||(!reverse && currentOrder < closestOrder && currentOrder > startOrder)) { closest = *it; } } else if ( (reverse && currentOrder < startOrder) || (!reverse && currentOrder > startOrder) ) { closest = *it; } // is it before the current first? if (first) { closestOrder = first->getTabOrder(); if ( (reverse && closestOrder < currentOrder) || (!reverse && closestOrder > currentOrder) ) { first = *it; } } else { first = *it; } } // search within children if ((*it)->getNextElement(startOrder, reverse, group, first, closest)) { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return true; } } ++it; } _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return false; } //! Returns the type of the gui element. /** This is needed for the .NET wrapper but will be used later for serializing and deserializing. If you wrote your own GUIElements, you need to set the type for your element as first parameter in the constructor of IGUIElement. For own (=unknown) elements, simply use EGUIET_ELEMENT as type */ EGUI_ELEMENT_TYPE getType() const { return Type; } //! Returns true if the gui element supports the given type. /** This is mostly used to check if you can cast a gui element to the class that goes with the type. Most gui elements will only support their own type, but if you derive your own classes from interfaces you can overload this function and add a check for the type of the base-class additionally. This allows for checks comparable to the dynamic_cast of c++ with enabled rtti. Note that you can't do that by calling BaseClass::hasType(type), but you have to do an explicit comparison check, because otherwise the base class usually just checks for the membervariable Type which contains the type of your derived class. */ virtual bool hasType(EGUI_ELEMENT_TYPE type) const { return type == Type; } //! Returns the type name of the gui element. /** This is needed serializing elements. For serializing your own elements, override this function and return your own type name which is created by your IGUIElementFactory */ virtual const c8* getTypeName() const { return GUIElementTypeNames[Type]; } //! Returns the name of the element. /** \return Name as character string. */ virtual const c8* getName() const { return Name.c_str(); } //! Sets the name of the element. /** \param name New name of the gui element. */ virtual void setName(const c8* name) { Name = name; } //! Sets the name of the element. /** \param name New name of the gui element. */ virtual void setName(const core::stringc& name) { Name = name; } //! Writes attributes of the scene node. /** Implement this to expose the attributes of your scene node for scripting languages, editors, debuggers or xml serialization purposes. */ virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { out->addString("Name", Name.c_str()); out->addInt("Id", ID ); out->addString("Caption", getText()); out->addRect("Rect", DesiredRect); out->addPosition2d("MinSize", core::position2di(MinSize.Width, MinSize.Height)); out->addPosition2d("MaxSize", core::position2di(MaxSize.Width, MaxSize.Height)); out->addEnum("LeftAlign", AlignLeft, GUIAlignmentNames); out->addEnum("RightAlign", AlignRight, GUIAlignmentNames); out->addEnum("TopAlign", AlignTop, GUIAlignmentNames); out->addEnum("BottomAlign", AlignBottom, GUIAlignmentNames); out->addBool("Visible", IsVisible); out->addBool("Enabled", IsEnabled); out->addBool("TabStop", IsTabStop); out->addBool("TabGroup", IsTabGroup); out->addInt("TabOrder", TabOrder); out->addBool("NoClip", NoClip); } //! Reads attributes of the scene node. /** Implement this to set the attributes of your scene node for scripting languages, editors, debuggers or xml deserialization purposes. */ virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { setName(in->getAttributeAsString("Name")); setID(in->getAttributeAsInt("Id")); setText(in->getAttributeAsStringW("Caption").c_str()); setVisible(in->getAttributeAsBool("Visible")); setEnabled(in->getAttributeAsBool("Enabled")); IsTabStop = in->getAttributeAsBool("TabStop"); IsTabGroup = in->getAttributeAsBool("TabGroup"); TabOrder = in->getAttributeAsInt("TabOrder"); core::position2di p = in->getAttributeAsPosition2d("MaxSize"); setMaxSize(core::dimension2du(p.X,p.Y)); p = in->getAttributeAsPosition2d("MinSize"); setMinSize(core::dimension2du(p.X,p.Y)); setAlignment((EGUI_ALIGNMENT) in->getAttributeAsEnumeration("LeftAlign", GUIAlignmentNames), (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("RightAlign", GUIAlignmentNames), (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("TopAlign", GUIAlignmentNames), (EGUI_ALIGNMENT)in->getAttributeAsEnumeration("BottomAlign", GUIAlignmentNames)); setRelativePosition(in->getAttributeAsRect("Rect")); setNotClipped(in->getAttributeAsBool("NoClip")); } protected: // not virtual because needed in constructor void addChildToEnd(IGUIElement* child) { if (child) { child->grab(); // prevent destruction when removed child->remove(); // remove from old parent child->LastParentRect = getAbsolutePosition(); child->Parent = this; Children.push_back(child); } } // not virtual because needed in constructor void recalculateAbsolutePosition(bool recursive) { core::rect parentAbsolute(0,0,0,0); core::rect parentAbsoluteClip; f32 fw=0.f, fh=0.f; if (Parent) { parentAbsolute = Parent->AbsoluteRect; if (NoClip) { IGUIElement* p=this; while (p && p->Parent) p = p->Parent; parentAbsoluteClip = p->AbsoluteClippingRect; } else parentAbsoluteClip = Parent->AbsoluteClippingRect; } const s32 diffx = parentAbsolute.getWidth() - LastParentRect.getWidth(); const s32 diffy = parentAbsolute.getHeight() - LastParentRect.getHeight(); if (AlignLeft == EGUIA_SCALE || AlignRight == EGUIA_SCALE) fw = (f32)parentAbsolute.getWidth(); if (AlignTop == EGUIA_SCALE || AlignBottom == EGUIA_SCALE) fh = (f32)parentAbsolute.getHeight(); switch (AlignLeft) { case EGUIA_UPPERLEFT: break; case EGUIA_LOWERRIGHT: DesiredRect.UpperLeftCorner.X += diffx; break; case EGUIA_CENTER: DesiredRect.UpperLeftCorner.X += diffx/2; break; case EGUIA_SCALE: DesiredRect.UpperLeftCorner.X = core::round32(ScaleRect.UpperLeftCorner.X * fw); break; } switch (AlignRight) { case EGUIA_UPPERLEFT: break; case EGUIA_LOWERRIGHT: DesiredRect.LowerRightCorner.X += diffx; break; case EGUIA_CENTER: DesiredRect.LowerRightCorner.X += diffx/2; break; case EGUIA_SCALE: DesiredRect.LowerRightCorner.X = core::round32(ScaleRect.LowerRightCorner.X * fw); break; } switch (AlignTop) { case EGUIA_UPPERLEFT: break; case EGUIA_LOWERRIGHT: DesiredRect.UpperLeftCorner.Y += diffy; break; case EGUIA_CENTER: DesiredRect.UpperLeftCorner.Y += diffy/2; break; case EGUIA_SCALE: DesiredRect.UpperLeftCorner.Y = core::round32(ScaleRect.UpperLeftCorner.Y * fh); break; } switch (AlignBottom) { case EGUIA_UPPERLEFT: break; case EGUIA_LOWERRIGHT: DesiredRect.LowerRightCorner.Y += diffy; break; case EGUIA_CENTER: DesiredRect.LowerRightCorner.Y += diffy/2; break; case EGUIA_SCALE: DesiredRect.LowerRightCorner.Y = core::round32(ScaleRect.LowerRightCorner.Y * fh); break; } RelativeRect = DesiredRect; const s32 w = RelativeRect.getWidth(); const s32 h = RelativeRect.getHeight(); // make sure the desired rectangle is allowed if (w < (s32)MinSize.Width) RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MinSize.Width; if (h < (s32)MinSize.Height) RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MinSize.Height; if (MaxSize.Width && w > (s32)MaxSize.Width) RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MaxSize.Width; if (MaxSize.Height && h > (s32)MaxSize.Height) RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MaxSize.Height; RelativeRect.repair(); AbsoluteRect = RelativeRect + parentAbsolute.UpperLeftCorner; if (!Parent) parentAbsoluteClip = AbsoluteRect; AbsoluteClippingRect = AbsoluteRect; AbsoluteClippingRect.clipAgainst(parentAbsoluteClip); LastParentRect = parentAbsolute; if ( recursive ) { // update all children core::list::Iterator it = Children.begin(); for (; it != Children.end(); ++it) { (*it)->recalculateAbsolutePosition(recursive); } } } protected: //! List of all children of this element core::list Children; //! Pointer to the parent IGUIElement* Parent; //! relative rect of element core::rect RelativeRect; //! absolute rect of element core::rect AbsoluteRect; //! absolute clipping rect of element core::rect AbsoluteClippingRect; //! the rectangle the element would prefer to be, //! if it was not constrained by parent or max/min size core::rect DesiredRect; //! for calculating the difference when resizing parent core::rect LastParentRect; //! relative scale of the element inside its parent core::rect ScaleRect; //! maximum and minimum size of the element core::dimension2du MaxSize, MinSize; //! is visible? bool IsVisible; //! is enabled? bool IsEnabled; //! is a part of a larger whole and should not be serialized? bool IsSubElement; //! does this element ignore its parent's clipping rectangle? bool NoClip; //! caption core::stringw Text; //! tooltip core::stringw ToolTipText; //! users can set this for identificating the element by string core::stringc Name; //! users can set this for identificating the element by integer s32 ID; //! tab stop like in windows bool IsTabStop; //! tab order s32 TabOrder; //! tab groups are containers like windows, use ctrl+tab to navigate bool IsTabGroup; //! tells the element how to act when its parent is resized EGUI_ALIGNMENT AlignLeft, AlignRight, AlignTop, AlignBottom; //! GUI Environment IGUIEnvironment* Environment; //! type of element EGUI_ELEMENT_TYPE Type; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIEditBox.h0000644000000000000000000001231312574354552015665 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_EDIT_BOX_H_INCLUDED__ #define __I_GUI_EDIT_BOX_H_INCLUDED__ #include "IGUIElement.h" #include "SColor.h" namespace irr { namespace gui { class IGUIFont; //! Single line edit box for editing simple text. /** \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_EDITBOX_ENTER \li EGET_EDITBOX_CHANGED \li EGET_EDITBOX_MARKING_CHANGED */ class IGUIEditBox : public IGUIElement { public: //! constructor IGUIEditBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_EDIT_BOX, environment, parent, id, rectangle) {} //! Sets another skin independent font. /** If this is set to zero, the button uses the font of the skin. \param font: New font to set. */ virtual void setOverrideFont(IGUIFont* font=0) = 0; //! Gets the override font (if any) /** \return The override font (may be 0) */ virtual IGUIFont* getOverrideFont() const = 0; //! Get the font which is used right now for drawing /** Currently this is the override font when one is set and the font of the active skin otherwise */ virtual IGUIFont* getActiveFont() const = 0; //! Sets another color for the text. /** If set, the edit box does not use the EGDC_BUTTON_TEXT color defined in the skin, but the set color instead. You don't need to call IGUIEditBox::enableOverrrideColor(true) after this, this is done by this function. If you set a color, and you want the text displayed with the color of the skin again, call IGUIEditBox::enableOverrideColor(false); \param color: New color of the text. */ virtual void setOverrideColor(video::SColor color) = 0; //! Gets the override color virtual video::SColor getOverrideColor() const = 0; //! Sets if the text should use the override color or the color in the gui skin. /** \param enable: If set to true, the override color, which can be set with IGUIEditBox::setOverrideColor is used, otherwise the EGDC_BUTTON_TEXT color of the skin. */ virtual void enableOverrideColor(bool enable) = 0; //! Checks if an override color is enabled /** \return true if the override color is enabled, false otherwise */ virtual bool isOverrideColorEnabled(void) const = 0; //! Sets whether to draw the background virtual void setDrawBackground(bool draw) = 0; //! Turns the border on or off /** \param border: true if you want the border to be drawn, false if not */ virtual void setDrawBorder(bool border) = 0; //! Sets text justification mode /** \param horizontal: EGUIA_UPPERLEFT for left justified (default), EGUIA_LOWERRIGHT for right justified, or EGUIA_CENTER for centered text. \param vertical: EGUIA_UPPERLEFT to align with top edge, EGUIA_LOWERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */ virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0; //! Enables or disables word wrap. /** \param enable: If set to true, words going over one line are broken to the next line. */ virtual void setWordWrap(bool enable) = 0; //! Checks if word wrap is enabled /** \return true if word wrap is enabled, false otherwise */ virtual bool isWordWrapEnabled() const = 0; //! Enables or disables newlines. /** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired, instead a newline character will be inserted. */ virtual void setMultiLine(bool enable) = 0; //! Checks if multi line editing is enabled /** \return true if multi-line is enabled, false otherwise */ virtual bool isMultiLineEnabled() const = 0; //! Enables or disables automatic scrolling with cursor position /** \param enable: If set to true, the text will move around with the cursor position */ virtual void setAutoScroll(bool enable) = 0; //! Checks to see if automatic scrolling is enabled /** \return true if automatic scrolling is enabled, false if not */ virtual bool isAutoScrollEnabled() const = 0; //! Sets whether the edit box is a password box. Setting this to true will /** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x \param passwordBox: true to enable password, false to disable \param passwordChar: the character that is displayed instead of letters */ virtual void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*') = 0; //! Returns true if the edit box is currently a password box. virtual bool isPasswordBox() const = 0; //! Gets the size area of the text in the edit box /** \return The size in pixels of the text */ virtual core::dimension2du getTextDimension() = 0; //! Sets the maximum amount of characters which may be entered in the box. /** \param max: Maximum amount of characters. If 0, the character amount is infinity. */ virtual void setMax(u32 max) = 0; //! Returns maximum amount of characters, previously set by setMax(); virtual u32 getMax() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIContextMenu.h0000644000000000000000000001416612574354552016610 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_CONTEXT_MENU_H_INCLUDED__ #define __I_GUI_CONTEXT_MENU_H_INCLUDED__ #include "IGUIElement.h" namespace irr { namespace gui { //! Close behavior. //! Default is ECMC_REMOVE enum ECONTEXT_MENU_CLOSE { //! do nothing - menu stays open ECMC_IGNORE = 0, //! remove the gui element ECMC_REMOVE = 1, //! call setVisible(false) ECMC_HIDE = 2 // note to implementors - this is planned as bitset, so continue with 4 if you need to add further flags. }; //! GUI Context menu interface. /** \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_ELEMENT_CLOSED \li EGET_MENU_ITEM_SELECTED */ class IGUIContextMenu : public IGUIElement { public: //! constructor IGUIContextMenu(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_CONTEXT_MENU, environment, parent, id, rectangle) {} //! set behavior when menus are closed virtual void setCloseHandling(ECONTEXT_MENU_CLOSE onClose) = 0; //! get current behavior when the menu will be closed virtual ECONTEXT_MENU_CLOSE getCloseHandling() const = 0; //! Get amount of menu items virtual u32 getItemCount() const = 0; //! Adds a menu item. /** \param text: Text of menu item. Set this to 0 to create an separator instead of a real item, which is the same like calling addSeparator(); \param commandId: Command id of menu item, a simple id you may set to whatever you want. \param enabled: Specifies if the menu item should be enabled. \param hasSubMenu: Set this to true if there should be a submenu at this item. You can access this submenu via getSubMenu(). \param checked: Specifies if the menu item should be initially checked. \param autoChecking: Specifies if the item should be checked by clicking \return Returns the index of the new item */ virtual u32 addItem(const wchar_t* text, s32 commandId=-1, bool enabled=true, bool hasSubMenu=false, bool checked=false, bool autoChecking=false) = 0; //! Insert a menu item at specified position. /** \param idx: Position to insert the new element, should be smaller than itemcount otherwise the item is added to the end. \param text: Text of menu item. Set this to 0 to create an separator instead of a real item, which is the same like calling addSeparator(); \param commandId: Command id of menu item, a simple id you may set to whatever you want. \param enabled: Specifies if the menu item should be enabled. \param hasSubMenu: Set this to true if there should be a submenu at this item. You can access this submenu via getSubMenu(). \param checked: Specifies if the menu item should be initially checked. \param autoChecking: Specifies if the item should be checked by clicking \return Returns the index of the new item */ virtual u32 insertItem(u32 idx, const wchar_t* text, s32 commandId=-1, bool enabled=true, bool hasSubMenu=false, bool checked=false, bool autoChecking=false) = 0; //! Find an item by it's CommandID /** \param commandId: We are looking for the first item which has this commandID \param idxStartSearch: Start searching from this index. \return Returns the index of the item when found or otherwise -1. */ virtual s32 findItemWithCommandId(s32 commandId, u32 idxStartSearch=0) const = 0; //! Adds a separator item to the menu virtual void addSeparator() = 0; //! Get text of the menu item. /** \param idx: Zero based index of the menu item */ virtual const wchar_t* getItemText(u32 idx) const = 0; //! Sets text of the menu item. /** \param idx: Zero based index of the menu item \param text: New text of the item. */ virtual void setItemText(u32 idx, const wchar_t* text) = 0; //! Check if a menu item is enabled /** \param idx: Zero based index of the menu item */ virtual bool isItemEnabled(u32 idx) const = 0; //! Sets if the menu item should be enabled. /** \param idx: Zero based index of the menu item \param enabled: True if it is enabled, otherwise false. */ virtual void setItemEnabled(u32 idx, bool enabled) = 0; //! Sets if the menu item should be checked. /** \param idx: Zero based index of the menu item \param enabled: True if it is enabled, otherwise false. */ virtual void setItemChecked(u32 idx, bool enabled) = 0; //! Check if a menu item is checked /** \param idx: Zero based index of the menu item */ virtual bool isItemChecked(u32 idx) const = 0; //! Removes a menu item /** \param idx: Zero based index of the menu item */ virtual void removeItem(u32 idx) = 0; //! Removes all menu items virtual void removeAllItems() = 0; //! Get the selected item in the menu /** \return Index of the selected item, -1 if none selected. */ virtual s32 getSelectedItem() const = 0; //! Get the command id of a menu item /** \param idx: Zero based index of the menu item */ virtual s32 getItemCommandId(u32 idx) const = 0; //! Sets the command id of a menu item /** \param idx: Zero based index of the menu item \param id: Command id of menu item, a simple id you may set to whatever you want. */ virtual void setItemCommandId(u32 idx, s32 id) = 0; //! Get a pointer to the submenu of an item. /** 0 is returned if there is no submenu \param idx: Zero based index of the menu item \return Returns a pointer to the submenu of an item. */ virtual IGUIContextMenu* getSubMenu(u32 idx) const = 0; //! should the element change the checked status on clicking virtual void setItemAutoChecking(u32 idx, bool autoChecking) = 0; //! does the element change the checked status on clicking virtual bool getItemAutoChecking(u32 idx) const = 0; //! When an eventparent is set it receives events instead of the usual parent element virtual void setEventParent(IGUIElement *parent) = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIComboBox.h0000644000000000000000000000464612574354552016051 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_COMBO_BOX_H_INCLUDED__ #define __I_GUI_COMBO_BOX_H_INCLUDED__ #include "IGUIElement.h" namespace irr { namespace gui { //! Combobox widget /** \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_COMBO_BOX_CHANGED */ class IGUIComboBox : public IGUIElement { public: //! constructor IGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_COMBO_BOX, environment, parent, id, rectangle) {} //! Returns amount of items in box virtual u32 getItemCount() const = 0; //! Returns string of an item. the idx may be a value from 0 to itemCount-1 virtual const wchar_t* getItem(u32 idx) const = 0; //! Returns item data of an item. the idx may be a value from 0 to itemCount-1 virtual u32 getItemData(u32 idx) const = 0; //! Returns index based on item data virtual s32 getIndexForItemData(u32 data ) const = 0; //! Adds an item and returns the index of it virtual u32 addItem(const wchar_t* text, u32 data = 0) = 0; //! Removes an item from the combo box. /** Warning. This will change the index of all following items */ virtual void removeItem(u32 idx) = 0; //! Deletes all items in the combo box virtual void clear() = 0; //! Returns id of selected item. returns -1 if no item is selected. virtual s32 getSelected() const = 0; //! Sets the selected item. Set this to -1 if no item should be selected virtual void setSelected(s32 idx) = 0; //! Sets text justification of the text area /** \param horizontal: EGUIA_UPPERLEFT for left justified (default), EGUIA_LOWEERRIGHT for right justified, or EGUIA_CENTER for centered text. \param vertical: EGUIA_UPPERLEFT to align with top edge, EGUIA_LOWEERRIGHT for bottom edge, or EGUIA_CENTER for centered text (default). */ virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) = 0; //! Set the maximal number of rows for the selection listbox virtual void setMaxSelectionRows(u32 max) = 0; //! Get the maximimal number of rows for the selection listbox virtual u32 getMaxSelectionRows() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIColorSelectDialog.h0000644000000000000000000000133312574354552017665 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__ #define __I_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__ #include "IGUIElement.h" namespace irr { namespace gui { //! Standard color chooser dialog. class IGUIColorSelectDialog : public IGUIElement { public: //! constructor IGUIColorSelectDialog(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_COLOR_SELECT_DIALOG, environment, parent, id, rectangle) {} }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUICheckBox.h0000644000000000000000000000166112574354552016021 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_CHECKBOX_H_INCLUDED__ #define __I_GUI_CHECKBOX_H_INCLUDED__ #include "IGUIElement.h" namespace irr { namespace gui { //! GUI Check box interface. /** \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_CHECKBOX_CHANGED */ class IGUICheckBox : public IGUIElement { public: //! constructor IGUICheckBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_CHECK_BOX, environment, parent, id, rectangle) {} //! Set if box is checked. virtual void setChecked(bool checked) = 0; //! Returns true if box is checked. virtual bool isChecked() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGUIButton.h0000644000000000000000000001226212574354552015605 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GUI_BUTTON_H_INCLUDED__ #define __I_GUI_BUTTON_H_INCLUDED__ #include "IGUIElement.h" namespace irr { namespace video { class ITexture; } // end namespace video namespace gui { class IGUIFont; class IGUISpriteBank; enum EGUI_BUTTON_STATE { //! The button is not pressed EGBS_BUTTON_UP=0, //! The button is currently pressed down EGBS_BUTTON_DOWN, //! The mouse cursor is over the button EGBS_BUTTON_MOUSE_OVER, //! The mouse cursor is not over the button EGBS_BUTTON_MOUSE_OFF, //! The button has the focus EGBS_BUTTON_FOCUSED, //! The button doesn't have the focus EGBS_BUTTON_NOT_FOCUSED, //! not used, counts the number of enumerated items EGBS_COUNT }; //! Names for gui button state icons const c8* const GUIButtonStateNames[] = { "buttonUp", "buttonDown", "buttonMouseOver", "buttonMouseOff", "buttonFocused", "buttonNotFocused", 0, 0, }; //! GUI Button interface. /** \par This element can create the following events of type EGUI_EVENT_TYPE: \li EGET_BUTTON_CLICKED */ class IGUIButton : public IGUIElement { public: //! constructor IGUIButton(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_BUTTON, environment, parent, id, rectangle) {} //! Sets another skin independent font. /** If this is set to zero, the button uses the font of the skin. \param font: New font to set. */ virtual void setOverrideFont(IGUIFont* font=0) = 0; //! Gets the override font (if any) /** \return The override font (may be 0) */ virtual IGUIFont* getOverrideFont(void) const = 0; //! Get the font which is used right now for drawing /** Currently this is the override font when one is set and the font of the active skin otherwise */ virtual IGUIFont* getActiveFont() const = 0; //! Sets an image which should be displayed on the button when it is in normal state. /** \param image: Image to be displayed */ virtual void setImage(video::ITexture* image=0) = 0; //! Sets a background image for the button when it is in normal state. /** \param image: Texture containing the image to be displayed \param pos: Position in the texture, where the image is located */ virtual void setImage(video::ITexture* image, const core::rect& pos) = 0; //! Sets a background image for the button when it is in pressed state. /** If no images is specified for the pressed state via setPressedImage(), this image is also drawn in pressed state. \param image: Image to be displayed */ virtual void setPressedImage(video::ITexture* image=0) = 0; //! Sets an image which should be displayed on the button when it is in pressed state. /** \param image: Texture containing the image to be displayed \param pos: Position in the texture, where the image is located */ virtual void setPressedImage(video::ITexture* image, const core::rect& pos) = 0; //! Sets the sprite bank used by the button virtual void setSpriteBank(IGUISpriteBank* bank=0) = 0; //! Sets the animated sprite for a specific button state /** \param index: Number of the sprite within the sprite bank, use -1 for no sprite \param state: State of the button to set the sprite for \param index: The sprite number from the current sprite bank \param color: The color of the sprite \param loop: True if the animation should loop, false if not */ virtual void setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color=video::SColor(255,255,255,255), bool loop=false) = 0; //! Sets if the button should behave like a push button. /** Which means it can be in two states: Normal or Pressed. With a click on the button, the user can change the state of the button. */ virtual void setIsPushButton(bool isPushButton=true) = 0; //! Sets the pressed state of the button if this is a pushbutton virtual void setPressed(bool pressed=true) = 0; //! Returns if the button is currently pressed virtual bool isPressed() const = 0; //! Sets if the alpha channel should be used for drawing background images on the button (default is false) virtual void setUseAlphaChannel(bool useAlphaChannel=true) = 0; //! Returns if the alpha channel should be used for drawing background images on the button virtual bool isAlphaChannelUsed() const = 0; //! Returns whether the button is a push button virtual bool isPushButton() const = 0; //! Sets if the button should use the skin to draw its border and button face (default is true) virtual void setDrawBorder(bool border=true) = 0; //! Returns if the border and button face are being drawn using the skin virtual bool isDrawingBorder() const = 0; //! Sets if the button should scale the button images to fit virtual void setScaleImage(bool scaleImage=true) = 0; //! Checks whether the button scales the used images virtual bool isScalingImage() const = 0; }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IGPUProgrammingServices.h0000644000000000000000000005143012574354552020327 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GPU_PROGRAMMING_SERVICES_H_INCLUDED__ #define __I_GPU_PROGRAMMING_SERVICES_H_INCLUDED__ #include "EShaderTypes.h" #include "EMaterialTypes.h" #include "EPrimitiveTypes.h" #include "path.h" namespace irr { namespace io { class IReadFile; } // end namespace io namespace video { class IVideoDriver; class IShaderConstantSetCallBack; //! Enumeration for different types of shading languages enum E_GPU_SHADING_LANGUAGE { //! The default language, so HLSL for Direct3D and GLSL for OpenGL. EGSL_DEFAULT = 0, //! Cg shading language.*/ EGSL_CG }; //! Interface making it possible to create and use programs running on the GPU. class IGPUProgrammingServices { public: //! Destructor virtual ~IGPUProgrammingServices() {} //! Adds a new high-level shading material renderer to the VideoDriver. /** Currently only HLSL/D3D9 and GLSL/OpenGL are supported. \param vertexShaderProgram String containing the source of the vertex shader program. This can be 0 if no vertex program shall be used. \param vertexShaderEntryPointName Name of the entry function of the vertexShaderProgram (p.e. "main") \param vsCompileTarget Vertex shader version the high level shader shall be compiled to. \param pixelShaderProgram String containing the source of the pixel shader program. This can be 0 if no pixel shader shall be used. \param pixelShaderEntryPointName Entry name of the function of the pixelShaderProgram (p.e. "main") \param psCompileTarget Pixel shader version the high level shader shall be compiled to. \param geometryShaderProgram String containing the source of the geometry shader program. This can be 0 if no geometry shader shall be used. \param geometryShaderEntryPointName Entry name of the function of the geometryShaderProgram (p.e. "main") \param gsCompileTarget Geometry shader version the high level shader shall be compiled to. \param inType Type of vertices passed to geometry shader \param outType Type of vertices created by geometry shader \param verticesOut Maximal number of vertices created by geometry shader. If 0, maximal number supported is assumed. \param callback Pointer to an implementation of IShaderConstantSetCallBack in which you can set the needed vertex, pixel, and geometry shader program constants. Set this to 0 if you don't need this. \param baseMaterial Base material which renderstates will be used to shade the material. \param userData a user data int. This int can be set to any value and will be set as parameter in the callback method when calling OnSetConstants(). In this way it is easily possible to use the same callback method for multiple materials and distinguish between them during the call. \param shaderLang a type of shading language used in current shader. \return Number of the material type which can be set in SMaterial::MaterialType to use the renderer. -1 is returned if an error occured, e.g. if a shader program could not be compiled or a compile target is not reachable. The error strings are then printed to the error log and can be catched with a custom event receiver. */ virtual s32 addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, const c8* geometryShaderProgram, const c8* geometryShaderEntryPointName = "main", E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0, E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) = 0; //! convenience function for use without geometry shaders s32 addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName="main", E_VERTEX_SHADER_TYPE vsCompileTarget=EVST_VS_1_1, const c8* pixelShaderProgram=0, const c8* pixelShaderEntryPointName="main", E_PIXEL_SHADER_TYPE psCompileTarget=EPST_PS_1_1, IShaderConstantSetCallBack* callback=0, E_MATERIAL_TYPE baseMaterial=video::EMT_SOLID, s32 userData=0, E_GPU_SHADING_LANGUAGE shadingLang=EGSL_DEFAULT) { return addHighLevelShaderMaterial( vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, 0, "main", EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, callback, baseMaterial, userData, shadingLang); } //! convenience function for use with many defaults, without geometry shader /** All shader names are set to "main" and compile targets are shader type 1.1. */ s32 addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* pixelShaderProgram=0, IShaderConstantSetCallBack* callback=0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0) { return addHighLevelShaderMaterial( vertexShaderProgram, "main", EVST_VS_1_1, pixelShaderProgram, "main", EPST_PS_1_1, 0, "main", EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, callback, baseMaterial, userData); } //! convenience function for use with many defaults, with geometry shader /** All shader names are set to "main" and compile targets are shader type 1.1 and geometry shader 4.0. */ s32 addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* pixelShaderProgram = 0, const c8* geometryShaderProgram = 0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0 ) { return addHighLevelShaderMaterial( vertexShaderProgram, "main", EVST_VS_1_1, pixelShaderProgram, "main", EPST_PS_1_1, geometryShaderProgram, "main", EGST_GS_4_0, inType, outType, verticesOut, callback, baseMaterial, userData); } //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. /** \param vertexShaderProgramFileName Text file containing the source of the vertex shader program. Set to empty string if no vertex shader shall be created. \param vertexShaderEntryPointName Name of the entry function of the vertexShaderProgram (p.e. "main") \param vsCompileTarget Vertex shader version the high level shader shall be compiled to. \param pixelShaderProgramFileName Text file containing the source of the pixel shader program. Set to empty string if no pixel shader shall be created. \param pixelShaderEntryPointName Entry name of the function of the pixelShaderProgram (p.e. "main") \param psCompileTarget Pixel shader version the high level shader shall be compiled to. \param geometryShaderProgramFileName Name of the source of the geometry shader program. Set to empty string if no geometry shader shall be created. \param geometryShaderEntryPointName Entry name of the function of the geometryShaderProgram (p.e. "main") \param gsCompileTarget Geometry shader version the high level shader shall be compiled to. \param inType Type of vertices passed to geometry shader \param outType Type of vertices created by geometry shader \param verticesOut Maximal number of vertices created by geometry shader. If 0, maximal number supported is assumed. \param callback Pointer to an implementation of IShaderConstantSetCallBack in which you can set the needed vertex, pixel, and geometry shader program constants. Set this to 0 if you don't need this. \param baseMaterial Base material which renderstates will be used to shade the material. \param userData a user data int. This int can be set to any value and will be set as parameter in the callback method when calling OnSetConstants(). In this way it is easily possible to use the same callback method for multiple materials and distinguish between them during the call. \param shaderLang a type of shading language used in current shader. \return Number of the material type which can be set in SMaterial::MaterialType to use the renderer. -1 is returned if an error occured, e.g. if a shader program could not be compiled or a compile target is not reachable. The error strings are then printed to the error log and can be catched with a custom event receiver. */ virtual s32 addHighLevelShaderMaterialFromFiles( const io::path& vertexShaderProgramFileName, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, const io::path& pixelShaderProgramFileName, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, const io::path& geometryShaderProgramFileName, const c8* geometryShaderEntryPointName = "main", E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0, E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) = 0; //! convenience function for use without geometry shaders s32 addHighLevelShaderMaterialFromFiles( const io::path& vertexShaderProgramFileName, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, const io::path& pixelShaderProgramFileName = "", const c8* pixelShaderEntryPointName = "main", E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0, E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) { return addHighLevelShaderMaterialFromFiles( vertexShaderProgramFileName, vertexShaderEntryPointName, vsCompileTarget, pixelShaderProgramFileName, pixelShaderEntryPointName, psCompileTarget, "", "main", EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, callback, baseMaterial, userData, shadingLang); } //! convenience function for use with many defaults, without geometry shader /** All shader names are set to "main" and compile targets are shader type 1.1. */ s32 addHighLevelShaderMaterialFromFiles( const io::path& vertexShaderProgramFileName, const io::path& pixelShaderProgramFileName = "", IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0 ) { return addHighLevelShaderMaterialFromFiles( vertexShaderProgramFileName, "main", EVST_VS_1_1, pixelShaderProgramFileName, "main", EPST_PS_1_1, "", "main", EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, callback, baseMaterial, userData); } //! convenience function for use with many defaults, with geometry shader /** All shader names are set to "main" and compile targets are shader type 1.1 and geometry shader 4.0. */ s32 addHighLevelShaderMaterialFromFiles( const io::path& vertexShaderProgramFileName, const io::path& pixelShaderProgramFileName = "", const io::path& geometryShaderProgramFileName = "", scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0 ) { return addHighLevelShaderMaterialFromFiles( vertexShaderProgramFileName, "main", EVST_VS_1_1, pixelShaderProgramFileName, "main", EPST_PS_1_1, geometryShaderProgramFileName, "main", EGST_GS_4_0, inType, outType, verticesOut, callback, baseMaterial, userData); } //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. /** \param vertexShaderProgram Text file handle containing the source of the vertex shader program. Set to 0 if no vertex shader shall be created. \param vertexShaderEntryPointName Name of the entry function of the vertexShaderProgram \param vsCompileTarget Vertex shader version the high level shader shall be compiled to. \param pixelShaderProgram Text file handle containing the source of the pixel shader program. Set to 0 if no pixel shader shall be created. \param pixelShaderEntryPointName Entry name of the function of the pixelShaderProgram (p.e. "main") \param psCompileTarget Pixel shader version the high level shader shall be compiled to. \param geometryShaderProgram Text file handle containing the source of the geometry shader program. Set to 0 if no geometry shader shall be created. \param geometryShaderEntryPointName Entry name of the function of the geometryShaderProgram (p.e. "main") \param gsCompileTarget Geometry shader version the high level shader shall be compiled to. \param inType Type of vertices passed to geometry shader \param outType Type of vertices created by geometry shader \param verticesOut Maximal number of vertices created by geometry shader. If 0, maximal number supported is assumed. \param callback Pointer to an implementation of IShaderConstantSetCallBack in which you can set the needed vertex and pixel shader program constants. Set this to 0 if you don't need this. \param baseMaterial Base material which renderstates will be used to shade the material. \param userData a user data int. This int can be set to any value and will be set as parameter in the callback method when calling OnSetConstants(). In this way it is easily possible to use the same callback method for multiple materials and distinguish between them during the call. \param shaderLang a type of shading language used in current shader. \return Number of the material type which can be set in SMaterial::MaterialType to use the renderer. -1 is returned if an error occured, e.g. if a shader program could not be compiled or a compile target is not reachable. The error strings are then printed to the error log and can be catched with a custom event receiver. */ virtual s32 addHighLevelShaderMaterialFromFiles( io::IReadFile* vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, io::IReadFile* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, io::IReadFile* geometryShaderProgram, const c8* geometryShaderEntryPointName = "main", E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0, E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) = 0; //! convenience function for use without geometry shaders s32 addHighLevelShaderMaterialFromFiles( io::IReadFile* vertexShaderProgram, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, io::IReadFile* pixelShaderProgram = 0, const c8* pixelShaderEntryPointName = "main", E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0, E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) { return addHighLevelShaderMaterialFromFiles( vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, 0, "main", EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, callback, baseMaterial, userData, shadingLang); } //! Adds a new ASM shader material renderer to the VideoDriver /** Note that it is a good idea to call IVideoDriver::queryFeature() in advance to check if the IVideoDriver supports the vertex and/or pixel shader version your are using. The material is added to the VideoDriver like with IVideoDriver::addMaterialRenderer() and can be used like it had been added with that method. \param vertexShaderProgram String containing the source of the vertex shader program. This can be 0 if no vertex program shall be used. For DX8 programs, the will always input registers look like this: v0: position, v1: normal, v2: color, v3: texture cooridnates, v4: texture coordinates 2 if available. For DX9 programs, you can manually set the registers using the dcl_ statements. \param pixelShaderProgram String containing the source of the pixel shader program. This can be 0 if you don't want to use a pixel shader. \param callback Pointer to an implementation of IShaderConstantSetCallBack in which you can set the needed vertex and pixel shader program constants. Set this to 0 if you don't need this. \param baseMaterial Base material which renderstates will be used to shade the material. \param userData a user data int. This int can be set to any value and will be set as parameter in the callback method when calling OnSetConstants(). In this way it is easily possible to use the same callback method for multiple materials and distinguish between them during the call. \return Returns the number of the material type which can be set in SMaterial::MaterialType to use the renderer. -1 is returned if an error occured. -1 is returned for example if a vertex or pixel shader program could not be compiled, the error strings are then printed out into the error log, and can be catched with a custom event receiver. */ virtual s32 addShaderMaterial(const c8* vertexShaderProgram = 0, const c8* pixelShaderProgram = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0) = 0; //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. /** \param vertexShaderProgram Text file containing the source of the vertex shader program. Set to 0 if no shader shall be created. \param pixelShaderProgram Text file containing the source of the pixel shader program. Set to 0 if no shader shall be created. \param callback Pointer to an IShaderConstantSetCallback object to which the OnSetConstants function is called. \param baseMaterial baseMaterial \param userData a user data int. This int can be set to any value and will be set as parameter in the callback method when calling OnSetConstants(). In this way it is easily possible to use the same callback method for multiple materials and distinguish between them during the call. \return Returns the number of the material type which can be set in SMaterial::MaterialType to use the renderer. -1 is returned if an error occured. -1 is returned for example if a vertex or pixel shader program could not be compiled, the error strings are then printed out into the error log, and can be catched with a custom event receiver. */ virtual s32 addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram, io::IReadFile* pixelShaderProgram, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0) = 0; //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. /** \param vertexShaderProgramFileName Text file name containing the source of the vertex shader program. Set to 0 if no shader shall be created. \param pixelShaderProgramFileName Text file name containing the source of the pixel shader program. Set to 0 if no shader shall be created. \param callback Pointer to an IShaderConstantSetCallback object on which the OnSetConstants function is called. \param baseMaterial baseMaterial \param userData a user data int. This int can be set to any value and will be set as parameter in the callback method when calling OnSetConstants(). In this way it is easily possible to use the same callback method for multiple materials and distinguish between them during the call. \return Returns the number of the material type which can be set in SMaterial::MaterialType to use the renderer. -1 is returned if an error occured. -1 is returned for example if a vertex or pixel shader program could not be compiled, the error strings are then printed out into the error log, and can be catched with a custom event receiver. */ virtual s32 addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName, const io::path& pixelShaderProgramFileName, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0) = 0; }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/IGeometryCreator.h0000644000000000000000000001466612574354552017112 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_GEOMETRY_CREATOR_H_INCLUDED__ #define __I_GEOMETRY_CREATOR_H_INCLUDED__ #include "IReferenceCounted.h" #include "IMesh.h" #include "IImage.h" namespace irr { namespace video { class IVideoDriver; class SMaterial; } namespace scene { //! Helper class for creating geometry on the fly. /** You can get an instance of this class through ISceneManager::getGeometryCreator() */ class IGeometryCreator : public IReferenceCounted { public: //! Creates a simple cube mesh. /** \param size Dimensions of the cube. \return Generated mesh. */ virtual IMesh* createCubeMesh(const core::vector3df& size=core::vector3df(5.f,5.f,5.f)) const =0; //! Create a pseudo-random mesh representing a hilly terrain. /** \param tileSize The size of each tile. \param tileCount The number of tiles in each dimension. \param material The material to apply to the mesh. \param hillHeight The maximum height of the hills. \param countHills The number of hills along each dimension. \param textureRepeatCount The number of times to repeat the material texture along each dimension. \return Generated mesh. */ virtual IMesh* createHillPlaneMesh( const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material, f32 hillHeight, const core::dimension2d& countHills, const core::dimension2d& textureRepeatCount) const =0; //! Create a simple rectangular textured plane mesh. /** \param tileSize The size of each tile. \param tileCount The number of tiles in each dimension. \param material The material to apply to the mesh. \param textureRepeatCount The number of times to repeat the material texture along each dimension. \return Generated mesh. */ IMesh* createPlaneMesh( const core::dimension2d& tileSize, const core::dimension2d& tileCount=core::dimension2du(1,1), video::SMaterial* material=0, const core::dimension2df& textureRepeatCount=core::dimension2df(1.f,1.f)) const { return createHillPlaneMesh(tileSize, tileCount, material, 0.f, core::dimension2df(), textureRepeatCount); } //! Create a terrain mesh from an image representing a heightfield. /** \param texture The texture to apply to the terrain. \param heightmap An image that will be interpreted as a heightmap. The brightness (average color) of each pixel is interpreted as a height, with a 255 brightness pixel producing the maximum height. \param stretchSize The size that each pixel will produce, i.e. a 512x512 heightmap and a stretchSize of (10.f, 20.f) will produce a mesh of size 5120.f x 10240.f \param maxHeight The maximum height of the terrain. \param driver The current video driver. \param defaultVertexBlockSize (to be documented) \param debugBorders (to be documented) \return Generated mesh. */ virtual IMesh* createTerrainMesh(video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize, f32 maxHeight, video::IVideoDriver* driver, const core::dimension2d& defaultVertexBlockSize, bool debugBorders=false) const =0; //! Create an arrow mesh, composed of a cylinder and a cone. /** \param tesselationCylinder Number of quads composing the cylinder. \param tesselationCone Number of triangles composing the cone's roof. \param height Total height of the arrow \param cylinderHeight Total height of the cylinder, should be lesser than total height \param widthCylinder Diameter of the cylinder \param widthCone Diameter of the cone's base, should be not smaller than the cylinder's diameter \param colorCylinder color of the cylinder \param colorCone color of the cone \return Generated mesh. */ virtual IMesh* createArrowMesh(const u32 tesselationCylinder = 4, const u32 tesselationCone = 8, const f32 height = 1.f, const f32 cylinderHeight = 0.6f, const f32 widthCylinder = 0.05f, const f32 widthCone = 0.3f, const video::SColor colorCylinder = 0xFFFFFFFF, const video::SColor colorCone = 0xFFFFFFFF) const =0; //! Create a sphere mesh. /** \param radius Radius of the sphere \param polyCountX Number of quads used for the horizontal tiling \param polyCountY Number of quads used for the vertical tiling \return Generated mesh. */ virtual IMesh* createSphereMesh(f32 radius = 5.f, u32 polyCountX = 16, u32 polyCountY = 16) const =0; //! Create a cylinder mesh. /** \param radius Radius of the cylinder. \param length Length of the cylinder. \param tesselation Number of quads around the circumference of the cylinder. \param color The color of the cylinder. \param closeTop If true, close the ends of the cylinder, otherwise leave them open. \param oblique (to be documented) \return Generated mesh. */ virtual IMesh* createCylinderMesh(f32 radius, f32 length, u32 tesselation, const video::SColor& color=video::SColor(0xffffffff), bool closeTop=true, f32 oblique=0.f) const =0; //! Create a cone mesh. /** \param radius Radius of the cone. \param length Length of the cone. \param tesselation Number of quads around the circumference of the cone. \param colorTop The color of the top of the cone. \param colorBottom The color of the bottom of the cone. \param oblique (to be documented) \return Generated mesh. */ virtual IMesh* createConeMesh(f32 radius, f32 length, u32 tesselation, const video::SColor& colorTop=video::SColor(0xffffffff), const video::SColor& colorBottom=video::SColor(0xffffffff), f32 oblique=0.f) const =0; //! Create a volume light mesh. /** \param subdivideU Horizontal patch count. \param subdivideV Vertical patch count. \param footColor Color at the bottom of the light. \param tailColor Color at the mid of the light. \param lpDistance Virtual distance of the light point for normals. \param lightDim Dimensions of the light. \return Generated mesh. */ virtual IMesh* createVolumeLightMesh( const u32 subdivideU=32, const u32 subdivideV=32, const video::SColor footColor = 0xffffffff, const video::SColor tailColor = 0xffffffff, const f32 lpDistance = 8.f, const core::vector3df& lightDim = core::vector3df(1.f,1.2f,1.f)) const =0; }; } // end namespace scene } // end namespace irr #endif // __I_GEOMETRY_CREATOR_H_INCLUDED__ irrlicht-1.8.3/include/IFileSystem.h0000644000000000000000000004661012574354552016055 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_FILE_SYSTEM_H_INCLUDED__ #define __I_FILE_SYSTEM_H_INCLUDED__ #include "IReferenceCounted.h" #include "IXMLReader.h" #include "IFileArchive.h" namespace irr { namespace video { class IVideoDriver; } // end namespace video namespace io { class IReadFile; class IWriteFile; class IFileList; class IXMLWriter; class IAttributes; //! The FileSystem manages files and archives and provides access to them. /** It manages where files are, so that modules which use the the IO do not need to know where every file is located. A file could be in a .zip-Archive or as file on disk, using the IFileSystem makes no difference to this. */ class IFileSystem : public virtual IReferenceCounted { public: //! Opens a file for read access. /** \param filename: Name of file to open. \return Pointer to the created file interface. The returned pointer should be dropped when no longer needed. See IReferenceCounted::drop() for more information. */ virtual IReadFile* createAndOpenFile(const path& filename) =0; //! Creates an IReadFile interface for accessing memory like a file. /** This allows you to use a pointer to memory where an IReadFile is requested. \param memory: A pointer to the start of the file in memory \param len: The length of the memory in bytes \param fileName: The name given to this file \param deleteMemoryWhenDropped: True if the memory should be deleted along with the IReadFile when it is dropped. \return Pointer to the created file interface. The returned pointer should be dropped when no longer needed. See IReferenceCounted::drop() for more information. */ virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const path& fileName, bool deleteMemoryWhenDropped=false) =0; //! Creates an IReadFile interface for accessing files inside files. /** This is useful e.g. for archives. \param fileName: The name given to this file \param alreadyOpenedFile: Pointer to the enclosing file \param pos: Start of the file inside alreadyOpenedFile \param areaSize: The length of the file \return A pointer to the created file interface. The returned pointer should be dropped when no longer needed. See IReferenceCounted::drop() for more information. */ virtual IReadFile* createLimitReadFile(const path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize) =0; //! Creates an IWriteFile interface for accessing memory like a file. /** This allows you to use a pointer to memory where an IWriteFile is requested. You are responsible for allocating enough memory. \param memory: A pointer to the start of the file in memory (allocated by you) \param len: The length of the memory in bytes \param fileName: The name given to this file \param deleteMemoryWhenDropped: True if the memory should be deleted along with the IWriteFile when it is dropped. \return Pointer to the created file interface. The returned pointer should be dropped when no longer needed. See IReferenceCounted::drop() for more information. */ virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const path& fileName, bool deleteMemoryWhenDropped=false) =0; //! Opens a file for write access. /** \param filename: Name of file to open. \param append: If the file already exist, all write operations are appended to the file. \return Pointer to the created file interface. 0 is returned, if the file could not created or opened for writing. The returned pointer should be dropped when no longer needed. See IReferenceCounted::drop() for more information. */ virtual IWriteFile* createAndWriteFile(const path& filename, bool append=false) =0; //! Adds an archive to the file system. /** After calling this, the Irrlicht Engine will also search and open files directly from this archive. This is useful for hiding data from the end user, speeding up file access and making it possible to access for example Quake3 .pk3 files, which are just renamed .zip files. By default Irrlicht supports ZIP, PAK, TAR, PNK, and directories as archives. You can provide your own archive types by implementing IArchiveLoader and passing an instance to addArchiveLoader. Irrlicht supports AES-encrypted zip files, and the advanced compression techniques lzma and bzip2. \param filename: Filename of the archive to add to the file system. \param ignoreCase: If set to true, files in the archive can be accessed without writing all letters in the right case. \param ignorePaths: If set to true, files in the added archive can be accessed without its complete path. \param archiveType: If no specific E_FILE_ARCHIVE_TYPE is selected then the type of archive will depend on the extension of the file name. If you use a different extension then you can use this parameter to force a specific type of archive. \param password An optional password, which is used in case of encrypted archives. \param retArchive A pointer that will be set to the archive that is added. \return True if the archive was added successfully, false if not. */ virtual bool addFileArchive(const path& filename, bool ignoreCase=true, bool ignorePaths=true, E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN, const core::stringc& password="", IFileArchive** retArchive=0) =0; //! Adds an archive to the file system. /** After calling this, the Irrlicht Engine will also search and open files directly from this archive. This is useful for hiding data from the end user, speeding up file access and making it possible to access for example Quake3 .pk3 files, which are just renamed .zip files. By default Irrlicht supports ZIP, PAK, TAR, PNK, and directories as archives. You can provide your own archive types by implementing IArchiveLoader and passing an instance to addArchiveLoader. Irrlicht supports AES-encrypted zip files, and the advanced compression techniques lzma and bzip2. If you want to add a directory as an archive, prefix its name with a slash in order to let Irrlicht recognize it as a folder mount (mypath/). Using this technique one can build up a search order, because archives are read first, and can be used more easily with relative filenames. \param file: Archive to add to the file system. \param ignoreCase: If set to true, files in the archive can be accessed without writing all letters in the right case. \param ignorePaths: If set to true, files in the added archive can be accessed without its complete path. \param archiveType: If no specific E_FILE_ARCHIVE_TYPE is selected then the type of archive will depend on the extension of the file name. If you use a different extension then you can use this parameter to force a specific type of archive. \param password An optional password, which is used in case of encrypted archives. \param retArchive A pointer that will be set to the archive that is added. \return True if the archive was added successfully, false if not. */ virtual bool addFileArchive(IReadFile* file, bool ignoreCase=true, bool ignorePaths=true, E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN, const core::stringc& password="", IFileArchive** retArchive=0) =0; //! Adds an archive to the file system. /** \param archive: The archive to add to the file system. \return True if the archive was added successfully, false if not. */ virtual bool addFileArchive(IFileArchive* archive) =0; //! Get the number of archives currently attached to the file system virtual u32 getFileArchiveCount() const =0; //! Removes an archive from the file system. /** This will close the archive and free any file handles, but will not close resources which have already been loaded and are now cached, for example textures and meshes. \param index: The index of the archive to remove \return True on success, false on failure */ virtual bool removeFileArchive(u32 index) =0; //! Removes an archive from the file system. /** This will close the archive and free any file handles, but will not close resources which have already been loaded and are now cached, for example textures and meshes. Note that a relative filename might be interpreted differently on each call, depending on the current working directory. In case you want to remove an archive that was added using a relative path name, you have to change to the same working directory again. This means, that the filename given on creation is not an identifier for the archive, but just a usual filename that is used for locating the archive to work with. \param filename The archive pointed to by the name will be removed \return True on success, false on failure */ virtual bool removeFileArchive(const path& filename) =0; //! Removes an archive from the file system. /** This will close the archive and free any file handles, but will not close resources which have already been loaded and are now cached, for example textures and meshes. \param archive The archive to remove. \return True on success, false on failure */ virtual bool removeFileArchive(const IFileArchive* archive) =0; //! Changes the search order of attached archives. /** \param sourceIndex: The index of the archive to change \param relative: The relative change in position, archives with a lower index are searched first */ virtual bool moveFileArchive(u32 sourceIndex, s32 relative) =0; //! Get the archive at a given index. virtual IFileArchive* getFileArchive(u32 index) =0; //! Adds an external archive loader to the engine. /** Use this function to add support for new archive types to the engine, for example proprietary or encrypted file storage. */ virtual void addArchiveLoader(IArchiveLoader* loader) =0; //! Gets the number of archive loaders currently added virtual u32 getArchiveLoaderCount() const = 0; //! Retrieve the given archive loader /** \param index The index of the loader to retrieve. This parameter is an 0-based array index. \return A pointer to the specified loader, 0 if the index is incorrect. */ virtual IArchiveLoader* getArchiveLoader(u32 index) const = 0; //! Adds a zip archive to the file system. /** \deprecated This function is provided for compatibility with older versions of Irrlicht and may be removed in Irrlicht 1.9, you should use addFileArchive instead. After calling this, the Irrlicht Engine will search and open files directly from this archive too. This is useful for hiding data from the end user, speeding up file access and making it possible to access for example Quake3 .pk3 files, which are no different than .zip files. \param filename: Filename of the zip archive to add to the file system. \param ignoreCase: If set to true, files in the archive can be accessed without writing all letters in the right case. \param ignorePaths: If set to true, files in the added archive can be accessed without its complete path. \return True if the archive was added successfully, false if not. */ _IRR_DEPRECATED_ virtual bool addZipFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) { return addFileArchive(filename, ignoreCase, ignorePaths, EFAT_ZIP); } //! Adds an unzipped archive (or basedirectory with subdirectories..) to the file system. /** \deprecated This function is provided for compatibility with older versions of Irrlicht and may be removed in Irrlicht 1.9, you should use addFileArchive instead. Useful for handling data which will be in a zip file \param filename: Filename of the unzipped zip archive base directory to add to the file system. \param ignoreCase: If set to true, files in the archive can be accessed without writing all letters in the right case. \param ignorePaths: If set to true, files in the added archive can be accessed without its complete path. \return True if the archive was added successful, false if not. */ _IRR_DEPRECATED_ virtual bool addFolderFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) { return addFileArchive(filename, ignoreCase, ignorePaths, EFAT_FOLDER); } //! Adds a pak archive to the file system. /** \deprecated This function is provided for compatibility with older versions of Irrlicht and may be removed in Irrlicht 1.9, you should use addFileArchive instead. After calling this, the Irrlicht Engine will search and open files directly from this archive too. This is useful for hiding data from the end user, speeding up file access and making it possible to access for example Quake2/KingPin/Hexen2 .pak files \param filename: Filename of the pak archive to add to the file system. \param ignoreCase: If set to true, files in the archive can be accessed without writing all letters in the right case. \param ignorePaths: If set to true, files in the added archive can be accessed without its complete path.(should not use with Quake2 paks \return True if the archive was added successful, false if not. */ _IRR_DEPRECATED_ virtual bool addPakFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) { return addFileArchive(filename, ignoreCase, ignorePaths, EFAT_PAK); } //! Get the current working directory. /** \return Current working directory as a string. */ virtual const path& getWorkingDirectory() =0; //! Changes the current working directory. /** \param newDirectory: A string specifying the new working directory. The string is operating system dependent. Under Windows it has the form ":\\\<..>". An example would be: "C:\Windows\" \return True if successful, otherwise false. */ virtual bool changeWorkingDirectoryTo(const path& newDirectory) =0; //! Converts a relative path to an absolute (unique) path, resolving symbolic links if required /** \param filename Possibly relative file or directory name to query. \result Absolute filename which points to the same file. */ virtual path getAbsolutePath(const path& filename) const =0; //! Get the directory a file is located in. /** \param filename: The file to get the directory from. \return String containing the directory of the file. */ virtual path getFileDir(const path& filename) const =0; //! Get the base part of a filename, i.e. the name without the directory part. /** If no directory is prefixed, the full name is returned. \param filename: The file to get the basename from \param keepExtension True if filename with extension is returned otherwise everything after the final '.' is removed as well. */ virtual path getFileBasename(const path& filename, bool keepExtension=true) const =0; //! flatten a path and file name for example: "/you/me/../." becomes "/you" virtual path& flattenFilename(path& directory, const path& root="/") const =0; //! Get the relative filename, relative to the given directory virtual path getRelativeFilename(const path& filename, const path& directory) const =0; //! Creates a list of files and directories in the current working directory and returns it. /** \return a Pointer to the created IFileList is returned. After the list has been used it has to be deleted using its IFileList::drop() method. See IReferenceCounted::drop() for more information. */ virtual IFileList* createFileList() =0; //! Creates an empty filelist /** \return a Pointer to the created IFileList is returned. After the list has been used it has to be deleted using its IFileList::drop() method. See IReferenceCounted::drop() for more information. */ virtual IFileList* createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths) =0; //! Set the active type of file system. virtual EFileSystemType setFileListSystem(EFileSystemType listType) =0; //! Determines if a file exists and could be opened. /** \param filename is the string identifying the file which should be tested for existence. \return True if file exists, and false if it does not exist or an error occured. */ virtual bool existFile(const path& filename) const =0; //! Creates a XML Reader from a file which returns all parsed strings as wide characters (wchar_t*). /** Use createXMLReaderUTF8() if you prefer char* instead of wchar_t*. See IIrrXMLReader for more information on how to use the parser. \return 0, if file could not be opened, otherwise a pointer to the created IXMLReader is returned. After use, the reader has to be deleted using its IXMLReader::drop() method. See IReferenceCounted::drop() for more information. */ virtual IXMLReader* createXMLReader(const path& filename) =0; //! Creates a XML Reader from a file which returns all parsed strings as wide characters (wchar_t*). /** Use createXMLReaderUTF8() if you prefer char* instead of wchar_t*. See IIrrXMLReader for more information on how to use the parser. \return 0, if file could not be opened, otherwise a pointer to the created IXMLReader is returned. After use, the reader has to be deleted using its IXMLReader::drop() method. See IReferenceCounted::drop() for more information. */ virtual IXMLReader* createXMLReader(IReadFile* file) =0; //! Creates a XML Reader from a file which returns all parsed strings as ASCII/UTF-8 characters (char*). /** Use createXMLReader() if you prefer wchar_t* instead of char*. See IIrrXMLReader for more information on how to use the parser. \return 0, if file could not be opened, otherwise a pointer to the created IXMLReader is returned. After use, the reader has to be deleted using its IXMLReaderUTF8::drop() method. See IReferenceCounted::drop() for more information. */ virtual IXMLReaderUTF8* createXMLReaderUTF8(const path& filename) =0; //! Creates a XML Reader from a file which returns all parsed strings as ASCII/UTF-8 characters (char*). /** Use createXMLReader() if you prefer wchar_t* instead of char*. See IIrrXMLReader for more information on how to use the parser. \return 0, if file could not be opened, otherwise a pointer to the created IXMLReader is returned. After use, the reader has to be deleted using its IXMLReaderUTF8::drop() method. See IReferenceCounted::drop() for more information. */ virtual IXMLReaderUTF8* createXMLReaderUTF8(IReadFile* file) =0; //! Creates a XML Writer from a file. /** \return 0, if file could not be opened, otherwise a pointer to the created IXMLWriter is returned. After use, the reader has to be deleted using its IXMLWriter::drop() method. See IReferenceCounted::drop() for more information. */ virtual IXMLWriter* createXMLWriter(const path& filename) =0; //! Creates a XML Writer from a file. /** \return 0, if file could not be opened, otherwise a pointer to the created IXMLWriter is returned. After use, the reader has to be deleted using its IXMLWriter::drop() method. See IReferenceCounted::drop() for more information. */ virtual IXMLWriter* createXMLWriter(IWriteFile* file) =0; //! Creates a new empty collection of attributes, usable for serialization and more. /** \param driver: Video driver to be used to load textures when specified as attribute values. Can be null to prevent automatic texture loading by attributes. \return Pointer to the created object. If you no longer need the object, you should call IAttributes::drop(). See IReferenceCounted::drop() for more information. */ virtual IAttributes* createEmptyAttributes(video::IVideoDriver* driver=0) =0; }; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/include/IFileList.h0000644000000000000000000000777012574354552015510 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_FILE_LIST_H_INCLUDED__ #define __I_FILE_LIST_H_INCLUDED__ #include "IReferenceCounted.h" #include "path.h" namespace irr { namespace io { //! Provides a list of files and folders. /** File lists usually contain a list of all files in a given folder, but can also contain a complete directory structure. */ class IFileList : public virtual IReferenceCounted { public: //! Get the number of files in the filelist. /** \return Amount of files and directories in the file list. */ virtual u32 getFileCount() const = 0; //! Gets the name of a file in the list, based on an index. /** The path is not included in this name. Use getFullFileName for this. \param index is the zero based index of the file which name should be returned. The index must be less than the amount getFileCount() returns. \return File name of the file. Returns 0, if an error occured. */ virtual const io::path& getFileName(u32 index) const = 0; //! Gets the full name of a file in the list including the path, based on an index. /** \param index is the zero based index of the file which name should be returned. The index must be less than the amount getFileCount() returns. \return File name of the file. Returns 0 if an error occured. */ virtual const io::path& getFullFileName(u32 index) const = 0; //! Returns the size of a file in the file list, based on an index. /** \param index is the zero based index of the file which should be returned. The index must be less than the amount getFileCount() returns. \return The size of the file in bytes. */ virtual u32 getFileSize(u32 index) const = 0; //! Returns the file offset of a file in the file list, based on an index. /** \param index is the zero based index of the file which should be returned. The index must be less than the amount getFileCount() returns. \return The offset of the file in bytes. */ virtual u32 getFileOffset(u32 index) const = 0; //! Returns the ID of a file in the file list, based on an index. /** This optional ID can be used to link the file list entry to information held elsewhere. For example this could be an index in an IFileArchive, linking the entry to its data offset, uncompressed size and CRC. \param index is the zero based index of the file which should be returned. The index must be less than the amount getFileCount() returns. \return The ID of the file. */ virtual u32 getID(u32 index) const = 0; //! Check if the file is a directory /** \param index The zero based index which will be checked. The index must be less than the amount getFileCount() returns. \return True if the file is a directory, else false. */ virtual bool isDirectory(u32 index) const = 0; //! Searches for a file or folder in the list /** Searches for a file by name \param filename The name of the file to search for. \param isFolder True if you are searching for a directory path, false if you are searching for a file \return Returns the index of the file in the file list, or -1 if no matching name name was found. */ virtual s32 findFile(const io::path& filename, bool isFolder=false) const = 0; //! Returns the base path of the file list virtual const io::path& getPath() const = 0; //! Add as a file or folder to the list /** \param fullPath The file name including path, from the root of the file list. \param isDirectory True if this is a directory rather than a file. \param offset The file offset inside an archive \param size The size of the file in bytes. \param id The ID of the file in the archive which owns it */ virtual u32 addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id=0) = 0; //! Sorts the file list. You should call this after adding any items to the file list virtual void sort() = 0; }; } // end namespace irr } // end namespace io #endif irrlicht-1.8.3/include/IFileArchive.h0000644000000000000000000001065312574354552016150 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt/ Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_FILE_ARCHIVE_H_INCLUDED__ #define __I_FILE_ARCHIVE_H_INCLUDED__ #include "IReadFile.h" #include "IFileList.h" namespace irr { namespace io { //! FileSystemType: which Filesystem should be used for e.g. browsing enum EFileSystemType { FILESYSTEM_NATIVE = 0, // Native OS FileSystem FILESYSTEM_VIRTUAL // Virtual FileSystem }; //! Contains the different types of archives enum E_FILE_ARCHIVE_TYPE { //! A PKZIP archive EFAT_ZIP = MAKE_IRR_ID('Z','I','P', 0), //! A gzip archive EFAT_GZIP = MAKE_IRR_ID('g','z','i','p'), //! A virtual directory EFAT_FOLDER = MAKE_IRR_ID('f','l','d','r'), //! An ID Software PAK archive EFAT_PAK = MAKE_IRR_ID('P','A','K', 0), //! A Nebula Device archive EFAT_NPK = MAKE_IRR_ID('N','P','K', 0), //! A Tape ARchive EFAT_TAR = MAKE_IRR_ID('T','A','R', 0), //! A wad Archive, Quake2, Halflife EFAT_WAD = MAKE_IRR_ID('W','A','D', 0), //! The type of this archive is unknown EFAT_UNKNOWN = MAKE_IRR_ID('u','n','k','n') }; //! The FileArchive manages archives and provides access to files inside them. class IFileArchive : public virtual IReferenceCounted { public: //! Opens a file based on its name /** Creates and returns a new IReadFile for a file in the archive. \param filename The file to open \return Returns A pointer to the created file on success, or 0 on failure. */ virtual IReadFile* createAndOpenFile(const path& filename) =0; //! Opens a file based on its position in the file list. /** Creates and returns \param index The zero based index of the file. \return Returns a pointer to the created file on success, or 0 on failure. */ virtual IReadFile* createAndOpenFile(u32 index) =0; //! Returns the complete file tree /** \return Returns the complete directory tree for the archive, including all files and folders */ virtual const IFileList* getFileList() const =0; //! get the archive type virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_UNKNOWN; } //! An optionally used password string /** This variable is publicly accessible from the interface in order to avoid single access patterns to this place, and hence allow some more obscurity. */ core::stringc Password; }; //! Class which is able to create an archive from a file. /** If you want the Irrlicht Engine be able to load archives of currently unsupported file formats (e.g .wad), then implement this and add your new Archive loader with IFileSystem::addArchiveLoader() to the engine. */ class IArchiveLoader : public virtual IReferenceCounted { public: //! Check if the file might be loaded by this class /** Check based on the file extension (e.g. ".zip") \param filename Name of file to check. \return True if file seems to be loadable. */ virtual bool isALoadableFileFormat(const path& filename) const =0; //! Check if the file might be loaded by this class /** This check may look into the file. \param file File handle to check. \return True if file seems to be loadable. */ virtual bool isALoadableFileFormat(io::IReadFile* file) const =0; //! Check to see if the loader can create archives of this type. /** Check based on the archive type. \param fileType The archive type to check. \return True if the archile loader supports this type, false if not */ virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const =0; //! Creates an archive from the filename /** \param filename File to use. \param ignoreCase Searching is performed without regarding the case \param ignorePaths Files are searched for without checking for the directories \return Pointer to newly created archive, or 0 upon error. */ virtual IFileArchive* createArchive(const path& filename, bool ignoreCase, bool ignorePaths) const =0; //! Creates an archive from the file /** \param file File handle to use. \param ignoreCase Searching is performed without regarding the case \param ignorePaths Files are searched for without checking for the directories \return Pointer to newly created archive, or 0 upon error. */ virtual IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const =0; }; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/include/IEventReceiver.h0000644000000000000000000003623012574354552016534 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_EVENT_RECEIVER_H_INCLUDED__ #define __I_EVENT_RECEIVER_H_INCLUDED__ #include "ILogger.h" #include "Keycodes.h" #include "irrString.h" namespace irr { //! Enumeration for all event types there are. enum EEVENT_TYPE { //! An event of the graphical user interface. /** GUI events are created by the GUI environment or the GUI elements in response to mouse or keyboard events. When a GUI element receives an event it will either process it and return true, or pass the event to its parent. If an event is not absorbed before it reaches the root element then it will then be passed to the user receiver. */ EET_GUI_EVENT = 0, //! A mouse input event. /** Mouse events are created by the device and passed to IrrlichtDevice::postEventFromUser in response to mouse input received from the operating system. Mouse events are first passed to the user receiver, then to the GUI environment and its elements, then finally the input receiving scene manager where it is passed to the active camera. */ EET_MOUSE_INPUT_EVENT, //! A key input event. /** Like mouse events, keyboard events are created by the device and passed to IrrlichtDevice::postEventFromUser. They take the same path as mouse events. */ EET_KEY_INPUT_EVENT, //! A joystick (joypad, gamepad) input event. /** Joystick events are created by polling all connected joysticks once per device run() and then passing the events to IrrlichtDevice::postEventFromUser. They take the same path as mouse events. Windows, SDL: Implemented. Linux: Implemented, with POV hat issues. MacOS / Other: Not yet implemented. */ EET_JOYSTICK_INPUT_EVENT, //! A log event /** Log events are only passed to the user receiver if there is one. If they are absorbed by the user receiver then no text will be sent to the console. */ EET_LOG_TEXT_EVENT, //! A user event with user data. /** This is not used by Irrlicht and can be used to send user specific data though the system. The Irrlicht 'window handle' can be obtained from IrrlichtDevice::getExposedVideoData() The usage and behavior depends on the operating system: Windows: send a WM_USER message to the Irrlicht Window; the wParam and lParam will be used to populate the UserData1 and UserData2 members of the SUserEvent. Linux: send a ClientMessage via XSendEvent to the Irrlicht Window; the data.l[0] and data.l[1] members will be casted to s32 and used as UserData1 and UserData2. MacOS: Not yet implemented */ EET_USER_EVENT, //! This enum is never used, it only forces the compiler to //! compile these enumeration values to 32 bit. EGUIET_FORCE_32_BIT = 0x7fffffff }; //! Enumeration for all mouse input events enum EMOUSE_INPUT_EVENT { //! Left mouse button was pressed down. EMIE_LMOUSE_PRESSED_DOWN = 0, //! Right mouse button was pressed down. EMIE_RMOUSE_PRESSED_DOWN, //! Middle mouse button was pressed down. EMIE_MMOUSE_PRESSED_DOWN, //! Left mouse button was left up. EMIE_LMOUSE_LEFT_UP, //! Right mouse button was left up. EMIE_RMOUSE_LEFT_UP, //! Middle mouse button was left up. EMIE_MMOUSE_LEFT_UP, //! The mouse cursor changed its position. EMIE_MOUSE_MOVED, //! The mouse wheel was moved. Use Wheel value in event data to find out //! in what direction and how fast. EMIE_MOUSE_WHEEL, //! Left mouse button double click. //! This event is generated after the second EMIE_LMOUSE_PRESSED_DOWN event. EMIE_LMOUSE_DOUBLE_CLICK, //! Right mouse button double click. //! This event is generated after the second EMIE_RMOUSE_PRESSED_DOWN event. EMIE_RMOUSE_DOUBLE_CLICK, //! Middle mouse button double click. //! This event is generated after the second EMIE_MMOUSE_PRESSED_DOWN event. EMIE_MMOUSE_DOUBLE_CLICK, //! Left mouse button triple click. //! This event is generated after the third EMIE_LMOUSE_PRESSED_DOWN event. EMIE_LMOUSE_TRIPLE_CLICK, //! Right mouse button triple click. //! This event is generated after the third EMIE_RMOUSE_PRESSED_DOWN event. EMIE_RMOUSE_TRIPLE_CLICK, //! Middle mouse button triple click. //! This event is generated after the third EMIE_MMOUSE_PRESSED_DOWN event. EMIE_MMOUSE_TRIPLE_CLICK, //! No real event. Just for convenience to get number of events EMIE_COUNT }; //! Masks for mouse button states enum E_MOUSE_BUTTON_STATE_MASK { EMBSM_LEFT = 0x01, EMBSM_RIGHT = 0x02, EMBSM_MIDDLE = 0x04, //! currently only on windows EMBSM_EXTRA1 = 0x08, //! currently only on windows EMBSM_EXTRA2 = 0x10, EMBSM_FORCE_32_BIT = 0x7fffffff }; namespace gui { class IGUIElement; //! Enumeration for all events which are sendable by the gui system enum EGUI_EVENT_TYPE { //! A gui element has lost its focus. /** GUIEvent.Caller is losing the focus to GUIEvent.Element. If the event is absorbed then the focus will not be changed. */ EGET_ELEMENT_FOCUS_LOST = 0, //! A gui element has got the focus. /** If the event is absorbed then the focus will not be changed. */ EGET_ELEMENT_FOCUSED, //! The mouse cursor hovered over a gui element. /** If an element has sub-elements you also get this message for the subelements */ EGET_ELEMENT_HOVERED, //! The mouse cursor left the hovered element. /** If an element has sub-elements you also get this message for the subelements */ EGET_ELEMENT_LEFT, //! An element would like to close. /** Windows and context menus use this event when they would like to close, this can be cancelled by absorbing the event. */ EGET_ELEMENT_CLOSED, //! A button was clicked. EGET_BUTTON_CLICKED, //! A scrollbar has changed its position. EGET_SCROLL_BAR_CHANGED, //! A checkbox has changed its check state. EGET_CHECKBOX_CHANGED, //! A new item in a listbox was selected. /** NOTE: You also get this event currently when the same item was clicked again after more than 500 ms. */ EGET_LISTBOX_CHANGED, //! An item in the listbox was selected, which was already selected. /** NOTE: You get the event currently only if the item was clicked again within 500 ms or selected by "enter" or "space". */ EGET_LISTBOX_SELECTED_AGAIN, //! A file has been selected in the file dialog EGET_FILE_SELECTED, //! A directory has been selected in the file dialog EGET_DIRECTORY_SELECTED, //! A file open dialog has been closed without choosing a file EGET_FILE_CHOOSE_DIALOG_CANCELLED, //! 'Yes' was clicked on a messagebox EGET_MESSAGEBOX_YES, //! 'No' was clicked on a messagebox EGET_MESSAGEBOX_NO, //! 'OK' was clicked on a messagebox EGET_MESSAGEBOX_OK, //! 'Cancel' was clicked on a messagebox EGET_MESSAGEBOX_CANCEL, //! In an editbox 'ENTER' was pressed EGET_EDITBOX_ENTER, //! The text in an editbox was changed. This does not include automatic changes in text-breaking. EGET_EDITBOX_CHANGED, //! The marked area in an editbox was changed. EGET_EDITBOX_MARKING_CHANGED, //! The tab was changed in an tab control EGET_TAB_CHANGED, //! A menu item was selected in a (context) menu EGET_MENU_ITEM_SELECTED, //! The selection in a combo box has been changed EGET_COMBO_BOX_CHANGED, //! The value of a spin box has changed EGET_SPINBOX_CHANGED, //! A table has changed EGET_TABLE_CHANGED, EGET_TABLE_HEADER_CHANGED, EGET_TABLE_SELECTED_AGAIN, //! A tree view node lost selection. See IGUITreeView::getLastEventNode(). EGET_TREEVIEW_NODE_DESELECT, //! A tree view node was selected. See IGUITreeView::getLastEventNode(). EGET_TREEVIEW_NODE_SELECT, //! A tree view node was expanded. See IGUITreeView::getLastEventNode(). EGET_TREEVIEW_NODE_EXPAND, //! A tree view node was collapsed. See IGUITreeView::getLastEventNode(). EGET_TREEVIEW_NODE_COLLAPSE, //! deprecated - use EGET_TREEVIEW_NODE_COLLAPSE instead. This //! may be removed by Irrlicht 1.9 EGET_TREEVIEW_NODE_COLLAPS = EGET_TREEVIEW_NODE_COLLAPSE, //! No real event. Just for convenience to get number of events EGET_COUNT }; } // end namespace gui //! SEvents hold information about an event. See irr::IEventReceiver for details on event handling. struct SEvent { //! Any kind of GUI event. struct SGUIEvent { //! IGUIElement who called the event gui::IGUIElement* Caller; //! If the event has something to do with another element, it will be held here. gui::IGUIElement* Element; //! Type of GUI Event gui::EGUI_EVENT_TYPE EventType; }; //! Any kind of mouse event. struct SMouseInput { //! X position of mouse cursor s32 X; //! Y position of mouse cursor s32 Y; //! mouse wheel delta, often 1.0 or -1.0, but can have other values < 0.f or > 0.f; /** Only valid if event was EMIE_MOUSE_WHEEL */ f32 Wheel; //! True if shift was also pressed bool Shift:1; //! True if ctrl was also pressed bool Control:1; //! A bitmap of button states. You can use isButtonPressed() to determine //! if a button is pressed or not. //! Currently only valid if the event was EMIE_MOUSE_MOVED u32 ButtonStates; //! Is the left button pressed down? bool isLeftPressed() const { return 0 != ( ButtonStates & EMBSM_LEFT ); } //! Is the right button pressed down? bool isRightPressed() const { return 0 != ( ButtonStates & EMBSM_RIGHT ); } //! Is the middle button pressed down? bool isMiddlePressed() const { return 0 != ( ButtonStates & EMBSM_MIDDLE ); } //! Type of mouse event EMOUSE_INPUT_EVENT Event; }; //! Any kind of keyboard event. struct SKeyInput { //! Character corresponding to the key (0, if not a character) wchar_t Char; //! Key which has been pressed or released EKEY_CODE Key; //! If not true, then the key was left up bool PressedDown:1; //! True if shift was also pressed bool Shift:1; //! True if ctrl was also pressed bool Control:1; }; //! A joystick event. /** Unlike other events, joystick events represent the result of polling * each connected joystick once per run() of the device. Joystick events will * not be generated by default. If joystick support is available for the * active device, _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ is defined, and * @ref irr::IrrlichtDevice::activateJoysticks() has been called, an event of * this type will be generated once per joystick per @ref IrrlichtDevice::run() * regardless of whether the state of the joystick has actually changed. */ struct SJoystickEvent { enum { NUMBER_OF_BUTTONS = 32, AXIS_X = 0, // e.g. analog stick 1 left to right AXIS_Y, // e.g. analog stick 1 top to bottom AXIS_Z, // e.g. throttle, or analog 2 stick 2 left to right AXIS_R, // e.g. rudder, or analog 2 stick 2 top to bottom AXIS_U, AXIS_V, NUMBER_OF_AXES }; /** A bitmap of button states. You can use IsButtonPressed() to ( check the state of each button from 0 to (NUMBER_OF_BUTTONS - 1) */ u32 ButtonStates; /** For AXIS_X, AXIS_Y, AXIS_Z, AXIS_R, AXIS_U and AXIS_V * Values are in the range -32768 to 32767, with 0 representing * the center position. You will receive the raw value from the * joystick, and so will usually want to implement a dead zone around * the center of the range. Axes not supported by this joystick will * always have a value of 0. On Linux, POV hats are represented as axes, * usually the last two active axis. */ s16 Axis[NUMBER_OF_AXES]; /** The POV represents the angle of the POV hat in degrees * 100, * from 0 to 35,900. A value of 65535 indicates that the POV hat * is centered (or not present). * This value is only supported on Windows. On Linux, the POV hat * will be sent as 2 axes instead. */ u16 POV; //! The ID of the joystick which generated this event. /** This is an internal Irrlicht index; it does not map directly * to any particular hardware joystick. */ u8 Joystick; //! A helper function to check if a button is pressed. bool IsButtonPressed(u32 button) const { if(button >= (u32)NUMBER_OF_BUTTONS) return false; return (ButtonStates & (1 << button)) ? true : false; } }; //! Any kind of log event. struct SLogEvent { //! Pointer to text which has been logged const c8* Text; //! Log level in which the text has been logged ELOG_LEVEL Level; }; //! Any kind of user event. struct SUserEvent { //! Some user specified data as int s32 UserData1; //! Another user specified data as int s32 UserData2; }; EEVENT_TYPE EventType; union { struct SGUIEvent GUIEvent; struct SMouseInput MouseInput; struct SKeyInput KeyInput; struct SJoystickEvent JoystickEvent; struct SLogEvent LogEvent; struct SUserEvent UserEvent; }; }; //! Interface of an object which can receive events. /** Many of the engine's classes inherit IEventReceiver so they are able to process events. Events usually start at a postEventFromUser function and are passed down through a chain of event receivers until OnEvent returns true. See irr::EEVENT_TYPE for a description of where each type of event starts, and the path it takes through the system. */ class IEventReceiver { public: //! Destructor virtual ~IEventReceiver() {} //! Called if an event happened. /** Please take care that you should only return 'true' when you want to _prevent_ Irrlicht * from processing the event any further. So 'true' does mean that an event is completely done. * Therefore your return value for all unprocessed events should be 'false'. \return True if the event was processed. */ virtual bool OnEvent(const SEvent& event) = 0; }; //! Information on a joystick, returned from @ref irr::IrrlichtDevice::activateJoysticks() struct SJoystickInfo { //! The ID of the joystick /** This is an internal Irrlicht index; it does not map directly * to any particular hardware joystick. It corresponds to the * irr::SJoystickEvent Joystick ID. */ u8 Joystick; //! The name that the joystick uses to identify itself. core::stringc Name; //! The number of buttons that the joystick has. u32 Buttons; //! The number of axes that the joystick has, i.e. X, Y, Z, R, U, V. /** Note: with a Linux device, the POV hat (if any) will use two axes. These * will be included in this count. */ u32 Axes; //! An indication of whether the joystick has a POV hat. /** A Windows device will identify the presence or absence or the POV hat. A * Linux device cannot, and will always return POV_HAT_UNKNOWN. */ enum { //! A hat is definitely present. POV_HAT_PRESENT, //! A hat is definitely not present. POV_HAT_ABSENT, //! The presence or absence of a hat cannot be determined. POV_HAT_UNKNOWN } PovHat; }; // struct SJoystickInfo } // end namespace irr #endif irrlicht-1.8.3/include/IDynamicMeshBuffer.h0000644000000000000000000001404012574354552017314 0ustar rootroot// Copyright (C) 2008-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_DYNAMIC_MESH_BUFFER_H_INCLUDED__ #define __I_DYNAMIC_MESH_BUFFER_H_INCLUDED__ #include "IMeshBuffer.h" #include "IVertexBuffer.h" #include "IIndexBuffer.h" namespace irr { namespace scene { /** a dynamic meshBuffer */ class IDynamicMeshBuffer : public IMeshBuffer { public: virtual IVertexBuffer &getVertexBuffer() const =0; virtual IIndexBuffer &getIndexBuffer() const =0; virtual void setVertexBuffer(IVertexBuffer *vertexBuffer) =0; virtual void setIndexBuffer(IIndexBuffer *indexBuffer) =0; //! Get the material of this meshbuffer /** \return Material of this buffer. */ virtual video::SMaterial& getMaterial() =0; //! Get the material of this meshbuffer /** \return Material of this buffer. */ virtual const video::SMaterial& getMaterial() const =0; //! Get the axis aligned bounding box of this meshbuffer. /** \return Axis aligned bounding box of this buffer. */ virtual const core::aabbox3df& getBoundingBox() const =0; //! Set axis aligned bounding box /** \param box User defined axis aligned bounding box to use for this buffer. */ virtual void setBoundingBox(const core::aabbox3df& box) =0; //! Recalculates the bounding box. Should be called if the mesh changed. virtual void recalculateBoundingBox() =0; //! Append the vertices and indices to the current buffer /** Only works for compatible vertex types. \param vertices Pointer to a vertex array. \param numVertices Number of vertices in the array. \param indices Pointer to index array. \param numIndices Number of indices in array. */ virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) { } //! Append the meshbuffer to the current buffer /** Only works for compatible vertex types \param other Buffer to append to this one. */ virtual void append(const IMeshBuffer* const other) { } // ------------------- To be removed? ------------------- // //! get the current hardware mapping hint virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const { return getVertexBuffer().getHardwareMappingHint(); } //! get the current hardware mapping hint virtual E_HARDWARE_MAPPING getHardwareMappingHint_Index() const { return getIndexBuffer().getHardwareMappingHint(); } //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint, E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX ) { if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_VERTEX) getVertexBuffer().setHardwareMappingHint(NewMappingHint); if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_INDEX) getIndexBuffer().setHardwareMappingHint(NewMappingHint); } //! flags the mesh as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX) { if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_VERTEX) getVertexBuffer().setDirty(); if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_INDEX) getIndexBuffer().setDirty(); } virtual u32 getChangedID_Vertex() const { return getVertexBuffer().getChangedID(); } virtual u32 getChangedID_Index() const { return getIndexBuffer().getChangedID(); } // ------------------- Old interface ------------------- // //! Get type of vertex data which is stored in this meshbuffer. /** \return Vertex type of this buffer. */ virtual video::E_VERTEX_TYPE getVertexType() const { return getVertexBuffer().getType(); } //! Get access to vertex data. The data is an array of vertices. /** Which vertex type is used can be determined by getVertexType(). \return Pointer to array of vertices. */ virtual const void* getVertices() const { return getVertexBuffer().getData(); } //! Get access to vertex data. The data is an array of vertices. /** Which vertex type is used can be determined by getVertexType(). \return Pointer to array of vertices. */ virtual void* getVertices() { return getVertexBuffer().getData(); } //! Get amount of vertices in meshbuffer. /** \return Number of vertices in this buffer. */ virtual u32 getVertexCount() const { return getVertexBuffer().size(); } //! Get type of index data which is stored in this meshbuffer. /** \return Index type of this buffer. */ virtual video::E_INDEX_TYPE getIndexType() const { return getIndexBuffer().getType(); } //! Get access to Indices. /** \return Pointer to indices array. */ virtual const u16* getIndices() const { return (u16*)getIndexBuffer().getData(); } //! Get access to Indices. /** \return Pointer to indices array. */ virtual u16* getIndices() { return (u16*)getIndexBuffer().getData(); } //! Get amount of indices in this meshbuffer. /** \return Number of indices in this buffer. */ virtual u32 getIndexCount() const { return getIndexBuffer().size(); } //! returns position of vertex i virtual const core::vector3df& getPosition(u32 i) const { return getVertexBuffer()[i].Pos; } //! returns position of vertex i virtual core::vector3df& getPosition(u32 i) { return getVertexBuffer()[i].Pos; } //! returns texture coords of vertex i virtual const core::vector2df& getTCoords(u32 i) const { return getVertexBuffer()[i].TCoords; } //! returns texture coords of vertex i virtual core::vector2df& getTCoords(u32 i) { return getVertexBuffer()[i].TCoords; } //! returns normal of vertex i virtual const core::vector3df& getNormal(u32 i) const { return getVertexBuffer()[i].Normal; } //! returns normal of vertex i virtual core::vector3df& getNormal(u32 i) { return getVertexBuffer()[i].Normal; } }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IDummyTransformationSceneNode.h0000644000000000000000000000252712574354552021576 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_DUMMY_TRANSFORMATION_SCENE_NODE_H_INCLUDED__ #define __I_DUMMY_TRANSFORMATION_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" namespace irr { namespace scene { //! Dummy scene node for adding additional transformations to the scene graph. /** This scene node does not render itself, and does not respond to set/getPosition, set/getRotation and set/getScale. Its just a simple scene node that takes a matrix as relative transformation, making it possible to insert any transformation anywhere into the scene graph. This scene node is for example used by the IAnimatedMeshSceneNode for emulating joint scene nodes when playing skeletal animations. */ class IDummyTransformationSceneNode : public ISceneNode { public: //! Constructor IDummyTransformationSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id) : ISceneNode(parent, mgr, id) {} //! Returns a reference to the current relative transformation matrix. /** This is the matrix, this scene node uses instead of scale, translation and rotation. */ virtual core::matrix4& getRelativeTransformationMatrix() = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ICursorControl.h0000644000000000000000000001554112574354552016606 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_CURSOR_CONTROL_H_INCLUDED__ #define __I_CURSOR_CONTROL_H_INCLUDED__ #include "IReferenceCounted.h" #include "position2d.h" #include "rect.h" namespace irr { namespace gui { class IGUISpriteBank; //! Default icons for cursors enum ECURSOR_ICON { // Following cursors might be system specific, or might use an Irrlicht icon-set. No guarantees so far. ECI_NORMAL, // arrow ECI_CROSS, // Crosshair ECI_HAND, // Hand ECI_HELP, // Arrow and question mark ECI_IBEAM, // typical text-selection cursor ECI_NO, // should not click icon ECI_WAIT, // hourclass ECI_SIZEALL, // arrow in all directions ECI_SIZENESW, // resizes in direction north-east or south-west ECI_SIZENWSE, // resizes in direction north-west or south-east ECI_SIZENS, // resizes in direction north or south ECI_SIZEWE, // resizes in direction west or east ECI_UP, // up-arrow // Implementer note: Should we add system specific cursors, which use guaranteed the system icons, // then I would recommend using a naming scheme like ECI_W32_CROSS, ECI_X11_CROSSHAIR and adding those // additionally. ECI_COUNT // maximal of defined cursors. Note that higher values can be created at runtime }; //! Names for ECURSOR_ICON const c8* const GUICursorIconNames[ECI_COUNT+1] = { "normal", "cross", "hand", "help", "ibeam", "no", "wait", "sizeall", "sizenesw", "sizenwse", "sizens", "sizewe", "sizeup", 0 }; //! structure used to set sprites as cursors. struct SCursorSprite { SCursorSprite() : SpriteBank(0), SpriteId(-1) { } SCursorSprite( gui::IGUISpriteBank * spriteBank, s32 spriteId, const core::position2d &hotspot=(core::position2d(0,0)) ) : SpriteBank(spriteBank), SpriteId(spriteId), HotSpot(hotspot) { } IGUISpriteBank * SpriteBank; s32 SpriteId; core::position2d HotSpot; }; //! platform specific behavior flags for the cursor enum ECURSOR_PLATFORM_BEHAVIOR { //! default - no platform specific behavior ECPB_NONE = 0, //! On X11 try caching cursor updates as XQueryPointer calls can be expensive. /** Update cursor positions only when the irrlicht timer has been updated or the timer is stopped. This means you usually get one cursor update per device->run() which will be fine in most cases. See this forum-thread for a more detailed explanation: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=45525 */ ECPB_X11_CACHE_UPDATES = 1 }; //! Interface to manipulate the mouse cursor. class ICursorControl : public virtual IReferenceCounted { public: //! Changes the visible state of the mouse cursor. /** \param visible: The new visible state. If true, the cursor will be visible, if false, it will be invisible. */ virtual void setVisible(bool visible) = 0; //! Returns if the cursor is currently visible. /** \return True if the cursor is visible, false if not. */ virtual bool isVisible() const = 0; //! Sets the new position of the cursor. /** The position must be between (0.0f, 0.0f) and (1.0f, 1.0f), where (0.0f, 0.0f) is the top left corner and (1.0f, 1.0f) is the bottom right corner of the render window. \param pos New position of the cursor. */ virtual void setPosition(const core::position2d &pos) = 0; //! Sets the new position of the cursor. /** The position must be between (0.0f, 0.0f) and (1.0f, 1.0f), where (0.0f, 0.0f) is the top left corner and (1.0f, 1.0f) is the bottom right corner of the render window. \param x New x-coord of the cursor. \param y New x-coord of the cursor. */ virtual void setPosition(f32 x, f32 y) = 0; //! Sets the new position of the cursor. /** \param pos: New position of the cursor. The coordinates are pixel units. */ virtual void setPosition(const core::position2d &pos) = 0; //! Sets the new position of the cursor. /** \param x New x-coord of the cursor. The coordinates are pixel units. \param y New y-coord of the cursor. The coordinates are pixel units. */ virtual void setPosition(s32 x, s32 y) = 0; //! Returns the current position of the mouse cursor. /** \return Returns the current position of the cursor. The returned position is the position of the mouse cursor in pixel units. */ virtual const core::position2d& getPosition() = 0; //! Returns the current position of the mouse cursor. /** \return Returns the current position of the cursor. The returned position is a value between (0.0f, 0.0f) and (1.0f, 1.0f), where (0.0f, 0.0f) is the top left corner and (1.0f, 1.0f) is the bottom right corner of the render window. */ virtual core::position2d getRelativePosition() = 0; //! Sets an absolute reference rect for setting and retrieving the cursor position. /** If this rect is set, the cursor position is not being calculated relative to the rendering window but to this rect. You can set the rect pointer to 0 to disable this feature again. This feature is useful when rendering into parts of foreign windows for example in an editor. \param rect: A pointer to an reference rectangle or 0 to disable the reference rectangle.*/ virtual void setReferenceRect(core::rect* rect=0) = 0; //! Sets the active cursor icon /** Setting cursor icons is so far only supported on Win32 and Linux */ virtual void setActiveIcon(ECURSOR_ICON iconId) {} //! Gets the currently active icon virtual ECURSOR_ICON getActiveIcon() const { return gui::ECI_NORMAL; } //! Add a custom sprite as cursor icon. /** \return Identification for the icon */ virtual ECURSOR_ICON addIcon(const gui::SCursorSprite& icon) { return gui::ECI_NORMAL; } //! replace a cursor icon. /** Changing cursor icons is so far only supported on Win32 and Linux Note that this only changes the icons within your application, system cursors outside your application will not be affected. */ virtual void changeIcon(ECURSOR_ICON iconId, const gui::SCursorSprite& sprite) {} //! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work. virtual core::dimension2di getSupportedIconSize() const { return core::dimension2di(0,0); } //! Set platform specific behavior flags. virtual void setPlatformBehavior(ECURSOR_PLATFORM_BEHAVIOR behavior) {} //! Return platform specific behavior. /** \return Behavior set by setPlatformBehavior or ECPB_NONE for platforms not implementing specific behaviors. */ virtual ECURSOR_PLATFORM_BEHAVIOR getPlatformBehavior() const { return ECPB_NONE; } }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/IColladaMeshWriter.h0000644000000000000000000003577212574354552017351 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__ #define __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__ #include "IMeshWriter.h" #include "ISceneNode.h" #include "IAnimatedMesh.h" #include "SMaterial.h" namespace irr { namespace io { class IWriteFile; } // end namespace io namespace scene { //! Lighting models - more or less the way Collada categorizes materials enum E_COLLADA_TECHNIQUE_FX { //! Blinn-phong which is default for opengl and dx fixed function pipelines. //! But several well-known renderers don't support it and prefer phong. ECTF_BLINN, //! Phong shading, default in many external renderers. ECTF_PHONG, //! diffuse shaded surface that is independent of lighting. ECTF_LAMBERT, // constantly shaded surface that is independent of lighting. ECTF_CONSTANT }; //! How to interpret the opacity in collada enum E_COLLADA_TRANSPARENT_FX { //! default - only alpha channel of color or texture is used. ECOF_A_ONE = 0, //! Alpha values for each RGB channel of color or texture are used. ECOF_RGB_ZERO = 1 }; //! Color names collada uses in it's color samplers enum E_COLLADA_COLOR_SAMPLER { ECCS_DIFFUSE, ECCS_AMBIENT, ECCS_EMISSIVE, ECCS_SPECULAR, ECCS_TRANSPARENT, ECCS_REFLECTIVE }; //! Irrlicht colors which can be mapped to E_COLLADA_COLOR_SAMPLER values enum E_COLLADA_IRR_COLOR { //! Don't write this element at all ECIC_NONE, //! Check IColladaMeshWriterProperties for custom color ECIC_CUSTOM, //! Use SMaterial::DiffuseColor ECIC_DIFFUSE, //! Use SMaterial::AmbientColor ECIC_AMBIENT, //! Use SMaterial::EmissiveColor ECIC_EMISSIVE, //! Use SMaterial::SpecularColor ECIC_SPECULAR }; //! Control when geometry elements are created enum E_COLLADA_GEOMETRY_WRITING { //! Default - write each mesh exactly once to collada. Optimal but will not work with many tools. ECGI_PER_MESH, //! Write each mesh as often as it's used with different materials-names in the scene. //! Material names which are used here are created on export, so using the IColladaMeshWriterNames //! interface you have some control over how many geometries are written. ECGI_PER_MESH_AND_MATERIAL }; //! Callback interface for properties which can be used to influence collada writing class IColladaMeshWriterProperties : public virtual IReferenceCounted { public: virtual ~IColladaMeshWriterProperties () {} //! Which lighting model should be used in the technique (FX) section when exporting effects (materials) virtual E_COLLADA_TECHNIQUE_FX getTechniqueFx(const video::SMaterial& material) const = 0; //! Which texture index should be used when writing the texture of the given sampler color. /** \return the index to the texture-layer or -1 if that texture should never be exported Note: for ECCS_TRANSPARENT by default the alpha channel is used, if you want to use RGB you have to set also the ECOF_RGB_ZERO flag in getTransparentFx. */ virtual s32 getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0; //! Return which color from Irrlicht should be used for the color requested by collada /** Note that collada allows exporting either texture or color, not both. So color mapping is only checked if we have no valid texture already. By default we try to return best fits when possible. For example ECCS_DIFFUSE is mapped to ECIC_DIFFUSE. When ECIC_CUSTOM is returned then the result of getCustomColor will be used. */ virtual E_COLLADA_IRR_COLOR getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0; //! Return custom colors for certain color types requested by collada. /** Only used when getColorMapping returns ECIC_CUSTOM for the same paramters. */ virtual video::SColor getCustomColor(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0; //! Return the transparence color interpretation. /** Not this is only about ECCS_TRANSPARENT and does not affect getTransparency. */ virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const = 0; //! Transparency value for that material. /** This value is additional to transparent settings, if both are set they will be multiplicated. \return 1.0 for fully transparent, 0.0 for not transparent and not written at all when < 0.f */ virtual f32 getTransparency(const video::SMaterial& material) const = 0; //! Reflectivity value for that material /** The amount of perfect mirror reflection to be added to the reflected light \return 0.0 - 1.0 for reflectivity and element is not written at all when < 0.f */ virtual f32 getReflectivity(const video::SMaterial& material) const = 0; //! Return index of refraction for that material /** By default we don't write that. \return a value greater equal 0.f to write \ when it is lesser than 0 nothing will be written */ virtual f32 getIndexOfRefraction(const video::SMaterial& material) const = 0; //! Should node be used in scene export? (only needed for scene-writing, ignored in mesh-writing) //! By default all visible nodes are exported. virtual bool isExportable(const irr::scene::ISceneNode * node) const = 0; //! Return the mesh for the given node. If it has no mesh or shouldn't export it's mesh //! you can return 0 in which case only the transformation matrix of the node will be used. // Note: Function is not const because there is no const getMesh() function. virtual IMesh* getMesh(irr::scene::ISceneNode * node) = 0; //! Return if the node has it's own material overwriting the mesh-materials /** Usually true except for mesh-nodes which have isReadOnlyMaterials set. This is mostly important for naming (as ISceneNode::getMaterial() already returns the correct material). You have to override it when exporting custom scenenodes with own materials. \return true => The node's own material is used, false => ignore node material and use the one from the mesh */ virtual bool useNodeMaterial(const scene::ISceneNode* node) const = 0; }; //! Callback interface to use custom names on collada writing. /** You can either modify names and id's written to collada or you can use this interface to just find out which names are used on writing. */ class IColladaMeshWriterNames : public virtual IReferenceCounted { public: virtual ~IColladaMeshWriterNames () {} //! Return a unique name for the given mesh /** Note that names really must be unique here per mesh-pointer, so mostly it's a good idea to return the nameForMesh from IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow the xs::NCName standard to be valid, you can run them through IColladaMeshWriter::toNCName to ensure that. \param mesh Pointer to the mesh which needs a name \param instance When E_COLLADA_GEOMETRY_WRITING is not ECGI_PER_MESH then several instances of the same mesh can be written and this counts them. */ virtual irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance) = 0; //! Return a unique name for the given node /** Note that names really must be unique here per node-pointer, so mostly it's a good idea to return the nameForNode from IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow the xs::NCName standard to be valid, you can run them through IColladaMeshWriter::toNCName to ensure that. */ virtual irr::core::stringw nameForNode(const scene::ISceneNode* node) = 0; //! Return a name for the material /** There is one material created in the writer for each unique name. So you can use this to control the number of materials which get written. For example Irrlicht does by default write one material for each material instanced by a node. So if you know that in your application material instances per node are identical between different nodes you can reduce the number of exported materials using that knowledge by using identical names for such shared materials. Names must follow the xs::NCName standard to be valid, you can run them through IColladaMeshWriter::toNCName to ensure that. */ virtual irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) = 0; }; //! Interface for writing meshes class IColladaMeshWriter : public IMeshWriter { public: IColladaMeshWriter() : Properties(0), DefaultProperties(0), NameGenerator(0), DefaultNameGenerator(0) , WriteTextures(true), WriteDefaultScene(true), ExportSMaterialOnce(true) , AmbientLight(0.f, 0.f, 0.f, 1.f) , GeometryWriting(ECGI_PER_MESH) { } //! Destructor virtual ~IColladaMeshWriter() { if ( Properties ) Properties->drop(); if ( DefaultProperties ) DefaultProperties->drop(); if ( NameGenerator ) NameGenerator->drop(); if ( DefaultNameGenerator ) DefaultNameGenerator->drop(); } //! writes a scene starting with the given node virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root) = 0; //! Set if texture information should be written virtual void setWriteTextures(bool write) { WriteTextures = write; } //! Get if texture information should be written virtual bool getWriteTextures() const { return WriteTextures; } //! Set if a default scene should be written when writing meshes. /** Many collada readers fail to read a mesh if the collada files doesn't contain a scene as well. The scene is doing an instantiation of the mesh. When using writeScene this flag is ignored (as we have scene there already) */ virtual void setWriteDefaultScene(bool write) { WriteDefaultScene = write; } //! Get if a default scene should be written virtual bool getWriteDefaultScene() const { return WriteDefaultScene; } //! Sets ambient color of the scene to write virtual void setAmbientLight(const video::SColorf &ambientColor) { AmbientLight = ambientColor; } //! Return ambient light of the scene which is written virtual video::SColorf getAmbientLight() const { return AmbientLight; } //! Control when and how often a mesh is written /** Optimally ECGI_PER_MESH would be always sufficent - writing geometry once per mesh. Unfortunately many tools (at the time of writing this nearly all of them) have trouble on import when different materials are used per node. So when you override materials per node and importing the resuling collada has materials problems in other tools try using other values here. \param writeStyle One of the E_COLLADA_GEOMETRY_WRITING settings. */ virtual void setGeometryWriting(E_COLLADA_GEOMETRY_WRITING writeStyle) { GeometryWriting = writeStyle; } //! Get the current style of geometry writing. virtual E_COLLADA_GEOMETRY_WRITING getGeometryWriting() const { return GeometryWriting; } //! Make certain there is only one collada material generated per Irrlicht material /** Checks before creating a collada material-name if an identical irr:::video::SMaterial has been exported already. If so don't export it with another name. This is set by default and leads to way smaller .dae files. Note that if you need to disable this flag for some reason you can still get a similar effect using the IColladaMeshWriterNames::nameForMaterial by returning identical names for identical materials there. */ virtual void setExportSMaterialsOnlyOnce(bool exportOnce) { ExportSMaterialOnce = exportOnce; } virtual bool getExportSMaterialsOnlyOnce() const { return ExportSMaterialOnce; } //! Set properties to use by the meshwriter instead of it's default properties. /** Overloading properties with an own class allows modifying the writing process in certain ways. By default properties are set to the DefaultProperties. */ virtual void setProperties(IColladaMeshWriterProperties * p) { if ( p == Properties ) return; if ( p ) p->grab(); if ( Properties ) Properties->drop(); Properties = p; } //! Get properties which are currently used. virtual IColladaMeshWriterProperties * getProperties() const { return Properties; } //! Return the original default properties of the writer. /** You can use this pointer in your own properties to access and return default values. */ IColladaMeshWriterProperties * getDefaultProperties() const { return DefaultProperties; } //! Install a generator to create custom names on export. virtual void setNameGenerator(IColladaMeshWriterNames * nameGenerator) { if ( nameGenerator == NameGenerator ) return; if ( nameGenerator ) nameGenerator->grab(); if ( NameGenerator ) NameGenerator->drop(); NameGenerator = nameGenerator; } //! Get currently used name generator virtual IColladaMeshWriterNames * getNameGenerator() const { return NameGenerator; } //! Return the original default name generator of the writer. /** You can use this pointer in your own generator to access and return default values. */ IColladaMeshWriterNames * getDefaultNameGenerator() const { return DefaultNameGenerator; } //! Restrict the characters of oldString a set of allowed characters in xs::NCName and add the prefix. /** A tool function to help when using a custom name generator to generative valid names for collada names and id's. */ virtual irr::core::stringw toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix=irr::core::stringw(L"_NC_")) const = 0; protected: // NOTE: You usually should also call setProperties with the same paraemter when using setDefaultProperties virtual void setDefaultProperties(IColladaMeshWriterProperties * p) { if ( p == DefaultProperties ) return; if ( p ) p->grab(); if ( DefaultProperties ) DefaultProperties->drop(); DefaultProperties = p; } // NOTE: You usually should also call setNameGenerator with the same paraemter when using setDefaultProperties virtual void setDefaultNameGenerator(IColladaMeshWriterNames * p) { if ( p == DefaultNameGenerator ) return; if ( p ) p->grab(); if ( DefaultNameGenerator ) DefaultNameGenerator->drop(); DefaultNameGenerator = p; } private: IColladaMeshWriterProperties * Properties; IColladaMeshWriterProperties * DefaultProperties; IColladaMeshWriterNames * NameGenerator; IColladaMeshWriterNames * DefaultNameGenerator; bool WriteTextures; bool WriteDefaultScene; bool ExportSMaterialOnce; video::SColorf AmbientLight; E_COLLADA_GEOMETRY_WRITING GeometryWriting; }; } // end namespace } // end namespace #endif irrlicht-1.8.3/include/ICameraSceneNode.h0000644000000000000000000001742412574354552016746 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_CAMERA_SCENE_NODE_H_INCLUDED__ #define __I_CAMERA_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" #include "IEventReceiver.h" namespace irr { namespace scene { struct SViewFrustum; //! Scene Node which is a (controlable) camera. /** The whole scene will be rendered from the cameras point of view. Because the ICameraScenNode is a SceneNode, it can be attached to any other scene node, and will follow its parents movement, rotation and so on. */ class ICameraSceneNode : public ISceneNode, public IEventReceiver { public: //! Constructor ICameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f)) : ISceneNode(parent, mgr, id, position, rotation, scale), IsOrthogonal(false) {} //! Sets the projection matrix of the camera. /** The core::matrix4 class has some methods to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH. Note that the matrix will only stay as set by this method until one of the following Methods are called: setNearValue, setFarValue, setAspectRatio, setFOV. \param projection The new projection matrix of the camera. \param isOrthogonal Set this to true if the matrix is an orthogonal one (e.g. from matrix4::buildProjectionMatrixOrtho). */ virtual void setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal=false) =0; //! Gets the current projection matrix of the camera. /** \return The current projection matrix of the camera. */ virtual const core::matrix4& getProjectionMatrix() const =0; //! Gets the current view matrix of the camera. /** \return The current view matrix of the camera. */ virtual const core::matrix4& getViewMatrix() const =0; //! Sets a custom view matrix affector. /** The matrix passed here, will be multiplied with the view matrix when it gets updated. This allows for custom camera setups like, for example, a reflection camera. \param affector The affector matrix. */ virtual void setViewMatrixAffector(const core::matrix4& affector) =0; //! Get the custom view matrix affector. /** \return The affector matrix. */ virtual const core::matrix4& getViewMatrixAffector() const =0; //! It is possible to send mouse and key events to the camera. /** Most cameras may ignore this input, but camera scene nodes which are created for example with ISceneManager::addCameraSceneNodeMaya or ISceneManager::addCameraSceneNodeFPS, may want to get this input for changing their position, look at target or whatever. */ virtual bool OnEvent(const SEvent& event) =0; //! Sets the look at target of the camera /** If the camera's target and rotation are bound ( @see bindTargetAndRotation() ) then calling this will also change the camera's scene node rotation to match the target. Note that setTarget uses the current absolute position internally, so if you changed setPosition since last rendering you must call updateAbsolutePosition before using this function. \param pos Look at target of the camera, in world co-ordinates. */ virtual void setTarget(const core::vector3df& pos) =0; //! Sets the rotation of the node. /** This only modifies the relative rotation of the node. If the camera's target and rotation are bound ( @see bindTargetAndRotation() ) then calling this will also change the camera's target to match the rotation. \param rotation New rotation of the node in degrees. */ virtual void setRotation(const core::vector3df& rotation) =0; //! Gets the current look at target of the camera /** \return The current look at target of the camera, in world co-ordinates */ virtual const core::vector3df& getTarget() const =0; //! Sets the up vector of the camera. /** \param pos: New upvector of the camera. */ virtual void setUpVector(const core::vector3df& pos) =0; //! Gets the up vector of the camera. /** \return The up vector of the camera, in world space. */ virtual const core::vector3df& getUpVector() const =0; //! Gets the value of the near plane of the camera. /** \return The value of the near plane of the camera. */ virtual f32 getNearValue() const =0; //! Gets the value of the far plane of the camera. /** \return The value of the far plane of the camera. */ virtual f32 getFarValue() const =0; //! Gets the aspect ratio of the camera. /** \return The aspect ratio of the camera. */ virtual f32 getAspectRatio() const =0; //! Gets the field of view of the camera. /** \return The field of view of the camera in radians. */ virtual f32 getFOV() const =0; //! Sets the value of the near clipping plane. (default: 1.0f) /** \param zn: New z near value. */ virtual void setNearValue(f32 zn) =0; //! Sets the value of the far clipping plane (default: 2000.0f) /** \param zf: New z far value. */ virtual void setFarValue(f32 zf) =0; //! Sets the aspect ratio (default: 4.0f / 3.0f) /** \param aspect: New aspect ratio. */ virtual void setAspectRatio(f32 aspect) =0; //! Sets the field of view (Default: PI / 2.5f) /** \param fovy: New field of view in radians. */ virtual void setFOV(f32 fovy) =0; //! Get the view frustum. /** Needed sometimes by bspTree or LOD render nodes. \return The current view frustum. */ virtual const SViewFrustum* getViewFrustum() const =0; //! Disables or enables the camera to get key or mouse inputs. /** If this is set to true, the camera will respond to key inputs otherwise not. */ virtual void setInputReceiverEnabled(bool enabled) =0; //! Checks if the input receiver of the camera is currently enabled. virtual bool isInputReceiverEnabled() const =0; //! Checks if a camera is orthogonal. virtual bool isOrthogonal() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return IsOrthogonal; } //! Binds the camera scene node's rotation to its target position and vice vera, or unbinds them. /** When bound, calling setRotation() will update the camera's target position to be along its +Z axis, and likewise calling setTarget() will update its rotation so that its +Z axis will point at the target point. FPS camera use this binding by default; other cameras do not. \param bound True to bind the camera's scene node rotation and targetting, false to unbind them. @see getTargetAndRotationBinding() */ virtual void bindTargetAndRotation(bool bound) =0; //! Queries if the camera scene node's rotation and its target position are bound together. /** @see bindTargetAndRotation() */ virtual bool getTargetAndRotationBinding(void) const =0; //! Writes attributes of the camera node virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { ISceneNode::serializeAttributes(out, options); if (!out) return; out->addBool ("IsOrthogonal", IsOrthogonal ); } //! Reads attributes of the camera node virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { ISceneNode::deserializeAttributes(in, options); if (!in) return; if ( in->findAttribute("IsOrthogonal") ) IsOrthogonal = in->getAttributeAsBool("IsOrthogonal"); } protected: void cloneMembers(ICameraSceneNode* toCopyFrom) { IsOrthogonal = toCopyFrom->IsOrthogonal; } bool IsOrthogonal; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IBoneSceneNode.h0000644000000000000000000000557612574354552016446 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_BONE_SCENE_NODE_H_INCLUDED__ #define __I_BONE_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" namespace irr { namespace scene { //! Enumeration for different bone animation modes enum E_BONE_ANIMATION_MODE { //! The bone is usually animated, unless it's parent is not animated EBAM_AUTOMATIC=0, //! The bone is animated by the skin, if it's parent is not animated then animation will resume from this bone onward EBAM_ANIMATED, //! The bone is not animated by the skin EBAM_UNANIMATED, //! Not an animation mode, just here to count the available modes EBAM_COUNT }; enum E_BONE_SKINNING_SPACE { //! local skinning, standard EBSS_LOCAL=0, //! global skinning EBSS_GLOBAL, EBSS_COUNT }; //! Names for bone animation modes const c8* const BoneAnimationModeNames[] = { "automatic", "animated", "unanimated", 0, }; //! Interface for bones used for skeletal animation. /** Used with ISkinnedMesh and IAnimatedMeshSceneNode. */ class IBoneSceneNode : public ISceneNode { public: IBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id=-1) : ISceneNode(parent, mgr, id),positionHint(-1),scaleHint(-1),rotationHint(-1) { } //! Get the name of the bone /** \deprecated Use getName instead. This method may be removed by Irrlicht 1.9 */ _IRR_DEPRECATED_ virtual const c8* getBoneName() const { return getName(); } //! Get the index of the bone virtual u32 getBoneIndex() const = 0; //! Sets the animation mode of the bone. /** \return True if successful. (Unused) */ virtual bool setAnimationMode(E_BONE_ANIMATION_MODE mode) = 0; //! Gets the current animation mode of the bone virtual E_BONE_ANIMATION_MODE getAnimationMode() const = 0; //! Get the axis aligned bounding box of this node virtual const core::aabbox3d& getBoundingBox() const = 0; //! Returns the relative transformation of the scene node. //virtual core::matrix4 getRelativeTransformation() const = 0; //! The animation method. virtual void OnAnimate(u32 timeMs) =0; //! The render method. /** Does nothing as bones are not visible. */ virtual void render() { } //! How the relative transformation of the bone is used virtual void setSkinningSpace( E_BONE_SKINNING_SPACE space ) =0; //! How the relative transformation of the bone is used virtual E_BONE_SKINNING_SPACE getSkinningSpace() const =0; //! Updates the absolute position based on the relative and the parents position virtual void updateAbsolutePositionOfAllChildren()=0; s32 positionHint; s32 scaleHint; s32 rotationHint; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IBillboardTextSceneNode.h0000644000000000000000000000405712574354552020313 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_BILLBOARD_TEXT_SCENE_NODE_H_INCLUDED__ #define __I_BILLBOARD_TEXT_SCENE_NODE_H_INCLUDED__ #include "IBillboardSceneNode.h" namespace irr { namespace scene { //! A billboard text scene node. /** Acts like a billboard which displays the currently set text. Due to the exclusion of RTTI in Irrlicht we have to avoid multiple inheritance. Hence, changes to the ITextSceneNode interface have to be copied here manually. */ class IBillboardTextSceneNode : public IBillboardSceneNode { public: //! Constructor IBillboardTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0)) : IBillboardSceneNode(parent, mgr, id, position) {} //! Sets the size of the billboard. virtual void setSize(const core::dimension2d& size) = 0; //! Returns the size of the billboard. virtual const core::dimension2d& getSize() const = 0; //! Set the color of all vertices of the billboard /** \param overallColor: the color to set */ virtual void setColor(const video::SColor & overallColor) = 0; //! Set the color of the top and bottom vertices of the billboard /** \param topColor: the color to set the top vertices \param bottomColor: the color to set the bottom vertices */ virtual void setColor(const video::SColor & topColor, const video::SColor & bottomColor) = 0; //! Gets the color of the top and bottom vertices of the billboard /** \param topColor: stores the color of the top vertices \param bottomColor: stores the color of the bottom vertices */ virtual void getColor(video::SColor & topColor, video::SColor & bottomColor) const = 0; //! sets the text string virtual void setText(const wchar_t* text) = 0; //! sets the color of the text virtual void setTextColor(video::SColor color) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IBillboardSceneNode.h0000644000000000000000000000535712574354552017452 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_BILLBOARD_SCENE_NODE_H_INCLUDED__ #define __I_BILLBOARD_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" namespace irr { namespace scene { //! A billboard scene node. /** A billboard is like a 3d sprite: A 2d element, which always looks to the camera. It is usually used for explosions, fire, lensflares, particles and things like that. */ class IBillboardSceneNode : public ISceneNode { public: //! Constructor IBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0)) : ISceneNode(parent, mgr, id, position) {} //! Sets the size of the billboard, making it rectangular. virtual void setSize(const core::dimension2d& size) = 0; //! Sets the size of the billboard with independent widths of the bottom and top edges. /** \param[in] height The height of the billboard. \param[in] bottomEdgeWidth The width of the bottom edge of the billboard. \param[in] topEdgeWidth The width of the top edge of the billboard. */ virtual void setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth) = 0; //! Returns the size of the billboard. /** This will return the width of the bottom edge of the billboard. Use getWidths() to retrieve the bottom and top edges independently. \return Size of the billboard. */ virtual const core::dimension2d& getSize() const = 0; //! Gets the size of the the billboard and handles independent top and bottom edge widths correctly. /** \param[out] height The height of the billboard. \param[out] bottomEdgeWidth The width of the bottom edge of the billboard. \param[out] topEdgeWidth The width of the top edge of the billboard. */ virtual void getSize(f32& height, f32& bottomEdgeWidth, f32& topEdgeWidth) const =0; //! Set the color of all vertices of the billboard /** \param[in] overallColor Color to set */ virtual void setColor(const video::SColor& overallColor) = 0; //! Set the color of the top and bottom vertices of the billboard /** \param[in] topColor Color to set the top vertices \param[in] bottomColor Color to set the bottom vertices */ virtual void setColor(const video::SColor& topColor, const video::SColor& bottomColor) = 0; //! Gets the color of the top and bottom vertices of the billboard /** \param[out] topColor Stores the color of the top vertices \param[out] bottomColor Stores the color of the bottom vertices */ virtual void getColor(video::SColor& topColor, video::SColor& bottomColor) const = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IAttributes.h0000644000000000000000000006363612574354552016126 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_ATTRIBUTES_H_INCLUDED__ #define __I_ATTRIBUTES_H_INCLUDED__ #include "IReferenceCounted.h" #include "SColor.h" #include "vector3d.h" #include "vector2d.h" #include "line2d.h" #include "line3d.h" #include "triangle3d.h" #include "position2d.h" #include "rect.h" #include "dimension2d.h" #include "matrix4.h" #include "quaternion.h" #include "plane3d.h" #include "triangle3d.h" #include "line2d.h" #include "line3d.h" #include "irrString.h" #include "irrArray.h" #include "IXMLReader.h" #include "EAttributes.h" #include "path.h" namespace irr { namespace video { class ITexture; } // end namespace video namespace io { class IXMLWriter; //! Provides a generic interface for attributes and their values and the possiblity to serialize them class IAttributes : public virtual IReferenceCounted { public: //! Returns amount of attributes in this collection of attributes. virtual u32 getAttributeCount() const = 0; //! Returns attribute name by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual const c8* getAttributeName(s32 index) = 0; //! Returns the type of an attribute //! \param attributeName: Name for the attribute virtual E_ATTRIBUTE_TYPE getAttributeType(const c8* attributeName) = 0; //! Returns attribute type by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual E_ATTRIBUTE_TYPE getAttributeType(s32 index) = 0; //! Returns the type string of the attribute //! \param attributeName: String for the attribute type virtual const wchar_t* getAttributeTypeString(const c8* attributeName) = 0; //! Returns the type string of the attribute by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual const wchar_t* getAttributeTypeString(s32 index) = 0; //! Returns if an attribute with a name exists virtual bool existsAttribute(const c8* attributeName) = 0; //! Returns attribute index from name, -1 if not found virtual s32 findAttribute(const c8* attributeName) const =0; //! Removes all attributes virtual void clear() = 0; //! Reads attributes from a xml file. //! \param reader The XML reader to read from //! \param readCurrentElementOnly If set to true, reading only works if current element has the name 'attributes' or //! the name specified using elementName. //! \param elementName The surrounding element name. If it is null, the default one, "attributes" will be taken. //! If set to false, the first appearing list of attributes are read. virtual bool read(io::IXMLReader* reader, bool readCurrentElementOnly=false, const wchar_t* elementName=0) = 0; //! Write these attributes into a xml file //! \param writer: The XML writer to write to //! \param writeXMLHeader: Writes a header to the XML file, required if at the beginning of the file //! \param elementName: The surrounding element name. If it is null, the default one, "attributes" will be taken. virtual bool write(io::IXMLWriter* writer, bool writeXMLHeader=false, const wchar_t* elementName=0) = 0; /* Integer Attribute */ //! Adds an attribute as integer virtual void addInt(const c8* attributeName, s32 value) = 0; //! Sets an attribute as integer value virtual void setAttribute(const c8* attributeName, s32 value) = 0; //! Gets an attribute as integer value //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual s32 getAttributeAsInt(const c8* attributeName) const =0; //! Gets an attribute as integer value //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual s32 getAttributeAsInt(s32 index) const =0; //! Sets an attribute as integer value virtual void setAttribute(s32 index, s32 value) = 0; /* Float Attribute */ //! Adds an attribute as float virtual void addFloat(const c8* attributeName, f32 value) = 0; //! Sets a attribute as float value virtual void setAttribute(const c8* attributeName, f32 value) = 0; //! Gets an attribute as float value //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual f32 getAttributeAsFloat(const c8* attributeName) = 0; //! Gets an attribute as float value //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual f32 getAttributeAsFloat(s32 index) = 0; //! Sets an attribute as float value virtual void setAttribute(s32 index, f32 value) = 0; /* String Attribute */ //! Adds an attribute as string virtual void addString(const c8* attributeName, const c8* value) = 0; //! Sets an attribute value as string. //! \param attributeName: Name for the attribute //! \param value: Value for the attribute. Set this to 0 to delete the attribute virtual void setAttribute(const c8* attributeName, const c8* value) = 0; //! Gets an attribute as string. //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() //! or 0 if attribute is not set. virtual core::stringc getAttributeAsString(const c8* attributeName) = 0; //! Gets an attribute as string. //! \param attributeName Name of the attribute to get. //! \param target Buffer where the string is copied to. virtual void getAttributeAsString(const c8* attributeName, c8* target) = 0; //! Returns attribute value as string by index. //! \param index Index value, must be between 0 and getAttributeCount()-1. virtual core::stringc getAttributeAsString(s32 index) = 0; //! Sets an attribute value as string. //! \param index Index value, must be between 0 and getAttributeCount()-1. //! \param value String to which the attribute is set. virtual void setAttribute(s32 index, const c8* value) = 0; // wide strings //! Adds an attribute as string virtual void addString(const c8* attributeName, const wchar_t* value) = 0; //! Sets an attribute value as string. //! \param attributeName: Name for the attribute //! \param value: Value for the attribute. Set this to 0 to delete the attribute virtual void setAttribute(const c8* attributeName, const wchar_t* value) = 0; //! Gets an attribute as string. //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() //! or 0 if attribute is not set. virtual core::stringw getAttributeAsStringW(const c8* attributeName) = 0; //! Gets an attribute as string. //! \param attributeName: Name of the attribute to get. //! \param target: Buffer where the string is copied to. virtual void getAttributeAsStringW(const c8* attributeName, wchar_t* target) = 0; //! Returns attribute value as string by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::stringw getAttributeAsStringW(s32 index) = 0; //! Sets an attribute value as string. //! \param index Index value, must be between 0 and getAttributeCount()-1. //! \param value String to which the attribute is set. virtual void setAttribute(s32 index, const wchar_t* value) = 0; /* Binary Data Attribute */ //! Adds an attribute as binary data virtual void addBinary(const c8* attributeName, void* data, s32 dataSizeInBytes) = 0; //! Sets an attribute as binary data virtual void setAttribute(const c8* attributeName, void* data, s32 dataSizeInBytes ) = 0; //! Gets an attribute as binary data /** \param attributeName: Name of the attribute to get. \param outData Pointer to buffer where data shall be stored. \param maxSizeInBytes Maximum number of bytes to write into outData. */ virtual void getAttributeAsBinaryData(const c8* attributeName, void* outData, s32 maxSizeInBytes) = 0; //! Gets an attribute as binary data /** \param index: Index value, must be between 0 and getAttributeCount()-1. \param outData Pointer to buffer where data shall be stored. \param maxSizeInBytes Maximum number of bytes to write into outData. */ virtual void getAttributeAsBinaryData(s32 index, void* outData, s32 maxSizeInBytes) = 0; //! Sets an attribute as binary data virtual void setAttribute(s32 index, void* data, s32 dataSizeInBytes ) = 0; /* Array Attribute */ //! Adds an attribute as wide string array virtual void addArray(const c8* attributeName, const core::array& value) = 0; //! Sets an attribute value as a wide string array. //! \param attributeName: Name for the attribute //! \param value: Value for the attribute. Set this to 0 to delete the attribute virtual void setAttribute(const c8* attributeName, const core::array& value) = 0; //! Gets an attribute as an array of wide strings. //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() //! or 0 if attribute is not set. virtual core::array getAttributeAsArray(const c8* attributeName) = 0; //! Returns attribute value as an array of wide strings by index. //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::array getAttributeAsArray(s32 index) = 0; //! Sets an attribute as an array of wide strings virtual void setAttribute(s32 index, const core::array& value) = 0; /* Bool Attribute */ //! Adds an attribute as bool virtual void addBool(const c8* attributeName, bool value) = 0; //! Sets an attribute as boolean value virtual void setAttribute(const c8* attributeName, bool value) = 0; //! Gets an attribute as boolean value //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual bool getAttributeAsBool(const c8* attributeName) = 0; //! Gets an attribute as boolean value //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual bool getAttributeAsBool(s32 index) = 0; //! Sets an attribute as boolean value virtual void setAttribute(s32 index, bool value) = 0; /* Enumeration Attribute */ //! Adds an attribute as enum virtual void addEnum(const c8* attributeName, const c8* enumValue, const c8* const* enumerationLiterals) = 0; //! Adds an attribute as enum virtual void addEnum(const c8* attributeName, s32 enumValue, const c8* const* enumerationLiterals) = 0; //! Sets an attribute as enumeration virtual void setAttribute(const c8* attributeName, const c8* enumValue, const c8* const* enumerationLiterals) = 0; //! Gets an attribute as enumeration //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual const c8* getAttributeAsEnumeration(const c8* attributeName) = 0; //! Gets an attribute as enumeration /** \param attributeName: Name of the attribute to get. \param enumerationLiteralsToUse: Use these enumeration literals to get the index value instead of the set ones. This is useful when the attribute list maybe was read from an xml file, and only contains the enumeration string, but no information about its index. \return Returns value of the attribute previously set by setAttribute() */ virtual s32 getAttributeAsEnumeration(const c8* attributeName, const c8* const* enumerationLiteralsToUse) = 0; //! Gets an attribute as enumeration /** \param index: Index value, must be between 0 and getAttributeCount()-1. \param enumerationLiteralsToUse: Use these enumeration literals to get the index value instead of the set ones. This is useful when the attribute list maybe was read from an xml file, and only contains the enumeration string, but no information about its index. \return Returns value of the attribute previously set by setAttribute() */ virtual s32 getAttributeAsEnumeration(s32 index, const c8* const* enumerationLiteralsToUse) = 0; //! Gets an attribute as enumeration //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual const c8* getAttributeAsEnumeration(s32 index) = 0; //! Gets the list of enumeration literals of an enumeration attribute //! \param attributeName Name of the attribute to get. //! \param outLiterals Set of strings to choose the enum name from. virtual void getAttributeEnumerationLiteralsOfEnumeration(const c8* attributeName, core::array& outLiterals) = 0; //! Gets the list of enumeration literals of an enumeration attribute //! \param index: Index value, must be between 0 and getAttributeCount()-1. //! \param outLiterals Set of strings to choose the enum name from. virtual void getAttributeEnumerationLiteralsOfEnumeration(s32 index, core::array& outLiterals) = 0; //! Sets an attribute as enumeration virtual void setAttribute(s32 index, const c8* enumValue, const c8* const* enumerationLiterals) = 0; /* SColor Attribute */ //! Adds an attribute as color virtual void addColor(const c8* attributeName, video::SColor value) = 0; //! Sets a attribute as color virtual void setAttribute(const c8* attributeName, video::SColor color) = 0; //! Gets an attribute as color //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual video::SColor getAttributeAsColor(const c8* attributeName) = 0; //! Gets an attribute as color //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual video::SColor getAttributeAsColor(s32 index) = 0; //! Sets an attribute as color virtual void setAttribute(s32 index, video::SColor color) = 0; /* SColorf Attribute */ //! Adds an attribute as floating point color virtual void addColorf(const c8* attributeName, video::SColorf value) = 0; //! Sets a attribute as floating point color virtual void setAttribute(const c8* attributeName, video::SColorf color) = 0; //! Gets an attribute as floating point color //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual video::SColorf getAttributeAsColorf(const c8* attributeName) = 0; //! Gets an attribute as floating point color //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual video::SColorf getAttributeAsColorf(s32 index) = 0; //! Sets an attribute as floating point color virtual void setAttribute(s32 index, video::SColorf color) = 0; /* Vector3d Attribute */ //! Adds an attribute as 3d vector virtual void addVector3d(const c8* attributeName, core::vector3df value) = 0; //! Sets a attribute as 3d vector virtual void setAttribute(const c8* attributeName, core::vector3df v) = 0; //! Gets an attribute as 3d vector //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::vector3df getAttributeAsVector3d(const c8* attributeName) = 0; //! Gets an attribute as 3d vector //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::vector3df getAttributeAsVector3d(s32 index) = 0; //! Sets an attribute as vector virtual void setAttribute(s32 index, core::vector3df v) = 0; /* Vector2d Attribute */ //! Adds an attribute as 2d vector virtual void addVector2d(const c8* attributeName, core::vector2df value) = 0; //! Sets a attribute as 2d vector virtual void setAttribute(const c8* attributeName, core::vector2df v) = 0; //! Gets an attribute as vector //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::vector2df getAttributeAsVector2d(const c8* attributeName) = 0; //! Gets an attribute as position //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::vector2df getAttributeAsVector2d(s32 index) = 0; //! Sets an attribute as 2d vector virtual void setAttribute(s32 index, core::vector2df v) = 0; /* Position2d Attribute */ //! Adds an attribute as 2d position virtual void addPosition2d(const c8* attributeName, core::position2di value) = 0; //! Sets a attribute as 2d position virtual void setAttribute(const c8* attributeName, core::position2di v) = 0; //! Gets an attribute as position //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::position2di getAttributeAsPosition2d(const c8* attributeName) = 0; //! Gets an attribute as position //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::position2di getAttributeAsPosition2d(s32 index) = 0; //! Sets an attribute as 2d position virtual void setAttribute(s32 index, core::position2di v) = 0; /* Rectangle Attribute */ //! Adds an attribute as rectangle virtual void addRect(const c8* attributeName, core::rect value) = 0; //! Sets an attribute as rectangle virtual void setAttribute(const c8* attributeName, core::rect v) = 0; //! Gets an attribute as rectangle //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::rect getAttributeAsRect(const c8* attributeName) = 0; //! Gets an attribute as rectangle //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::rect getAttributeAsRect(s32 index) = 0; //! Sets an attribute as rectangle virtual void setAttribute(s32 index, core::rect v) = 0; /* Dimension2d Attribute */ //! Adds an attribute as dimension2d virtual void addDimension2d(const c8* attributeName, core::dimension2d value) = 0; //! Sets an attribute as dimension2d virtual void setAttribute(const c8* attributeName, core::dimension2d v) = 0; //! Gets an attribute as dimension2d //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::dimension2d getAttributeAsDimension2d(const c8* attributeName) = 0; //! Gets an attribute as dimension2d //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::dimension2d getAttributeAsDimension2d(s32 index) = 0; //! Sets an attribute as dimension2d virtual void setAttribute(s32 index, core::dimension2d v) = 0; /* matrix attribute */ //! Adds an attribute as matrix virtual void addMatrix(const c8* attributeName, const core::matrix4& v) = 0; //! Sets an attribute as matrix virtual void setAttribute(const c8* attributeName, const core::matrix4& v) = 0; //! Gets an attribute as a matrix4 //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::matrix4 getAttributeAsMatrix(const c8* attributeName) = 0; //! Gets an attribute as matrix //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::matrix4 getAttributeAsMatrix(s32 index) = 0; //! Sets an attribute as matrix virtual void setAttribute(s32 index, const core::matrix4& v) = 0; /* quaternion attribute */ //! Adds an attribute as quaternion virtual void addQuaternion(const c8* attributeName, core::quaternion v) = 0; //! Sets an attribute as quaternion virtual void setAttribute(const c8* attributeName, core::quaternion v) = 0; //! Gets an attribute as a quaternion //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::quaternion getAttributeAsQuaternion(const c8* attributeName) = 0; //! Gets an attribute as quaternion //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::quaternion getAttributeAsQuaternion(s32 index) = 0; //! Sets an attribute as quaternion virtual void setAttribute(s32 index, core::quaternion v) = 0; /* 3d bounding box */ //! Adds an attribute as axis aligned bounding box virtual void addBox3d(const c8* attributeName, core::aabbox3df v) = 0; //! Sets an attribute as axis aligned bounding box virtual void setAttribute(const c8* attributeName, core::aabbox3df v) = 0; //! Gets an attribute as a axis aligned bounding box //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::aabbox3df getAttributeAsBox3d(const c8* attributeName) = 0; //! Gets an attribute as axis aligned bounding box //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::aabbox3df getAttributeAsBox3d(s32 index) = 0; //! Sets an attribute as axis aligned bounding box virtual void setAttribute(s32 index, core::aabbox3df v) = 0; /* plane */ //! Adds an attribute as 3d plane virtual void addPlane3d(const c8* attributeName, core::plane3df v) = 0; //! Sets an attribute as 3d plane virtual void setAttribute(const c8* attributeName, core::plane3df v) = 0; //! Gets an attribute as a 3d plane //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::plane3df getAttributeAsPlane3d(const c8* attributeName) = 0; //! Gets an attribute as 3d plane //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::plane3df getAttributeAsPlane3d(s32 index) = 0; //! Sets an attribute as 3d plane virtual void setAttribute(s32 index, core::plane3df v) = 0; /* 3d triangle */ //! Adds an attribute as 3d triangle virtual void addTriangle3d(const c8* attributeName, core::triangle3df v) = 0; //! Sets an attribute as 3d trianle virtual void setAttribute(const c8* attributeName, core::triangle3df v) = 0; //! Gets an attribute as a 3d triangle //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::triangle3df getAttributeAsTriangle3d(const c8* attributeName) = 0; //! Gets an attribute as 3d triangle //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::triangle3df getAttributeAsTriangle3d(s32 index) = 0; //! Sets an attribute as 3d triangle virtual void setAttribute(s32 index, core::triangle3df v) = 0; /* line 2d */ //! Adds an attribute as a 2d line virtual void addLine2d(const c8* attributeName, core::line2df v) = 0; //! Sets an attribute as a 2d line virtual void setAttribute(const c8* attributeName, core::line2df v) = 0; //! Gets an attribute as a 2d line //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::line2df getAttributeAsLine2d(const c8* attributeName) = 0; //! Gets an attribute as a 2d line //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::line2df getAttributeAsLine2d(s32 index) = 0; //! Sets an attribute as a 2d line virtual void setAttribute(s32 index, core::line2df v) = 0; /* line 3d */ //! Adds an attribute as a 3d line virtual void addLine3d(const c8* attributeName, core::line3df v) = 0; //! Sets an attribute as a 3d line virtual void setAttribute(const c8* attributeName, core::line3df v) = 0; //! Gets an attribute as a 3d line //! \param attributeName: Name of the attribute to get. //! \return Returns value of the attribute previously set by setAttribute() virtual core::line3df getAttributeAsLine3d(const c8* attributeName) = 0; //! Gets an attribute as a 3d line //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual core::line3df getAttributeAsLine3d(s32 index) = 0; //! Sets an attribute as a 3d line virtual void setAttribute(s32 index, core::line3df v) = 0; /* Texture Attribute */ //! Adds an attribute as texture reference virtual void addTexture(const c8* attributeName, video::ITexture* texture, const io::path& filename = "") = 0; //! Sets an attribute as texture reference virtual void setAttribute(const c8* attributeName, video::ITexture* texture, const io::path& filename = "") = 0; //! Gets an attribute as texture reference //! \param attributeName: Name of the attribute to get. virtual video::ITexture* getAttributeAsTexture(const c8* attributeName) = 0; //! Gets an attribute as texture reference //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual video::ITexture* getAttributeAsTexture(s32 index) = 0; //! Sets an attribute as texture reference virtual void setAttribute(s32 index, video::ITexture* texture, const io::path& filename = "") = 0; /* User Pointer Attribute */ //! Adds an attribute as user pointner virtual void addUserPointer(const c8* attributeName, void* userPointer) = 0; //! Sets an attribute as user pointer virtual void setAttribute(const c8* attributeName, void* userPointer) = 0; //! Gets an attribute as user pointer //! \param attributeName: Name of the attribute to get. virtual void* getAttributeAsUserPointer(const c8* attributeName) = 0; //! Gets an attribute as user pointer //! \param index: Index value, must be between 0 and getAttributeCount()-1. virtual void* getAttributeAsUserPointer(s32 index) = 0; //! Sets an attribute as user pointer virtual void setAttribute(s32 index, void* userPointer) = 0; }; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/include/IAttributeExchangingObject.h0000644000000000000000000000371012574354552021051 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_ATTRIBUTE_EXCHANGING_OBJECT_H_INCLUDED__ #define __I_ATTRIBUTE_EXCHANGING_OBJECT_H_INCLUDED__ #include "IReferenceCounted.h" namespace irr { namespace io { class IAttributes; //! Enumeration flags passed through SAttributeReadWriteOptions to the IAttributeExchangingObject object enum E_ATTRIBUTE_READ_WRITE_FLAGS { //! Serialization/Deserializion is done for an xml file EARWF_FOR_FILE = 0x00000001, //! Serialization/Deserializion is done for an editor property box EARWF_FOR_EDITOR = 0x00000002, //! When writing filenames, relative paths should be used EARWF_USE_RELATIVE_PATHS = 0x00000004 }; //! struct holding data describing options struct SAttributeReadWriteOptions { //! Constructor SAttributeReadWriteOptions() : Flags(0), Filename(0) { } //! Combination of E_ATTRIBUTE_READ_WRITE_FLAGS or other, custom ones s32 Flags; //! Optional filename const fschar_t* Filename; }; //! An object which is able to serialize and deserialize its attributes into an attributes object class IAttributeExchangingObject : virtual public IReferenceCounted { public: //! Writes attributes of the object. /** Implement this to expose the attributes of your scene node animator for scripting languages, editors, debuggers or xml serialization purposes. */ virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const {} //! Reads attributes of the object. /** Implement this to set the attributes of your scene node animator for scripting languages, editors, debuggers or xml deserialization purposes. */ virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) {} }; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/include/IAnimatedMeshSceneNode.h0000644000000000000000000002235112574354552020110 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_ANIMATED_MESH_SCENE_NODE_H_INCLUDED__ #define __I_ANIMATED_MESH_SCENE_NODE_H_INCLUDED__ #include "ISceneNode.h" #include "IBoneSceneNode.h" #include "IAnimatedMeshMD2.h" #include "IAnimatedMeshMD3.h" namespace irr { namespace scene { class IShadowVolumeSceneNode; enum E_JOINT_UPDATE_ON_RENDER { //! do nothing EJUOR_NONE = 0, //! get joints positions from the mesh (for attached nodes, etc) EJUOR_READ, //! control joint positions in the mesh (eg. ragdolls, or set the animation from animateJoints() ) EJUOR_CONTROL }; class IAnimatedMeshSceneNode; //! Callback interface for catching events of ended animations. /** Implement this interface and use IAnimatedMeshSceneNode::setAnimationEndCallback to be able to be notified if an animation playback has ended. **/ class IAnimationEndCallBack : public virtual IReferenceCounted { public: //! Will be called when the animation playback has ended. /** See IAnimatedMeshSceneNode::setAnimationEndCallback for more informations. \param node: Node of which the animation has ended. */ virtual void OnAnimationEnd(IAnimatedMeshSceneNode* node) = 0; }; //! Scene node capable of displaying an animated mesh and its shadow. /** The shadow is optional: If a shadow should be displayed too, just invoke the IAnimatedMeshSceneNode::createShadowVolumeSceneNode().*/ class IAnimatedMeshSceneNode : public ISceneNode { public: //! Constructor IAnimatedMeshSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) : ISceneNode(parent, mgr, id, position, rotation, scale) {} //! Destructor virtual ~IAnimatedMeshSceneNode() {} //! Sets the current frame number. /** From now on the animation is played from this frame. \param frame: Number of the frame to let the animation be started from. The frame number must be a valid frame number of the IMesh used by this scene node. Set IAnimatedMesh::getMesh() for details. */ virtual void setCurrentFrame(f32 frame) = 0; //! Sets the frame numbers between the animation is looped. /** The default is 0 - MaximalFrameCount of the mesh. \param begin: Start frame number of the loop. \param end: End frame number of the loop. \return True if successful, false if not. */ virtual bool setFrameLoop(s32 begin, s32 end) = 0; //! Sets the speed with which the animation is played. /** \param framesPerSecond: Frames per second played. */ virtual void setAnimationSpeed(f32 framesPerSecond) = 0; //! Gets the speed with which the animation is played. /** \return Frames per second played. */ virtual f32 getAnimationSpeed() const =0; //! Creates shadow volume scene node as child of this node. /** The shadow can be rendered using the ZPass or the zfail method. ZPass is a little bit faster because the shadow volume creation is easier, but with this method there occur ugly looking artifacs when the camera is inside the shadow volume. These error do not occur with the ZFail method. \param shadowMesh: Optional custom mesh for shadow volume. \param id: Id of the shadow scene node. This id can be used to identify the node later. \param zfailmethod: If set to true, the shadow will use the zfail method, if not, zpass is used. \param infinity: Value used by the shadow volume algorithm to scale the shadow volume (for zfail shadow volume we support only finite shadows, so camera zfar must be larger than shadow back cap, which is depend on infinity parameter). \return Pointer to the created shadow scene node. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh=0, s32 id=-1, bool zfailmethod=true, f32 infinity=1000.0f) = 0; //! Get a pointer to a joint in the mesh (if the mesh is a bone based mesh). /** With this method it is possible to attach scene nodes to joints for example possible to attach a weapon to the left hand of an animated model. This example shows how: \code ISceneNode* hand = yourAnimatedMeshSceneNode->getJointNode("LeftHand"); hand->addChild(weaponSceneNode); \endcode Please note that the joint returned by this method may not exist before this call and the joints in the node were created by it. \param jointName: Name of the joint. \return Pointer to the scene node which represents the joint with the specified name. Returns 0 if the contained mesh is not an skinned mesh or the name of the joint could not be found. */ virtual IBoneSceneNode* getJointNode(const c8* jointName)=0; //! same as getJointNode(const c8* jointName), but based on id virtual IBoneSceneNode* getJointNode(u32 jointID) = 0; //! Gets joint count. /** \return Amount of joints in the mesh. */ virtual u32 getJointCount() const = 0; //! Starts a default MD2 animation. /** With this method it is easily possible to start a Run, Attack, Die or whatever animation, if the mesh contained in this scene node is an md2 mesh. Otherwise, nothing happens. \param anim: An MD2 animation type, which should be played, for example EMAT_STAND for the standing animation. \return True if successful, and false if not, for example if the mesh in the scene node is not a md2 mesh. */ virtual bool setMD2Animation(EMD2_ANIMATION_TYPE anim) = 0; //! Starts a special MD2 animation. /** With this method it is easily possible to start a Run, Attack, Die or whatever animation, if the mesh contained in this scene node is an md2 mesh. Otherwise, nothing happens. This method uses a character string to identify the animation. If the animation is a standard md2 animation, you might want to start this animation with the EMD2_ANIMATION_TYPE enumeration instead. \param animationName: Name of the animation which should be played. \return Returns true if successful, and false if not, for example if the mesh in the scene node is not an md2 mesh, or no animation with this name could be found. */ virtual bool setMD2Animation(const c8* animationName) = 0; //! Returns the currently displayed frame number. virtual f32 getFrameNr() const = 0; //! Returns the current start frame number. virtual s32 getStartFrame() const = 0; //! Returns the current end frame number. virtual s32 getEndFrame() const = 0; //! Sets looping mode which is on by default. /** If set to false, animations will not be played looped. */ virtual void setLoopMode(bool playAnimationLooped) = 0; //! returns the current loop mode /** When true the animations are played looped */ virtual bool getLoopMode() const = 0; //! Sets a callback interface which will be called if an animation playback has ended. /** Set this to 0 to disable the callback again. Please note that this will only be called when in non looped mode, see IAnimatedMeshSceneNode::setLoopMode(). */ virtual void setAnimationEndCallback(IAnimationEndCallBack* callback=0) = 0; //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. /** In this way it is possible to change the materials a mesh causing all mesh scene nodes referencing this mesh to change too. */ virtual void setReadOnlyMaterials(bool readonly) = 0; //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style virtual bool isReadOnlyMaterials() const = 0; //! Sets a new mesh virtual void setMesh(IAnimatedMesh* mesh) = 0; //! Returns the current mesh virtual IAnimatedMesh* getMesh(void) = 0; //! Get the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, or the absolutetransformation if it's a normal scenenode virtual const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname) = 0; //! Set how the joints should be updated on render virtual void setJointMode(E_JOINT_UPDATE_ON_RENDER mode)=0; //! Sets the transition time in seconds /** Note: This needs to enable joints, and setJointmode set to EJUOR_CONTROL. You must call animateJoints(), or the mesh will not animate. */ virtual void setTransitionTime(f32 Time) =0; //! animates the joints in the mesh based on the current frame. /** Also takes in to account transitions. */ virtual void animateJoints(bool CalculateAbsolutePositions=true) = 0; //! render mesh ignoring its transformation. /** Culling is unaffected. */ virtual void setRenderFromIdentity( bool On )=0; //! Creates a clone of this scene node and its children. /** \param newParent An optional new parent. \param newManager An optional new scene manager. \return The newly created clone of this node. */ virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0) = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IAnimatedMeshMD3.h0000644000000000000000000001553312574354552016634 0ustar rootroot// Copyright (C) 2007-2012 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_ANIMATED_MESH_MD3_H_INCLUDED__ #define __I_ANIMATED_MESH_MD3_H_INCLUDED__ #include "IAnimatedMesh.h" #include "IQ3Shader.h" #include "quaternion.h" namespace irr { namespace scene { enum eMD3Models { EMD3_HEAD = 0, EMD3_UPPER, EMD3_LOWER, EMD3_WEAPON, EMD3_NUMMODELS }; //! Animation list enum EMD3_ANIMATION_TYPE { // Animations for both lower and upper parts of the player EMD3_BOTH_DEATH_1 = 0, EMD3_BOTH_DEAD_1, EMD3_BOTH_DEATH_2, EMD3_BOTH_DEAD_2, EMD3_BOTH_DEATH_3, EMD3_BOTH_DEAD_3, // Animations for the upper part EMD3_TORSO_GESTURE, EMD3_TORSO_ATTACK_1, EMD3_TORSO_ATTACK_2, EMD3_TORSO_DROP, EMD3_TORSO_RAISE, EMD3_TORSO_STAND_1, EMD3_TORSO_STAND_2, // Animations for the lower part EMD3_LEGS_WALK_CROUCH, EMD3_LEGS_WALK, EMD3_LEGS_RUN, EMD3_LEGS_BACK, EMD3_LEGS_SWIM, EMD3_LEGS_JUMP_1, EMD3_LEGS_LAND_1, EMD3_LEGS_JUMP_2, EMD3_LEGS_LAND_2, EMD3_LEGS_IDLE, EMD3_LEGS_IDLE_CROUCH, EMD3_LEGS_TURN, //! Not an animation, but amount of animation types. EMD3_ANIMATION_COUNT }; struct SMD3AnimationInfo { //! First frame s32 first; //! Last frame s32 num; //! Looping frames s32 looping; //! Frames per second s32 fps; }; // byte-align structures #include "irrpack.h" //! this holds the header info of the MD3 file struct SMD3Header { c8 headerID[4]; //id of file, always "IDP3" s32 Version; //this is a version number, always 15 s8 fileName[68]; //sometimes left Blank... 65 chars, 32bit aligned == 68 chars s32 numFrames; //number of KeyFrames s32 numTags; //number of 'tags' per frame s32 numMeshes; //number of meshes/skins s32 numMaxSkins; //maximum number of unique skins used in md3 file. artefact md2 s32 frameStart; //starting position of frame-structur s32 tagStart; //starting position of tag-structures s32 tagEnd; //ending position of tag-structures/starting position of mesh-structures s32 fileSize; } PACK_STRUCT; //! this holds the header info of an MD3 mesh section struct SMD3MeshHeader { c8 meshID[4]; //id, must be IDP3 c8 meshName[68]; //name of mesh 65 chars, 32 bit aligned == 68 chars s32 numFrames; //number of meshframes in mesh s32 numShader; //number of skins in mesh s32 numVertices; //number of vertices s32 numTriangles; //number of Triangles s32 offset_triangles; //starting position of Triangle data, relative to start of Mesh_Header s32 offset_shaders; //size of header s32 offset_st; //starting position of texvector data, relative to start of Mesh_Header s32 vertexStart; //starting position of vertex data,relative to start of Mesh_Header s32 offset_end; } PACK_STRUCT; //! Compressed Vertex Data struct SMD3Vertex { s16 position[3]; u8 normal[2]; } PACK_STRUCT; //! Texture Coordinate struct SMD3TexCoord { f32 u; f32 v; } PACK_STRUCT; //! Triangle Index struct SMD3Face { s32 Index[3]; } PACK_STRUCT; // Default alignment #include "irrunpack.h" //! Holding Frame Data for a Mesh struct SMD3MeshBuffer : public IReferenceCounted { SMD3MeshHeader MeshHeader; core::stringc Shader; core::array < s32 > Indices; core::array < SMD3Vertex > Vertices; core::array < SMD3TexCoord > Tex; }; //! hold a tag info for connecting meshes /** Basically its an alternate way to describe a transformation. */ struct SMD3QuaternionTag { virtual ~SMD3QuaternionTag() { position.X = 0.f; } // construct copy constructor SMD3QuaternionTag( const SMD3QuaternionTag & copyMe ) { *this = copyMe; } // construct for searching SMD3QuaternionTag( const core::stringc& name ) : Name ( name ) {} // construct from a position and euler angles in degrees SMD3QuaternionTag ( const core::vector3df &pos, const core::vector3df &angle ) : position(pos), rotation(angle * core::DEGTORAD) {} // set to matrix void setto ( core::matrix4 &m ) { rotation.getMatrix ( m, position ); } bool operator == ( const SMD3QuaternionTag &other ) const { return Name == other.Name; } SMD3QuaternionTag & operator=( const SMD3QuaternionTag & copyMe ) { Name = copyMe.Name; position = copyMe.position; rotation = copyMe.rotation; return *this; } core::stringc Name; core::vector3df position; core::quaternion rotation; }; //! holds a associative list of named quaternions struct SMD3QuaternionTagList { SMD3QuaternionTagList() { Container.setAllocStrategy(core::ALLOC_STRATEGY_SAFE); } // construct copy constructor SMD3QuaternionTagList(const SMD3QuaternionTagList& copyMe) { *this = copyMe; } virtual ~SMD3QuaternionTagList() {} SMD3QuaternionTag* get(const core::stringc& name) { SMD3QuaternionTag search ( name ); s32 index = Container.linear_search ( search ); if ( index >= 0 ) return &Container[index]; return 0; } u32 size () const { return Container.size(); } void set_used(u32 new_size) { s32 diff = (s32) new_size - (s32) Container.allocated_size(); if ( diff > 0 ) { SMD3QuaternionTag e(""); for ( s32 i = 0; i < diff; ++i ) Container.push_back(e); } } const SMD3QuaternionTag& operator[](u32 index) const { return Container[index]; } SMD3QuaternionTag& operator[](u32 index) { return Container[index]; } void push_back(const SMD3QuaternionTag& other) { Container.push_back(other); } SMD3QuaternionTagList& operator = (const SMD3QuaternionTagList & copyMe) { Container = copyMe.Container; return *this; } private: core::array < SMD3QuaternionTag > Container; }; //! Holding Frames Buffers and Tag Infos struct SMD3Mesh: public IReferenceCounted { SMD3Mesh () { MD3Header.numFrames = 0; } virtual ~SMD3Mesh() { for (u32 i=0; idrop(); } core::stringc Name; core::array Buffer; SMD3QuaternionTagList TagList; SMD3Header MD3Header; }; //! Interface for using some special functions of MD3 meshes class IAnimatedMeshMD3 : public IAnimatedMesh { public: //! tune how many frames you want to render inbetween. virtual void setInterpolationShift(u32 shift, u32 loopMode) =0; //! get the tag list of the mesh. virtual SMD3QuaternionTagList* getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) =0; //! get the original md3 mesh. virtual SMD3Mesh* getOriginalMesh() =0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IAnimatedMeshMD2.h0000644000000000000000000000460212574354552016626 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_ANIMATED_MESH_MD2_H_INCLUDED__ #define __I_ANIMATED_MESH_MD2_H_INCLUDED__ #include "IAnimatedMesh.h" namespace irr { namespace scene { //! Types of standard md2 animations enum EMD2_ANIMATION_TYPE { EMAT_STAND = 0, EMAT_RUN, EMAT_ATTACK, EMAT_PAIN_A, EMAT_PAIN_B, EMAT_PAIN_C, EMAT_JUMP, EMAT_FLIP, EMAT_SALUTE, EMAT_FALLBACK, EMAT_WAVE, EMAT_POINT, EMAT_CROUCH_STAND, EMAT_CROUCH_WALK, EMAT_CROUCH_ATTACK, EMAT_CROUCH_PAIN, EMAT_CROUCH_DEATH, EMAT_DEATH_FALLBACK, EMAT_DEATH_FALLFORWARD, EMAT_DEATH_FALLBACKSLOW, EMAT_BOOM, //! Not an animation, but amount of animation types. EMAT_COUNT }; //! Interface for using some special functions of MD2 meshes class IAnimatedMeshMD2 : public IAnimatedMesh { public: //! Get frame loop data for a default MD2 animation type. /** \param l The EMD2_ANIMATION_TYPE to get the frames for. \param outBegin The returned beginning frame for animation type specified. \param outEnd The returned ending frame for the animation type specified. \param outFPS The number of frames per second, this animation should be played at. \return beginframe, endframe and frames per second for a default MD2 animation type. */ virtual void getFrameLoop(EMD2_ANIMATION_TYPE l, s32& outBegin, s32& outEnd, s32& outFPS) const = 0; //! Get frame loop data for a special MD2 animation type, identified by name. /** \param name Name of the animation. \param outBegin The returned beginning frame for animation type specified. \param outEnd The returned ending frame for the animation type specified. \param outFPS The number of frames per second, this animation should be played at. \return beginframe, endframe and frames per second for a special MD2 animation type. */ virtual bool getFrameLoop(const c8* name, s32& outBegin, s32& outEnd, s32& outFPS) const = 0; //! Get amount of md2 animations in this file. virtual s32 getAnimationCount() const = 0; //! Get name of md2 animation. /** \param nr: Zero based index of animation. */ virtual const c8* getAnimationName(s32 nr) const = 0; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/IAnimatedMesh.h0000644000000000000000000000715512574354552016331 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __I_ANIMATED_MESH_H_INCLUDED__ #define __I_ANIMATED_MESH_H_INCLUDED__ #include "aabbox3d.h" #include "IMesh.h" namespace irr { namespace scene { //! Possible types of (animated) meshes. enum E_ANIMATED_MESH_TYPE { //! Unknown animated mesh type. EAMT_UNKNOWN = 0, //! Quake 2 MD2 model file EAMT_MD2, //! Quake 3 MD3 model file EAMT_MD3, //! Maya .obj static model EAMT_OBJ, //! Quake 3 .bsp static Map EAMT_BSP, //! 3D Studio .3ds file EAMT_3DS, //! My3D Mesh, the file format by Zhuck Dimitry EAMT_MY3D, //! Pulsar LMTools .lmts file. This Irrlicht loader was written by Jonas Petersen EAMT_LMTS, //! Cartography Shop .csm file. This loader was created by Saurav Mohapatra. EAMT_CSM, //! .oct file for Paul Nette's FSRad or from Murphy McCauley's Blender .oct exporter. /** The oct file format contains 3D geometry and lightmaps and can be loaded directly by Irrlicht */ EAMT_OCT, //! Halflife MDL model file EAMT_MDL_HALFLIFE, //! generic skinned mesh EAMT_SKINNED }; //! Interface for an animated mesh. /** There are already simple implementations of this interface available so you don't have to implement this interface on your own if you need to: You might want to use irr::scene::SAnimatedMesh, irr::scene::SMesh, irr::scene::SMeshBuffer etc. */ class IAnimatedMesh : public IMesh { public: //! Gets the frame count of the animated mesh. /** \return The amount of frames. If the amount is 1, it is a static, non animated mesh. */ virtual u32 getFrameCount() const = 0; //! Gets the animation speed of the animated mesh. /** \return The number of frames per second to play the animation with by default. If the amount is 0, it is a static, non animated mesh. */ virtual f32 getAnimationSpeed() const = 0; //! Sets the animation speed of the animated mesh. /** \param fps Number of frames per second to play the animation with by default. If the amount is 0, it is not animated. The actual speed is set in the scene node the mesh is instantiated in.*/ virtual void setAnimationSpeed(f32 fps) =0; //! Returns the IMesh interface for a frame. /** \param frame: Frame number as zero based index. The maximum frame number is getFrameCount() - 1; \param detailLevel: Level of detail. 0 is the lowest, 255 the highest level of detail. Most meshes will ignore the detail level. \param startFrameLoop: Because some animated meshes (.MD2) are blended between 2 static frames, and maybe animated in a loop, the startFrameLoop and the endFrameLoop have to be defined, to prevent the animation to be blended between frames which are outside of this loop. If startFrameLoop and endFrameLoop are both -1, they are ignored. \param endFrameLoop: see startFrameLoop. \return Returns the animated mesh based on a detail level. */ virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1) = 0; //! Returns the type of the animated mesh. /** In most cases it is not neccessary to use this method. This is useful for making a safe downcast. For example, if getMeshType() returns EAMT_MD2 it's safe to cast the IAnimatedMesh to IAnimatedMeshMD2. \returns Type of the mesh. */ virtual E_ANIMATED_MESH_TYPE getMeshType() const { return EAMT_UNKNOWN; } }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/heapsort.h0000644000000000000000000000272112574354552015500 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_HEAPSORT_H_INCLUDED__ #define __IRR_HEAPSORT_H_INCLUDED__ #include "irrTypes.h" namespace irr { namespace core { //! Sinks an element into the heap. template inline void heapsink(T*array, s32 element, s32 max) { while ((element<<1) < max) // there is a left child { s32 j = (element<<1); if (j+1 < max && array[j] < array[j+1]) j = j+1; // take right child if (array[element] < array[j]) { T t = array[j]; // swap elements array[j] = array[element]; array[element] = t; element = j; } else return; } } //! Sorts an array with size 'size' using heapsort. template inline void heapsort(T* array_, s32 size) { // for heapsink we pretent this is not c++, where // arrays start with index 0. So we decrease the array pointer, // the maximum always +2 and the element always +1 T* virtualArray = array_ - 1; s32 virtualSize = size + 2; s32 i; // build heap for (i=((size-1)/2); i>=0; --i) heapsink(virtualArray, i+1, virtualSize-1); // sort array, leave out the last element (0) for (i=size-1; i>0; --i) { T t = array_[0]; array_[0] = array_[i]; array_[i] = t; heapsink(virtualArray, 1, i + 1); } } } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/fast_atof.h0000644000000000000000000002304012574354552015616 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h #ifndef __FAST_ATOF_H_INCLUDED__ #define __FAST_ATOF_H_INCLUDED__ #include "irrMath.h" #include "irrString.h" namespace irr { namespace core { //! Selection of characters which count as decimal point in fast_atof // TODO: This should probably also be used in irr::core::string, but the float-to-string code // used there has to be rewritten first. IRRLICHT_API extern irr::core::stringc LOCALE_DECIMAL_POINTS; // we write [17] here instead of [] to work around a swig bug const float fast_atof_table[17] = { 0.f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f, 0.0000000001f, 0.00000000001f, 0.000000000001f, 0.0000000000001f, 0.00000000000001f, 0.000000000000001f, 0.0000000000000001f }; //! Convert a simple string of base 10 digits into an unsigned 32 bit integer. /** \param[in] in: The string of digits to convert. No leading chars are allowed, only digits 0 to 9. Parsing stops at the first non-digit. \param[out] out: (optional) If provided, it will be set to point at the first character not used in the calculation. \return The unsigned integer value of the digits. If the string specifies too many digits to encode in an u32 then INT_MAX will be returned. */ inline u32 strtoul10(const char* in, const char** out=0) { if (!in) { if (out) *out = in; return 0; } bool overflow=false; u32 unsignedValue = 0; while ( ( *in >= '0') && ( *in <= '9' )) { const u32 tmp = ( unsignedValue * 10 ) + ( *in - '0' ); if (tmp (u32)INT_MAX) { if (negative) return (s32)INT_MIN; else return (s32)INT_MAX; } else { if (negative) return -((s32)unsignedValue); else return (s32)unsignedValue; } } //! Convert a hex-encoded character to an unsigned integer. /** \param[in] in The digit to convert. Only digits 0 to 9 and chars A-F,a-f will be considered. \return The unsigned integer value of the digit. 0xffffffff if the input is not hex */ inline u32 ctoul16(char in) { if (in >= '0' && in <= '9') return in - '0'; else if (in >= 'a' && in <= 'f') return 10u + in - 'a'; else if (in >= 'A' && in <= 'F') return 10u + in - 'A'; else return 0xffffffff; } //! Convert a simple string of base 16 digits into an unsigned 32 bit integer. /** \param[in] in: The string of digits to convert. No leading chars are allowed, only digits 0 to 9 and chars A-F,a-f are allowed. Parsing stops at the first illegal char. \param[out] out: (optional) If provided, it will be set to point at the first character not used in the calculation. \return The unsigned integer value of the digits. If the string specifies too many digits to encode in an u32 then INT_MAX will be returned. */ inline u32 strtoul16(const char* in, const char** out=0) { if (!in) { if (out) *out = in; return 0; } bool overflow=false; u32 unsignedValue = 0; while (true) { u32 tmp = 0; if ((*in >= '0') && (*in <= '9')) tmp = (unsignedValue << 4u) + (*in - '0'); else if ((*in >= 'A') && (*in <= 'F')) tmp = (unsignedValue << 4u) + (*in - 'A') + 10; else if ((*in >= 'a') && (*in <= 'f')) tmp = (unsignedValue << 4u) + (*in - 'a') + 10; else break; if (tmp= '0') && (*in <= '7')) tmp = (unsignedValue << 3u) + (*in - '0'); else break; if (tmp= '0') && ( *in <= '9' ) ) { // If it looks like we're going to overflow, bail out // now and start using floating point. if (intValue >= MAX_SAFE_U32_VALUE) break; intValue = (intValue * 10) + (*in - '0'); ++in; } f32 floatValue = (f32)intValue; // If there are any digits left to parse, then we need to use // floating point arithmetic from here. while ( ( *in >= '0') && ( *in <= '9' ) ) { floatValue = (floatValue * 10.f) + (f32)(*in - '0'); ++in; if (floatValue > FLT_MAX) // Just give up. break; } if (out) *out = in; return floatValue; } //! Provides a fast function for converting a string into a float. /** This is not guaranteed to be as accurate as atof(), but is approximately 6 to 8 times as fast. \param[in] in The string to convert. \param[out] result The resultant float will be written here. \return Pointer to the first character in the string that wasn't used to create the float value. */ inline const char* fast_atof_move(const char* in, f32& result) { // Please run the regression test when making any modifications to this function. result = 0.f; if (!in) return 0; const bool negative = ('-' == *in); if (negative || ('+'==*in)) ++in; f32 value = strtof10(in, &in); if ( LOCALE_DECIMAL_POINTS.findFirst(*in) >= 0 ) { const char* afterDecimal = ++in; const f32 decimal = strtof10(in, &afterDecimal); value += decimal * fast_atof_table[afterDecimal - in]; in = afterDecimal; } if ('e' == *in || 'E' == *in) { ++in; // Assume that the exponent is a whole number. // strtol10() will deal with both + and - signs, // but calculate as f32 to prevent overflow at FLT_MAX value *= powf(10.f, (f32)strtol10(in, &in)); } result = negative?-value:value; return in; } //! Convert a string to a floating point number /** \param floatAsString The string to convert. \param out Optional pointer to the first character in the string that wasn't used to create the float value. \result Float value parsed from the input string */ inline float fast_atof(const char* floatAsString, const char** out=0) { float ret; if (out) *out=fast_atof_move(floatAsString, ret); else fast_atof_move(floatAsString, ret); return ret; } } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/ETerrainElements.h0000644000000000000000000000170212574354552017057 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_TERRAIN_ELEMENTS_H__ #define __E_TERRAIN_ELEMENTS_H__ namespace irr { namespace scene { //! enumeration for patch sizes specifying the size of patches in the TerrainSceneNode enum E_TERRAIN_PATCH_SIZE { //! patch size of 9, at most, use 4 levels of detail with this patch size. ETPS_9 = 9, //! patch size of 17, at most, use 5 levels of detail with this patch size. ETPS_17 = 17, //! patch size of 33, at most, use 6 levels of detail with this patch size. ETPS_33 = 33, //! patch size of 65, at most, use 7 levels of detail with this patch size. ETPS_65 = 65, //! patch size of 129, at most, use 8 levels of detail with this patch size. ETPS_129 = 129 }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/EShaderTypes.h0000644000000000000000000000334212574354552016213 0ustar rootroot#ifndef __E_SHADER_TYPES_H_INCLUDED__ #define __E_SHADER_TYPES_H_INCLUDED__ #include "irrTypes.h" namespace irr { namespace video { //! Compile target enumeration for the addHighLevelShaderMaterial() method. enum E_VERTEX_SHADER_TYPE { EVST_VS_1_1 = 0, EVST_VS_2_0, EVST_VS_2_a, EVST_VS_3_0, EVST_VS_4_0, EVST_VS_4_1, EVST_VS_5_0, //! This is not a type, but a value indicating how much types there are. EVST_COUNT }; //! Names for all vertex shader types, each entry corresponds to a E_VERTEX_SHADER_TYPE entry. const c8* const VERTEX_SHADER_TYPE_NAMES[] = { "vs_1_1", "vs_2_0", "vs_2_a", "vs_3_0", "vs_4_0", "vs_4_1", "vs_5_0", 0 }; //! Compile target enumeration for the addHighLevelShaderMaterial() method. enum E_PIXEL_SHADER_TYPE { EPST_PS_1_1 = 0, EPST_PS_1_2, EPST_PS_1_3, EPST_PS_1_4, EPST_PS_2_0, EPST_PS_2_a, EPST_PS_2_b, EPST_PS_3_0, EPST_PS_4_0, EPST_PS_4_1, EPST_PS_5_0, //! This is not a type, but a value indicating how much types there are. EPST_COUNT }; //! Names for all pixel shader types, each entry corresponds to a E_PIXEL_SHADER_TYPE entry. const c8* const PIXEL_SHADER_TYPE_NAMES[] = { "ps_1_1", "ps_1_2", "ps_1_3", "ps_1_4", "ps_2_0", "ps_2_a", "ps_2_b", "ps_3_0", "ps_4_0", "ps_4_1", "ps_5_0", 0 }; //! Enum for supported geometry shader types enum E_GEOMETRY_SHADER_TYPE { EGST_GS_4_0 = 0, //! This is not a type, but a value indicating how much types there are. EGST_COUNT }; //! String names for supported geometry shader types const c8* const GEOMETRY_SHADER_TYPE_NAMES[] = { "gs_4_0", 0 }; } // end namespace video } // end namespace irr #endif // __E_SHADER_TYPES_H_INCLUDED__ irrlicht-1.8.3/include/ESceneNodeTypes.h0000644000000000000000000000572712574354552016661 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_SCENE_NODE_TYPES_H_INCLUDED__ #define __E_SCENE_NODE_TYPES_H_INCLUDED__ #include "irrTypes.h" namespace irr { namespace scene { //! An enumeration for all types of built-in scene nodes /** A scene node type is represented by a four character code such as 'cube' or 'mesh' instead of simple numbers, to avoid name clashes with external scene nodes.*/ enum ESCENE_NODE_TYPE { //! of type CSceneManager (note that ISceneManager is not(!) an ISceneNode) ESNT_SCENE_MANAGER = MAKE_IRR_ID('s','m','n','g'), //! simple cube scene node ESNT_CUBE = MAKE_IRR_ID('c','u','b','e'), //! Sphere scene node ESNT_SPHERE = MAKE_IRR_ID('s','p','h','r'), //! Text Scene Node ESNT_TEXT = MAKE_IRR_ID('t','e','x','t'), //! Water Surface Scene Node ESNT_WATER_SURFACE = MAKE_IRR_ID('w','a','t','r'), //! Terrain Scene Node ESNT_TERRAIN = MAKE_IRR_ID('t','e','r','r'), //! Sky Box Scene Node ESNT_SKY_BOX = MAKE_IRR_ID('s','k','y','_'), //! Sky Dome Scene Node ESNT_SKY_DOME = MAKE_IRR_ID('s','k','y','d'), //! Shadow Volume Scene Node ESNT_SHADOW_VOLUME = MAKE_IRR_ID('s','h','d','w'), //! Octree Scene Node ESNT_OCTREE = MAKE_IRR_ID('o','c','t','r'), //! Mesh Scene Node ESNT_MESH = MAKE_IRR_ID('m','e','s','h'), //! Light Scene Node ESNT_LIGHT = MAKE_IRR_ID('l','g','h','t'), //! Empty Scene Node ESNT_EMPTY = MAKE_IRR_ID('e','m','t','y'), //! Dummy Transformation Scene Node ESNT_DUMMY_TRANSFORMATION = MAKE_IRR_ID('d','m','m','y'), //! Camera Scene Node ESNT_CAMERA = MAKE_IRR_ID('c','a','m','_'), //! Billboard Scene Node ESNT_BILLBOARD = MAKE_IRR_ID('b','i','l','l'), //! Animated Mesh Scene Node ESNT_ANIMATED_MESH = MAKE_IRR_ID('a','m','s','h'), //! Particle System Scene Node ESNT_PARTICLE_SYSTEM = MAKE_IRR_ID('p','t','c','l'), //! Quake3 Shader Scene Node ESNT_Q3SHADER_SCENE_NODE = MAKE_IRR_ID('q','3','s','h'), //! Quake3 Model Scene Node ( has tag to link to ) ESNT_MD3_SCENE_NODE = MAKE_IRR_ID('m','d','3','_'), //! Volume Light Scene Node ESNT_VOLUME_LIGHT = MAKE_IRR_ID('v','o','l','l'), //! Maya Camera Scene Node /** Legacy, for loading version <= 1.4.x .irr files */ ESNT_CAMERA_MAYA = MAKE_IRR_ID('c','a','m','M'), //! First Person Shooter Camera /** Legacy, for loading version <= 1.4.x .irr files */ ESNT_CAMERA_FPS = MAKE_IRR_ID('c','a','m','F'), //! Unknown scene node ESNT_UNKNOWN = MAKE_IRR_ID('u','n','k','n'), //! Will match with any scene node when checking types ESNT_ANY = MAKE_IRR_ID('a','n','y','_') }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/ESceneNodeAnimatorTypes.h0000644000000000000000000000241712574354552020345 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_SCENE_NODE_ANIMATOR_TYPES_H_INCLUDED__ #define __E_SCENE_NODE_ANIMATOR_TYPES_H_INCLUDED__ namespace irr { namespace scene { //! An enumeration for all types of built-in scene node animators enum ESCENE_NODE_ANIMATOR_TYPE { //! Fly circle scene node animator ESNAT_FLY_CIRCLE = 0, //! Fly straight scene node animator ESNAT_FLY_STRAIGHT, //! Follow spline scene node animator ESNAT_FOLLOW_SPLINE, //! Rotation scene node animator ESNAT_ROTATION, //! Texture scene node animator ESNAT_TEXTURE, //! Deletion scene node animator ESNAT_DELETION, //! Collision respose scene node animator ESNAT_COLLISION_RESPONSE, //! FPS camera animator ESNAT_CAMERA_FPS, //! Maya camera animator ESNAT_CAMERA_MAYA, //! Amount of built-in scene node animators ESNAT_COUNT, //! Unknown scene node animator ESNAT_UNKNOWN, //! This enum is never used, it only forces the compiler to compile this enumeration to 32 bit. ESNAT_FORCE_32_BIT = 0x7fffffff }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/EPrimitiveTypes.h0000644000000000000000000000266512574354552016764 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_PRIMITIVE_TYPES_H_INCLUDED__ #define __E_PRIMITIVE_TYPES_H_INCLUDED__ namespace irr { namespace scene { //! Enumeration for all primitive types there are. enum E_PRIMITIVE_TYPE { //! All vertices are non-connected points. EPT_POINTS=0, //! All vertices form a single connected line. EPT_LINE_STRIP, //! Just as LINE_STRIP, but the last and the first vertex is also connected. EPT_LINE_LOOP, //! Every two vertices are connected creating n/2 lines. EPT_LINES, //! After the first two vertices each vertex defines a new triangle. //! Always the two last and the new one form a new triangle. EPT_TRIANGLE_STRIP, //! After the first two vertices each vertex defines a new triangle. //! All around the common first vertex. EPT_TRIANGLE_FAN, //! Explicitly set all vertices for each triangle. EPT_TRIANGLES, //! After the first two vertices each further tw vetices create a quad with the preceding two. EPT_QUAD_STRIP, //! Every four vertices create a quad. EPT_QUADS, //! Just as LINE_LOOP, but filled. EPT_POLYGON, //! The single vertices are expanded to quad billboards on the GPU. EPT_POINT_SPRITES }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/EMessageBoxFlags.h0000644000000000000000000000136012574354552016770 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_MESSAGE_BOX_FLAGS_H_INCLUDED__ #define __E_MESSAGE_BOX_FLAGS_H_INCLUDED__ namespace irr { namespace gui { //! enumeration for message box layout flags enum EMESSAGE_BOX_FLAG { //! Flag for the ok button EMBF_OK = 0x1, //! Flag for the cancel button EMBF_CANCEL = 0x2, //! Flag for the yes button EMBF_YES = 0x4, //! Flag for the no button EMBF_NO = 0x8, //! This value is not used. It only forces this enumeration to compile in 32 bit. EMBF_FORCE_32BIT = 0x7fffffff }; } // namespace gui } // namespace irr #endif irrlicht-1.8.3/include/EMeshWriterEnums.h0000644000000000000000000000303712574354552017062 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_MESH_WRITER_ENUMS_H_INCLUDED__ #define __E_MESH_WRITER_ENUMS_H_INCLUDED__ #include "irrTypes.h" namespace irr { namespace scene { //! An enumeration for all supported types of built-in mesh writers /** A scene mesh writers is represented by a four character code such as 'irrm' or 'coll' instead of simple numbers, to avoid name clashes with external mesh writers.*/ enum EMESH_WRITER_TYPE { //! Irrlicht native mesh writer, for static .irrmesh files. EMWT_IRR_MESH = MAKE_IRR_ID('i','r','r','m'), //! COLLADA mesh writer for .dae and .xml files EMWT_COLLADA = MAKE_IRR_ID('c','o','l','l'), //! STL mesh writer for .stl files EMWT_STL = MAKE_IRR_ID('s','t','l',0), //! OBJ mesh writer for .obj files EMWT_OBJ = MAKE_IRR_ID('o','b','j',0), //! PLY mesh writer for .ply files EMWT_PLY = MAKE_IRR_ID('p','l','y',0) }; //! flags configuring mesh writing enum E_MESH_WRITER_FLAGS { //! no writer flags EMWF_NONE = 0, //! write lightmap textures out if possible EMWF_WRITE_LIGHTMAPS = 0x1, //! write in a way that consumes less disk space EMWF_WRITE_COMPRESSED = 0x2, //! write in binary format rather than text EMWF_WRITE_BINARY = 0x4 }; } // end namespace scene } // end namespace irr #endif // __E_MESH_WRITER_ENUMS_H_INCLUDED__ irrlicht-1.8.3/include/EMaterialTypes.h0000644000000000000000000002303712574354552016546 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_MATERIAL_TYPES_H_INCLUDED__ #define __E_MATERIAL_TYPES_H_INCLUDED__ namespace irr { namespace video { //! Abstracted and easy to use fixed function/programmable pipeline material modes. enum E_MATERIAL_TYPE { //! Standard solid material. /** Only first texture is used, which is supposed to be the diffuse material. */ EMT_SOLID = 0, //! Solid material with 2 texture layers. /** The second is blended onto the first using the alpha value of the vertex colors. This material is currently not implemented in OpenGL. */ EMT_SOLID_2_LAYER, //! Material type with standard lightmap technique /** There should be 2 textures: The first texture layer is a diffuse map, the second is a light map. Dynamic light is ignored. */ EMT_LIGHTMAP, //! Material type with lightmap technique like EMT_LIGHTMAP. /** But lightmap and diffuse texture are added instead of modulated. */ EMT_LIGHTMAP_ADD, //! Material type with standard lightmap technique /** There should be 2 textures: The first texture layer is a diffuse map, the second is a light map. Dynamic light is ignored. The texture colors are effectively multiplied by 2 for brightening. Like known in DirectX as D3DTOP_MODULATE2X. */ EMT_LIGHTMAP_M2, //! Material type with standard lightmap technique /** There should be 2 textures: The first texture layer is a diffuse map, the second is a light map. Dynamic light is ignored. The texture colors are effectively multiplyied by 4 for brightening. Like known in DirectX as D3DTOP_MODULATE4X. */ EMT_LIGHTMAP_M4, //! Like EMT_LIGHTMAP, but also supports dynamic lighting. EMT_LIGHTMAP_LIGHTING, //! Like EMT_LIGHTMAP_M2, but also supports dynamic lighting. EMT_LIGHTMAP_LIGHTING_M2, //! Like EMT_LIGHTMAP_4, but also supports dynamic lighting. EMT_LIGHTMAP_LIGHTING_M4, //! Detail mapped material. /** The first texture is diffuse color map, the second is added to this and usually displayed with a bigger scale value so that it adds more detail. The detail map is added to the diffuse map using ADD_SIGNED, so that it is possible to add and substract color from the diffuse map. For example a value of (127,127,127) will not change the appearance of the diffuse map at all. Often used for terrain rendering. */ EMT_DETAIL_MAP, //! Look like a reflection of the environment around it. /** To make this possible, a texture called 'sphere map' is used, which must be set as the first texture. */ EMT_SPHERE_MAP, //! A reflecting material with an optional non reflecting texture layer. /** The reflection map should be set as first texture. */ EMT_REFLECTION_2_LAYER, //! A transparent material. /** Only the first texture is used. The new color is calculated by simply adding the source color and the dest color. This means if for example a billboard using a texture with black background and a red circle on it is drawn with this material, the result is that only the red circle will be drawn a little bit transparent, and everything which was black is 100% transparent and not visible. This material type is useful for particle effects. */ EMT_TRANSPARENT_ADD_COLOR, //! Makes the material transparent based on the texture alpha channel. /** The final color is blended together from the destination color and the texture color, using the alpha channel value as blend factor. Only first texture is used. If you are using this material with small textures, it is a good idea to load the texture in 32 bit mode (video::IVideoDriver::setTextureCreationFlag()). Also, an alpha ref is used, which can be manipulated using SMaterial::MaterialTypeParam. This value controls how sharp the edges become when going from a transparent to a solid spot on the texture. */ EMT_TRANSPARENT_ALPHA_CHANNEL, //! Makes the material transparent based on the texture alpha channel. /** If the alpha channel value is greater than 127, a pixel is written to the target, otherwise not. This material does not use alpha blending and is a lot faster than EMT_TRANSPARENT_ALPHA_CHANNEL. It is ideal for drawing stuff like leafes of plants, because the borders are not blurry but sharp. Only first texture is used. If you are using this material with small textures and 3d object, it is a good idea to load the texture in 32 bit mode (video::IVideoDriver::setTextureCreationFlag()). */ EMT_TRANSPARENT_ALPHA_CHANNEL_REF, //! Makes the material transparent based on the vertex alpha value. EMT_TRANSPARENT_VERTEX_ALPHA, //! A transparent reflecting material with an optional additional non reflecting texture layer. /** The reflection map should be set as first texture. The transparency depends on the alpha value in the vertex colors. A texture which will not reflect can be set as second texture. Please note that this material type is currently not 100% implemented in OpenGL. */ EMT_TRANSPARENT_REFLECTION_2_LAYER, //! A solid normal map renderer. /** First texture is the color map, the second should be the normal map. Note that you should use this material only when drawing geometry consisting of vertices of type S3DVertexTangents (EVT_TANGENTS). You can convert any mesh into this format using IMeshManipulator::createMeshWithTangents() (See SpecialFX2 Tutorial). This shader runs on vertex shader 1.1 and pixel shader 1.1 capable hardware and falls back to a fixed function lighted material if this hardware is not available. Only two lights are supported by this shader, if there are more, the nearest two are chosen. */ EMT_NORMAL_MAP_SOLID, //! A transparent normal map renderer. /** First texture is the color map, the second should be the normal map. Note that you should use this material only when drawing geometry consisting of vertices of type S3DVertexTangents (EVT_TANGENTS). You can convert any mesh into this format using IMeshManipulator::createMeshWithTangents() (See SpecialFX2 Tutorial). This shader runs on vertex shader 1.1 and pixel shader 1.1 capable hardware and falls back to a fixed function lighted material if this hardware is not available. Only two lights are supported by this shader, if there are more, the nearest two are chosen. */ EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR, //! A transparent (based on the vertex alpha value) normal map renderer. /** First texture is the color map, the second should be the normal map. Note that you should use this material only when drawing geometry consisting of vertices of type S3DVertexTangents (EVT_TANGENTS). You can convert any mesh into this format using IMeshManipulator::createMeshWithTangents() (See SpecialFX2 Tutorial). This shader runs on vertex shader 1.1 and pixel shader 1.1 capable hardware and falls back to a fixed function lighted material if this hardware is not available. Only two lights are supported by this shader, if there are more, the nearest two are chosen. */ EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA, //! Just like EMT_NORMAL_MAP_SOLID, but uses parallax mapping. /** Looks a lot more realistic. This only works when the hardware supports at least vertex shader 1.1 and pixel shader 1.4. First texture is the color map, the second should be the normal map. The normal map texture should contain the height value in the alpha component. The IVideoDriver::makeNormalMapTexture() method writes this value automatically when creating normal maps from a heightmap when using a 32 bit texture. The height scale of the material (affecting the bumpiness) is being controlled by the SMaterial::MaterialTypeParam member. If set to zero, the default value (0.02f) will be applied. Otherwise the value set in SMaterial::MaterialTypeParam is taken. This value depends on with which scale the texture is mapped on the material. Too high or low values of MaterialTypeParam can result in strange artifacts. */ EMT_PARALLAX_MAP_SOLID, //! A material like EMT_PARALLAX_MAP_SOLID, but transparent. /** Using EMT_TRANSPARENT_ADD_COLOR as base material. */ EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR, //! A material like EMT_PARALLAX_MAP_SOLID, but transparent. /** Using EMT_TRANSPARENT_VERTEX_ALPHA as base material. */ EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA, //! BlendFunc = source * sourceFactor + dest * destFactor ( E_BLEND_FUNC ) /** Using only first texture. Generic blending method. */ EMT_ONETEXTURE_BLEND, //! This value is not used. It only forces this enumeration to compile to 32 bit. EMT_FORCE_32BIT = 0x7fffffff }; //! Array holding the built in material type names const char* const sBuiltInMaterialTypeNames[] = { "solid", "solid_2layer", "lightmap", "lightmap_add", "lightmap_m2", "lightmap_m4", "lightmap_light", "lightmap_light_m2", "lightmap_light_m4", "detail_map", "sphere_map", "reflection_2layer", "trans_add", "trans_alphach", "trans_alphach_ref", "trans_vertex_alpha", "trans_reflection_2layer", "normalmap_solid", "normalmap_trans_add", "normalmap_trans_vertexalpha", "parallaxmap_solid", "parallaxmap_trans_add", "parallaxmap_trans_vertexalpha", "onetexture_blend", 0 }; } // end namespace video } // end namespace irr #endif // __E_MATERIAL_TYPES_H_INCLUDED__ irrlicht-1.8.3/include/EMaterialFlags.h0000644000000000000000000000543712574354552016502 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_MATERIAL_FLAGS_H_INCLUDED__ #define __E_MATERIAL_FLAGS_H_INCLUDED__ namespace irr { namespace video { //! Material flags enum E_MATERIAL_FLAG { //! Draw as wireframe or filled triangles? Default: false EMF_WIREFRAME = 0x1, //! Draw as point cloud or filled triangles? Default: false EMF_POINTCLOUD = 0x2, //! Flat or Gouraud shading? Default: true EMF_GOURAUD_SHADING = 0x4, //! Will this material be lighted? Default: true EMF_LIGHTING = 0x8, //! Is the ZBuffer enabled? Default: true EMF_ZBUFFER = 0x10, //! May be written to the zbuffer or is it readonly. Default: true /** This flag is ignored, if the material type is a transparent type. */ EMF_ZWRITE_ENABLE = 0x20, //! Is backface culling enabled? Default: true EMF_BACK_FACE_CULLING = 0x40, //! Is frontface culling enabled? Default: false /** Overrides EMF_BACK_FACE_CULLING if both are enabled. */ EMF_FRONT_FACE_CULLING = 0x80, //! Is bilinear filtering enabled? Default: true EMF_BILINEAR_FILTER = 0x100, //! Is trilinear filtering enabled? Default: false /** If the trilinear filter flag is enabled, the bilinear filtering flag is ignored. */ EMF_TRILINEAR_FILTER = 0x200, //! Is anisotropic filtering? Default: false /** In Irrlicht you can use anisotropic texture filtering in conjunction with bilinear or trilinear texture filtering to improve rendering results. Primitives will look less blurry with this flag switched on. */ EMF_ANISOTROPIC_FILTER = 0x400, //! Is fog enabled? Default: false EMF_FOG_ENABLE = 0x800, //! Normalizes normals. Default: false /** You can enable this if you need to scale a dynamic lighted model. Usually, its normals will get scaled too then and it will get darker. If you enable the EMF_NORMALIZE_NORMALS flag, the normals will be normalized again, and the model will look as bright as it should. */ EMF_NORMALIZE_NORMALS = 0x1000, //! Access to all layers texture wrap settings. Overwrites separate layer settings. EMF_TEXTURE_WRAP = 0x2000, //! AntiAliasing mode EMF_ANTI_ALIASING = 0x4000, //! ColorMask bits, for enabling the color planes EMF_COLOR_MASK = 0x8000, //! ColorMaterial enum for vertex color interpretation EMF_COLOR_MATERIAL = 0x10000, //! Flag for enabling/disabling mipmap usage EMF_USE_MIP_MAPS = 0x20000, //! Flag for blend operation EMF_BLEND_OPERATION = 0x40000, //! Flag for polygon offset EMF_POLYGON_OFFSET = 0x80000 }; } // end namespace video } // end namespace irr #endif // __E_MATERIAL_FLAGS_H_INCLUDED__ irrlicht-1.8.3/include/EHardwareBufferFlags.h0000644000000000000000000000165212574354552017626 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_HARDWARE_BUFFER_FLAGS_INCLUDED__ #define __E_HARDWARE_BUFFER_FLAGS_INCLUDED__ namespace irr { namespace scene { enum E_HARDWARE_MAPPING { //! Don't store on the hardware EHM_NEVER=0, //! Rarely changed, usually stored completely on the hardware EHM_STATIC, //! Sometimes changed, driver optimized placement EHM_DYNAMIC, //! Always changed, cache optimizing on the GPU EHM_STREAM }; enum E_BUFFER_TYPE { //! Does not change anything EBT_NONE=0, //! Change the vertex mapping EBT_VERTEX, //! Change the index mapping EBT_INDEX, //! Change both vertex and index mapping to the same value EBT_VERTEX_AND_INDEX }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/EGUIElementTypes.h0000644000000000000000000000470012574354552016742 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_GUI_ELEMENT_TYPES_H_INCLUDED__ #define __E_GUI_ELEMENT_TYPES_H_INCLUDED__ #include "irrTypes.h" namespace irr { namespace gui { //! List of all basic Irrlicht GUI elements. /** An IGUIElement returns this when calling IGUIElement::getType(); */ enum EGUI_ELEMENT_TYPE { //! A button (IGUIButton) EGUIET_BUTTON = 0, //! A check box (IGUICheckBox) EGUIET_CHECK_BOX, //! A combo box (IGUIComboBox) EGUIET_COMBO_BOX, //! A context menu (IGUIContextMenu) EGUIET_CONTEXT_MENU, //! A menu (IGUIMenu) EGUIET_MENU, //! An edit box (IGUIEditBox) EGUIET_EDIT_BOX, //! A file open dialog (IGUIFileOpenDialog) EGUIET_FILE_OPEN_DIALOG, //! A color select open dialog (IGUIColorSelectDialog) EGUIET_COLOR_SELECT_DIALOG, //! A in/out fader (IGUIInOutFader) EGUIET_IN_OUT_FADER, //! An image (IGUIImage) EGUIET_IMAGE, //! A list box (IGUIListBox) EGUIET_LIST_BOX, //! A mesh viewer (IGUIMeshViewer) EGUIET_MESH_VIEWER, //! A message box (IGUIWindow) EGUIET_MESSAGE_BOX, //! A modal screen EGUIET_MODAL_SCREEN, //! A scroll bar (IGUIScrollBar) EGUIET_SCROLL_BAR, //! A spin box (IGUISpinBox) EGUIET_SPIN_BOX, //! A static text (IGUIStaticText) EGUIET_STATIC_TEXT, //! A tab (IGUITab) EGUIET_TAB, //! A tab control EGUIET_TAB_CONTROL, //! A Table EGUIET_TABLE, //! A tool bar (IGUIToolBar) EGUIET_TOOL_BAR, //! A Tree View EGUIET_TREE_VIEW, //! A window EGUIET_WINDOW, //! Unknown type. EGUIET_ELEMENT, //! The root of the GUI EGUIET_ROOT, //! Not an element, amount of elements in there EGUIET_COUNT, //! This enum is never used, it only forces the compiler to compile this enumeration to 32 bit. EGUIET_FORCE_32_BIT = 0x7fffffff }; //! Names for built-in element types const c8* const GUIElementTypeNames[] = { "button", "checkBox", "comboBox", "contextMenu", "menu", "editBox", "fileOpenDialog", "colorSelectDialog", "inOutFader", "image", "listBox", "meshViewer", "messageBox", "modalScreen", "scrollBar", "spinBox", "staticText", "tab", "tabControl", "table", "toolBar", "treeview", "window", "element", "root", 0 }; } // end namespace gui } // end namespace irr #endif irrlicht-1.8.3/include/EGUIAlignment.h0000644000000000000000000000141412574354552016241 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_GUI_ALIGNMENT_H_INCLUDED__ #define __E_GUI_ALIGNMENT_H_INCLUDED__ namespace irr { namespace gui { enum EGUI_ALIGNMENT { //! Aligned to parent's top or left side (default) EGUIA_UPPERLEFT=0, //! Aligned to parent's bottom or right side EGUIA_LOWERRIGHT, //! Aligned to the center of parent EGUIA_CENTER, //! Stretched to fit parent EGUIA_SCALE }; //! Names for alignments const c8* const GUIAlignmentNames[] = { "upperLeft", "lowerRight", "center", "scale", 0 }; } // namespace gui } // namespace irr #endif // __E_GUI_ALIGNMENT_H_INCLUDED__ irrlicht-1.8.3/include/EDriverTypes.h0000644000000000000000000000413212574354552016236 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_DRIVER_TYPES_H_INCLUDED__ #define __E_DRIVER_TYPES_H_INCLUDED__ namespace irr { namespace video { //! An enum for all types of drivers the Irrlicht Engine supports. enum E_DRIVER_TYPE { //! Null driver, useful for applications to run the engine without visualisation. /** The null device is able to load textures, but does not render and display any graphics. */ EDT_NULL, //! The Irrlicht Engine Software renderer. /** Runs on all platforms, with every hardware. It should only be used for 2d graphics, but it can also perform some primitive 3d functions. These 3d drawing functions are quite fast, but very inaccurate, and don't even support clipping in 3D mode. */ EDT_SOFTWARE, //! The Burning's Software Renderer, an alternative software renderer /** Basically it can be described as the Irrlicht Software renderer on steroids. It rasterizes 3D geometry perfectly: It is able to perform correct 3d clipping, perspective correct texture mapping, perspective correct color mapping, and renders sub pixel correct, sub texel correct primitives. In addition, it does bilinear texel filtering and supports more materials than the EDT_SOFTWARE driver. This renderer has been written entirely by Thomas Alten, thanks a lot for this huge contribution. */ EDT_BURNINGSVIDEO, //! Direct3D8 device, only available on Win32 platforms. /** Performs hardware accelerated rendering of 3D and 2D primitives. */ EDT_DIRECT3D8, //! Direct3D 9 device, only available on Win32 platforms. /** Performs hardware accelerated rendering of 3D and 2D primitives. */ EDT_DIRECT3D9, //! OpenGL device, available on most platforms. /** Performs hardware accelerated rendering of 3D and 2D primitives. */ EDT_OPENGL, //! No driver, just for counting the elements EDT_COUNT }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/EDriverFeatures.h0000644000000000000000000000623312574354552016714 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_DRIVER_FEATURES_H_INCLUDED__ #define __E_DRIVER_FEATURES_H_INCLUDED__ namespace irr { namespace video { //! enumeration for querying features of the video driver. enum E_VIDEO_DRIVER_FEATURE { //! Is driver able to render to a surface? EVDF_RENDER_TO_TARGET = 0, //! Is hardeware transform and lighting supported? EVDF_HARDWARE_TL, //! Are multiple textures per material possible? EVDF_MULTITEXTURE, //! Is driver able to render with a bilinear filter applied? EVDF_BILINEAR_FILTER, //! Can the driver handle mip maps? EVDF_MIP_MAP, //! Can the driver update mip maps automatically? EVDF_MIP_MAP_AUTO_UPDATE, //! Are stencilbuffers switched on and does the device support stencil buffers? EVDF_STENCIL_BUFFER, //! Is Vertex Shader 1.1 supported? EVDF_VERTEX_SHADER_1_1, //! Is Vertex Shader 2.0 supported? EVDF_VERTEX_SHADER_2_0, //! Is Vertex Shader 3.0 supported? EVDF_VERTEX_SHADER_3_0, //! Is Pixel Shader 1.1 supported? EVDF_PIXEL_SHADER_1_1, //! Is Pixel Shader 1.2 supported? EVDF_PIXEL_SHADER_1_2, //! Is Pixel Shader 1.3 supported? EVDF_PIXEL_SHADER_1_3, //! Is Pixel Shader 1.4 supported? EVDF_PIXEL_SHADER_1_4, //! Is Pixel Shader 2.0 supported? EVDF_PIXEL_SHADER_2_0, //! Is Pixel Shader 3.0 supported? EVDF_PIXEL_SHADER_3_0, //! Are ARB vertex programs v1.0 supported? EVDF_ARB_VERTEX_PROGRAM_1, //! Are ARB fragment programs v1.0 supported? EVDF_ARB_FRAGMENT_PROGRAM_1, //! Is GLSL supported? EVDF_ARB_GLSL, //! Is HLSL supported? EVDF_HLSL, //! Are non-square textures supported? EVDF_TEXTURE_NSQUARE, //! Are non-power-of-two textures supported? EVDF_TEXTURE_NPOT, //! Are framebuffer objects supported? EVDF_FRAMEBUFFER_OBJECT, //! Are vertex buffer objects supported? EVDF_VERTEX_BUFFER_OBJECT, //! Supports Alpha To Coverage EVDF_ALPHA_TO_COVERAGE, //! Supports Color masks (disabling color planes in output) EVDF_COLOR_MASK, //! Supports multiple render targets at once EVDF_MULTIPLE_RENDER_TARGETS, //! Supports separate blend settings for multiple render targets EVDF_MRT_BLEND, //! Supports separate color masks for multiple render targets EVDF_MRT_COLOR_MASK, //! Supports separate blend functions for multiple render targets EVDF_MRT_BLEND_FUNC, //! Supports geometry shaders EVDF_GEOMETRY_SHADER, //! Supports occlusion queries EVDF_OCCLUSION_QUERY, //! Supports polygon offset/depth bias for avoiding z-fighting EVDF_POLYGON_OFFSET, //! Support for different blend functions. Without, only ADD is available EVDF_BLEND_OPERATIONS, //! Support for texture coord transformation via texture matrix EVDF_TEXTURE_MATRIX, //! Support for NVidia's CG shader language EVDF_CG, //! Only used for counting the elements of this enum EVDF_COUNT }; } // end namespace video } // end namespace irr #endif irrlicht-1.8.3/include/EDeviceTypes.h0000644000000000000000000000442012574354552016202 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_DEVICE_TYPES_H_INCLUDED__ #define __E_DEVICE_TYPES_H_INCLUDED__ namespace irr { //! An enum for the different device types supported by the Irrlicht Engine. enum E_DEVICE_TYPE { //! A device native to Microsoft Windows /** This device uses the Win32 API and works in all versions of Windows. */ EIDT_WIN32, //! A device native to Windows CE devices /** This device works on Windows Mobile, Pocket PC and Microsoft SmartPhone devices */ EIDT_WINCE, //! A device native to Unix style operating systems. /** This device uses the X11 windowing system and works in Linux, Solaris, FreeBSD, OSX and other operating systems which support X11. */ EIDT_X11, //! A device native to Mac OSX /** This device uses Apple's Cocoa API and works in Mac OSX 10.2 and above. */ EIDT_OSX, //! A device which uses Simple DirectMedia Layer /** The SDL device works under all platforms supported by SDL but first must be compiled in by defining the IRR_USE_SDL_DEVICE macro in IrrCompileConfig.h */ EIDT_SDL, //! A device for raw framebuffer access /** Best used with embedded devices and mobile systems. Does not need X11 or other graphical subsystems. May support hw-acceleration via OpenGL-ES for FBDirect */ EIDT_FRAMEBUFFER, //! A simple text only device supported by all platforms. /** This device allows applications to run from the command line without opening a window. It can render the output of the software drivers to the console as ASCII. It only supports mouse and keyboard in Windows operating systems. */ EIDT_CONSOLE, //! This selection allows Irrlicht to choose the best device from the ones available. /** If this selection is chosen then Irrlicht will try to use the IrrlichtDevice native to your operating system. If this is unavailable then the X11, SDL and then console device will be tried. This ensures that Irrlicht will run even if your platform is unsupported, although it may not be able to render anything. */ EIDT_BEST }; } // end namespace irr #endif // __E_DEVICE_TYPES_H_INCLUDED__ irrlicht-1.8.3/include/EDebugSceneTypes.h0000644000000000000000000000210412574354552017004 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_DEBUG_SCENE_TYPES_H_INCLUDED__ #define __E_DEBUG_SCENE_TYPES_H_INCLUDED__ namespace irr { namespace scene { //! An enumeration for all types of debug data for built-in scene nodes (flags) enum E_DEBUG_SCENE_TYPE { //! No Debug Data ( Default ) EDS_OFF = 0, //! Show Bounding Boxes of SceneNode EDS_BBOX = 1, //! Show Vertex Normals EDS_NORMALS = 2, //! Shows Skeleton/Tags EDS_SKELETON = 4, //! Overlays Mesh Wireframe EDS_MESH_WIRE_OVERLAY = 8, //! Temporary use transparency Material Type EDS_HALF_TRANSPARENCY = 16, //! Show Bounding Boxes of all MeshBuffers EDS_BBOX_BUFFERS = 32, //! EDS_BBOX | EDS_BBOX_BUFFERS EDS_BBOX_ALL = EDS_BBOX | EDS_BBOX_BUFFERS, //! Show all debug infos EDS_FULL = 0xffffffff }; } // end namespace scene } // end namespace irr #endif // __E_DEBUG_SCENE_TYPES_H_INCLUDED__ irrlicht-1.8.3/include/ECullingTypes.h0000644000000000000000000000164212574354552016403 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_CULLING_TYPES_H_INCLUDED__ #define __E_CULLING_TYPES_H_INCLUDED__ #include "irrTypes.h" namespace irr { namespace scene { //! An enumeration for all types of automatic culling for built-in scene nodes enum E_CULLING_TYPE { EAC_OFF = 0, EAC_BOX = 1, EAC_FRUSTUM_BOX = 2, EAC_FRUSTUM_SPHERE = 4, EAC_OCC_QUERY = 8 }; //! Names for culling type const c8* const AutomaticCullingNames[] = { "false", "box", // camera box against node box "frustum_box", // camera frustum against node box "frustum_sphere", // camera frustum against node sphere "occ_query", // occlusion query 0 }; } // end namespace scene } // end namespace irr #endif // __E_CULLING_TYPES_H_INCLUDED__ irrlicht-1.8.3/include/EAttributes.h0000644000000000000000000000276012574354552016111 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_ATTRIBUTES_H_INCLUDED__ #define __E_ATTRIBUTES_H_INCLUDED__ namespace irr { namespace io { //! Types of attributes available for IAttributes enum E_ATTRIBUTE_TYPE { // integer attribute EAT_INT = 0, // float attribute EAT_FLOAT, // string attribute EAT_STRING, // boolean attribute EAT_BOOL, // enumeration attribute EAT_ENUM, // color attribute EAT_COLOR, // floating point color attribute EAT_COLORF, // 3d vector attribute EAT_VECTOR3D, // 2d position attribute EAT_POSITION2D, // vector 2d attribute EAT_VECTOR2D, // rectangle attribute EAT_RECT, // matrix attribute EAT_MATRIX, // quaternion attribute EAT_QUATERNION, // 3d bounding box EAT_BBOX, // plane EAT_PLANE, // 3d triangle EAT_TRIANGLE3D, // line 2d EAT_LINE2D, // line 3d EAT_LINE3D, // array of stringws attribute EAT_STRINGWARRAY, // array of float EAT_FLOATARRAY, // array of int EAT_INTARRAY, // binary data attribute EAT_BINARY, // texture reference attribute EAT_TEXTURE, // user pointer void* EAT_USER_POINTER, // dimension attribute EAT_DIMENSION2D, // known attribute type count EAT_COUNT, // unknown attribute EAT_UNKNOWN }; } // end namespace io } // end namespace irr #endif irrlicht-1.8.3/include/driverChoice.h0000644000000000000000000000236712574354552016267 0ustar rootroot// Copyright (C) 2009-2012 Christian Stehno // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __E_DRIVER_CHOICE_H_INCLUDED__ #define __E_DRIVER_CHOICE_H_INCLUDED__ #include #include #include "EDriverTypes.h" #include "irrTypes.h" #include "IrrlichtDevice.h" namespace irr { //! ask user for driver static irr::video::E_DRIVER_TYPE driverChoiceConsole(bool allDrivers=true) { const char* const names[] = {"NullDriver","Software Renderer","Burning's Video","Direct3D 8.1","Direct3D 9.0c","OpenGL 1.x/2.x/3.x"}; printf("Please select the driver you want:\n"); irr::u32 i=0; for (i=irr::video::EDT_COUNT; i>0; --i) { if (allDrivers || (irr::IrrlichtDevice::isDriverSupported(irr::video::E_DRIVER_TYPE(i-1)))) printf(" (%c) %s\n", 'a'+irr::video::EDT_COUNT-i, names[i-1]); } char c; std::cin >> c; c = irr::video::EDT_COUNT+'a'-c; for (i=irr::video::EDT_COUNT; i>0; --i) { if (!(allDrivers || (irr::IrrlichtDevice::isDriverSupported(irr::video::E_DRIVER_TYPE(i-1))))) --c; if ((char)i==c) return irr::video::E_DRIVER_TYPE(i-1); } return irr::video::EDT_COUNT; } } // end namespace irr #endif irrlicht-1.8.3/include/dimension2d.h0000644000000000000000000001325112574354552016066 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_DIMENSION2D_H_INCLUDED__ #define __IRR_DIMENSION2D_H_INCLUDED__ #include "irrTypes.h" #include "irrMath.h" // for irr::core::equals() namespace irr { namespace core { template class vector2d; //! Specifies a 2 dimensional size. template class dimension2d { public: //! Default constructor for empty dimension dimension2d() : Width(0), Height(0) {} //! Constructor with width and height dimension2d(const T& width, const T& height) : Width(width), Height(height) {} dimension2d(const vector2d& other); // Defined in vector2d.h //! Use this constructor only where you are sure that the conversion is valid. template explicit dimension2d(const dimension2d& other) : Width((T)other.Width), Height((T)other.Height) { } template dimension2d& operator=(const dimension2d& other) { Width = (T) other.Width; Height = (T) other.Height; return *this; } //! Equality operator bool operator==(const dimension2d& other) const { return core::equals(Width, other.Width) && core::equals(Height, other.Height); } //! Inequality operator bool operator!=(const dimension2d& other) const { return ! (*this == other); } bool operator==(const vector2d& other) const; // Defined in vector2d.h bool operator!=(const vector2d& other) const { return !(*this == other); } //! Set to new values dimension2d& set(const T& width, const T& height) { Width = width; Height = height; return *this; } //! Divide width and height by scalar dimension2d& operator/=(const T& scale) { Width /= scale; Height /= scale; return *this; } //! Divide width and height by scalar dimension2d operator/(const T& scale) const { return dimension2d(Width/scale, Height/scale); } //! Multiply width and height by scalar dimension2d& operator*=(const T& scale) { Width *= scale; Height *= scale; return *this; } //! Multiply width and height by scalar dimension2d operator*(const T& scale) const { return dimension2d(Width*scale, Height*scale); } //! Add another dimension to this one. dimension2d& operator+=(const dimension2d& other) { Width += other.Width; Height += other.Height; return *this; } //! Add two dimensions dimension2d operator+(const dimension2d& other) const { return dimension2d(Width+other.Width, Height+other.Height); } //! Subtract a dimension from this one dimension2d& operator-=(const dimension2d& other) { Width -= other.Width; Height -= other.Height; return *this; } //! Subtract one dimension from another dimension2d operator-(const dimension2d& other) const { return dimension2d(Width-other.Width, Height-other.Height); } //! Get area T getArea() const { return Width*Height; } //! Get the optimal size according to some properties /** This is a function often used for texture dimension calculations. The function returns the next larger or smaller dimension which is a power-of-two dimension (2^n,2^m) and/or square (Width=Height). \param requirePowerOfTwo Forces the result to use only powers of two as values. \param requireSquare Makes width==height in the result \param larger Choose whether the result is larger or smaller than the current dimension. If one dimension need not be changed it is kept with any value of larger. \param maxValue Maximum texturesize. if value > 0 size is clamped to maxValue \return The optimal dimension under the given constraints. */ dimension2d getOptimalSize( bool requirePowerOfTwo=true, bool requireSquare=false, bool larger=true, u32 maxValue = 0) const { u32 i=1; u32 j=1; if (requirePowerOfTwo) { while (i<(u32)Width) i<<=1; if (!larger && i!=1 && i!=(u32)Width) i>>=1; while (j<(u32)Height) j<<=1; if (!larger && j!=1 && j!=(u32)Height) j>>=1; } else { i=(u32)Width; j=(u32)Height; } if (requireSquare) { if ((larger && (i>j)) || (!larger && (i 0 && i > maxValue) i = maxValue; if ( maxValue > 0 && j > maxValue) j = maxValue; return dimension2d((T)i,(T)j); } //! Get the interpolated dimension /** \param other Other dimension to interpolate with. \param d Value between 0.0f and 1.0f. \return Interpolated dimension. */ dimension2d getInterpolated(const dimension2d& other, f32 d) const { f32 inv = (1.0f - d); return dimension2d( (T)(other.Width*inv + Width*d), (T)(other.Height*inv + Height*d)); } //! Width of the dimension. T Width; //! Height of the dimension. T Height; }; //! Typedef for an f32 dimension. typedef dimension2d dimension2df; //! Typedef for an unsigned integer dimension. typedef dimension2d dimension2du; //! Typedef for an integer dimension. /** There are few cases where negative dimensions make sense. Please consider using dimension2du instead. */ typedef dimension2d dimension2di; } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/CVertexBuffer.h0000644000000000000000000001130412574354552016362 0ustar rootroot// Copyright (C) 2008-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_VERTEX_BUFFER_H_INCLUDED__ #define __C_VERTEX_BUFFER_H_INCLUDED__ #include "IVertexBuffer.h" namespace irr { namespace scene { class CVertexBuffer : public IVertexBuffer { class IVertexList { public: virtual ~IVertexList(){}; virtual u32 stride() const =0; virtual u32 size() const =0; virtual void push_back (const video::S3DVertex &element) =0; virtual video::S3DVertex& operator [](const u32 index) const =0; virtual video::S3DVertex& getLast() =0; virtual void set_used(u32 usedNow) =0; virtual void reallocate(u32 new_size) =0; virtual u32 allocated_size() const =0; virtual video::S3DVertex* pointer() =0; virtual video::E_VERTEX_TYPE getType() const =0; }; template class CSpecificVertexList : public IVertexList { public: core::array Vertices; virtual u32 stride() const {return sizeof(T);} virtual u32 size() const {return Vertices.size();} virtual void push_back (const video::S3DVertex &element) {Vertices.push_back((T&)element);} virtual video::S3DVertex& operator [](const u32 index) const {return (video::S3DVertex&)Vertices[index];} virtual video::S3DVertex& getLast() {return (video::S3DVertex&)Vertices.getLast();} virtual void set_used(u32 usedNow) {Vertices.set_used(usedNow);} virtual void reallocate(u32 new_size) {Vertices.reallocate(new_size);} virtual u32 allocated_size() const { return Vertices.allocated_size(); } virtual video::S3DVertex* pointer() {return Vertices.pointer();} virtual video::E_VERTEX_TYPE getType() const {return T().getType();} }; public: IVertexList *Vertices; CVertexBuffer(video::E_VERTEX_TYPE vertexType) : Vertices(0), MappingHint(EHM_NEVER), ChangedID(1) { setType(vertexType); } CVertexBuffer(const IVertexBuffer &VertexBufferCopy) : Vertices(0), MappingHint(EHM_NEVER), ChangedID(1) { setType(VertexBufferCopy.getType()); reallocate(VertexBufferCopy.size()); for (u32 n=0;n; break; } case video::EVT_2TCOORDS: { NewVertices=new CSpecificVertexList; break; } case video::EVT_TANGENTS: { NewVertices=new CSpecificVertexList; break; } } if (Vertices) { NewVertices->reallocate( Vertices->size() ); for(u32 n=0;nsize();++n) NewVertices->push_back((*Vertices)[n]); delete Vertices; } Vertices=NewVertices; } virtual void* getData() {return Vertices->pointer();} virtual video::E_VERTEX_TYPE getType() const {return Vertices->getType();} virtual u32 stride() const {return Vertices->stride();} virtual u32 size() const { return Vertices->size(); } virtual void push_back (const video::S3DVertex &element) { Vertices->push_back(element); } virtual video::S3DVertex& operator [](const u32 index) const { return (*Vertices)[index]; } virtual video::S3DVertex& getLast() { return Vertices->getLast(); } virtual void set_used(u32 usedNow) { Vertices->set_used(usedNow); } virtual void reallocate(u32 new_size) { Vertices->reallocate(new_size); } virtual u32 allocated_size() const { return Vertices->allocated_size(); } virtual video::S3DVertex* pointer() { return Vertices->pointer(); } //! get the current hardware mapping hint virtual E_HARDWARE_MAPPING getHardwareMappingHint() const { return MappingHint; } //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint ) { MappingHint=NewMappingHint; } //! flags the mesh as changed, reloads hardware buffers virtual void setDirty() { ++ChangedID; } //! Get the currently used ID for identification of changes. /** This shouldn't be used for anything outside the VideoDriver. */ virtual u32 getChangedID() const {return ChangedID;} E_HARDWARE_MAPPING MappingHint; u32 ChangedID; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/coreutil.h0000644000000000000000000001071212574354552015500 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_CORE_UTIL_H_INCLUDED__ #define __IRR_CORE_UTIL_H_INCLUDED__ #include "irrString.h" #include "path.h" namespace irr { namespace core { /*! \file coreutil.h \brief File containing useful basic utility functions */ // ----------- some basic quite often used string functions ----------------- //! search if a filename has a proper extension inline s32 isFileExtension ( const io::path& filename, const io::path& ext0, const io::path& ext1, const io::path& ext2) { s32 extPos = filename.findLast ( '.' ); if ( extPos < 0 ) return 0; extPos += 1; if ( filename.equals_substring_ignore_case ( ext0, extPos ) ) return 1; if ( filename.equals_substring_ignore_case ( ext1, extPos ) ) return 2; if ( filename.equals_substring_ignore_case ( ext2, extPos ) ) return 3; return 0; } //! search if a filename has a proper extension inline bool hasFileExtension ( const io::path& filename, const io::path& ext0, const io::path& ext1 = "", const io::path& ext2 = "") { return isFileExtension ( filename, ext0, ext1, ext2 ) > 0; } //! cut the filename extension from a source file path and store it in a dest file path inline io::path& cutFilenameExtension ( io::path &dest, const io::path &source ) { s32 endPos = source.findLast ( '.' ); dest = source.subString ( 0, endPos < 0 ? source.size () : endPos ); return dest; } //! get the filename extension from a file path inline io::path& getFileNameExtension ( io::path &dest, const io::path &source ) { s32 endPos = source.findLast ( '.' ); if ( endPos < 0 ) dest = ""; else dest = source.subString ( endPos, source.size () ); return dest; } //! delete path from filename inline io::path& deletePathFromFilename(io::path& filename) { // delete path from filename const fschar_t* s = filename.c_str(); const fschar_t* p = s + filename.size(); // search for path separator or beginning while ( *p != '/' && *p != '\\' && p != s ) p--; if ( p != s ) { ++p; filename = p; } return filename; } //! trim paths inline io::path& deletePathFromPath(io::path& filename, s32 pathCount) { // delete path from filename s32 i = filename.size(); // search for path separator or beginning while ( i>=0 ) { if ( filename[i] == '/' || filename[i] == '\\' ) { if ( --pathCount <= 0 ) break; } --i; } if ( i>0 ) { filename [ i + 1 ] = 0; filename.validate(); } else filename=""; return filename; } //! looks if file is in the same directory of path. returns offset of directory. //! 0 means in same directory. 1 means file is direct child of path inline s32 isInSameDirectory ( const io::path& path, const io::path& file ) { s32 subA = 0; s32 subB = 0; s32 pos; if ( path.size() && !path.equalsn ( file, path.size() ) ) return -1; pos = 0; while ( (pos = path.findNext ( '/', pos )) >= 0 ) { subA += 1; pos += 1; } pos = 0; while ( (pos = file.findNext ( '/', pos )) >= 0 ) { subB += 1; pos += 1; } return subB - subA; } // splits a path into components static inline void splitFilename(const io::path &name, io::path* path=0, io::path* filename=0, io::path* extension=0, bool make_lower=false) { s32 i = name.size(); s32 extpos = i; // search for path separator or beginning while ( i >= 0 ) { if ( name[i] == '.' ) { extpos = i; if ( extension ) *extension = name.subString ( extpos + 1, name.size() - (extpos + 1), make_lower ); } else if ( name[i] == '/' || name[i] == '\\' ) { if ( filename ) *filename = name.subString ( i + 1, extpos - (i + 1), make_lower ); if ( path ) { *path = name.subString ( 0, i + 1, make_lower ); path->replace ( '\\', '/' ); } return; } i -= 1; } if ( filename ) *filename = name.subString ( 0, extpos, make_lower ); } //! some standard function ( to remove dependencies ) #undef isdigit #undef isspace #undef isupper inline s32 isdigit(s32 c) { return c >= '0' && c <= '9'; } inline s32 isspace(s32 c) { return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v'; } inline s32 isupper(s32 c) { return c >= 'A' && c <= 'Z'; } } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/include/CMeshBuffer.h0000644000000000000000000001737112574354552016013 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __T_MESH_BUFFER_H_INCLUDED__ #define __T_MESH_BUFFER_H_INCLUDED__ #include "irrArray.h" #include "IMeshBuffer.h" namespace irr { namespace scene { //! Template implementation of the IMeshBuffer interface template class CMeshBuffer : public IMeshBuffer { public: //! Default constructor for empty meshbuffer CMeshBuffer():ChangedID_Vertex(1),ChangedID_Index(1),MappingHint_Vertex(EHM_NEVER), MappingHint_Index(EHM_NEVER) { #ifdef _DEBUG setDebugName("SMeshBuffer"); #endif } //! Get material of this meshbuffer /** \return Material of this buffer */ virtual const video::SMaterial& getMaterial() const { return Material; } //! Get material of this meshbuffer /** \return Material of this buffer */ virtual video::SMaterial& getMaterial() { return Material; } //! Get pointer to vertices /** \return Pointer to vertices. */ virtual const void* getVertices() const { return Vertices.const_pointer(); } //! Get pointer to vertices /** \return Pointer to vertices. */ virtual void* getVertices() { return Vertices.pointer(); } //! Get number of vertices /** \return Number of vertices. */ virtual u32 getVertexCount() const { return Vertices.size(); } //! Get type of index data which is stored in this meshbuffer. /** \return Index type of this buffer. */ virtual video::E_INDEX_TYPE getIndexType() const { return video::EIT_16BIT; } //! Get pointer to indices /** \return Pointer to indices. */ virtual const u16* getIndices() const { return Indices.const_pointer(); } //! Get pointer to indices /** \return Pointer to indices. */ virtual u16* getIndices() { return Indices.pointer(); } //! Get number of indices /** \return Number of indices. */ virtual u32 getIndexCount() const { return Indices.size(); } //! Get the axis aligned bounding box /** \return Axis aligned bounding box of this buffer. */ virtual const core::aabbox3d& getBoundingBox() const { return BoundingBox; } //! Set the axis aligned bounding box /** \param box New axis aligned bounding box for this buffer. */ //! set user axis aligned bounding box virtual void setBoundingBox(const core::aabbox3df& box) { BoundingBox = box; } //! Recalculate the bounding box. /** should be called if the mesh changed. */ virtual void recalculateBoundingBox() { if (Vertices.empty()) BoundingBox.reset(0,0,0); else { BoundingBox.reset(Vertices[0].Pos); for (u32 i=1; i(vertices)[i]); BoundingBox.addInternalPoint(reinterpret_cast(vertices)[i].Pos); } Indices.reallocate(getIndexCount()+numIndices); for (i=0; igetVertexCount()); for (i=0; igetVertexCount(); ++i) { Vertices.push_back(reinterpret_cast(other->getVertices())[i]); } Indices.reallocate(getIndexCount()+other->getIndexCount()); for (i=0; igetIndexCount(); ++i) { Indices.push_back(other->getIndices()[i]+vertexCount); } BoundingBox.addInternalBox(other->getBoundingBox()); */ } //! get the current hardware mapping hint virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const { return MappingHint_Vertex; } //! get the current hardware mapping hint virtual E_HARDWARE_MAPPING getHardwareMappingHint_Index() const { return MappingHint_Index; } //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint, E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX ) { if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_VERTEX) MappingHint_Vertex=NewMappingHint; if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_INDEX) MappingHint_Index=NewMappingHint; } //! flags the mesh as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX) { if (Buffer==EBT_VERTEX_AND_INDEX ||Buffer==EBT_VERTEX) ++ChangedID_Vertex; if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_INDEX) ++ChangedID_Index; } //! Get the currently used ID for identification of changes. /** This shouldn't be used for anything outside the VideoDriver. */ virtual u32 getChangedID_Vertex() const {return ChangedID_Vertex;} //! Get the currently used ID for identification of changes. /** This shouldn't be used for anything outside the VideoDriver. */ virtual u32 getChangedID_Index() const {return ChangedID_Index;} u32 ChangedID_Vertex; u32 ChangedID_Index; //! hardware mapping hint E_HARDWARE_MAPPING MappingHint_Vertex; E_HARDWARE_MAPPING MappingHint_Index; //! Material for this meshbuffer. video::SMaterial Material; //! Vertices of this buffer core::array Vertices; //! Indices into the vertices of this buffer. core::array Indices; //! Bounding box of this meshbuffer. core::aabbox3d BoundingBox; }; //! Standard meshbuffer typedef CMeshBuffer SMeshBuffer; //! Meshbuffer with two texture coords per vertex, e.g. for lightmaps typedef CMeshBuffer SMeshBufferLightMap; //! Meshbuffer with vertices having tangents stored, e.g. for normal mapping typedef CMeshBuffer SMeshBufferTangents; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/CIndexBuffer.h0000644000000000000000000001136412574354552016162 0ustar rootroot// Copyright (C) 2008-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_INDEX_BUFFER_H_INCLUDED__ #define __C_INDEX_BUFFER_H_INCLUDED__ #include "IIndexBuffer.h" namespace irr { namespace scene { class CIndexBuffer : public IIndexBuffer { class IIndexList { public: virtual ~IIndexList(){}; virtual u32 stride() const =0; virtual u32 size() const =0; virtual void push_back(const u32 &element) =0; virtual u32 operator [](u32 index) const =0; virtual u32 getLast() =0; virtual void setValue(u32 index, u32 value) =0; virtual void set_used(u32 usedNow) =0; virtual void reallocate(u32 new_size) =0; virtual u32 allocated_size() const =0; virtual void* pointer() =0; virtual video::E_INDEX_TYPE getType() const =0; }; template class CSpecificIndexList : public IIndexList { public: core::array Indices; virtual u32 stride() const {return sizeof(T);} virtual u32 size() const {return Indices.size();} virtual void push_back(const u32 &element) { // push const ref due to compiler problem with gcc 4.6, big endian Indices.push_back((const T&)element); } virtual u32 operator [](u32 index) const { return (u32)(Indices[index]); } virtual u32 getLast() {return (u32)Indices.getLast();} virtual void setValue(u32 index, u32 value) { Indices[index]=(T)value; } virtual void set_used(u32 usedNow) { Indices.set_used(usedNow); } virtual void reallocate(u32 new_size) { Indices.reallocate(new_size); } virtual u32 allocated_size() const { return Indices.allocated_size(); } virtual void* pointer() {return Indices.pointer();} virtual video::E_INDEX_TYPE getType() const { if (sizeof(T)==sizeof(u16)) return video::EIT_16BIT; else return video::EIT_32BIT; } }; public: IIndexList *Indices; CIndexBuffer(video::E_INDEX_TYPE IndexType) :Indices(0), MappingHint(EHM_NEVER), ChangedID(1) { setType(IndexType); } CIndexBuffer(const IIndexBuffer &IndexBufferCopy) :Indices(0), MappingHint(EHM_NEVER), ChangedID(1) { setType(IndexBufferCopy.getType()); reallocate(IndexBufferCopy.size()); for (u32 n=0;n; break; } case video::EIT_32BIT: { NewIndices=new CSpecificIndexList; break; } } if (Indices) { NewIndices->reallocate( Indices->size() ); for(u32 n=0;nsize();++n) NewIndices->push_back((*Indices)[n]); delete Indices; } Indices=NewIndices; } virtual void* getData() {return Indices->pointer();} virtual video::E_INDEX_TYPE getType() const {return Indices->getType();} virtual u32 stride() const {return Indices->stride();} virtual u32 size() const { return Indices->size(); } virtual void push_back(const u32 &element) { Indices->push_back(element); } virtual u32 operator [](u32 index) const { return (*Indices)[index]; } virtual u32 getLast() { return Indices->getLast(); } virtual void setValue(u32 index, u32 value) { Indices->setValue(index, value); } virtual void set_used(u32 usedNow) { Indices->set_used(usedNow); } virtual void reallocate(u32 new_size) { Indices->reallocate(new_size); } virtual u32 allocated_size() const { return Indices->allocated_size(); } virtual void* pointer() { return Indices->pointer(); } //! get the current hardware mapping hint virtual E_HARDWARE_MAPPING getHardwareMappingHint() const { return MappingHint; } //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint ) { MappingHint=NewMappingHint; } //! flags the mesh as changed, reloads hardware buffers virtual void setDirty() { ++ChangedID; } //! Get the currently used ID for identification of changes. /** This shouldn't be used for anything outside the VideoDriver. */ virtual u32 getChangedID() const {return ChangedID;} E_HARDWARE_MAPPING MappingHint; u32 ChangedID; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/CDynamicMeshBuffer.h0000644000000000000000000000462612574354552017317 0ustar rootroot// Copyright (C) 2008-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __C_DYNAMIC_MESHBUFFER_H_INCLUDED__ #define __C_DYNAMIC_MESHBUFFER_H_INCLUDED__ #include "IDynamicMeshBuffer.h" #include "CVertexBuffer.h" #include "CIndexBuffer.h" namespace irr { namespace scene { class CDynamicMeshBuffer: public IDynamicMeshBuffer { public: //! constructor CDynamicMeshBuffer(video::E_VERTEX_TYPE vertexType, video::E_INDEX_TYPE indexType) { VertexBuffer=new CVertexBuffer(vertexType); IndexBuffer=new CIndexBuffer(indexType); } //! destructor virtual ~CDynamicMeshBuffer() { if (VertexBuffer) VertexBuffer->drop(); if (IndexBuffer) IndexBuffer->drop(); } virtual IVertexBuffer& getVertexBuffer() const { return *VertexBuffer; } virtual IIndexBuffer& getIndexBuffer() const { return *IndexBuffer; } virtual void setVertexBuffer(IVertexBuffer *newVertexBuffer) { if (newVertexBuffer) newVertexBuffer->grab(); if (VertexBuffer) VertexBuffer->drop(); VertexBuffer=newVertexBuffer; } virtual void setIndexBuffer(IIndexBuffer *newIndexBuffer) { if (newIndexBuffer) newIndexBuffer->grab(); if (IndexBuffer) IndexBuffer->drop(); IndexBuffer=newIndexBuffer; } //! Get Material of this buffer. virtual const video::SMaterial& getMaterial() const { return Material; } //! Get Material of this buffer. virtual video::SMaterial& getMaterial() { return Material; } //! Get bounding box virtual const core::aabbox3d& getBoundingBox() const { return BoundingBox; } //! Set bounding box virtual void setBoundingBox( const core::aabbox3df& box) { BoundingBox = box; } //! Recalculate bounding box virtual void recalculateBoundingBox() { if (!getVertexBuffer().size()) BoundingBox.reset(0,0,0); else { BoundingBox.reset(getVertexBuffer()[0].Pos); for (u32 i=1; i BoundingBox; private: IVertexBuffer *VertexBuffer; IIndexBuffer *IndexBuffer; }; } // end namespace scene } // end namespace irr #endif irrlicht-1.8.3/include/aabbox3d.h0000644000000000000000000002504112574354552015336 0ustar rootroot// Copyright (C) 2002-2012 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #ifndef __IRR_AABBOX_3D_H_INCLUDED__ #define __IRR_AABBOX_3D_H_INCLUDED__ #include "irrMath.h" #include "plane3d.h" #include "line3d.h" namespace irr { namespace core { //! Axis aligned bounding box in 3d dimensional space. /** Has some useful methods used with occlusion culling or clipping. */ template class aabbox3d { public: //! Default Constructor. aabbox3d(): MinEdge(-1,-1,-1), MaxEdge(1,1,1) {} //! Constructor with min edge and max edge. aabbox3d(const vector3d& min, const vector3d& max): MinEdge(min), MaxEdge(max) {} //! Constructor with only one point. aabbox3d(const vector3d& init): MinEdge(init), MaxEdge(init) {} //! Constructor with min edge and max edge as single values, not vectors. aabbox3d(T minx, T miny, T minz, T maxx, T maxy, T maxz): MinEdge(minx, miny, minz), MaxEdge(maxx, maxy, maxz) {} // operators //! Equality operator /** \param other box to compare with. \return True if both boxes are equal, else false. */ inline bool operator==(const aabbox3d& other) const { return (MinEdge == other.MinEdge && other.MaxEdge == MaxEdge);} //! Inequality operator /** \param other box to compare with. \return True if both boxes are different, else false. */ inline bool operator!=(const aabbox3d& other) const { return !(MinEdge == other.MinEdge && other.MaxEdge == MaxEdge);} // functions //! Resets the bounding box to a one-point box. /** \param x X coord of the point. \param y Y coord of the point. \param z Z coord of the point. */ void reset(T x, T y, T z) { MaxEdge.set(x,y,z); MinEdge = MaxEdge; } //! Resets the bounding box. /** \param initValue New box to set this one to. */ void reset(const aabbox3d& initValue) { *this = initValue; } //! Resets the bounding box to a one-point box. /** \param initValue New point. */ void reset(const vector3d& initValue) { MaxEdge = initValue; MinEdge = initValue; } //! Adds a point to the bounding box /** The box grows bigger, if point was outside of the box. \param p: Point to add into the box. */ void addInternalPoint(const vector3d& p) { addInternalPoint(p.X, p.Y, p.Z); } //! Adds another bounding box /** The box grows bigger, if the new box was outside of the box. \param b: Other bounding box to add into this box. */ void addInternalBox(const aabbox3d& b) { addInternalPoint(b.MaxEdge); addInternalPoint(b.MinEdge); } //! Adds a point to the bounding box /** The box grows bigger, if point is outside of the box. \param x X coordinate of the point to add to this box. \param y Y coordinate of the point to add to this box. \param z Z coordinate of the point to add to this box. */ void addInternalPoint(T x, T y, T z) { if (x>MaxEdge.X) MaxEdge.X = x; if (y>MaxEdge.Y) MaxEdge.Y = y; if (z>MaxEdge.Z) MaxEdge.Z = z; if (x getCenter() const { return (MinEdge + MaxEdge) / 2; } //! Get extent of the box (maximal distance of two points in the box) /** \return Extent of the bounding box. */ vector3d getExtent() const { return MaxEdge - MinEdge; } //! Check if the box is empty. /** This means that there is no space between the min and max edge. \return True if box is empty, else false. */ bool isEmpty() const { return MinEdge.equals ( MaxEdge ); } //! Get the volume enclosed by the box in cubed units T getVolume() const { const vector3d e = getExtent(); return e.X * e.Y * e.Z; } //! Get the surface area of the box in squared units T getArea() const { const vector3d e = getExtent(); return 2*(e.X*e.Y + e.X*e.Z + e.Y*e.Z); } //! Stores all 8 edges of the box into an array /** \param edges: Pointer to array of 8 edges. */ void getEdges(vector3d *edges) const { const core::vector3d middle = getCenter(); const core::vector3d diag = middle - MaxEdge; /* Edges are stored in this way: Hey, am I an ascii artist, or what? :) niko. /3--------/7 / | / | / | / | 1---------5 | | /2- - -|- -6 | / | / |/ | / 0---------4/ */ edges[0].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z + diag.Z); edges[1].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z + diag.Z); edges[2].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z - diag.Z); edges[3].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z - diag.Z); edges[4].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z + diag.Z); edges[5].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z + diag.Z); edges[6].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z - diag.Z); edges[7].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z - diag.Z); } //! Repairs the box. /** Necessary if for example MinEdge and MaxEdge are swapped. */ void repair() { T t; if (MinEdge.X > MaxEdge.X) { t=MinEdge.X; MinEdge.X = MaxEdge.X; MaxEdge.X=t; } if (MinEdge.Y > MaxEdge.Y) { t=MinEdge.Y; MinEdge.Y = MaxEdge.Y; MaxEdge.Y=t; } if (MinEdge.Z > MaxEdge.Z) { t=MinEdge.Z; MinEdge.Z = MaxEdge.Z; MaxEdge.Z=t; } } //! Calculates a new interpolated bounding box. /** d=0 returns other, d=1 returns this, all other values blend between the two boxes. \param other Other box to interpolate between \param d Value between 0.0f and 1.0f. \return Interpolated box. */ aabbox3d getInterpolated(const aabbox3d& other, f32 d) const { f32 inv = 1.0f - d; return aabbox3d((other.MinEdge*inv) + (MinEdge*d), (other.MaxEdge*inv) + (MaxEdge*d)); } //! Determines if a point is within this box. /** Border is included (IS part of the box)! \param p: Point to check. \return True if the point is within the box and false if not */ bool isPointInside(const vector3d& p) const { return (p.X >= MinEdge.X && p.X <= MaxEdge.X && p.Y >= MinEdge.Y && p.Y <= MaxEdge.Y && p.Z >= MinEdge.Z && p.Z <= MaxEdge.Z); } //! Determines if a point is within this box and not its borders. /** Border is excluded (NOT part of the box)! \param p: Point to check. \return True if the point is within the box and false if not. */ bool isPointTotalInside(const vector3d& p) const { return (p.X > MinEdge.X && p.X < MaxEdge.X && p.Y > MinEdge.Y && p.Y < MaxEdge.Y && p.Z > MinEdge.Z && p.Z < MaxEdge.Z); } //! Check if this box is completely inside the 'other' box. /** \param other: Other box to check against. \return True if this box is completly inside the other box, otherwise false. */ bool isFullInside(const aabbox3d& other) const { return (MinEdge.X >= other.MinEdge.X && MinEdge.Y >= other.MinEdge.Y && MinEdge.Z >= other.MinEdge.Z && MaxEdge.X <= other.MaxEdge.X && MaxEdge.Y <= other.MaxEdge.Y && MaxEdge.Z <= other.MaxEdge.Z); } //! Determines if the axis-aligned box intersects with another axis-aligned box. /** \param other: Other box to check a intersection with. \return True if there is an intersection with the other box, otherwise false. */ bool intersectsWithBox(const aabbox3d& other) const { return (MinEdge.X <= other.MaxEdge.X && MinEdge.Y <= other.MaxEdge.Y && MinEdge.Z <= other.MaxEdge.Z && MaxEdge.X >= other.MinEdge.X && MaxEdge.Y >= other.MinEdge.Y && MaxEdge.Z >= other.MinEdge.Z); } //! Tests if the box intersects with a line /** \param line: Line to test intersection with. \return True if there is an intersection , else false. */ bool intersectsWithLine(const line3d& line) const { return intersectsWithLine(line.getMiddle(), line.getVector().normalize(), (T)(line.getLength() * 0.5)); } //! Tests if the box intersects with a line /** \param linemiddle Center of the line. \param linevect Vector of the line. \param halflength Half length of the line. \return True if there is an intersection, else false. */ bool intersectsWithLine(const vector3d& linemiddle, const vector3d& linevect, T halflength) const { const vector3d e = getExtent() * (T)0.5; const vector3d t = getCenter() - linemiddle; if ((fabs(t.X) > e.X + halflength * fabs(linevect.X)) || (fabs(t.Y) > e.Y + halflength * fabs(linevect.Y)) || (fabs(t.Z) > e.Z + halflength * fabs(linevect.Z)) ) return false; T r = e.Y * (T)fabs(linevect.Z) + e.Z * (T)fabs(linevect.Y); if (fabs(t.Y*linevect.Z - t.Z*linevect.Y) > r ) return false; r = e.X * (T)fabs(linevect.Z) + e.Z * (T)fabs(linevect.X); if (fabs(t.Z*linevect.X - t.X*linevect.Z) > r ) return false; r = e.X * (T)fabs(linevect.Y) + e.Y * (T)fabs(linevect.X); if (fabs(t.X*linevect.Y - t.Y*linevect.X) > r) return false; return true; } //! Classifies a relation with a plane. /** \param plane Plane to classify relation to. \return Returns ISREL3D_FRONT if the box is in front of the plane, ISREL3D_BACK if the box is behind the plane, and ISREL3D_CLIPPED if it is on both sides of the plane. */ EIntersectionRelation3D classifyPlaneRelation(const plane3d& plane) const { vector3d nearPoint(MaxEdge); vector3d farPoint(MinEdge); if (plane.Normal.X > (T)0) { nearPoint.X = MinEdge.X; farPoint.X = MaxEdge.X; } if (plane.Normal.Y > (T)0) { nearPoint.Y = MinEdge.Y; farPoint.Y = MaxEdge.Y; } if (plane.Normal.Z > (T)0) { nearPoint.Z = MinEdge.Z; farPoint.Z = MaxEdge.Z; } if (plane.Normal.dotProduct(nearPoint) + plane.D > (T)0) return ISREL3D_FRONT; if (plane.Normal.dotProduct(farPoint) + plane.D > (T)0) return ISREL3D_CLIPPED; return ISREL3D_BACK; } //! The near edge vector3d MinEdge; //! The far edge vector3d MaxEdge; }; //! Typedef for a f32 3d bounding box. typedef aabbox3d aabbox3df; //! Typedef for an integer 3d bounding box. typedef aabbox3d aabbox3di; } // end namespace core } // end namespace irr #endif irrlicht-1.8.3/examples/0000755000000000000000000000000012574354552013673 5ustar rootrootirrlicht-1.8.3/examples/whereAreTheBinaries.txt0000644000000000000000000000043712574354552020320 0ustar rootrootIf you are searching for executeables of the examples and the demo, you'll find some for Windows in the directory /bin/win32-VisualStudio. For Linux, just go into the directory of the example you want and execute a simple 'make' after you made the engine from source/Irrlicht. irrlicht-1.8.3/examples/Makefile0000644000000000000000000000014712574354552015335 0ustar rootrootDIRS = $(wildcard [012]* Demo) all: $(DIRS) $(DIRS): -@cd $@ && make clean && make .PHONY: $(DIRS) irrlicht-1.8.3/examples/Demo/0000755000000000000000000000000012574354552014557 5ustar rootrootirrlicht-1.8.3/examples/Demo/resscript.rc0000644000000000000000000000327512574354552017132 0ustar rootroot//Microsoft Developer Studio generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // Deutsch (Österreich) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEA) #ifdef _WIN32 LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN #pragma code_page(1252) #endif //_WIN32 #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDI_ICON1 ICON DISCARDABLE "icon.ico" #endif // Deutsch (Österreich) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED irrlicht-1.8.3/examples/Demo/resource.h0000644000000000000000000000071212574354552016557 0ustar rootroot//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by resscript.rc // #define IDI_ICON1 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif irrlicht-1.8.3/examples/Demo/Makefile0000644000000000000000000000217212574354552016221 0ustar rootroot# Irrlicht Engine Demo Makefile Target = Demo Sources = CDemo.cpp CMainMenu.cpp main.cpp CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -Wall -O3 -ffast-math ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif all: all_linux # target specific settings all_linux: SYSTEM=Linux all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/$(SYSTEM) -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_win32 clean_win32: SYSTEM=Win32-gcc all_win32: LDFLAGS = -L../../lib/$(SYSTEM) -lIrrlicht -lopengl32 -lm # if you enable sound add the proper library for linking #LDFLAGS += -lIrrKlang #LDFLAGS += -laudiere #LDFLAGS += -lSDL_mixer -lSDL all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) OBJ = $(Sources:.cpp=.o) all_linux all_win32: $(OBJ) $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) @$(RM) $(OBJ) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/Demo/main.cpp0000644000000000000000000000173712574354552016217 0ustar rootroot// This is a Demo of the Irrlicht Engine (c) 2005-2009 by N.Gebhardt. // This file is not documented. #include #ifdef _IRR_WINDOWS_ #include #endif #include #include "CMainMenu.h" #include "CDemo.h" using namespace irr; #ifdef _WIN32 #pragma comment(lib, "Irrlicht.lib") INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) #else int main(int argc, char* argv[]) #endif { bool fullscreen = false; bool music = true; bool shadows = false; bool additive = false; bool vsync = false; bool aa = false; #ifndef _IRR_WINDOWS_ video::E_DRIVER_TYPE driverType = video::EDT_OPENGL; #else video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9; #endif CMainMenu menu; //#ifndef _DEBUG if (menu.run(fullscreen, music, shadows, additive, vsync, aa, driverType)) //#endif { CDemo demo(fullscreen, music, shadows, additive, vsync, aa, driverType); demo.run(); } return 0; } irrlicht-1.8.3/examples/Demo/icon.ico0000644000000000000000000000427612574354552016214 0ustar rootroot ¨( @€€€€€€€€€ÀÀÀÀÜÀðʦ """)))UUUMMMBBB999€|ÿPPÿ“ÖÿìÌÆÖïÖçç©­3f™Ì3333f3™3Ì3ÿff3fff™fÌfÿ™™3™f™™™Ì™ÿÌÌ3ÌfÌ™ÌÌÌÿÿfÿ™ÿÌ3333f3™3Ì3ÿ3333333f33™33Ì33ÿ3f3f33ff3f™3fÌ3fÿ3™3™33™f3™™3™Ì3™ÿ3Ì3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿff3fff™fÌfÿf3f33f3ff3™f3Ìf3ÿffff3fffff™ffÌf™f™3f™ff™™f™Ìf™ÿfÌfÌ3fÌ™fÌÌfÌÿfÿfÿ3fÿ™fÿÌÌÿÿÌ™™™3™™™™Ì™™33™f™3Ì™ÿ™f™f3™3f™f™™fÌ™3ÿ™™3™™f™™™™™Ì™™ÿ™Ì™Ì3fÌf™Ì™™ÌÌ™Ìÿ™ÿ™ÿ3™Ìf™ÿ™™ÿÌ™ÿÿÌ™3ÌfÌ™ÌÌ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌfÌf3™ffÌf™ÌfÌ™fÿ̙̙3Ì™fÌ™™Ì™ÌÌ™ÿÌÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÿÌÿ3™ÿfÌÿ™ÌÿÌÌÿÿÌ3ÿfÿ™Ì3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿfÿf3Ìffÿf™ÿfÌÌfÿÿ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÿ3Ìÿfÿÿ™ÿÿÌffÿfÿffÿÿÿffÿfÿÿÿf!¥___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøðûÿ¤  €€€ÿÿÿÿÿÿÿÿÿÿÿÿ mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿmmìêêêê’ììñÿðìmì¼ôóm÷óÿììòÿôììñÿmm CìC ïð mðÿôôCômmïñòó÷÷ð÷ì êðÿôôômmôÿÿ’ ¼ôô¼ðð ì÷ôôômmôÿÿ’ mðÿÿÿÿò ôôômmôÿÿ’¼ÿôï¼ñ êïðCôôômmôÿÿïmììì¼ êðÿïïCìïêmCôÿÿêCñðmðÿCmñ¼òÿÿÿñ¼òÿô’÷ðóô¼ðóÿñ¼ò¼ïïïêmÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿmCCCCCCCCCCCCC®®®®®®®®®®®®®®®®®f Cµ÷®µµ®®®µµ®µ®®®®µ"KLK Cñð®ðð®®µô÷íô÷®®ðóDRzytQ Còðêðñê®óñ®íô’®µô÷CDtz  ™tKD Còðêðñ®¼ó쮵ô÷íô¼®Dy     ztKD Còðêðÿÿÿô﮵ôÿÿÿñìJy     šzuLDCòðêðòìíôìíôïìíñðCDy     ztKD Còðêðñ®®µôííô÷®®ðóCDtzz zyKD Còð®ðÿÿÿÿñ®íôÿÿÿÿ÷CDLuztKD Cµí®íµííí®®®µííí®®DKKK C®®®®®®®®®®®®®®®®®f#" CCCCCCCCCCCCCCCCC irrlicht-1.8.3/examples/Demo/Demo_vc9.vcproj0000644000000000000000000001506612574354552017461 0ustar rootroot irrlicht-1.8.3/examples/Demo/Demo_vc8.vcproj0000644000000000000000000001472012574354552017454 0ustar rootroot irrlicht-1.8.3/examples/Demo/Demo_vc12.vcxproj0000644000000000000000000004402412574354552017717 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47} Demo Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset NDEBUG;%(PreprocessorDefinitions) true true Win32 .\Release/Demo.tlb MaxSpeed Default false ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\Demo.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Windows NDEBUG;%(PreprocessorDefinitions) true true .\Release/Demo.tlb MaxSpeed Default false ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 $(OutDir)$(TargetName)$(TargetExt) ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Windows _DEBUG;%(PreprocessorDefinitions) true true Win32 .\Debug/Demo.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Windows _DEBUG;%(PreprocessorDefinitions) true true .\Debug/Demo.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Windows Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/Demo/Demo_vc11.vcxproj0000644000000000000000000004402612574354552017720 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47} Demo Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset NDEBUG;%(PreprocessorDefinitions) true true Win32 .\Release/Demo.tlb MaxSpeed Default false ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\Demo.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Windows NDEBUG;%(PreprocessorDefinitions) true true .\Release/Demo.tlb MaxSpeed Default false ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\Demo.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Windows _DEBUG;%(PreprocessorDefinitions) true true Win32 .\Debug/Demo.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Windows _DEBUG;%(PreprocessorDefinitions) true true .\Debug/Demo.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Windows Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/Demo/Demo_vc10.vcxproj0000644000000000000000000004402312574354552017714 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47} Demo Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset NDEBUG;%(PreprocessorDefinitions) true true Win32 .\Release/Demo.tlb MaxSpeed Default false ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\Demo.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Windows NDEBUG;%(PreprocessorDefinitions) true true .\Release/Demo.tlb MaxSpeed Default false ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 $(OutDir)$(TargetName)$(TargetExt) ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Windows _DEBUG;%(PreprocessorDefinitions) true true Win32 .\Debug/Demo.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Windows _DEBUG;%(PreprocessorDefinitions) true true .\Debug/Demo.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Windows Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/Demo/Demo.vcproj0000644000000000000000000001334512574354552016676 0ustar rootroot irrlicht-1.8.3/examples/Demo/demo.dev0000644000000000000000000000276212574354552016212 0ustar rootroot[Project] FileName=demo.dev Name=Irrlicht Tech Demo UnitCount=5 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=Demo.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 [Unit2] FileName=CDemo.h CompileCpp=1 Folder=Irrlicht Tech Demo Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=CMainMenu.cpp CompileCpp=1 Folder=Irrlicht Tech Demo Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=CMainMenu.h CompileCpp=1 Folder=Irrlicht Tech Demo Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=CDemo.cpp CompileCpp=1 Folder=Irrlicht Tech Demo Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= irrlicht-1.8.3/examples/Demo/demo.cbp0000644000000000000000000000347212574354552016177 0ustar rootroot irrlicht-1.8.3/examples/Demo/CMainMenu.h0000644000000000000000000000166312574354552016552 0ustar rootroot// This is a Demo of the Irrlicht Engine (c) 2005 by N.Gebhardt. // This file is not documentated. #ifndef __C_MAIN_MENU_H_INCLUDED__ #define __C_MAIN_MENU_H_INCLUDED__ #include using namespace irr; class CMainMenu : public IEventReceiver { public: CMainMenu(); bool run(bool& outFullscreen, bool& outMusic, bool& outShadows, bool& outAdditive, bool &outVSync, bool& outAA, video::E_DRIVER_TYPE& outDriver); virtual bool OnEvent(const SEvent& event); private: void setTransparency(); gui::IGUIButton* startButton; IrrlichtDevice *MenuDevice; s32 selected; bool start; bool fullscreen; bool music; bool shadows; bool additive; bool transparent; bool vsync; bool aa; scene::IAnimatedMesh* quakeLevel; scene::ISceneNode* lightMapNode; scene::ISceneNode* dynamicNode; video::SColor SkinColor [ gui::EGDC_COUNT ]; void getOriginalSkinColor(); }; #endif irrlicht-1.8.3/examples/Demo/CMainMenu.cpp0000644000000000000000000002657212574354552017113 0ustar rootroot// This is a Demo of the Irrlicht Engine (c) 2005-2009 by N.Gebhardt. // This file is not documented. #include "CMainMenu.h" CMainMenu::CMainMenu() : startButton(0), MenuDevice(0), selected(2), start(false), fullscreen(true), music(true), shadows(false), additive(false), transparent(true), vsync(false), aa(false) { } bool CMainMenu::run(bool& outFullscreen, bool& outMusic, bool& outShadows, bool& outAdditive, bool& outVSync, bool& outAA, video::E_DRIVER_TYPE& outDriver) { //video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9; //video::E_DRIVER_TYPE driverType = video::EDT_OPENGL; video::E_DRIVER_TYPE driverType = video::EDT_BURNINGSVIDEO; //video::E_DRIVER_TYPE driverType = video::EDT_SOFTWARE; MenuDevice = createDevice(driverType, core::dimension2d(512, 384), 16, false, false, false, this); if (MenuDevice->getFileSystem()->existFile("irrlicht.dat")) MenuDevice->getFileSystem()->addFileArchive("irrlicht.dat"); else MenuDevice->getFileSystem()->addFileArchive("../../media/irrlicht.dat"); video::IVideoDriver* driver = MenuDevice->getVideoDriver(); scene::ISceneManager* smgr = MenuDevice->getSceneManager(); gui::IGUIEnvironment* guienv = MenuDevice->getGUIEnvironment(); core::stringw str = "Irrlicht Engine Demo v"; str += MenuDevice->getVersion(); MenuDevice->setWindowCaption(str.c_str()); // set new Skin gui::IGUISkin* newskin = guienv->createSkin(gui::EGST_BURNING_SKIN); guienv->setSkin(newskin); newskin->drop(); // load font gui::IGUIFont* font = guienv->getFont("../../media/fonthaettenschweiler.bmp"); if (font) guienv->getSkin()->setFont(font); // add images const s32 leftX = 260; // add tab control gui::IGUITabControl* tabctrl = guienv->addTabControl(core::rect(leftX,10,512-10,384-10), 0, true, true); gui::IGUITab* optTab = tabctrl->addTab(L"Demo"); gui::IGUITab* aboutTab = tabctrl->addTab(L"About"); // add list box gui::IGUIListBox* box = guienv->addListBox(core::rect(10,10,220,120), optTab, 1); box->addItem(L"OpenGL 1.5"); box->addItem(L"Direct3D 8.1"); box->addItem(L"Direct3D 9.0c"); box->addItem(L"Burning's Video 0.47"); box->addItem(L"Irrlicht Software Renderer 1.0"); box->setSelected(selected); // add button startButton = guienv->addButton(core::rect(30,295,200,324), optTab, 2, L"Start Demo"); // add checkbox const s32 d = 50; guienv->addCheckBox(fullscreen, core::rect(20,85+d,130,110+d), optTab, 3, L"Fullscreen"); guienv->addCheckBox(music, core::rect(135,85+d,245,110+d), optTab, 4, L"Music & Sfx"); guienv->addCheckBox(shadows, core::rect(20,110+d,135,135+d), optTab, 5, L"Realtime shadows"); guienv->addCheckBox(additive, core::rect(20,135+d,230,160+d), optTab, 6, L"Old HW compatible blending"); guienv->addCheckBox(vsync, core::rect(20,160+d,230,185+d), optTab, 7, L"Vertical synchronisation"); guienv->addCheckBox(aa, core::rect(20,185+d,230,210+d), optTab, 8, L"Antialiasing"); // add about text const wchar_t* text2 = L"This is the tech demo of the Irrlicht engine. To start, "\ L"select a video driver which works best with your hardware and press 'Start Demo'.\n"\ L"What you currently see is displayed using the Burning Software Renderer (Thomas Alten).\n"\ L"The Irrlicht Engine was written by me, Nikolaus Gebhardt. The models, "\ L"maps and textures were placed at my disposal by B.Collins, M.Cook and J.Marton. The music was created by "\ L"M.Rohde and is played back by irrKlang.\n"\ L"For more informations, please visit the homepage of the Irrlicht engine:\nhttp://irrlicht.sourceforge.net"; guienv->addStaticText(text2, core::rect(10, 10, 230, 320), true, true, aboutTab); // add md2 model scene::IAnimatedMesh* mesh = smgr->getMesh("../../media/faerie.md2"); scene::IAnimatedMeshSceneNode* modelNode = smgr->addAnimatedMeshSceneNode(mesh); if (modelNode) { modelNode->setPosition( core::vector3df(0.f, 0.f, -5.f) ); modelNode->setMaterialTexture(0, driver->getTexture("../../media/faerie2.bmp")); modelNode->setMaterialFlag(video::EMF_LIGHTING, true); modelNode->getMaterial(0).Shininess = 50.f; modelNode->getMaterial(0).NormalizeNormals = true; modelNode->setMD2Animation(scene::EMAT_STAND); } // set ambient light (no sun light in the catacombs) smgr->setAmbientLight( video::SColorf(0.2f, 0.2f, 0.2f) ); scene::ILightSceneNode *light; scene::ISceneNodeAnimator* anim; scene::ISceneNode* bill; enum eLightParticle { LIGHT_NONE, LIGHT_GLOBAL, LIGHT_RED, LIGHT_BLUE }; core::vector3df lightDir[2] = { core::vector3df(0.f, 0.1f, 0.4f), core::vector3df(0.f, 0.1f, -0.4f), }; struct SLightParticle { eLightParticle type; u32 dir; }; const SLightParticle lightParticle[] = { //LIGHT_GLOBAL,0, {LIGHT_RED,0}, {LIGHT_BLUE,0}, {LIGHT_RED,1}, {LIGHT_BLUE,1}, {LIGHT_NONE,0} }; const SLightParticle *l = lightParticle; while ( l->type != LIGHT_NONE ) { switch ( l->type ) { case LIGHT_GLOBAL: // add illumination from the background light = smgr->addLightSceneNode(0, core::vector3df(10.f,40.f,-5.f), video::SColorf(0.2f, 0.2f, 0.2f), 90.f); break; case LIGHT_RED: // add light nearly red light = smgr->addLightSceneNode(0, core::vector3df(0,1,0), video::SColorf(0.8f, 0.f, 0.f, 0.0f), 30.0f); // attach red billboard to the light bill = smgr->addBillboardSceneNode(light, core::dimension2d(10, 10)); if ( bill ) { bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bill->setMaterialTexture(0, driver->getTexture("../../media/particlered.bmp")); } // add fly circle animator to the light anim = smgr->createFlyCircleAnimator(core::vector3df(0.f,0.f,-5.f),20.f, 0.002f, lightDir [l->dir] ); light->addAnimator(anim); anim->drop(); break; case LIGHT_BLUE: // add light nearly blue light = smgr->addLightSceneNode(0, core::vector3df(0,1,0), video::SColorf(0.f, 0.0f, 0.8f, 0.0f), 30.0f); // attach blue billboard to the light bill = smgr->addBillboardSceneNode(light, core::dimension2d(10, 10)); if (bill) { bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bill->setMaterialTexture(0, driver->getTexture("../../media/portal1.bmp")); } // add fly circle animator to the light anim = smgr->createFlyCircleAnimator(core::vector3df(0.f,0.f,-5.f),20.f, -0.002f, lightDir [l->dir], 0.5f); light->addAnimator(anim); anim->drop(); break; case LIGHT_NONE: break; } l += 1; } // create a fixed camera smgr->addCameraSceneNode(0, core::vector3df(45,0,0), core::vector3df(0,0,10)); // irrlicht logo and background // add irrlicht logo bool oldMipMapState = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); guienv->addImage(driver->getTexture("../../media/irrlichtlogo3.png"), core::position2d(5,5)); video::ITexture* irrlichtBack = driver->getTexture("../../media/demoback.jpg"); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); // query original skin color getOriginalSkinColor(); // set transparency setTransparency(); // draw all while(MenuDevice->run()) { if (MenuDevice->isWindowActive()) { driver->beginScene(false, true, video::SColor(0,0,0,0)); if (irrlichtBack) driver->draw2DImage(irrlichtBack, core::position2d(0,0)); smgr->drawAll(); guienv->drawAll(); driver->endScene(); } } MenuDevice->drop(); outFullscreen = fullscreen; outMusic = music; outShadows = shadows; outAdditive = additive; outVSync = vsync; outAA = aa; switch(selected) { case 0: outDriver = video::EDT_OPENGL; break; case 1: outDriver = video::EDT_DIRECT3D8; break; case 2: outDriver = video::EDT_DIRECT3D9; break; case 3: outDriver = video::EDT_BURNINGSVIDEO; break; case 4: outDriver = video::EDT_SOFTWARE; break; } return start; } bool CMainMenu::OnEvent(const SEvent& event) { if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.Key == KEY_F9 && event.KeyInput.PressedDown == false) { video::IImage* image = MenuDevice->getVideoDriver()->createScreenShot(); if (image) { MenuDevice->getVideoDriver()->writeImageToFile(image, "screenshot_main.jpg"); image->drop(); } } else if (event.EventType == irr::EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_RMOUSE_LEFT_UP ) { core::rect r(event.MouseInput.X, event.MouseInput.Y, 0, 0); gui::IGUIContextMenu* menu = MenuDevice->getGUIEnvironment()->addContextMenu(r, 0, 45); menu->addItem(L"transparent menus", 666, transparent == false); menu->addItem(L"solid menus", 666, transparent == true); menu->addSeparator(); menu->addItem(L"Cancel"); } else if (event.EventType == EET_GUI_EVENT) { s32 id = event.GUIEvent.Caller->getID(); switch(id) { case 45: // context menu if (event.GUIEvent.EventType == gui::EGET_MENU_ITEM_SELECTED) { s32 s = ((gui::IGUIContextMenu*)event.GUIEvent.Caller)->getSelectedItem(); if (s == 0 || s == 1) { transparent = !transparent; setTransparency(); } } break; case 1: if (event.GUIEvent.EventType == gui::EGET_LISTBOX_CHANGED || event.GUIEvent.EventType == gui::EGET_LISTBOX_SELECTED_AGAIN) { selected = ((gui::IGUIListBox*)event.GUIEvent.Caller)->getSelected(); //startButton->setEnabled(selected != 4); startButton->setEnabled(true); } break; case 2: if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) { MenuDevice->closeDevice(); start = true; } case 3: if (event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) fullscreen = ((gui::IGUICheckBox*)event.GUIEvent.Caller)->isChecked(); break; case 4: if (event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) music = ((gui::IGUICheckBox*)event.GUIEvent.Caller)->isChecked(); break; case 5: if (event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) shadows = ((gui::IGUICheckBox*)event.GUIEvent.Caller)->isChecked(); break; case 6: if (event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) additive = ((gui::IGUICheckBox*)event.GUIEvent.Caller)->isChecked(); break; case 7: if (event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) vsync = ((gui::IGUICheckBox*)event.GUIEvent.Caller)->isChecked(); break; case 8: if (event.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) aa = ((gui::IGUICheckBox*)event.GUIEvent.Caller)->isChecked(); break; } } return false; } void CMainMenu::getOriginalSkinColor() { irr::gui::IGUISkin * skin = MenuDevice->getGUIEnvironment()->getSkin(); for (s32 i=0; igetColor( (gui::EGUI_DEFAULT_COLOR)i ); } } void CMainMenu::setTransparency() { irr::gui::IGUISkin * skin = MenuDevice->getGUIEnvironment()->getSkin(); for (u32 i=0; isetColor((gui::EGUI_DEFAULT_COLOR)i, col); } } irrlicht-1.8.3/examples/Demo/CDemo.h0000644000000000000000000000436212574354552015724 0ustar rootroot// This is a Demo of the Irrlicht Engine (c) 2006 by N.Gebhardt. // This file is not documented. #ifndef __C_DEMO_H_INCLUDED__ #define __C_DEMO_H_INCLUDED__ //#define USE_IRRKLANG //#define USE_SDL_MIXER #include #ifdef _IRR_WINDOWS_ #include #endif using namespace irr; // audio support #ifdef USE_IRRKLANG #include // problem here? go to http://www.ambiera.com/irrklang and download // the irrKlang library or undefine USE_IRRKLANG at the beginning // of this file. #ifdef _IRR_WINDOWS_ #pragma comment (lib, "irrKlang.lib") #endif #endif #ifdef USE_SDL_MIXER # include # include #endif const int CAMERA_COUNT = 7; class CDemo : public IEventReceiver { public: CDemo(bool fullscreen, bool music, bool shadows, bool additive, bool vsync, bool aa, video::E_DRIVER_TYPE driver); ~CDemo(); void run(); virtual bool OnEvent(const SEvent& event); private: void createLoadingScreen(); void loadSceneData(); void switchToNextScene(); void shoot(); void createParticleImpacts(); bool fullscreen; bool music; bool shadows; bool additive; bool vsync; bool aa; video::E_DRIVER_TYPE driverType; IrrlichtDevice *device; #ifdef USE_IRRKLANG void startIrrKlang(); irrklang::ISoundEngine* irrKlang; irrklang::ISoundSource* ballSound; irrklang::ISoundSource* impactSound; #endif #ifdef USE_SDL_MIXER void startSound(); void playSound(Mix_Chunk *); void pollSound(); Mix_Music *stream; Mix_Chunk *ballSound; Mix_Chunk *impactSound; #endif struct SParticleImpact { u32 when; core::vector3df pos; core::vector3df outVector; }; int currentScene; video::SColor backColor; gui::IGUIStaticText* statusText; gui::IGUIInOutFader* inOutFader; scene::IQ3LevelMesh* quakeLevelMesh; scene::ISceneNode* quakeLevelNode; scene::ISceneNode* skyboxNode; scene::IAnimatedMeshSceneNode* model1; scene::IAnimatedMeshSceneNode* model2; scene::IParticleSystemSceneNode* campFire; scene::IMetaTriangleSelector* metaSelector; scene::ITriangleSelector* mapSelector; s32 sceneStartTime; s32 timeForThisScene; core::array Impacts; }; #endif irrlicht-1.8.3/examples/Demo/CDemo.cpp0000644000000000000000000006003312574354552016254 0ustar rootroot// This is a Demo of the Irrlicht Engine (c) 2005-2009 by N.Gebhardt. // This file is not documented. #include "CDemo.h" CDemo::CDemo(bool f, bool m, bool s, bool a, bool v, bool fsaa, video::E_DRIVER_TYPE d) : fullscreen(f), music(m), shadows(s), additive(a), vsync(v), aa(fsaa), driverType(d), device(0), #ifdef USE_IRRKLANG irrKlang(0), ballSound(0), impactSound(0), #endif #ifdef USE_SDL_MIXER stream(0), ballSound(0), impactSound(0), #endif currentScene(-2), backColor(0), statusText(0), inOutFader(0), quakeLevelMesh(0), quakeLevelNode(0), skyboxNode(0), model1(0), model2(0), campFire(0), metaSelector(0), mapSelector(0), sceneStartTime(0), timeForThisScene(0) { } CDemo::~CDemo() { if (mapSelector) mapSelector->drop(); if (metaSelector) metaSelector->drop(); #ifdef USE_IRRKLANG if (irrKlang) irrKlang->drop(); #endif } void CDemo::run() { core::dimension2d resolution (800, 600); if ( driverType == video::EDT_BURNINGSVIDEO || driverType == video::EDT_SOFTWARE ) { resolution.Width = 640; resolution.Height = 480; } irr::SIrrlichtCreationParameters params; params.DriverType=driverType; params.WindowSize=resolution; params.Bits=32; params.Fullscreen=fullscreen; params.Stencilbuffer=shadows; params.Vsync=vsync; params.AntiAlias=aa?8:0; params.EventReceiver=this; device = createDeviceEx(params); if (!device) return; if (device->getFileSystem()->existFile("irrlicht.dat")) device->getFileSystem()->addFileArchive("irrlicht.dat"); else device->getFileSystem()->addFileArchive("../../media/irrlicht.dat"); if (device->getFileSystem()->existFile("map-20kdm2.pk3")) device->getFileSystem()->addFileArchive("map-20kdm2.pk3"); else device->getFileSystem()->addFileArchive("../../media/map-20kdm2.pk3"); video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* guienv = device->getGUIEnvironment(); device->setWindowCaption(L"Irrlicht Engine Demo"); // set ambient light smgr->setAmbientLight ( video::SColorf ( 0x00c0c0c0 ) ); wchar_t tmp[255]; // draw everything s32 now = 0; s32 lastfps = 0; sceneStartTime = device->getTimer()->getTime(); while(device->run() && driver) { if (device->isWindowActive()) { #ifdef USE_IRRKLANG // update 3D position for sound engine scene::ICameraSceneNode* cam = smgr->getActiveCamera(); if (cam && irrKlang) irrKlang->setListenerPosition(cam->getAbsolutePosition(), cam->getTarget()); #endif // load next scene if necessary now = device->getTimer()->getTime(); if (now - sceneStartTime > timeForThisScene && timeForThisScene!=-1) switchToNextScene(); createParticleImpacts(); driver->beginScene(timeForThisScene != -1, true, backColor); smgr->drawAll(); guienv->drawAll(); driver->endScene(); // write statistics const s32 nowfps = driver->getFPS(); swprintf(tmp, 255, L"%ls fps:%3d triangles:%0.3f mio/s", driver->getName(), driver->getFPS(), driver->getPrimitiveCountDrawn(1) * (1.f / 1000000.f)); statusText->setText(tmp); if ( nowfps != lastfps ) { device->setWindowCaption(tmp); lastfps = nowfps; } } } device->drop(); } bool CDemo::OnEvent(const SEvent& event) { if (!device) return false; if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.Key == KEY_ESCAPE && event.KeyInput.PressedDown == false) { // user wants to quit. if (currentScene < 3) timeForThisScene = 0; else device->closeDevice(); } else if (((event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.Key == KEY_SPACE && event.KeyInput.PressedDown == false) || (event.EventType == EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)) && currentScene == 3) { // shoot shoot(); } else if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.Key == KEY_F9 && event.KeyInput.PressedDown == false) { video::IImage* image = device->getVideoDriver()->createScreenShot(); if (image) { device->getVideoDriver()->writeImageToFile(image, "screenshot.bmp"); device->getVideoDriver()->writeImageToFile(image, "screenshot.png"); device->getVideoDriver()->writeImageToFile(image, "screenshot.tga"); device->getVideoDriver()->writeImageToFile(image, "screenshot.ppm"); device->getVideoDriver()->writeImageToFile(image, "screenshot.jpg"); device->getVideoDriver()->writeImageToFile(image, "screenshot.pcx"); image->drop(); } } else if (device->getSceneManager()->getActiveCamera()) { device->getSceneManager()->getActiveCamera()->OnEvent(event); return true; } return false; } void CDemo::switchToNextScene() { currentScene++; if (currentScene > 3) currentScene = 1; scene::ISceneManager* sm = device->getSceneManager(); scene::ISceneNodeAnimator* sa = 0; scene::ICameraSceneNode* camera = 0; camera = sm->getActiveCamera(); if (camera) { sm->setActiveCamera(0); camera->remove(); camera = 0; } switch(currentScene) { case -1: // loading screen timeForThisScene = 0; createLoadingScreen(); break; case 0: // load scene timeForThisScene = 0; loadSceneData(); break; case 1: // panorama camera { currentScene += 1; //camera = sm->addCameraSceneNode(0, core::vector3df(0,0,0), core::vector3df(-586,708,52)); //camera->setTarget(core::vector3df(0,400,0)); core::array points; points.push_back(core::vector3df(-931.473755f, 138.300003f, 987.279114f)); // -49873 points.push_back(core::vector3df(-847.902222f, 136.757553f, 915.792725f)); // -50559 points.push_back(core::vector3df(-748.680420f, 152.254501f, 826.418945f)); // -51964 points.push_back(core::vector3df(-708.428406f, 213.569580f, 784.466675f)); // -53251 points.push_back(core::vector3df(-686.217651f, 288.141174f, 762.965576f)); // -54015 points.push_back(core::vector3df(-679.685059f, 365.095612f, 756.551453f)); // -54733 points.push_back(core::vector3df(-671.317871f, 447.360107f, 749.394592f)); // -55588 points.push_back(core::vector3df(-669.468445f, 583.335632f, 747.711853f)); // -56178 points.push_back(core::vector3df(-667.611267f, 727.313232f, 746.018250f)); // -56757 points.push_back(core::vector3df(-665.853210f, 862.791931f, 744.436096f)); // -57859 points.push_back(core::vector3df(-642.649597f, 1026.047607f, 724.259827f)); // -59705 points.push_back(core::vector3df(-517.793884f, 838.396790f, 490.326050f)); // -60983 points.push_back(core::vector3df(-474.387299f, 715.691467f, 344.639984f)); // -61629 points.push_back(core::vector3df(-444.600250f, 601.155701f, 180.938095f)); // -62319 points.push_back(core::vector3df(-414.808899f, 479.691406f, 4.866660f)); // -63048 points.push_back(core::vector3df(-410.418945f, 429.642242f, -134.332687f)); // -63757 points.push_back(core::vector3df(-399.837585f, 411.498383f, -349.350983f)); // -64418 points.push_back(core::vector3df(-390.756653f, 403.970093f, -524.454407f)); // -65005 points.push_back(core::vector3df(-334.864227f, 350.065491f, -732.397400f)); // -65701 points.push_back(core::vector3df(-195.253387f, 349.577209f, -812.475891f)); // -66335 points.push_back(core::vector3df(16.255573f, 363.743134f, -833.800415f)); // -67170 points.push_back(core::vector3df(234.940964f, 352.957825f, -820.150696f)); // -67939 points.push_back(core::vector3df(436.797668f, 349.236450f, -816.914185f)); // -68596 points.push_back(core::vector3df(575.236206f, 356.244812f, -719.788513f)); // -69166 points.push_back(core::vector3df(594.131042f, 387.173828f, -609.675598f)); // -69744 points.push_back(core::vector3df(617.615234f, 412.002899f, -326.174072f)); // -70640 points.push_back(core::vector3df(606.456848f, 403.221954f, -104.179291f)); // -71390 points.push_back(core::vector3df(610.958252f, 407.037750f, 117.209778f)); // -72085 points.push_back(core::vector3df(597.956909f, 395.167877f, 345.942200f)); // -72817 points.push_back(core::vector3df(587.383118f, 391.444519f, 566.098633f)); // -73477 points.push_back(core::vector3df(559.572449f, 371.991333f, 777.689453f)); // -74124 points.push_back(core::vector3df(423.753204f, 329.990051f, 925.859741f)); // -74941 points.push_back(core::vector3df(247.520050f, 252.818954f, 935.311829f)); // -75651 points.push_back(core::vector3df(114.756012f, 199.799759f, 805.014160f)); points.push_back(core::vector3df(96.783348f, 181.639481f, 648.188110f)); points.push_back(core::vector3df(97.865623f, 138.905975f, 484.812561f)); points.push_back(core::vector3df(99.612457f, 102.463669f, 347.603210f)); points.push_back(core::vector3df(99.612457f, 102.463669f, 347.603210f)); points.push_back(core::vector3df(99.612457f, 102.463669f, 347.603210f)); timeForThisScene = (points.size()-3)* 1000; camera = sm->addCameraSceneNode(0, points[0], core::vector3df(0 ,400,0)); //camera->setTarget(core::vector3df(0,400,0)); sa = sm->createFollowSplineAnimator(device->getTimer()->getTime(), points); camera->addAnimator(sa); sa->drop(); model1->setVisible(false); model2->setVisible(false); campFire->setVisible(false); inOutFader->fadeIn(7000); } break; case 2: // down fly anim camera camera = sm->addCameraSceneNode(0, core::vector3df(100,40,-80), core::vector3df(844,670,-885)); sa = sm->createFlyStraightAnimator(core::vector3df(94, 1002, 127), core::vector3df(108, 15, -60), 10000, true); camera->addAnimator(sa); timeForThisScene = 9900; model1->setVisible(true); model2->setVisible(false); campFire->setVisible(false); sa->drop(); break; case 3: // interactive, go around { model1->setVisible(true); model2->setVisible(true); campFire->setVisible(true); timeForThisScene = -1; SKeyMap keyMap[9]; keyMap[0].Action = EKA_MOVE_FORWARD; keyMap[0].KeyCode = KEY_UP; keyMap[1].Action = EKA_MOVE_FORWARD; keyMap[1].KeyCode = KEY_KEY_W; keyMap[2].Action = EKA_MOVE_BACKWARD; keyMap[2].KeyCode = KEY_DOWN; keyMap[3].Action = EKA_MOVE_BACKWARD; keyMap[3].KeyCode = KEY_KEY_S; keyMap[4].Action = EKA_STRAFE_LEFT; keyMap[4].KeyCode = KEY_LEFT; keyMap[5].Action = EKA_STRAFE_LEFT; keyMap[5].KeyCode = KEY_KEY_A; keyMap[6].Action = EKA_STRAFE_RIGHT; keyMap[6].KeyCode = KEY_RIGHT; keyMap[7].Action = EKA_STRAFE_RIGHT; keyMap[7].KeyCode = KEY_KEY_D; keyMap[8].Action = EKA_JUMP_UP; keyMap[8].KeyCode = KEY_KEY_J; camera = sm->addCameraSceneNodeFPS(0, 100.0f, .4f, -1, keyMap, 9, false, 3.f); camera->setPosition(core::vector3df(108,140,-140)); camera->setFarValue(5000.0f); scene::ISceneNodeAnimatorCollisionResponse* collider = sm->createCollisionResponseAnimator( metaSelector, camera, core::vector3df(25,50,25), core::vector3df(0, quakeLevelMesh ? -10.f : 0.0f,0), core::vector3df(0,45,0), 0.005f); camera->addAnimator(collider); collider->drop(); } break; } sceneStartTime = device->getTimer()->getTime(); } void CDemo::loadSceneData() { // load quake level video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* sm = device->getSceneManager(); // Quake3 Shader controls Z-Writing sm->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); quakeLevelMesh = (scene::IQ3LevelMesh*) sm->getMesh("maps/20kdm2.bsp"); if (quakeLevelMesh) { u32 i; //move all quake level meshes (non-realtime) core::matrix4 m; m.setTranslation(core::vector3df(-1300,-70,-1249)); for ( i = 0; i != scene::quake3::E_Q3_MESH_SIZE; ++i ) sm->getMeshManipulator()->transform(quakeLevelMesh->getMesh(i), m); quakeLevelNode = sm->addOctreeSceneNode( quakeLevelMesh->getMesh( scene::quake3::E_Q3_MESH_GEOMETRY)); if (quakeLevelNode) { //quakeLevelNode->setPosition(core::vector3df(-1300,-70,-1249)); quakeLevelNode->setVisible(true); // create map triangle selector mapSelector = sm->createOctreeTriangleSelector(quakeLevelMesh->getMesh(0), quakeLevelNode, 128); // if not using shader and no gamma it's better to use more lighting, because // quake3 level are usually dark quakeLevelNode->setMaterialType ( video::EMT_LIGHTMAP_M4 ); // set additive blending if wanted if (additive) quakeLevelNode->setMaterialType(video::EMT_LIGHTMAP_ADD); } // the additional mesh can be quite huge and is unoptimized scene::IMesh * additional_mesh = quakeLevelMesh->getMesh ( scene::quake3::E_Q3_MESH_ITEMS ); for ( i = 0; i!= additional_mesh->getMeshBufferCount (); ++i ) { scene::IMeshBuffer *meshBuffer = additional_mesh->getMeshBuffer ( i ); const video::SMaterial &material = meshBuffer->getMaterial(); //! The ShaderIndex is stored in the material parameter s32 shaderIndex = (s32) material.MaterialTypeParam2; // the meshbuffer can be rendered without additional support, or it has no shader const scene::quake3::IShader *shader = quakeLevelMesh->getShader ( shaderIndex ); if ( 0 == shader ) { continue; } // Now add the MeshBuffer(s) with the current Shader to the Manager sm->addQuake3SceneNode ( meshBuffer, shader ); } } // load sydney model and create 2 instances scene::IAnimatedMesh* mesh = 0; mesh = sm->getMesh("../../media/sydney.md2"); if (mesh) { model1 = sm->addAnimatedMeshSceneNode(mesh); if (model1) { model1->setMaterialTexture(0, driver->getTexture("../../media/spheremap.jpg")); model1->setPosition(core::vector3df(100,40,-80)); model1->setScale(core::vector3df(2,2,2)); model1->setMD2Animation(scene::EMAT_STAND); model1->setMaterialFlag(video::EMF_LIGHTING, false); model1->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true); model1->setMaterialType(video::EMT_SPHERE_MAP); model1->addShadowVolumeSceneNode(); } model2 = sm->addAnimatedMeshSceneNode(mesh); if (model2) { model2->setPosition(core::vector3df(180,15,-60)); model2->setScale(core::vector3df(2,2,2)); model2->setMD2Animation(scene::EMAT_RUN); model2->setMaterialTexture(0, device->getVideoDriver()->getTexture("../../media/sydney.bmp")); model2->setMaterialFlag(video::EMF_LIGHTING, true); model2->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true); model2->addShadowVolumeSceneNode(); } } scene::ISceneNodeAnimator* anim = 0; // create sky box driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); skyboxNode = sm->addSkyBoxSceneNode( driver->getTexture("../../media/irrlicht2_up.jpg"), driver->getTexture("../../media/irrlicht2_dn.jpg"), driver->getTexture("../../media/irrlicht2_lf.jpg"), driver->getTexture("../../media/irrlicht2_rt.jpg"), driver->getTexture("../../media/irrlicht2_ft.jpg"), driver->getTexture("../../media/irrlicht2_bk.jpg")); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true); // create walk-between-portals animation core::vector3df waypoint[2]; waypoint[0].set(-150,40,100); waypoint[1].set(350,40,100); if (model2) { anim = device->getSceneManager()->createFlyStraightAnimator( waypoint[0], waypoint[1], 2000, true); model2->addAnimator(anim); anim->drop(); } // create animation for portals; core::array textures; for (s32 g=1; g<8; ++g) { core::stringc tmp("../../media/portal"); tmp += g; tmp += ".bmp"; video::ITexture* t = driver->getTexture( tmp ); textures.push_back(t); } anim = sm->createTextureAnimator(textures, 100); // create portals scene::IBillboardSceneNode* bill = 0; for (int r=0; r<2; ++r) { bill = sm->addBillboardSceneNode(0, core::dimension2d(100,100), waypoint[r]+ core::vector3df(0,20,0)); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialTexture(0, driver->getTexture("../../media/portal1.bmp")); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bill->addAnimator(anim); } anim->drop(); // create cirlce flying dynamic light with transparent billboard attached scene::ILightSceneNode* light = 0; light = sm->addLightSceneNode(0, core::vector3df(0,0,0), video::SColorf(1.0f, 1.0f, 1.f, 1.0f), 500.f); anim = sm->createFlyCircleAnimator( core::vector3df(100,150,80), 80.0f, 0.0005f); light->addAnimator(anim); anim->drop(); bill = device->getSceneManager()->addBillboardSceneNode( light, core::dimension2d(40,40)); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialTexture(0, driver->getTexture("../../media/particlewhite.bmp")); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); // create meta triangle selector with all triangles selectors in it. metaSelector = sm->createMetaTriangleSelector(); metaSelector->addTriangleSelector(mapSelector); // create camp fire campFire = sm->addParticleSystemSceneNode(false); campFire->setPosition(core::vector3df(100,120,600)); campFire->setScale(core::vector3df(2,2,2)); scene::IParticleEmitter* em = campFire->createBoxEmitter( core::aabbox3d(-7,0,-7,7,1,7), core::vector3df(0.0f,0.06f,0.0f), 80,100, video::SColor(1,255,255,255),video::SColor(1,255,255,255), 800,2000); em->setMinStartSize(core::dimension2d(20.0f, 10.0f)); em->setMaxStartSize(core::dimension2d(20.0f, 10.0f)); campFire->setEmitter(em); em->drop(); scene::IParticleAffector* paf = campFire->createFadeOutParticleAffector(); campFire->addAffector(paf); paf->drop(); campFire->setMaterialFlag(video::EMF_LIGHTING, false); campFire->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); campFire->setMaterialTexture(0, driver->getTexture("../../media/fireball.bmp")); campFire->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); // load music #ifdef USE_IRRKLANG if (music) startIrrKlang(); #endif #ifdef USE_SDL_MIXER if (music) startSound(); #endif } void CDemo::createLoadingScreen() { core::dimension2d size = device->getVideoDriver()->getScreenSize(); device->getCursorControl()->setVisible(false); // setup loading screen backColor.set(255,90,90,156); // create in fader inOutFader = device->getGUIEnvironment()->addInOutFader(); inOutFader->setColor(backColor, video::SColor ( 0, 230, 230, 230 )); // irrlicht logo device->getGUIEnvironment()->addImage(device->getVideoDriver()->getTexture("../../media/irrlichtlogo2.png"), core::position2d(5,5)); // loading text const int lwidth = size.Width - 20; const int lheight = 16; core::rect pos(10, size.Height-lheight-10, 10+lwidth, size.Height-10); device->getGUIEnvironment()->addImage(pos); statusText = device->getGUIEnvironment()->addStaticText(L"Loading...", pos, true); statusText->setOverrideColor(video::SColor(255,205,200,200)); // load bigger font device->getGUIEnvironment()->getSkin()->setFont( device->getGUIEnvironment()->getFont("../../media/fonthaettenschweiler.bmp")); // set new font color device->getGUIEnvironment()->getSkin()->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,100,100,100)); } void CDemo::shoot() { scene::ISceneManager* sm = device->getSceneManager(); scene::ICameraSceneNode* camera = sm->getActiveCamera(); if (!camera || !mapSelector) return; SParticleImpact imp; imp.when = 0; // get line of camera core::vector3df start = camera->getPosition(); core::vector3df end = (camera->getTarget() - start); end.normalize(); start += end*8.0f; end = start + (end * camera->getFarValue()); core::triangle3df triangle; core::line3d line(start, end); // get intersection point with map scene::ISceneNode* hitNode; if (sm->getSceneCollisionManager()->getCollisionPoint( line, mapSelector, end, triangle, hitNode)) { // collides with wall core::vector3df out = triangle.getNormal(); out.setLength(0.03f); imp.when = 1; imp.outVector = out; imp.pos = end; } else { // doesnt collide with wall core::vector3df start = camera->getPosition(); core::vector3df end = (camera->getTarget() - start); end.normalize(); start += end*8.0f; end = start + (end * camera->getFarValue()); } // create fire ball scene::ISceneNode* node = 0; node = sm->addBillboardSceneNode(0, core::dimension2d(25,25), start); node->setMaterialFlag(video::EMF_LIGHTING, false); node->setMaterialTexture(0, device->getVideoDriver()->getTexture("../../media/fireball.bmp")); node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); f32 length = (f32)(end - start).getLength(); const f32 speed = 0.6f; u32 time = (u32)(length / speed); scene::ISceneNodeAnimator* anim = 0; // set flight line anim = sm->createFlyStraightAnimator(start, end, time); node->addAnimator(anim); anim->drop(); anim = sm->createDeleteAnimator(time); node->addAnimator(anim); anim->drop(); if (imp.when) { // create impact note imp.when = device->getTimer()->getTime() + (time - 100); Impacts.push_back(imp); } // play sound #ifdef USE_IRRKLANG if (ballSound) irrKlang->play2D(ballSound); #endif #ifdef USE_SDL_MIXER if (ballSound) playSound(ballSound); #endif } void CDemo::createParticleImpacts() { u32 now = device->getTimer()->getTime(); scene::ISceneManager* sm = device->getSceneManager(); for (s32 i=0; i<(s32)Impacts.size(); ++i) if (now > Impacts[i].when) { // create smoke particle system scene::IParticleSystemSceneNode* pas = 0; pas = sm->addParticleSystemSceneNode(false, 0, -1, Impacts[i].pos); pas->setParticleSize(core::dimension2d(10.0f, 10.0f)); scene::IParticleEmitter* em = pas->createBoxEmitter( core::aabbox3d(-5,-5,-5,5,5,5), Impacts[i].outVector, 20,40, video::SColor(50,255,255,255),video::SColor(50,255,255,255), 1200,1600, 20); pas->setEmitter(em); em->drop(); scene::IParticleAffector* paf = campFire->createFadeOutParticleAffector(); pas->addAffector(paf); paf->drop(); pas->setMaterialFlag(video::EMF_LIGHTING, false); pas->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); pas->setMaterialTexture(0, device->getVideoDriver()->getTexture("../../media/smoke.bmp")); pas->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); scene::ISceneNodeAnimator* anim = sm->createDeleteAnimator(2000); pas->addAnimator(anim); anim->drop(); // play impact sound #ifdef USE_IRRKLANG if (irrKlang) { irrklang::ISound* sound = irrKlang->play3D(impactSound, Impacts[i].pos, false, false, true); if (sound) { // adjust max value a bit to make to sound of an impact louder sound->setMinDistance(400); sound->drop(); } } #endif #ifdef USE_SDL_MIXER if (impactSound) playSound(impactSound); #endif // delete entry Impacts.erase(i); i--; } } #ifdef USE_IRRKLANG void CDemo::startIrrKlang() { irrKlang = irrklang::createIrrKlangDevice(); if (!irrKlang) return; // play music irrklang::ISound* snd = irrKlang->play2D("../../media/IrrlichtTheme.ogg", true, false, true); if ( !snd ) snd = irrKlang->play2D("IrrlichtTheme.ogg", true, false, true); if (snd) { snd->setVolume(0.5f); // 50% volume snd->drop(); } // preload both sound effects ballSound = irrKlang->getSoundSource("../../media/ball.wav"); impactSound = irrKlang->getSoundSource("../../media/impact.wav"); } #endif #ifdef USE_SDL_MIXER void CDemo::startSound() { stream = NULL; ballSound = NULL; impactSound = NULL; SDL_Init(SDL_INIT_AUDIO); if (Mix_OpenAudio(22050, AUDIO_S16, 2, 128)) return; stream = Mix_LoadMUS("../../media/IrrlichtTheme.ogg"); if (stream) Mix_PlayMusic(stream, -1); ballSound = Mix_LoadWAV("../../media/ball.wav"); impactSound = Mix_LoadWAV("../../media/impact.wav"); } void CDemo::playSound(Mix_Chunk *sample) { if (sample) Mix_PlayChannel(-1, sample, 0); } void CDemo::pollSound(void) { SDL_Event event; while (SDL_PollEvent(&event)) ; } #endif irrlicht-1.8.3/examples/BuildAllExamples_vc12.sln0000644000000000000000000007045612574354552020447 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.40629.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "..\source\Irrlicht\Irrlicht12.0.vcxproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "01.HelloWorld", "01.HelloWorld\HelloWorld_vc12.vcxproj", "{5AD4C95C-BA38-4692-BA4B-8C25A86208F9}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "02.Quake3Map", "02.Quake3Map\Quake3Map_vc12.vcxproj", "{D1A464A2-D479-458C-98A2-60965D823CD1}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "03.CustomSceneNode", "03.CustomSceneNode\CustomSceneNode_vc12.vcxproj", "{171CCDFA-C140-4956-8EB7-F0168F4521D3}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "04.Movement", "04.Movement\Movement_vc12.vcxproj", "{7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "05.UserInterface", "05.UserInterface\UserInterface_vc12.vcxproj", "{622C9DD7-0391-49FF-AF53-24F9D5A8EC53}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "06.2DGraphics", "06.2DGraphics\2DGraphics_vc12.vcxproj", "{E71B6F18-10DC-4101-A541-F6D33F71B2BD}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "07.Collision", "07.Collision\Collision_vc12.vcxproj", "{3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "08.SpecialFX", "08.SpecialFX\SpecialFX_vc12.vcxproj", "{C869BF55-B9D6-4980-BC92-60FA0CF8411A}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "09.Meshviewer", "09.Meshviewer\Meshviewer_vc12.vcxproj", "{2AE24484-22FC-481B-9A40-7CD0DA5C8E06}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "11.PerPixelLighting", "11.PerPixelLighting\PerPixelLighting_vc12.vcxproj", "{C4B42409-542D-4EFC-9E6B-44713FD47A33}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "12.TerrainRendering", "12.TerrainRendering\TerrainRendering_vc12.vcxproj", "{3A5B74E5-6390-43B0-A459-2793B81FFD31}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "13.RenderToTexture", "13.RenderToTexture\RenderToTexture_vc12.vcxproj", "{0914E5C8-5352-467B-8421-C9EB35BD5596}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "14.Win32Window", "14.Win32Window\Win32Window_vc12.vcxproj", "{772FBE05-D05A-467B-9842-BEC409EEA8D0}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "15.LoadIrrFile", "15.LoadIrrFile\LoadIrrFile_vc12.vcxproj", "{78C9F424-523C-49AC-94B7-823AA4A26BF9}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16.Quake3MapShader", "16.Quake3MapShader\Quake3MapShader_vc12.vcxproj", "{EB3B38EA-5CE7-4983-845B-880661E69D09}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17.HelloWorld_Mobile", "17.HelloWorld_Mobile\17. HelloWorld for Windows Mobile on PC_vc12.vcxproj", "{2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "18.SplitScreen", "18.SplitScreen\SplitScreen_vc12.vcxproj", "{1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "19.MouseAndJoystick", "19.MouseAndJoystick\MouseAndJoystick_vc12.vcxproj", "{FE853A36-E0D1-4AC5-A792-B643E70D2953}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "20.ManagedLights", "20.ManagedLights\ManagedLights_vc12.vcxproj", "{16007FE2-142B-47F8-93E1-519BA3F39E71}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "21.Quake3Explorer", "21.Quake3Explorer\Quake3Explorer_vc12.vcxproj", "{CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "22.MaterialViewer", "22.MaterialViewer\MaterialViewer_vc12.vcxproj", "{4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "23.SMeshHandling", "23.SMeshHandling\SMeshHandling_vc12.vcxproj", "{6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "24.CursorControl", "24.CursorControl\CursorControl_vc12.vcxproj", "{02B67A37-50E1-49DB-BECF-905BC029C2FE}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo\Demo_vc12.vcxproj", "{6F076455-D955-45D4-9C68-4AD4E45F2D47}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GUIEditor", "..\tools\GUIEditor\GUI Editor_vc12.vcxproj", "{853A396E-C031-4C26-A716-5B4E176BE11D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FontTool", "..\tools\IrrFontTool\newFontTool\irrFontTool_vc12.vcxproj", "{4D53E40F-37E3-42B1-8848-F4C6F8313A17}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeshConverter", "..\tools\MeshConverter\MeshConverter_vc12.vcxproj", "{E72B637E-4AA6-46F3-885F-AC67B4B470ED}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "26.OcclusionQuery", "26.OcclusionQuery\OcclusionQuery_vc12.vcxproj", "{5CE0E2E7-879D-4152-B61D-24E7D0707B45}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "25.XmlHandling", "25.XmlHandling\XmlHandling_vc12.vcxproj", "{8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "10.Shaders", "10.Shaders\Shaders_vc12.vcxproj", "{27158C82-CD15-4A9B-9848-35E7065B209F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.ActiveCfg = Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.Build.0 = Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|x64.ActiveCfg = Release|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|x64.Build.0 = Release|x64 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|Win32.ActiveCfg = Debug|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|Win32.Build.0 = Debug|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|x64.ActiveCfg = Debug|x64 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|x64.Build.0 = Debug|x64 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|Win32.ActiveCfg = Release|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|Win32.Build.0 = Release|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|x64.ActiveCfg = Release|x64 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|x64.Build.0 = Release|x64 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|Win32.ActiveCfg = Debug|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|Win32.Build.0 = Debug|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|x64.ActiveCfg = Debug|x64 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|x64.Build.0 = Debug|x64 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|Win32.ActiveCfg = Release|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|Win32.Build.0 = Release|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|x64.ActiveCfg = Release|x64 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|x64.Build.0 = Release|x64 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|Win32.ActiveCfg = Debug|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|Win32.Build.0 = Debug|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|x64.ActiveCfg = Debug|x64 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|x64.Build.0 = Debug|x64 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|Win32.ActiveCfg = Release|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|Win32.Build.0 = Release|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|x64.ActiveCfg = Release|x64 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|x64.Build.0 = Release|x64 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|Win32.ActiveCfg = Debug|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|Win32.Build.0 = Debug|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|x64.ActiveCfg = Debug|x64 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|x64.Build.0 = Debug|x64 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|Win32.ActiveCfg = Release|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|Win32.Build.0 = Release|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|x64.ActiveCfg = Release|x64 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|x64.Build.0 = Release|x64 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|Win32.ActiveCfg = Debug|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|Win32.Build.0 = Debug|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|x64.ActiveCfg = Debug|x64 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|x64.Build.0 = Debug|x64 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|Win32.ActiveCfg = Release|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|Win32.Build.0 = Release|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|x64.ActiveCfg = Release|x64 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|x64.Build.0 = Release|x64 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|Win32.ActiveCfg = Debug|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|Win32.Build.0 = Debug|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|x64.ActiveCfg = Debug|x64 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|x64.Build.0 = Debug|x64 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|Win32.ActiveCfg = Release|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|Win32.Build.0 = Release|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|x64.ActiveCfg = Release|x64 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|x64.Build.0 = Release|x64 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|Win32.ActiveCfg = Debug|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|Win32.Build.0 = Debug|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|x64.ActiveCfg = Debug|x64 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|x64.Build.0 = Debug|x64 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|Win32.ActiveCfg = Release|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|Win32.Build.0 = Release|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|x64.ActiveCfg = Release|x64 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|x64.Build.0 = Release|x64 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|Win32.ActiveCfg = Debug|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|Win32.Build.0 = Debug|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|x64.ActiveCfg = Debug|x64 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|x64.Build.0 = Debug|x64 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|Win32.ActiveCfg = Release|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|Win32.Build.0 = Release|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|x64.ActiveCfg = Release|x64 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|x64.Build.0 = Release|x64 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|Win32.ActiveCfg = Debug|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|Win32.Build.0 = Debug|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|x64.ActiveCfg = Debug|x64 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|x64.Build.0 = Debug|x64 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|Win32.ActiveCfg = Release|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|Win32.Build.0 = Release|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|x64.ActiveCfg = Release|x64 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|x64.Build.0 = Release|x64 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|Win32.ActiveCfg = Debug|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|Win32.Build.0 = Debug|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|x64.ActiveCfg = Debug|x64 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|x64.Build.0 = Debug|x64 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|Win32.ActiveCfg = Release|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|Win32.Build.0 = Release|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|x64.ActiveCfg = Release|x64 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|x64.Build.0 = Release|x64 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|Win32.ActiveCfg = Debug|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|Win32.Build.0 = Debug|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|x64.ActiveCfg = Debug|x64 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|x64.Build.0 = Debug|x64 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|Win32.ActiveCfg = Release|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|Win32.Build.0 = Release|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|x64.ActiveCfg = Release|x64 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|x64.Build.0 = Release|x64 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|Win32.ActiveCfg = Debug|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|Win32.Build.0 = Debug|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|x64.ActiveCfg = Debug|x64 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|x64.Build.0 = Debug|x64 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|Win32.ActiveCfg = Release|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|Win32.Build.0 = Release|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|x64.ActiveCfg = Release|x64 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|x64.Build.0 = Release|x64 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|Win32.ActiveCfg = Debug|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|Win32.Build.0 = Debug|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|x64.ActiveCfg = Debug|x64 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|x64.Build.0 = Debug|x64 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|Win32.ActiveCfg = Release|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|Win32.Build.0 = Release|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|x64.ActiveCfg = Release|x64 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|x64.Build.0 = Release|x64 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|Win32.ActiveCfg = Debug|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|Win32.Build.0 = Debug|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|x64.ActiveCfg = Debug|x64 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|x64.Build.0 = Debug|x64 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|Win32.ActiveCfg = Release|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|Win32.Build.0 = Release|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|x64.ActiveCfg = Release|x64 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|x64.Build.0 = Release|x64 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|Win32.ActiveCfg = Debug|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|Win32.Build.0 = Debug|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|x64.ActiveCfg = Debug|x64 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|x64.Build.0 = Debug|x64 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|Win32.ActiveCfg = Release|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|Win32.Build.0 = Release|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|x64.ActiveCfg = Release|x64 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|x64.Build.0 = Release|x64 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.ActiveCfg = Debug|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.Build.0 = Debug|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|x64.ActiveCfg = Debug|x64 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|x64.Build.0 = Debug|x64 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.ActiveCfg = Release|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.Build.0 = Release|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|x64.ActiveCfg = Release|x64 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|x64.Build.0 = Release|x64 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|Win32.ActiveCfg = Debug|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|Win32.Build.0 = Debug|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|x64.ActiveCfg = Debug|x64 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|x64.Build.0 = Debug|x64 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|Win32.ActiveCfg = Release|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|Win32.Build.0 = Release|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|x64.ActiveCfg = Release|x64 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|x64.Build.0 = Release|x64 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|Win32.ActiveCfg = Debug|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|Win32.Build.0 = Debug|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|x64.ActiveCfg = Debug|x64 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|x64.Build.0 = Debug|x64 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|Win32.ActiveCfg = Release|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|Win32.Build.0 = Release|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|x64.ActiveCfg = Release|x64 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|x64.Build.0 = Release|x64 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|Win32.ActiveCfg = Debug|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|Win32.Build.0 = Debug|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|x64.ActiveCfg = Debug|x64 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|x64.Build.0 = Debug|x64 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|Win32.ActiveCfg = Release|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|Win32.Build.0 = Release|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|x64.ActiveCfg = Release|x64 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|x64.Build.0 = Release|x64 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.ActiveCfg = Debug|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.Build.0 = Debug|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|x64.ActiveCfg = Debug|x64 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|x64.Build.0 = Debug|x64 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.ActiveCfg = Release|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.Build.0 = Release|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|x64.ActiveCfg = Release|x64 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|x64.Build.0 = Release|x64 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|Win32.ActiveCfg = Debug|Win32 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|Win32.Build.0 = Debug|Win32 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|x64.ActiveCfg = Debug|x64 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|x64.Build.0 = Debug|x64 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|Win32.ActiveCfg = Release|Win32 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|Win32.Build.0 = Release|Win32 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|x64.ActiveCfg = Release|x64 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|x64.Build.0 = Release|x64 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|Win32.ActiveCfg = Debug|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|Win32.Build.0 = Debug|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|x64.ActiveCfg = Debug|x64 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|x64.Build.0 = Debug|x64 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|Win32.ActiveCfg = Release|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|Win32.Build.0 = Release|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|x64.ActiveCfg = Release|x64 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|x64.Build.0 = Release|x64 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|Win32.ActiveCfg = Debug|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|Win32.Build.0 = Debug|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|x64.ActiveCfg = Debug|x64 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|x64.Build.0 = Debug|x64 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|Win32.ActiveCfg = Release|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|Win32.Build.0 = Release|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|x64.ActiveCfg = Release|x64 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|x64.Build.0 = Release|x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.ActiveCfg = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.Build.0 = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|x64.ActiveCfg = Debug|x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|x64.Build.0 = Debug|x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|Win32.ActiveCfg = Release|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|Win32.Build.0 = Release|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|x64.ActiveCfg = Release|x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|x64.Build.0 = Release|x64 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.ActiveCfg = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.Build.0 = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|x64.ActiveCfg = Debug|x64 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|x64.Build.0 = Debug|x64 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.ActiveCfg = Release|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.Build.0 = Release|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|x64.ActiveCfg = Release|x64 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|x64.Build.0 = Release|x64 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.ActiveCfg = Debug|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.Build.0 = Debug|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|x64.ActiveCfg = Debug|x64 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|x64.Build.0 = Debug|x64 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.ActiveCfg = Release|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.Build.0 = Release|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|x64.ActiveCfg = Release|x64 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|x64.Build.0 = Release|x64 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|Win32.ActiveCfg = Debug|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|Win32.Build.0 = Debug|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|x64.ActiveCfg = Debug|x64 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|x64.Build.0 = Debug|x64 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|Win32.ActiveCfg = Release|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|Win32.Build.0 = Release|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|x64.ActiveCfg = Release|x64 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|x64.Build.0 = Release|x64 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Debug|Win32.ActiveCfg = Debug|Win32 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Debug|Win32.Build.0 = Debug|Win32 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Debug|x64.ActiveCfg = Debug|x64 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Debug|x64.Build.0 = Debug|x64 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Release|Win32.ActiveCfg = Release|Win32 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Release|Win32.Build.0 = Release|Win32 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Release|x64.ActiveCfg = Release|x64 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Release|x64.Build.0 = Release|x64 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|Win32.ActiveCfg = Debug|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|Win32.Build.0 = Debug|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|x64.ActiveCfg = Debug|x64 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|x64.Build.0 = Debug|x64 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|Win32.ActiveCfg = Release|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|Win32.Build.0 = Release|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|x64.ActiveCfg = Release|x64 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|x64.Build.0 = Release|x64 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|Win32.ActiveCfg = Debug|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|Win32.Build.0 = Debug|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|x64.ActiveCfg = Debug|x64 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|x64.Build.0 = Debug|x64 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|Win32.ActiveCfg = Release|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|Win32.Build.0 = Release|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|x64.ActiveCfg = Release|x64 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/examples/BuildAllExamples_vc11.sln0000644000000000000000000007105012574354552020435 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2012 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "..\source\Irrlicht\Irrlicht11.0.vcxproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "01.HelloWorld", "01.HelloWorld\HelloWorld_vc11.vcxproj", "{5AD4C95C-BA38-4692-BA4B-8C25A86208F9}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "02.Quake3Map", "02.Quake3Map\Quake3Map_vc11.vcxproj", "{D1A464A2-D479-458C-98A2-60965D823CD1}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "03.CustomSceneNode", "03.CustomSceneNode\CustomSceneNode_vc11.vcxproj", "{171CCDFA-C140-4956-8EB7-F0168F4521D3}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "04.Movement", "04.Movement\Movement_vc11.vcxproj", "{7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "05.UserInterface", "05.UserInterface\UserInterface_vc11.vcxproj", "{622C9DD7-0391-49FF-AF53-24F9D5A8EC53}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "06.2DGraphics", "06.2DGraphics\2DGraphics_vc11.vcxproj", "{E71B6F18-10DC-4101-A541-F6D33F71B2BD}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "07.Collision", "07.Collision\Collision_vc11.vcxproj", "{3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "08.SpecialFX", "08.SpecialFX\SpecialFX_vc11.vcxproj", "{C869BF55-B9D6-4980-BC92-60FA0CF8411A}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "09.Meshviewer", "09.Meshviewer\Meshviewer_vc11.vcxproj", "{2AE24484-22FC-481B-9A40-7CD0DA5C8E06}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "10.Shaders", "10.Shaders\Shaders_vc11.vcxproj", "{27158C82-CD15-4A9B-9848-35E7065B209F}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "11.PerPixelLighting", "11.PerPixelLighting\PerPixelLighting_vc11.vcxproj", "{C4B42409-542D-4EFC-9E6B-44713FD47A33}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "12.TerrainRendering", "12.TerrainRendering\TerrainRendering_vc11.vcxproj", "{3A5B74E5-6390-43B0-A459-2793B81FFD31}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "13.RenderToTexture", "13.RenderToTexture\RenderToTexture_vc11.vcxproj", "{0914E5C8-5352-467B-8421-C9EB35BD5596}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "14.Win32Window", "14.Win32Window\Win32Window_vc11.vcxproj", "{772FBE05-D05A-467B-9842-BEC409EEA8D0}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "15.LoadIrrFile", "15.LoadIrrFile\LoadIrrFile_vc11.vcxproj", "{78C9F424-523C-49AC-94B7-823AA4A26BF9}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16.Quake3MapShader", "16.Quake3MapShader\Quake3MapShader_vc11.vcxproj", "{EB3B38EA-5CE7-4983-845B-880661E69D09}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17.HelloWorld_Mobile", "17.HelloWorld_Mobile\17. HelloWorld for Windows Mobile on PC_vc11.vcxproj", "{2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "18.SplitScreen", "18.SplitScreen\SplitScreen_vc11.vcxproj", "{1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "19.MouseAndJoystick", "19.MouseAndJoystick\MouseAndJoystick_vc11.vcxproj", "{FE853A36-E0D1-4AC5-A792-B643E70D2953}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "20.ManagedLights", "20.ManagedLights\ManagedLights_vc11.vcxproj", "{16007FE2-142B-47F8-93E1-519BA3F39E71}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "21.Quake3Explorer", "21.Quake3Explorer\Quake3Explorer_vc11.vcxproj", "{CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "22.MaterialViewer", "22.MaterialViewer\MaterialViewer_vc11.vcxproj", "{4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "23.SMeshHandling", "23.SMeshHandling\SMeshHandling_vc11.vcxproj", "{6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "24.CursorControl", "24.CursorControl\CursorControl_vc11.vcxproj", "{02B67A37-50E1-49DB-BECF-905BC029C2FE}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo\Demo_vc11.vcxproj", "{6F076455-D955-45D4-9C68-4AD4E45F2D47}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GUIEditor", "..\tools\GUIEditor\GUI Editor_vc11.vcxproj", "{853A396E-C031-4C26-A716-5B4E176BE11D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FontTool", "..\tools\IrrFontTool\newFontTool\irrFontTool_vc11.vcxproj", "{4D53E40F-37E3-42B1-8848-F4C6F8313A17}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeshConverter", "..\tools\MeshConverter\MeshConverter_vc11.vcxproj", "{E72B637E-4AA6-46F3-885F-AC67B4B470ED}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "26.OcclusionQuery", "26.OcclusionQuery\OcclusionQuery_vc11.vcxproj", "{5CE0E2E7-879D-4152-B61D-24E7D0707B45}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "25.XmlHandling", "25.XmlHandling\XmlHandling_vc11.vcxproj", "{8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.ActiveCfg = Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.Build.0 = Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.Build.2 = Static lib - Release - Fast FPU|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.Build.4 = SDL-Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|x64.ActiveCfg = Release|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|x64.Build.0 = Release|x64 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|Win32.ActiveCfg = Debug|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|Win32.Build.0 = Debug|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|x64.ActiveCfg = Debug|x64 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|x64.Build.0 = Debug|x64 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|Win32.ActiveCfg = Release|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|Win32.Build.0 = Release|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|x64.ActiveCfg = Release|x64 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|x64.Build.0 = Release|x64 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|Win32.ActiveCfg = Debug|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|Win32.Build.0 = Debug|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|x64.ActiveCfg = Debug|x64 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|x64.Build.0 = Debug|x64 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|Win32.ActiveCfg = Release|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|Win32.Build.0 = Release|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|x64.ActiveCfg = Release|x64 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|x64.Build.0 = Release|x64 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|Win32.ActiveCfg = Debug|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|Win32.Build.0 = Debug|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|x64.ActiveCfg = Debug|x64 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|x64.Build.0 = Debug|x64 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|Win32.ActiveCfg = Release|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|Win32.Build.0 = Release|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|x64.ActiveCfg = Release|x64 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|x64.Build.0 = Release|x64 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|Win32.ActiveCfg = Debug|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|Win32.Build.0 = Debug|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|x64.ActiveCfg = Debug|x64 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|x64.Build.0 = Debug|x64 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|Win32.ActiveCfg = Release|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|Win32.Build.0 = Release|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|x64.ActiveCfg = Release|x64 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|x64.Build.0 = Release|x64 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|Win32.ActiveCfg = Debug|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|Win32.Build.0 = Debug|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|x64.ActiveCfg = Debug|x64 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|x64.Build.0 = Debug|x64 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|Win32.ActiveCfg = Release|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|Win32.Build.0 = Release|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|x64.ActiveCfg = Release|x64 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|x64.Build.0 = Release|x64 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|Win32.ActiveCfg = Debug|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|Win32.Build.0 = Debug|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|x64.ActiveCfg = Debug|x64 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|x64.Build.0 = Debug|x64 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|Win32.ActiveCfg = Release|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|Win32.Build.0 = Release|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|x64.ActiveCfg = Release|x64 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|x64.Build.0 = Release|x64 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|Win32.ActiveCfg = Debug|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|Win32.Build.0 = Debug|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|x64.ActiveCfg = Debug|x64 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|x64.Build.0 = Debug|x64 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|Win32.ActiveCfg = Release|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|Win32.Build.0 = Release|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|x64.ActiveCfg = Release|x64 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|x64.Build.0 = Release|x64 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|Win32.ActiveCfg = Debug|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|Win32.Build.0 = Debug|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|x64.ActiveCfg = Debug|x64 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|x64.Build.0 = Debug|x64 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|Win32.ActiveCfg = Release|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|Win32.Build.0 = Release|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|x64.ActiveCfg = Release|x64 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|x64.Build.0 = Release|x64 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|Win32.ActiveCfg = Debug|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|Win32.Build.0 = Debug|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|x64.ActiveCfg = Debug|x64 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|x64.Build.0 = Debug|x64 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|Win32.ActiveCfg = Release|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|Win32.Build.0 = Release|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|x64.ActiveCfg = Release|x64 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|x64.Build.0 = Release|x64 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|Win32.ActiveCfg = Debug|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|Win32.Build.0 = Debug|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|x64.ActiveCfg = Debug|x64 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|x64.Build.0 = Debug|x64 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|Win32.ActiveCfg = Release|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|Win32.Build.0 = Release|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|x64.ActiveCfg = Release|x64 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|x64.Build.0 = Release|x64 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|Win32.ActiveCfg = Debug|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|Win32.Build.0 = Debug|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|x64.ActiveCfg = Debug|x64 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|x64.Build.0 = Debug|x64 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|Win32.ActiveCfg = Release|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|Win32.Build.0 = Release|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|x64.ActiveCfg = Release|x64 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|x64.Build.0 = Release|x64 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|Win32.ActiveCfg = Debug|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|Win32.Build.0 = Debug|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|x64.ActiveCfg = Debug|x64 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|x64.Build.0 = Debug|x64 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|Win32.ActiveCfg = Release|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|Win32.Build.0 = Release|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|x64.ActiveCfg = Release|x64 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|x64.Build.0 = Release|x64 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|Win32.ActiveCfg = Debug|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|Win32.Build.0 = Debug|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|x64.ActiveCfg = Debug|x64 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|x64.Build.0 = Debug|x64 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|Win32.ActiveCfg = Release|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|Win32.Build.0 = Release|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|x64.ActiveCfg = Release|x64 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|x64.Build.0 = Release|x64 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|Win32.ActiveCfg = Debug|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|Win32.Build.0 = Debug|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|x64.ActiveCfg = Debug|x64 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|x64.Build.0 = Debug|x64 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|Win32.ActiveCfg = Release|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|Win32.Build.0 = Release|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|x64.ActiveCfg = Release|x64 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|x64.Build.0 = Release|x64 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|Win32.ActiveCfg = Debug|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|Win32.Build.0 = Debug|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|x64.ActiveCfg = Debug|x64 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|x64.Build.0 = Debug|x64 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|Win32.ActiveCfg = Release|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|Win32.Build.0 = Release|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|x64.ActiveCfg = Release|x64 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|x64.Build.0 = Release|x64 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|Win32.ActiveCfg = Debug|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|Win32.Build.0 = Debug|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|x64.ActiveCfg = Debug|x64 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|x64.Build.0 = Debug|x64 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|Win32.ActiveCfg = Release|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|Win32.Build.0 = Release|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|x64.ActiveCfg = Release|x64 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|x64.Build.0 = Release|x64 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.ActiveCfg = Debug|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.Build.0 = Debug|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|x64.ActiveCfg = Debug|x64 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|x64.Build.0 = Debug|x64 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.ActiveCfg = Release|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.Build.0 = Release|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|x64.ActiveCfg = Release|x64 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|x64.Build.0 = Release|x64 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|Win32.ActiveCfg = Debug|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|Win32.Build.0 = Debug|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|x64.ActiveCfg = Debug|x64 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|x64.Build.0 = Debug|x64 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|Win32.ActiveCfg = Release|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|Win32.Build.0 = Release|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|x64.ActiveCfg = Release|x64 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|x64.Build.0 = Release|x64 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|Win32.ActiveCfg = Debug|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|Win32.Build.0 = Debug|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|x64.ActiveCfg = Debug|x64 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|x64.Build.0 = Debug|x64 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|Win32.ActiveCfg = Release|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|Win32.Build.0 = Release|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|x64.ActiveCfg = Release|x64 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|x64.Build.0 = Release|x64 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|Win32.ActiveCfg = Debug|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|Win32.Build.0 = Debug|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|x64.ActiveCfg = Debug|x64 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|x64.Build.0 = Debug|x64 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|Win32.ActiveCfg = Release|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|Win32.Build.0 = Release|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|x64.ActiveCfg = Release|x64 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|x64.Build.0 = Release|x64 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.ActiveCfg = Debug|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.Build.0 = Debug|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|x64.ActiveCfg = Debug|x64 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|x64.Build.0 = Debug|x64 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.ActiveCfg = Release|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.Build.0 = Release|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|x64.ActiveCfg = Release|x64 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|x64.Build.0 = Release|x64 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|Win32.ActiveCfg = Debug|Win32 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|Win32.Build.0 = Debug|Win32 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|x64.ActiveCfg = Debug|x64 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|x64.Build.0 = Debug|x64 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|Win32.ActiveCfg = Release|Win32 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|Win32.Build.0 = Release|Win32 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|x64.ActiveCfg = Release|x64 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|x64.Build.0 = Release|x64 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|Win32.ActiveCfg = Debug|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|Win32.Build.0 = Debug|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|x64.ActiveCfg = Debug|x64 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|x64.Build.0 = Debug|x64 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|Win32.ActiveCfg = Release|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|Win32.Build.0 = Release|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|x64.ActiveCfg = Release|x64 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|x64.Build.0 = Release|x64 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|Win32.ActiveCfg = Debug|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|Win32.Build.0 = Debug|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|x64.ActiveCfg = Debug|x64 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|x64.Build.0 = Debug|x64 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|Win32.ActiveCfg = Release|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|Win32.Build.0 = Release|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|x64.ActiveCfg = Release|x64 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|x64.Build.0 = Release|x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.ActiveCfg = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.Build.0 = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|x64.ActiveCfg = Debug|x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|x64.Build.0 = Debug|x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|Win32.ActiveCfg = Release|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|Win32.Build.0 = Release|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|x64.ActiveCfg = Release|x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|x64.Build.0 = Release|x64 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.ActiveCfg = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.Build.0 = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|x64.ActiveCfg = Debug|x64 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|x64.Build.0 = Debug|x64 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.ActiveCfg = Release|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.Build.0 = Release|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|x64.ActiveCfg = Release|x64 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|x64.Build.0 = Release|x64 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.ActiveCfg = Debug|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.Build.0 = Debug|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|x64.ActiveCfg = Debug|x64 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|x64.Build.0 = Debug|x64 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.ActiveCfg = Release|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.Build.0 = Release|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|x64.ActiveCfg = Release|x64 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|x64.Build.0 = Release|x64 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|Win32.ActiveCfg = Debug|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|Win32.Build.0 = Debug|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|x64.ActiveCfg = Debug|x64 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|x64.Build.0 = Debug|x64 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|Win32.ActiveCfg = Release|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|Win32.Build.0 = Release|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|x64.ActiveCfg = Release|x64 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|x64.Build.0 = Release|x64 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Debug|Win32.ActiveCfg = Debug|Win32 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Debug|Win32.Build.0 = Debug|Win32 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Debug|x64.ActiveCfg = Debug|x64 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Debug|x64.Build.0 = Debug|x64 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Release|Win32.ActiveCfg = Release|Win32 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Release|Win32.Build.0 = Release|Win32 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Release|x64.ActiveCfg = Release|x64 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Release|x64.Build.0 = Release|x64 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|Win32.ActiveCfg = Debug|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|Win32.Build.0 = Debug|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|x64.ActiveCfg = Debug|x64 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|x64.Build.0 = Debug|x64 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|Win32.ActiveCfg = Release|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|Win32.Build.0 = Release|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|x64.ActiveCfg = Release|x64 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/examples/BuildAllExamples_vc10.sln0000644000000000000000000007105012574354552020434 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "..\source\Irrlicht\Irrlicht10.0.vcxproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "01.HelloWorld", "01.HelloWorld\HelloWorld_vc10.vcxproj", "{5AD4C95C-BA38-4692-BA4B-8C25A86208F9}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "02.Quake3Map", "02.Quake3Map\Quake3Map_vc10.vcxproj", "{D1A464A2-D479-458C-98A2-60965D823CD1}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "03.CustomSceneNode", "03.CustomSceneNode\CustomSceneNode_vc10.vcxproj", "{171CCDFA-C140-4956-8EB7-F0168F4521D3}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "04.Movement", "04.Movement\Movement_vc10.vcxproj", "{7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "05.UserInterface", "05.UserInterface\UserInterface_vc10.vcxproj", "{622C9DD7-0391-49FF-AF53-24F9D5A8EC53}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "06.2DGraphics", "06.2DGraphics\2DGraphics_vc10.vcxproj", "{E71B6F18-10DC-4101-A541-F6D33F71B2BD}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "07.Collision", "07.Collision\Collision_vc10.vcxproj", "{3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "08.SpecialFX", "08.SpecialFX\SpecialFX_vc10.vcxproj", "{C869BF55-B9D6-4980-BC92-60FA0CF8411A}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "09.Meshviewer", "09.Meshviewer\Meshviewer_vc10.vcxproj", "{2AE24484-22FC-481B-9A40-7CD0DA5C8E06}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "10.Shaders", "10.Shaders\Shaders_vc10.vcxproj", "{27158C82-CD15-4A9B-9848-35E7065B209F}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "11.PerPixelLighting", "11.PerPixelLighting\PerPixelLighting_vc10.vcxproj", "{C4B42409-542D-4EFC-9E6B-44713FD47A33}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "12.TerrainRendering", "12.TerrainRendering\TerrainRendering_vc10.vcxproj", "{3A5B74E5-6390-43B0-A459-2793B81FFD31}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "13.RenderToTexture", "13.RenderToTexture\RenderToTexture_vc10.vcxproj", "{0914E5C8-5352-467B-8421-C9EB35BD5596}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "14.Win32Window", "14.Win32Window\Win32Window_vc10.vcxproj", "{772FBE05-D05A-467B-9842-BEC409EEA8D0}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "15.LoadIrrFile", "15.LoadIrrFile\LoadIrrFile_vc10.vcxproj", "{78C9F424-523C-49AC-94B7-823AA4A26BF9}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16.Quake3MapShader", "16.Quake3MapShader\Quake3MapShader_vc10.vcxproj", "{EB3B38EA-5CE7-4983-845B-880661E69D09}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17.HelloWorld_Mobile", "17.HelloWorld_Mobile\17. HelloWorld for Windows Mobile on PC_vc10.vcxproj", "{2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "18.SplitScreen", "18.SplitScreen\SplitScreen_vc10.vcxproj", "{1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "19.MouseAndJoystick", "19.MouseAndJoystick\MouseAndJoystick_vc10.vcxproj", "{FE853A36-E0D1-4AC5-A792-B643E70D2953}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "20.ManagedLights", "20.ManagedLights\ManagedLights_vc10.vcxproj", "{16007FE2-142B-47F8-93E1-519BA3F39E71}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "21.Quake3Explorer", "21.Quake3Explorer\Quake3Explorer_vc10.vcxproj", "{CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "22.MaterialViewer", "22.MaterialViewer\MaterialViewer_vc10.vcxproj", "{4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "23.SMeshHandling", "23.SMeshHandling\SMeshHandling_vc10.vcxproj", "{6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "24.CursorControl", "24.CursorControl\CursorControl_vc10.vcxproj", "{02B67A37-50E1-49DB-BECF-905BC029C2FE}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo", "Demo\Demo_vc10.vcxproj", "{6F076455-D955-45D4-9C68-4AD4E45F2D47}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GUIEditor", "..\tools\GUIEditor\GUI Editor_vc10.vcxproj", "{853A396E-C031-4C26-A716-5B4E176BE11D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FontTool", "..\tools\IrrFontTool\newFontTool\irrFontTool_vc10.vcxproj", "{4D53E40F-37E3-42B1-8848-F4C6F8313A17}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeshConverter", "..\tools\MeshConverter\MeshConverter_vc10.vcxproj", "{E72B637E-4AA6-46F3-885F-AC67B4B470ED}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "26.OcclusionQuery", "26.OcclusionQuery\OcclusionQuery_vc10.vcxproj", "{5CE0E2E7-879D-4152-B61D-24E7D0707B45}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "25.XmlHandling", "25.XmlHandling\XmlHandling_vc10.vcxproj", "{8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.ActiveCfg = Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.Build.0 = Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.Build.2 = Static lib - Release - Fast FPU|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|x64.Build.4 = SDL-Debug|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|x64.ActiveCfg = Release|x64 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|x64.Build.0 = Release|x64 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|Win32.ActiveCfg = Debug|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|Win32.Build.0 = Debug|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|x64.ActiveCfg = Debug|x64 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|x64.Build.0 = Debug|x64 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|Win32.ActiveCfg = Release|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|Win32.Build.0 = Release|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|x64.ActiveCfg = Release|x64 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|x64.Build.0 = Release|x64 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|Win32.ActiveCfg = Debug|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|Win32.Build.0 = Debug|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|x64.ActiveCfg = Debug|x64 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|x64.Build.0 = Debug|x64 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|Win32.ActiveCfg = Release|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|Win32.Build.0 = Release|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|x64.ActiveCfg = Release|x64 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|x64.Build.0 = Release|x64 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|Win32.ActiveCfg = Debug|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|Win32.Build.0 = Debug|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|x64.ActiveCfg = Debug|x64 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|x64.Build.0 = Debug|x64 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|Win32.ActiveCfg = Release|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|Win32.Build.0 = Release|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|x64.ActiveCfg = Release|x64 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|x64.Build.0 = Release|x64 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|Win32.ActiveCfg = Debug|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|Win32.Build.0 = Debug|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|x64.ActiveCfg = Debug|x64 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|x64.Build.0 = Debug|x64 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|Win32.ActiveCfg = Release|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|Win32.Build.0 = Release|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|x64.ActiveCfg = Release|x64 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|x64.Build.0 = Release|x64 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|Win32.ActiveCfg = Debug|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|Win32.Build.0 = Debug|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|x64.ActiveCfg = Debug|x64 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|x64.Build.0 = Debug|x64 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|Win32.ActiveCfg = Release|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|Win32.Build.0 = Release|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|x64.ActiveCfg = Release|x64 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|x64.Build.0 = Release|x64 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|Win32.ActiveCfg = Debug|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|Win32.Build.0 = Debug|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|x64.ActiveCfg = Debug|x64 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|x64.Build.0 = Debug|x64 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|Win32.ActiveCfg = Release|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|Win32.Build.0 = Release|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|x64.ActiveCfg = Release|x64 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|x64.Build.0 = Release|x64 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|Win32.ActiveCfg = Debug|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|Win32.Build.0 = Debug|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|x64.ActiveCfg = Debug|x64 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|x64.Build.0 = Debug|x64 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|Win32.ActiveCfg = Release|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|Win32.Build.0 = Release|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|x64.ActiveCfg = Release|x64 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|x64.Build.0 = Release|x64 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|Win32.ActiveCfg = Debug|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|Win32.Build.0 = Debug|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|x64.ActiveCfg = Debug|x64 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|x64.Build.0 = Debug|x64 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|Win32.ActiveCfg = Release|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|Win32.Build.0 = Release|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|x64.ActiveCfg = Release|x64 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|x64.Build.0 = Release|x64 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|Win32.ActiveCfg = Debug|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|Win32.Build.0 = Debug|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|x64.ActiveCfg = Debug|x64 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|x64.Build.0 = Debug|x64 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|Win32.ActiveCfg = Release|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|Win32.Build.0 = Release|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|x64.ActiveCfg = Release|x64 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|x64.Build.0 = Release|x64 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|Win32.ActiveCfg = Debug|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|Win32.Build.0 = Debug|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|x64.ActiveCfg = Debug|x64 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|x64.Build.0 = Debug|x64 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|Win32.ActiveCfg = Release|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|Win32.Build.0 = Release|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|x64.ActiveCfg = Release|x64 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|x64.Build.0 = Release|x64 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|Win32.ActiveCfg = Debug|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|Win32.Build.0 = Debug|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|x64.ActiveCfg = Debug|x64 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|x64.Build.0 = Debug|x64 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|Win32.ActiveCfg = Release|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|Win32.Build.0 = Release|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|x64.ActiveCfg = Release|x64 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|x64.Build.0 = Release|x64 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|Win32.ActiveCfg = Debug|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|Win32.Build.0 = Debug|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|x64.ActiveCfg = Debug|x64 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|x64.Build.0 = Debug|x64 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|Win32.ActiveCfg = Release|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|Win32.Build.0 = Release|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|x64.ActiveCfg = Release|x64 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|x64.Build.0 = Release|x64 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|Win32.ActiveCfg = Debug|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|Win32.Build.0 = Debug|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|x64.ActiveCfg = Debug|x64 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|x64.Build.0 = Debug|x64 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|Win32.ActiveCfg = Release|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|Win32.Build.0 = Release|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|x64.ActiveCfg = Release|x64 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|x64.Build.0 = Release|x64 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|Win32.ActiveCfg = Debug|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|Win32.Build.0 = Debug|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|x64.ActiveCfg = Debug|x64 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|x64.Build.0 = Debug|x64 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|Win32.ActiveCfg = Release|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|Win32.Build.0 = Release|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|x64.ActiveCfg = Release|x64 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|x64.Build.0 = Release|x64 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|Win32.ActiveCfg = Debug|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|Win32.Build.0 = Debug|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|x64.ActiveCfg = Debug|x64 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|x64.Build.0 = Debug|x64 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|Win32.ActiveCfg = Release|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|Win32.Build.0 = Release|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|x64.ActiveCfg = Release|x64 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|x64.Build.0 = Release|x64 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|Win32.ActiveCfg = Debug|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|Win32.Build.0 = Debug|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|x64.ActiveCfg = Debug|x64 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|x64.Build.0 = Debug|x64 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|Win32.ActiveCfg = Release|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|Win32.Build.0 = Release|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|x64.ActiveCfg = Release|x64 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|x64.Build.0 = Release|x64 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.ActiveCfg = Debug|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.Build.0 = Debug|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|x64.ActiveCfg = Debug|x64 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|x64.Build.0 = Debug|x64 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.ActiveCfg = Release|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.Build.0 = Release|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|x64.ActiveCfg = Release|x64 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|x64.Build.0 = Release|x64 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|Win32.ActiveCfg = Debug|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|Win32.Build.0 = Debug|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|x64.ActiveCfg = Debug|x64 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|x64.Build.0 = Debug|x64 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|Win32.ActiveCfg = Release|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|Win32.Build.0 = Release|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|x64.ActiveCfg = Release|x64 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|x64.Build.0 = Release|x64 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|Win32.ActiveCfg = Debug|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|Win32.Build.0 = Debug|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|x64.ActiveCfg = Debug|x64 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|x64.Build.0 = Debug|x64 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|Win32.ActiveCfg = Release|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|Win32.Build.0 = Release|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|x64.ActiveCfg = Release|x64 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|x64.Build.0 = Release|x64 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|Win32.ActiveCfg = Debug|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|Win32.Build.0 = Debug|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|x64.ActiveCfg = Debug|x64 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|x64.Build.0 = Debug|x64 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|Win32.ActiveCfg = Release|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|Win32.Build.0 = Release|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|x64.ActiveCfg = Release|x64 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|x64.Build.0 = Release|x64 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.ActiveCfg = Debug|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.Build.0 = Debug|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|x64.ActiveCfg = Debug|x64 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|x64.Build.0 = Debug|x64 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.ActiveCfg = Release|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.Build.0 = Release|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|x64.ActiveCfg = Release|x64 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|x64.Build.0 = Release|x64 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|Win32.ActiveCfg = Debug|Win32 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|Win32.Build.0 = Debug|Win32 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|x64.ActiveCfg = Debug|x64 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|x64.Build.0 = Debug|x64 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|Win32.ActiveCfg = Release|Win32 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|Win32.Build.0 = Release|Win32 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|x64.ActiveCfg = Release|x64 {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|x64.Build.0 = Release|x64 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|Win32.ActiveCfg = Debug|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|Win32.Build.0 = Debug|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|x64.ActiveCfg = Debug|x64 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|x64.Build.0 = Debug|x64 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|Win32.ActiveCfg = Release|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|Win32.Build.0 = Release|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|x64.ActiveCfg = Release|x64 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|x64.Build.0 = Release|x64 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|Win32.ActiveCfg = Debug|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|Win32.Build.0 = Debug|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|x64.ActiveCfg = Debug|x64 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|x64.Build.0 = Debug|x64 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|Win32.ActiveCfg = Release|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|Win32.Build.0 = Release|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|x64.ActiveCfg = Release|x64 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|x64.Build.0 = Release|x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.ActiveCfg = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.Build.0 = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|x64.ActiveCfg = Debug|x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|x64.Build.0 = Debug|x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|Win32.ActiveCfg = Release|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|Win32.Build.0 = Release|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|x64.ActiveCfg = Release|x64 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|x64.Build.0 = Release|x64 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.ActiveCfg = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.Build.0 = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|x64.ActiveCfg = Debug|x64 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|x64.Build.0 = Debug|x64 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.ActiveCfg = Release|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.Build.0 = Release|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|x64.ActiveCfg = Release|x64 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|x64.Build.0 = Release|x64 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.ActiveCfg = Debug|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.Build.0 = Debug|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|x64.ActiveCfg = Debug|x64 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|x64.Build.0 = Debug|x64 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.ActiveCfg = Release|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.Build.0 = Release|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|x64.ActiveCfg = Release|x64 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|x64.Build.0 = Release|x64 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|Win32.ActiveCfg = Debug|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|Win32.Build.0 = Debug|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|x64.ActiveCfg = Debug|x64 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|x64.Build.0 = Debug|x64 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|Win32.ActiveCfg = Release|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|Win32.Build.0 = Release|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|x64.ActiveCfg = Release|x64 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|x64.Build.0 = Release|x64 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Debug|Win32.ActiveCfg = Debug|Win32 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Debug|Win32.Build.0 = Debug|Win32 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Debug|x64.ActiveCfg = Debug|x64 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Debug|x64.Build.0 = Debug|x64 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Release|Win32.ActiveCfg = Release|Win32 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Release|Win32.Build.0 = Release|Win32 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Release|x64.ActiveCfg = Release|x64 {5CE0E2E7-879D-4152-B61D-24E7D0707B45}.Release|x64.Build.0 = Release|x64 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|Win32.ActiveCfg = Debug|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|Win32.Build.0 = Debug|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|x64.ActiveCfg = Debug|x64 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|x64.Build.0 = Debug|x64 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|Win32.ActiveCfg = Release|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|Win32.Build.0 = Release|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|x64.ActiveCfg = Release|x64 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/examples/BuildAllExamples_v9.sln0000644000000000000000000004667712574354552020242 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 10.00 # Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "01.HelloWorld_vc9", "01.HelloWorld\HelloWorld_vc9.vcproj", "{5AD4C95C-BA38-4692-BA4B-8C25A86208F9}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "02.Quake3Map_vc9", "02.Quake3Map\Quake3Map_vc9.vcproj", "{D1A464A2-D479-458C-98A2-60965D823CD1}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "03.CustomSceneNode_vc9", "03.CustomSceneNode\CustomSceneNode_vc9.vcproj", "{171CCDFA-C140-4956-8EB7-F0168F4521D3}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "04.Movement_vc9", "04.Movement\Movement_vc9.vcproj", "{7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "05.UserInterface_vc8", "05.UserInterface\UserInterface_vc9.vcproj", "{622C9DD7-0391-49FF-AF53-24F9D5A8EC53}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "06.2DGraphics_vc9", "06.2DGraphics\2DGraphics_vc9.vcproj", "{E71B6F18-10DC-4101-A541-F6D33F71B2BD}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "07.Collision_vc9", "07.Collision\Collision_vc9.vcproj", "{3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "08.SpecialFX_vc9", "08.SpecialFX\SpecialFX_vc9.vcproj", "{C869BF55-B9D6-4980-BC92-60FA0CF8411A}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "09.Meshviewer_vc9", "09.Meshviewer\Meshviewer_vc9.vcproj", "{2AE24484-22FC-481B-9A40-7CD0DA5C8E06}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "10.Shaders_vc9", "10.Shaders\Shaders_vc9.vcproj", "{27158C82-CD15-4A9B-9848-35E7065B209F}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "11.PerPixelLighting_vc9", "11.PerPixelLighting\PerPixelLighting_vc9.vcproj", "{C4B42409-542D-4EFC-9E6B-44713FD47A33}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "12.TerrainRendering_vc9", "12.TerrainRendering\TerrainRendering_vc9.vcproj", "{3A5B74E5-6390-43B0-A459-2793B81FFD31}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "13.RenderToTexture_vc9", "13.RenderToTexture\RenderToTexture_vc9.vcproj", "{0914E5C8-5352-467B-8421-C9EB35BD5596}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "14.Win32Window_vc9", "14.Win32Window\Win32Window_vc9.vcproj", "{772FBE05-D05A-467B-9842-BEC409EEA8D0}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "15.LoadIrrFile_vc9", "15.LoadIrrFile\LoadIrrFile_vc9.vcproj", "{78C9F424-523C-49AC-94B7-823AA4A26BF9}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "..\source\Irrlicht\Irrlicht9.0.vcproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo_vc9", "Demo\Demo_vc9.vcproj", "{6F076455-D955-45D4-9C68-4AD4E45F2D47}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16.Quake3MapShader_vc9", "16.Quake3MapShader\Quake3MapShader_vc9.vcproj", "{EB3B38EA-5CE7-4983-845B-880661E69D09}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17.HelloWorld_Mobile_v9", "17.HelloWorld_Mobile\17. HelloWorld for Windows Mobile on PC_v9.vcproj", "{2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "18.SplitScreen_vc9", "18.SplitScreen\SplitScreen_vc9.vcproj", "{1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "19.MouseAndJoystick_vc9", "19.MouseAndJoystick\MouseAndJoystick_vc9.vcproj", "{FE853A36-E0D1-4AC5-A792-B643E70D2953}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "20.ManagedLights_vc9", "20.ManagedLights\ManagedLights_vc9.vcproj", "{16007FE2-142B-47F8-93E1-519BA3F39E71}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "21.Quake3Explorer_vc9", "21.Quake3Explorer\Quake3Explorer_vc9.vcproj", "{CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "22.MaterialViewer_vc9", "22.MaterialViewer\MaterialViewer_vc9.vcproj", "{F4C8112D-57A8-4D01-BB62-BAC6A09A6902}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "23.SMeshHandling_vc9", "23.SMeshHandling\SMeshHandling_vc9.vcproj", "{6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "24.CursorControl_vc9", "24.CursorControl\CursorControl_vc9.vcproj", "{02B67A37-50E1-49DB-BECF-905BC029C2FE}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GUI Editor_v9", "..\tools\GUIEditor\GUI Editor_v9.vcproj", "{853A396E-C031-4C26-A716-5B4E176BE11D}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Font Tool", "..\tools\IrrFontTool\newFontTool\irrFontTool_v9.vcproj", "{4D53E40F-37E3-42B1-8848-F4C6F8313A17}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mesh Converter", "..\tools\MeshConverter\MeshConverter_v9.vcproj", "{E72B637E-4AA6-46F3-885F-AC67B4B470ED}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "25.XmlHandling_vc9", "25.XmlHandling\XmlHandling_vc9.vcproj", "{8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "26.OcclusionQuery_vc9", "26.OcclusionQuery\OcclusionQuery_vc9.vcproj", "{9A859369-0A56-4DAB-9E0C-9F93C91CF0F2}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|Win32.ActiveCfg = Debug|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|Win32.Build.0 = Debug|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|Win32.ActiveCfg = Release|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|Win32.Build.0 = Release|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|Win32.ActiveCfg = Debug|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|Win32.Build.0 = Debug|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|Win32.ActiveCfg = Release|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|Win32.Build.0 = Release|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|Win32.ActiveCfg = Debug|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|Win32.Build.0 = Debug|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|Win32.ActiveCfg = Release|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|Win32.Build.0 = Release|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|Win32.ActiveCfg = Debug|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|Win32.Build.0 = Debug|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|Win32.ActiveCfg = Release|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|Win32.Build.0 = Release|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|Win32.ActiveCfg = Debug|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|Win32.Build.0 = Debug|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|Win32.ActiveCfg = Release|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|Win32.Build.0 = Release|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|Win32.ActiveCfg = Debug|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|Win32.Build.0 = Debug|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|Win32.ActiveCfg = Release|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|Win32.Build.0 = Release|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|Win32.ActiveCfg = Debug|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|Win32.Build.0 = Debug|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|Win32.ActiveCfg = Release|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|Win32.Build.0 = Release|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|Win32.ActiveCfg = Debug|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|Win32.Build.0 = Debug|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|Win32.ActiveCfg = Release|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|Win32.Build.0 = Release|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|Win32.ActiveCfg = Debug|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|Win32.Build.0 = Debug|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|Win32.ActiveCfg = Release|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|Win32.Build.0 = Release|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|Win32.ActiveCfg = Debug|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|Win32.Build.0 = Debug|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|Win32.ActiveCfg = Release|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|Win32.Build.0 = Release|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|Win32.ActiveCfg = Debug|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|Win32.Build.0 = Debug|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|Win32.ActiveCfg = Release|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|Win32.Build.0 = Release|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|Win32.ActiveCfg = Debug|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|Win32.Build.0 = Debug|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|Win32.ActiveCfg = Release|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|Win32.Build.0 = Release|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|Win32.ActiveCfg = Debug|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|Win32.Build.0 = Debug|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|Win32.ActiveCfg = Release|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|Win32.Build.0 = Release|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|Win32.ActiveCfg = Debug|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|Win32.Build.0 = Debug|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|Win32.ActiveCfg = Release|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|Win32.Build.0 = Release|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|Win32.ActiveCfg = Debug|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|Win32.Build.0 = Debug|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|Win32.ActiveCfg = Release|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|Win32.Build.0 = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.ActiveCfg = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.Build.0 = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|Win32.ActiveCfg = Release|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|Win32.Build.0 = Release|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|Win32.ActiveCfg = Debug|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|Win32.Build.0 = Debug|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|Win32.ActiveCfg = Release|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|Win32.Build.0 = Release|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.ActiveCfg = Debug|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.Build.0 = Debug|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.ActiveCfg = Release|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.Build.0 = Release|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|Win32.ActiveCfg = Debug|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug|Win32.Build.0 = Debug|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|Win32.ActiveCfg = Release|Win32 {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release|Win32.Build.0 = Release|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|Win32.ActiveCfg = Debug|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|Win32.Build.0 = Debug|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|Win32.ActiveCfg = Release|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|Win32.Build.0 = Release|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|Win32.ActiveCfg = Debug|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|Win32.Build.0 = Debug|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|Win32.ActiveCfg = Release|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|Win32.Build.0 = Release|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.ActiveCfg = Debug|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.Build.0 = Debug|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.ActiveCfg = Release|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.Build.0 = Release|Win32 {F4C8112D-57A8-4D01-BB62-BAC6A09A6902}.Debug|Win32.ActiveCfg = Debug|Win32 {F4C8112D-57A8-4D01-BB62-BAC6A09A6902}.Debug|Win32.Build.0 = Debug|Win32 {F4C8112D-57A8-4D01-BB62-BAC6A09A6902}.Release|Win32.ActiveCfg = Release|Win32 {F4C8112D-57A8-4D01-BB62-BAC6A09A6902}.Release|Win32.Build.0 = Release|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|Win32.ActiveCfg = Debug|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|Win32.Build.0 = Debug|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|Win32.ActiveCfg = Release|Win32 {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|Win32.Build.0 = Release|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|Win32.ActiveCfg = Debug|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|Win32.Build.0 = Debug|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|Win32.ActiveCfg = Release|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|Win32.Build.0 = Release|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.ActiveCfg = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.Build.0 = Debug|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.ActiveCfg = Release|Win32 {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.Build.0 = Release|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.ActiveCfg = Debug|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.Build.0 = Debug|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.ActiveCfg = Release|Win32 {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.Build.0 = Release|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|Win32.ActiveCfg = Debug|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|Win32.Build.0 = Debug|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|Win32.ActiveCfg = Release|Win32 {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|Win32.Build.0 = Release|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|Win32.ActiveCfg = Debug|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Debug|Win32.Build.0 = Debug|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|Win32.ActiveCfg = Release|Win32 {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E}.Release|Win32.Build.0 = Release|Win32 {9A859369-0A56-4DAB-9E0C-9F93C91CF0F2}.Debug|Win32.ActiveCfg = Debug|Win32 {9A859369-0A56-4DAB-9E0C-9F93C91CF0F2}.Debug|Win32.Build.0 = Debug|Win32 {9A859369-0A56-4DAB-9E0C-9F93C91CF0F2}.Release|Win32.ActiveCfg = Release|Win32 {9A859369-0A56-4DAB-9E0C-9F93C91CF0F2}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/examples/BuildAllExamples_v8.sln0000644000000000000000000003775312574354552020234 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "..\source\Irrlicht\Irrlicht8.0.vcproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "01.HelloWorld_vc8", "01.HelloWorld\HelloWorld_vc8.vcproj", "{5AD4C95C-BA38-4692-BA4B-8C25A86208F9}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "02.Quake3Map_vc8", "02.Quake3Map\Quake3Map_vc8.vcproj", "{D1A464A2-D479-458C-98A2-60965D823CD1}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "03.CustomSceneNode_vc8", "03.CustomSceneNode\CustomSceneNode_vc8.vcproj", "{171CCDFA-C140-4956-8EB7-F0168F4521D3}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "04.Movement_vc8", "04.Movement\Movement_vc8.vcproj", "{7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "05.UserInterface_vc8", "05.UserInterface\UserInterface_vc8.vcproj", "{622C9DD7-0391-49FF-AF53-24F9D5A8EC53}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "06.2DGraphics_vc8", "06.2DGraphics\2DGraphics_vc8.vcproj", "{E71B6F18-10DC-4101-A541-F6D33F71B2BD}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "07.Collision_vc8", "07.Collision\Collision_vc8.vcproj", "{3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "08.SpecialFX_vc8", "08.SpecialFX\SpecialFX_vc8.vcproj", "{C869BF55-B9D6-4980-BC92-60FA0CF8411A}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "09.Meshviewer_vc8", "09.Meshviewer\Meshviewer_vc8.vcproj", "{2AE24484-22FC-481B-9A40-7CD0DA5C8E06}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "10.Shaders_vc8", "10.Shaders\Shaders_vc8.vcproj", "{27158C82-CD15-4A9B-9848-35E7065B209F}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "11.PerPixelLighting_vc8", "11.PerPixelLighting\PerPixelLighting_vc8.vcproj", "{C4B42409-542D-4EFC-9E6B-44713FD47A33}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "12.TerrainRendering_vc8", "12.TerrainRendering\TerrainRendering_vc8.vcproj", "{3A5B74E5-6390-43B0-A459-2793B81FFD31}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "13.RenderToTexture_vc8", "13.RenderToTexture\RenderToTexture_vc8.vcproj", "{0914E5C8-5352-467B-8421-C9EB35BD5596}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "14.Win32Window_vc8", "14.Win32Window\Win32Window_vc8.vcproj", "{772FBE05-D05A-467B-9842-BEC409EEA8D0}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "15.LoadIrrFile_vc8", "15.LoadIrrFile\LoadIrrFile_vc8.vcproj", "{78C9F424-523C-49AC-94B7-823AA4A26BF9}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16.Quake3MapShader_vc8", "16.Quake3MapShader\Quake3MapShader_vc8.vcproj", "{EB3B38EA-5CE7-4983-845B-880661E69D09}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17.HelloWorld for Windows Mobile on PC", "17.HelloWorld_Mobile\17. HelloWorld for Windows Mobile on PC_v8.vcproj", "{2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "19.MouseAndJoystick_vc8", "19.MouseAndJoystick\MouseAndJoystick_vc8.vcproj", "{FE853A36-E0D1-4AC5-A792-B643E70D2953}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "20.ManagedLights_vc8", "20.ManagedLights\ManagedLights_vc8.vcproj", "{16007FE2-142B-47F8-93E1-519BA3F39E71}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "21.Quake3Explorer_vc8", "21.Quake3Explorer\Quake3Explorer_vc8.vcproj", "{CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "22.MaterialViewer_vc8", "22.MaterialViewer\MaterialViewer_vc8.vcproj", "{2856AB41-9BC5-4716-9B35-762A65F6F5D1}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "23.SMeshHandling_vc8", "23.SMeshHandling\SMeshHandling_vc8.vcproj", "{08D2F676-9DEB-4443-AEF7-52CC6F7D5F7C}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "24.CursorControl_vc8", "24.CursorControl\CursorControl_vc8.vcproj", "{02B67A37-50E1-49DB-BECF-905BC029C2FE}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo_vc8", "Demo\Demo_vc8.vcproj", "{6F076455-D955-45D4-9C68-4AD4E45F2D47}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|Win32.ActiveCfg = Debug|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Debug|Win32.Build.0 = Debug|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|Win32.ActiveCfg = Release|Win32 {5AD4C95C-BA38-4692-BA4B-8C25A86208F9}.Release|Win32.Build.0 = Release|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|Win32.ActiveCfg = Debug|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Debug|Win32.Build.0 = Debug|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|Win32.ActiveCfg = Release|Win32 {D1A464A2-D479-458C-98A2-60965D823CD1}.Release|Win32.Build.0 = Release|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|Win32.ActiveCfg = Debug|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Debug|Win32.Build.0 = Debug|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|Win32.ActiveCfg = Release|Win32 {171CCDFA-C140-4956-8EB7-F0168F4521D3}.Release|Win32.Build.0 = Release|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|Win32.ActiveCfg = Debug|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Debug|Win32.Build.0 = Debug|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|Win32.ActiveCfg = Release|Win32 {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}.Release|Win32.Build.0 = Release|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|Win32.ActiveCfg = Debug|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Debug|Win32.Build.0 = Debug|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|Win32.ActiveCfg = Release|Win32 {622C9DD7-0391-49FF-AF53-24F9D5A8EC53}.Release|Win32.Build.0 = Release|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|Win32.ActiveCfg = Debug|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Debug|Win32.Build.0 = Debug|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|Win32.ActiveCfg = Release|Win32 {E71B6F18-10DC-4101-A541-F6D33F71B2BD}.Release|Win32.Build.0 = Release|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|Win32.ActiveCfg = Debug|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Debug|Win32.Build.0 = Debug|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|Win32.ActiveCfg = Release|Win32 {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E}.Release|Win32.Build.0 = Release|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|Win32.ActiveCfg = Debug|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Debug|Win32.Build.0 = Debug|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|Win32.ActiveCfg = Release|Win32 {C869BF55-B9D6-4980-BC92-60FA0CF8411A}.Release|Win32.Build.0 = Release|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|Win32.ActiveCfg = Debug|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Debug|Win32.Build.0 = Debug|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|Win32.ActiveCfg = Release|Win32 {2AE24484-22FC-481B-9A40-7CD0DA5C8E06}.Release|Win32.Build.0 = Release|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|Win32.ActiveCfg = Debug|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Debug|Win32.Build.0 = Debug|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|Win32.ActiveCfg = Release|Win32 {27158C82-CD15-4A9B-9848-35E7065B209F}.Release|Win32.Build.0 = Release|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|Win32.ActiveCfg = Debug|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Debug|Win32.Build.0 = Debug|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|Win32.ActiveCfg = Release|Win32 {C4B42409-542D-4EFC-9E6B-44713FD47A33}.Release|Win32.Build.0 = Release|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|Win32.ActiveCfg = Debug|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Debug|Win32.Build.0 = Debug|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|Win32.ActiveCfg = Release|Win32 {3A5B74E5-6390-43B0-A459-2793B81FFD31}.Release|Win32.Build.0 = Release|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|Win32.ActiveCfg = Debug|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Debug|Win32.Build.0 = Debug|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|Win32.ActiveCfg = Release|Win32 {0914E5C8-5352-467B-8421-C9EB35BD5596}.Release|Win32.Build.0 = Release|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|Win32.ActiveCfg = Debug|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Debug|Win32.Build.0 = Debug|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|Win32.ActiveCfg = Release|Win32 {772FBE05-D05A-467B-9842-BEC409EEA8D0}.Release|Win32.Build.0 = Release|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|Win32.ActiveCfg = Debug|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Debug|Win32.Build.0 = Debug|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|Win32.ActiveCfg = Release|Win32 {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|Win32.Build.0 = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.ActiveCfg = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.Build.0 = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|Win32.ActiveCfg = Release|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|Win32.Build.0 = Release|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|Win32.ActiveCfg = Debug|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug|Win32.Build.0 = Debug|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|Win32.ActiveCfg = Release|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release|Win32.Build.0 = Release|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|Win32.ActiveCfg = Debug|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Debug|Win32.Build.0 = Debug|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|Win32.ActiveCfg = Release|Win32 {FE853A36-E0D1-4AC5-A792-B643E70D2953}.Release|Win32.Build.0 = Release|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|Win32.ActiveCfg = Debug|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|Win32.Build.0 = Debug|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|Win32.ActiveCfg = Release|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|Win32.Build.0 = Release|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.ActiveCfg = Debug|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.Build.0 = Debug|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.ActiveCfg = Release|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.Build.0 = Release|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.ActiveCfg = Debug|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.Build.0 = Debug|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.ActiveCfg = Release|Win32 {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.Build.0 = Release|Win32 {2856AB41-9BC5-4716-9B35-762A65F6F5D1}.Debug|Win32.ActiveCfg = Debug|Win32 {2856AB41-9BC5-4716-9B35-762A65F6F5D1}.Debug|Win32.Build.0 = Debug|Win32 {2856AB41-9BC5-4716-9B35-762A65F6F5D1}.Release|Win32.ActiveCfg = Release|Win32 {2856AB41-9BC5-4716-9B35-762A65F6F5D1}.Release|Win32.Build.0 = Release|Win32 {08D2F676-9DEB-4443-AEF7-52CC6F7D5F7C}.Debug|Win32.ActiveCfg = Debug|Win32 {08D2F676-9DEB-4443-AEF7-52CC6F7D5F7C}.Debug|Win32.Build.0 = Debug|Win32 {08D2F676-9DEB-4443-AEF7-52CC6F7D5F7C}.Release|Win32.ActiveCfg = Release|Win32 {08D2F676-9DEB-4443-AEF7-52CC6F7D5F7C}.Release|Win32.Build.0 = Release|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|Win32.ActiveCfg = Debug|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Debug|Win32.Build.0 = Debug|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|Win32.ActiveCfg = Release|Win32 {02B67A37-50E1-49DB-BECF-905BC029C2FE}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/examples/BuildAllExamples.workspace0000644000000000000000000000360712574354552021010 0ustar rootroot irrlicht-1.8.3/examples/buildAllExamples.sh0000755000000000000000000000023712574354552017463 0ustar rootroot#! /bin/bash [ -z $1 ] || TARGET=$1 [ -z $TARGET ] && TARGET=all for i in [012]* Demo; do echo "Building $i"; pushd $i && make clean $TARGET; popd; done irrlicht-1.8.3/examples/BuildAllExamples.MacOSX/0000755000000000000000000000000012574354552020153 5ustar rootrootirrlicht-1.8.3/examples/BuildAllExamples.MacOSX/DemoApp-Info.plist0000644000000000000000000000135212574354552023447 0ustar rootroot CFBundleDevelopmentRegion English CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier com.irrlicht.${EXECUTABLE_NAME} CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature IRRL CFBundleVersion 1.0 NSMainNibFile MainMenu NSPrincipalClass NSApplication irrlicht-1.8.3/examples/26.OcclusionQuery/0000755000000000000000000000000012574354552017105 5ustar rootrootirrlicht-1.8.3/examples/26.OcclusionQuery/OcclusionQuery_vc9.vcproj0000644000000000000000000001231012574354552024074 0ustar rootroot irrlicht-1.8.3/examples/26.OcclusionQuery/OcclusionQuery_vc8.vcproj0000644000000000000000000001221012574354552024072 0ustar rootroot irrlicht-1.8.3/examples/26.OcclusionQuery/OcclusionQuery_vc12.vcxproj0000644000000000000000000003302212574354552024341 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 26.OcclusionQuery {5CE0E2E7-879D-4152-B61D-24E7D0707B45} OcclusionQuery Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug\OcclusionQuery.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\26.OcclusionQuery.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug\OcclusionQuery.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\26.OcclusionQuery.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release\OcclusionQuery.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\26.OcclusionQuery.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release\OcclusionQuery.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\26.OcclusionQuery.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/26.OcclusionQuery/OcclusionQuery_vc11.vcxproj0000644000000000000000000003302112574354552024337 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 26.OcclusionQuery {5CE0E2E7-879D-4152-B61D-24E7D0707B45} OcclusionQuery Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug\OcclusionQuery.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\26.OcclusionQuery.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug\OcclusionQuery.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\26.OcclusionQuery.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release\OcclusionQuery.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\26.OcclusionQuery.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release\OcclusionQuery.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\26.OcclusionQuery.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/26.OcclusionQuery/OcclusionQuery_vc10.vcxproj0000644000000000000000000003302112574354552024336 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 26.OcclusionQuery {5CE0E2E7-879D-4152-B61D-24E7D0707B45} OcclusionQuery Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug\OcclusionQuery.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\26.OcclusionQuery.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug\OcclusionQuery.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\26.OcclusionQuery.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release\OcclusionQuery.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\26.OcclusionQuery.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release\OcclusionQuery.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\26.OcclusionQuery.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/26.OcclusionQuery/OcclusionQuery.vcproj0000644000000000000000000001061412574354552023320 0ustar rootroot irrlicht-1.8.3/examples/26.OcclusionQuery/OcclusionQuery.dev0000644000000000000000000000175212574354552022576 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 26 OcclusionQuery UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=26.OcclusionQuery.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/26.OcclusionQuery/OcclusionQuery.cbp0000644000000000000000000000271012574354552022557 0ustar rootroot irrlicht-1.8.3/examples/26.OcclusionQuery/Makefile0000644000000000000000000000233512574354552020550 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 26.OcclusionQuery Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32: CPPFLAGS += -D__GNUWIN32__ -D_WIN32 -DWIN32 -D_WINDOWS -D_MBCS -D_USRDLL all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/26.OcclusionQuery/main.cpp0000644000000000000000000001714412574354552020544 0ustar rootroot/** Example 026 OcclusionQuery This Tutorial shows how to speed up rendering by use of the OcclusionQuery feature. The usual rendering tries to avoid rendering of scene nodes by culling those nodes which are outside the visible area, the view frustum. However, this technique does not cope with occluded objects which are still in the line of sight, but occluded by some larger object between the object and the eye (camera). Occlusion queries check exactly that. The queries basically measure the number of pixels that a previous render left on the screen. Since those pixels cannot be recognized at the end of a rendering anymore, the pixel count is measured directly when rendering. Thus, one needs to render the occluder (the object in front) first. This object needs to write to the z-buffer in order to become a real occluder. Then the node is rendered and in case a z-pass happens, i.e. the pixel is written to the framebuffer, the pixel is counted in the query. The result of a query is the number of pixels which got through. One can, based on this number, judge if the scene node is visible enough to be rendered, or if the node should be removed in the next round. Also note that the number of pixels is a safe over approximation in general. The pixels might be overdrawn later on, and the GPU tries to avoid inaccuracies which could lead to false negatives in the queries. As you might have recognized already, we had to render the node to get the numbers. So where's the benefit, you might say. There are several ways where occlusion queries can help. It is often a good idea to just render the bbox of the node instead of the actual mesh. This is really fast and is a safe over approximation. If you need a more exact render with the actual geometry, it's a good idea to render with just basic solid material. Avoid complex shaders and state changes through textures. There's no need while just doing the occlusion query. At least if the render is not used for the actual scene. This is the third way to optimize occlusion queries. Just check the queries every 5th or 10th frame, or even less frequent. This depends on the movement speed of the objects and camera. */ #ifdef _MSC_VER // We'll also define this to stop MSVC complaining about sprintf(). #define _CRT_SECURE_NO_WARNINGS #pragma comment(lib, "Irrlicht.lib") #endif #include #include "driverChoice.h" using namespace irr; /* We need keyboard input events to switch some parameters */ class MyEventReceiver : public IEventReceiver { public: // This is the one method that we have to implement virtual bool OnEvent(const SEvent& event) { // Remember whether each key is down or up if (event.EventType == irr::EET_KEY_INPUT_EVENT) KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; return false; } // This is used to check whether a key is being held down virtual bool IsKeyDown(EKEY_CODE keyCode) const { return KeyIsDown[keyCode]; } MyEventReceiver() { for (u32 i=0; i(640, 480), 16, false, false, false, &receiver); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); smgr->getGUIEnvironment()->addStaticText(L"Press Space to hide occluder.", core::recti(10,10, 200,50)); /* Create the node to be occluded. We create a sphere node with high poly count. */ scene::ISceneNode * node = smgr->addSphereSceneNode(10, 64); if (node) { node->setPosition(core::vector3df(0,0,60)); node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp")); node->setMaterialFlag(video::EMF_LIGHTING, false); } /* Now we create another node, the occluder. It's a simple plane. */ scene::ISceneNode* plane = smgr->addMeshSceneNode(smgr->addHillPlaneMesh( "plane", core::dimension2df(10,10), core::dimension2du(2,2)), 0, -1, core::vector3df(0,0,20), core::vector3df(270,0,0)); if (plane) { plane->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg")); plane->setMaterialFlag(video::EMF_LIGHTING, false); plane->setMaterialFlag(video::EMF_BACK_FACE_CULLING, true); } /* Here we create the occlusion query. Because we don't have a plain mesh scene node (ESNT_MESH or ESNT_ANIMATED_MESH), we pass the base geometry as well. Instead, we could also pass a simpler mesh or the bounding box. But we will use a time based method, where the occlusion query renders to the frame buffer and in case of success (occlusion), the mesh is not drawn for several frames. */ driver->addOcclusionQuery(node, ((scene::IMeshSceneNode*)node)->getMesh()); /* We have done everything, just a camera and draw it. We also write the current frames per second and the name of the driver to the caption of the window to examine the render speedup. We also store the time for measuring the time since the last occlusion query ran and store whether the node should be visible in the next frames. */ smgr->addCameraSceneNode(); int lastFPS = -1; u32 timeNow = device->getTimer()->getTime(); bool nodeVisible=true; while(device->run()) { plane->setVisible(!receiver.IsKeyDown(irr::KEY_SPACE)); driver->beginScene(true, true, video::SColor(255,113,113,133)); /* First, we draw the scene, possibly without the occluded element. This is necessary because we need the occluder to be drawn first. You can also use several scene managers to collect a number of possible occluders in a separately rendered scene. */ node->setVisible(nodeVisible); smgr->drawAll(); smgr->getGUIEnvironment()->drawAll(); /* Once in a while, here every 100 ms, we check the visibility. We run the queries, update the pixel value, and query the result. Since we already rendered the node we render the query invisible. The update is made blocking, as we need the result immediately. If you don't need the result immediately, e.g. because you have other things to render, you can call the update non-blocking. This gives the GPU more time to pass back the results without flushing the render pipeline. If the update was called non-blocking, the result from getOcclusionQueryResult is either the previous value, or 0xffffffff if no value has been generated at all, yet. The result is taken immediately as visibility flag for the node. */ if (device->getTimer()->getTime()-timeNow>100) { driver->runAllOcclusionQueries(false); driver->updateAllOcclusionQueries(); nodeVisible=driver->getOcclusionQueryResult(node)>0; timeNow=device->getTimer()->getTime(); } driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw tmp(L"OcclusionQuery Example ["); tmp += driver->getName(); tmp += L"] fps: "; tmp += fps; device->setWindowCaption(tmp.c_str()); lastFPS = fps; } } /* In the end, delete the Irrlicht device. */ device->drop(); return 0; } /* That's it. Compile and play around with the program. **/ irrlicht-1.8.3/examples/25.XmlHandling/0000755000000000000000000000000012574354552016325 5ustar rootrootirrlicht-1.8.3/examples/25.XmlHandling/XmlHandling_vc9.vcproj0000644000000000000000000000760612574354552022551 0ustar rootroot irrlicht-1.8.3/examples/25.XmlHandling/XmlHandling_vc8.vcproj0000644000000000000000000000770712574354552022552 0ustar rootroot irrlicht-1.8.3/examples/25.XmlHandling/XmlHandling_vc12.vcxproj0000644000000000000000000002412612574354552023007 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 25.XmlHandling {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E} 25.XmlHandling Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) false Level3 Cdecl ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) false Level3 Cdecl ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/25.XmlHandling/XmlHandling_vc11.vcxproj0000644000000000000000000002412512574354552023005 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 25.XmlHandling {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E} 25.XmlHandling Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) false Level3 Cdecl ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) false Level3 Cdecl ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/25.XmlHandling/XmlHandling_vc10.vcxproj0000644000000000000000000002412512574354552023004 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 25.XmlHandling {8FDA260E-EF27-4F8C-8720-7AF707DD0D9E} 25.XmlHandling Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) false Level3 Cdecl ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) false Level3 Cdecl ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/25.XmlHandling/XmlHandling.vcproj0000644000000000000000000001032112574354552021754 0ustar rootroot irrlicht-1.8.3/examples/25.XmlHandling/XmlHandling.cbp0000644000000000000000000000265612574354552021231 0ustar rootroot irrlicht-1.8.3/examples/25.XmlHandling/Makefile0000644000000000000000000000425512574354552017773 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler # Name of the executable created (.exe will be added automatically if necessary) Target := 25.XmlHandling # List of source files, separated by spaces Sources := main.cpp # Path to Irrlicht directory, should contain include/ and lib/ IrrlichtHome := ../.. # Path for the executable. Note that Irrlicht.dll should usually also be there for win32 systems BinPath = ../../bin/$(SYSTEM) # general compiler settings (might need to be set when compiling the lib, too) # preprocessor flags, e.g. defines and include paths USERCPPFLAGS = # compiler flags such as optimization flags USERCXXFLAGS = -O3 -ffast-math #USERCXXFLAGS = -g -Wall # linker flags such as additional libraries and link paths USERLDFLAGS = #### #no changes necessary below this line #### CPPFLAGS = -I$(IrrlichtHome)/include -I/usr/X11R6/include $(USERCPPFLAGS) CXXFLAGS = $(USERCXXFLAGS) LDFLAGS = $(USERLDFLAGS) #default target is Linux all: all_linux # target specific settings all_linux all_win32 static_win32: LDFLAGS += -L$(IrrlichtHome)/lib/$(SYSTEM) -lIrrlicht all_linux: LDFLAGS += -L/usr/X11R6/lib$(LIBSELECT) -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32 clean_win32 static_win32: SYSTEM=Win32-gcc all_win32 clean_win32 static_win32: SUF=.exe static_win32: CPPFLAGS += -D_IRR_STATIC_LIB_ all_win32: LDFLAGS += -lopengl32 -lm static_win32: LDFLAGS += -lgdi32 -lwinspool -lcomdlg32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -lopengl32 # name of the binary - only valid for targets which set SYSTEM DESTPATH = $(BinPath)/$(Target)$(SUF) all_linux all_win32 static_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 static_win32 clean clean_linux clean_win32 #multilib handling ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif #solaris real-time features ifeq ($(HOSTTYPE), sun4) LDFLAGS += -lrt endif irrlicht-1.8.3/examples/25.XmlHandling/main.cpp0000644000000000000000000003600712574354552017763 0ustar rootroot/** Example 025 Xml Handling Demonstrates loading and saving of configurations via XML @author Y.M. Bosman \ This demo features a fully usable system for configuration handling. The code can easily be integrated into own apps. */ #include using namespace irr; using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; #ifdef _IRR_WINDOWS_ #pragma comment(lib, "Irrlicht.lib") #endif /* SettingManager class. This class loads and writes the settings and manages the options. The class makes use of irrMap which is a an associative arrays using a red-black tree it allows easy mapping of a key to a value, along the way there is some information on how to use it. */ class SettingManager { public: // Construct setting managers and set default settings SettingManager(const stringw& settings_file): SettingsFile(settings_file), NullDevice(0) { // Irrlicht null device, we want to load settings before we actually created our device, therefore, nulldevice NullDevice = irr::createDevice(irr::video::EDT_NULL); //DriverOptions is an irrlicht map, //we can insert values in the map in two ways by calling insert(key,value) or by using the [key] operator //the [] operator overrides values if they already exist DriverOptions.insert(L"Software", EDT_SOFTWARE); DriverOptions.insert(L"OpenGL", EDT_OPENGL); DriverOptions.insert(L"Direct3D9", EDT_DIRECT3D9); //some resolution options ResolutionOptions.insert(L"640x480", dimension2du(640,480)); ResolutionOptions.insert(L"800x600", dimension2du(800,600)); ResolutionOptions.insert(L"1024x768", dimension2du(1024,768)); //our preferred defaults SettingMap.insert(L"driver", L"Direct3D9"); SettingMap.insert(L"resolution", L"640x480"); SettingMap.insert(L"fullscreen", L"0"); //0 is false } // Destructor, you could store settings automatically on exit of your // application if you wanted to in our case we simply drop the // nulldevice ~SettingManager() { if (NullDevice) { NullDevice->closeDevice(); NullDevice->drop(); } }; /* Load xml from disk, overwrite default settings The xml we are trying to load has the following structure settings nested in sections nested in the root node, like so
		
		
			
		
	
*/ bool load() { //if not able to create device don't attempt to load if (!NullDevice) return false; irr::io::IXMLReader* xml = NullDevice->getFileSystem()->createXMLReader(SettingsFile); //create xml reader if (!xml) return false; const stringw settingTag(L"setting"); //we'll be looking for this tag in the xml stringw currentSection; //keep track of our current section const stringw videoTag(L"video"); //constant for videotag //while there is more to read while (xml->read()) { //check the node type switch (xml->getNodeType()) { //we found a new element case irr::io::EXN_ELEMENT: { //we currently are in the empty or mygame section and find the video tag so we set our current section to video if (currentSection.empty() && videoTag.equals_ignore_case(xml->getNodeName())) { currentSection = videoTag; } //we are in the video section and we find a setting to parse else if (currentSection.equals_ignore_case(videoTag) && settingTag.equals_ignore_case(xml->getNodeName() )) { //read in the key stringw key = xml->getAttributeValueSafe(L"name"); //if there actually is a key to set if (!key.empty()) { //set the setting in the map to the value, //the [] operator overrides values if they already exist or inserts a new key value //pair into the settings map if it was not defined yet SettingMap[key] = xml->getAttributeValueSafe(L"value"); } } //.. // You can add your own sections and tags to read in here //.. } break; //we found the end of an element case irr::io::EXN_ELEMENT_END: //we were at the end of the video section so we reset our tag currentSection=L""; break; } } // don't forget to delete the xml reader xml->drop(); return true; } // Save the xml to disk. We use the nulldevice. bool save() { //if not able to create device don't attempt to save if (!NullDevice) return false; //create xml writer irr::io::IXMLWriter* xwriter = NullDevice->getFileSystem()->createXMLWriter( SettingsFile ); if (!xwriter) return false; //write out the obligatory xml header. Each xml-file needs to have exactly one of those. xwriter->writeXMLHeader(); //start element mygame, you replace the label "mygame" with anything you want xwriter->writeElement(L"mygame"); xwriter->writeLineBreak(); //new line //start section with video settings xwriter->writeElement(L"video"); xwriter->writeLineBreak(); //new line // getIterator gets us a pointer to the first node of the settings map // every iteration we increase the iterator which gives us the next map node // until we reach the end we write settings one by one by using the nodes key and value functions map::Iterator i = SettingMap.getIterator(); for(; !i.atEnd(); i++) { //write element as //the second parameter indicates this is an empty element with no children, just attributes xwriter->writeElement(L"setting",true, L"name", i->getKey().c_str(), L"value",i->getValue().c_str() ); xwriter->writeLineBreak(); } xwriter->writeLineBreak(); //close video section xwriter->writeClosingTag(L"video"); xwriter->writeLineBreak(); //.. // You can add writing sound settings, savegame information etc //.. //close mygame section xwriter->writeClosingTag(L"mygame"); //delete xml writer xwriter->drop(); return true; } // Set setting in our manager void setSetting(const stringw& name, const stringw& value) { SettingMap[name]=value; } // set setting overload to quickly assign integers to our setting map void setSetting(const stringw& name, s32 value) { SettingMap[name]=stringw(value); } // Get setting as string stringw getSetting(const stringw& key) const { //the find function or irrmap returns a pointer to a map Node //if the key can be found, otherwise it returns null //the map node has the function getValue and getKey, as we already know the key, we return node->getValue() map::Node* n = SettingMap.find(key); if (n) return n->getValue(); else return L""; } // bool getSettingAsBoolean(const stringw& key ) const { stringw s = getSetting(key); if (s.empty()) return false; return s.equals_ignore_case(L"1"); } // s32 getSettingAsInteger(const stringw& key) const { //we implicitly cast to string instead of stringw because strtol10 does not accept wide strings const stringc s = getSetting(key); if (s.empty()) return 0; return strtol10(s.c_str()); } public: map DriverOptions; //available options for driver config map ResolutionOptions; //available options for resolution config private: SettingManager(const SettingManager& other); // defined but not implemented SettingManager& operator=(const SettingManager& other); // defined but not implemented map SettingMap; //current config stringw SettingsFile; // location of the xml, usually the irr::IrrlichtDevice* NullDevice; }; /* Application context for global variables */ struct SAppContext { SAppContext() : Device(0),Gui(0), Driver(0), Settings(0), ShouldQuit(false), ButtonSave(0), ButtonExit(0), ListboxDriver(0), ListboxResolution(0), CheckboxFullscreen(0) { } ~SAppContext() { if (Settings) delete Settings; if (Device) { Device->closeDevice(); Device->drop(); } } IrrlichtDevice* Device; IGUIEnvironment* Gui; IVideoDriver* Driver; SettingManager* Settings; bool ShouldQuit; //settings dialog IGUIButton* ButtonSave; IGUIButton* ButtonExit; IGUIListBox* ListboxDriver; IGUIListBox* ListboxResolution; IGUICheckBox* CheckboxFullscreen; }; /* A typical event receiver. */ class MyEventReceiver : public IEventReceiver { public: MyEventReceiver(SAppContext & a) : App(a) { } virtual bool OnEvent(const SEvent& event) { if (event.EventType == EET_GUI_EVENT ) { switch ( event.GUIEvent.EventType ) { //handle button click events case EGET_BUTTON_CLICKED: { //Our save button was called so we obtain the settings from our dialog and save them if ( event.GUIEvent.Caller == App.ButtonSave ) { //if there is a selection write it if ( App.ListboxDriver->getSelected() != -1) App.Settings->setSetting(L"driver", App.ListboxDriver->getListItem(App.ListboxDriver->getSelected())); //if there is a selection write it if ( App.ListboxResolution->getSelected() != -1) App.Settings->setSetting(L"resolution", App.ListboxResolution->getListItem(App.ListboxResolution->getSelected())); App.Settings->setSetting(L"fullscreen", App.CheckboxFullscreen->isChecked()); if (App.Settings->save()) { App.Gui->addMessageBox(L"settings save",L"settings saved, please restart for settings to change effect","",true); } } // cancel/exit button clicked, tell the application to exit else if ( event.GUIEvent.Caller == App.ButtonExit) { App.ShouldQuit = true; } } break; } } return false; } private: SAppContext & App; }; /* Function to create a video settings dialog This dialog shows the current settings from the configuration xml and allows them to be changed */ void createSettingsDialog(SAppContext& app) { // first get rid of alpha in gui for (irr::s32 i=0; igetSkin()->getColor((irr::gui::EGUI_DEFAULT_COLOR)i); col.setAlpha(255); app.Gui->getSkin()->setColor((irr::gui::EGUI_DEFAULT_COLOR)i, col); } //create video settings windows gui::IGUIWindow* windowSettings = app.Gui->addWindow(rect(10,10,400,400),true,L"Videosettings"); app.Gui->addStaticText (L"Select your desired video settings", rect< s32 >(10,20, 200, 40), false, true, windowSettings); // add listbox for driver choice app.Gui->addStaticText (L"Driver", rect< s32 >(10,50, 200, 60), false, true, windowSettings); app.ListboxDriver = app.Gui->addListBox(rect(10,60,220,120), windowSettings, 1,true); //add all available options to the driver choice listbox map::Iterator i = app.Settings->DriverOptions.getIterator(); for(; !i.atEnd(); i++) app.ListboxDriver->addItem(i->getKey().c_str()); //set currently selected driver app.ListboxDriver->setSelected(app.Settings->getSetting("driver").c_str()); // add listbox for resolution choice app.Gui->addStaticText (L"Resolution", rect< s32 >(10,130, 200, 140), false, true, windowSettings); app.ListboxResolution = app.Gui->addListBox(rect(10,140,220,200), windowSettings, 1,true); //add all available options to the resolution listbox map::Iterator ri = app.Settings->ResolutionOptions.getIterator(); for(; !ri.atEnd(); ri++) app.ListboxResolution->addItem(ri->getKey().c_str()); //set currently selected resolution app.ListboxResolution->setSelected(app.Settings->getSetting("resolution").c_str()); //add checkbox to toggle fullscreen, initially set to loaded setting app.CheckboxFullscreen = app.Gui->addCheckBox( app.Settings->getSettingAsBoolean("fullscreen"), rect(10,220,220,240), windowSettings, -1, L"Fullscreen"); //last but not least add save button app.ButtonSave = app.Gui->addButton( rect(80,250,150,270), windowSettings, 2, L"Save video settings"); //exit/cancel button app.ButtonExit = app.Gui->addButton( rect(160,250,240,270), windowSettings, 2, L"Cancel and exit"); } /* The main function. Creates all objects and does the XML handling. */ int main() { //create new application context SAppContext app; //create device creation parameters that can get overwritten by our settings file SIrrlichtCreationParameters param; param.DriverType = EDT_SOFTWARE; param.WindowSize.set(640,480); // Try to load config. // I leave it as an exercise of the reader to store the configuration in the local application data folder, // the only logical place to store config data for games. For all other operating systems I redirect to your manuals app.Settings = new SettingManager("../../media/settings.xml"); if ( !app.Settings->load() ) { // ... // Here add your own exception handling, for now we continue because there are defaults set in SettingManager constructor // ... } else { //settings xml loaded from disk, //map driversetting to driver type and test if the setting is valid //the DriverOptions map contains string representations mapped to to irrlicht E_DRIVER_TYPE enum //e.g "direct3d9" will become 4 //see DriverOptions in the settingmanager class for details map::Node* driver = app.Settings->DriverOptions.find( app.Settings->getSetting("driver") ); if (driver) { if ( irr::IrrlichtDevice::isDriverSupported( static_cast( driver->getValue() ))) { // selected driver is supported, so we use it. param.DriverType = static_cast( driver->getValue()); } } //map resolution setting to dimension in a similar way as demonstrated above map::Node* res = app.Settings->ResolutionOptions.find( app.Settings->getSetting("resolution") ); if (res) { param.WindowSize = res->getValue(); } //get fullscreen setting from config param.Fullscreen = app.Settings->getSettingAsBoolean("fullscreen"); } //create the irrlicht device using the settings app.Device = createDeviceEx(param); if (app.Device == 0) { // You can add your own exception handling on driver failure exit(0); } app.Device->setWindowCaption(L"Xmlhandling - Irrlicht engine tutorial"); app.Driver = app.Device->getVideoDriver(); app.Gui = app.Device->getGUIEnvironment(); createSettingsDialog(app); //set event receiver so we can respond to gui events MyEventReceiver receiver(app); app.Device->setEventReceiver(&receiver); //enter main loop while (!app.ShouldQuit && app.Device->run()) { if (app.Device->isWindowActive()) { app.Driver->beginScene(true, true, SColor(0,200,200,200)); app.Gui->drawAll(); app.Driver->endScene(); } app.Device->sleep(10); } //app destroys device in destructor return 0; } /* **/ irrlicht-1.8.3/examples/25.XmlHandling/.objs/0000755000000000000000000000000012574354552017340 5ustar rootrootirrlicht-1.8.3/examples/24.CursorControl/0000755000000000000000000000000012574354552016735 5ustar rootrootirrlicht-1.8.3/examples/24.CursorControl/Makefile0000644000000000000000000000425712574354552020405 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler # Name of the executable created (.exe will be added automatically if necessary) Target := 24.CursorControl # List of source files, separated by spaces Sources := main.cpp # Path to Irrlicht directory, should contain include/ and lib/ IrrlichtHome := ../.. # Path for the executable. Note that Irrlicht.dll should usually also be there for win32 systems BinPath = ../../bin/$(SYSTEM) # general compiler settings (might need to be set when compiling the lib, too) # preprocessor flags, e.g. defines and include paths USERCPPFLAGS = # compiler flags such as optimization flags USERCXXFLAGS = -O3 -ffast-math #USERCXXFLAGS = -g -Wall # linker flags such as additional libraries and link paths USERLDFLAGS = #### #no changes necessary below this line #### CPPFLAGS = -I$(IrrlichtHome)/include -I/usr/X11R6/include $(USERCPPFLAGS) CXXFLAGS = $(USERCXXFLAGS) LDFLAGS = $(USERLDFLAGS) #default target is Linux all: all_linux # target specific settings all_linux all_win32 static_win32: LDFLAGS += -L$(IrrlichtHome)/lib/$(SYSTEM) -lIrrlicht all_linux: LDFLAGS += -L/usr/X11R6/lib$(LIBSELECT) -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32 clean_win32 static_win32: SYSTEM=Win32-gcc all_win32 clean_win32 static_win32: SUF=.exe static_win32: CPPFLAGS += -D_IRR_STATIC_LIB_ all_win32: LDFLAGS += -lopengl32 -lm static_win32: LDFLAGS += -lgdi32 -lwinspool -lcomdlg32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -lopengl32 # name of the binary - only valid for targets which set SYSTEM DESTPATH = $(BinPath)/$(Target)$(SUF) all_linux all_win32 static_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 static_win32 clean clean_linux clean_win32 #multilib handling ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif #solaris real-time features ifeq ($(HOSTTYPE), sun4) LDFLAGS += -lrt endif irrlicht-1.8.3/examples/24.CursorControl/main.cpp0000644000000000000000000004316212574354552020373 0ustar rootroot/** Example 024 CursorControl Show how to modify cursors and offer some useful tool-functions for creating cursors. It can also be used for experiments with the mouse in general. */ #include #include "driverChoice.h" using namespace irr; using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; #ifdef _IRR_WINDOWS_ #pragma comment(lib, "Irrlicht.lib") #endif const int DELAY_TIME = 3000; enum ETimerAction { ETA_MOUSE_VISIBLE, ETA_MOUSE_INVISIBLE, }; /* Structure to allow delayed execution of some actions. */ struct TimerAction { u32 TargetTime; ETimerAction Action; }; /* */ struct SAppContext { SAppContext() : Device(0), InfoStatic(0), EventBox(0), CursorBox(0), SpriteBox(0) , ButtonSetVisible(0), ButtonSetInvisible(0), ButtonSimulateBadFps(0) , ButtonChangeIcon(0) , SimulateBadFps(false) { } void update() { if (!Device) return; u32 timeNow = Device->getTimer()->getTime(); for ( u32 i=0; i < TimerActions.size(); ++i ) { if ( timeNow >= TimerActions[i].TargetTime ) { runTimerAction(TimerActions[i]); TimerActions.erase(i); } else { ++i; } } } void runTimerAction(const TimerAction& action) { if (ETA_MOUSE_VISIBLE == action.Action) { Device->getCursorControl()->setVisible(true); ButtonSetVisible->setEnabled(true); } else if ( ETA_MOUSE_INVISIBLE == action.Action) { Device->getCursorControl()->setVisible(false); ButtonSetInvisible->setEnabled(true); } } /* Add another icon which the user can click and select as cursor later on. */ void addIcon(const stringw& name, const SCursorSprite &sprite, bool addCursor=true) { // Sprites are just icons - not yet cursors. They can be displayed by Irrlicht sprite functions and be used to create cursors. SpriteBox->addItem(name.c_str(), sprite.SpriteId); Sprites.push_back(sprite); // create the cursor together with the icon? if ( addCursor ) { /* Here we create a hardware cursor from a sprite */ Device->getCursorControl()->addIcon(sprite); // ... and add it to the cursors selection listbox to the other system cursors. CursorBox->addItem(name.c_str()); } } IrrlichtDevice * Device; gui::IGUIStaticText * InfoStatic; gui::IGUIListBox * EventBox; gui::IGUIListBox * CursorBox; gui::IGUIListBox * SpriteBox; gui::IGUIButton * ButtonSetVisible; gui::IGUIButton * ButtonSetInvisible; gui::IGUIButton * ButtonSimulateBadFps; gui::IGUIButton * ButtonChangeIcon; array TimerActions; bool SimulateBadFps; array Sprites; }; /* Helper function to print mouse event names into a stringw */ void PrintMouseEventName(const SEvent& event, stringw &result) { switch ( event.MouseInput.Event ) { case EMIE_LMOUSE_PRESSED_DOWN: result += stringw(L"EMIE_LMOUSE_PRESSED_DOWN"); break; case EMIE_RMOUSE_PRESSED_DOWN: result += stringw(L"EMIE_RMOUSE_PRESSED_DOWN"); break; case EMIE_MMOUSE_PRESSED_DOWN: result += stringw(L"EMIE_MMOUSE_PRESSED_DOWN"); break; case EMIE_LMOUSE_LEFT_UP: result += stringw(L"EMIE_LMOUSE_LEFT_UP"); break; case EMIE_RMOUSE_LEFT_UP: result += stringw(L"EMIE_RMOUSE_LEFT_UP"); break; case EMIE_MMOUSE_LEFT_UP: result += stringw(L"EMIE_MMOUSE_LEFT_UP"); break; case EMIE_MOUSE_MOVED: result += stringw(L"EMIE_MOUSE_MOVED"); break; case EMIE_MOUSE_WHEEL: result += stringw(L"EMIE_MOUSE_WHEEL"); break; case EMIE_LMOUSE_DOUBLE_CLICK: result += stringw(L"EMIE_LMOUSE_DOUBLE_CLICK"); break; case EMIE_RMOUSE_DOUBLE_CLICK: result += stringw(L"EMIE_RMOUSE_DOUBLE_CLICK"); break; case EMIE_MMOUSE_DOUBLE_CLICK: result += stringw(L"EMIE_MMOUSE_DOUBLE_CLICK"); break; case EMIE_LMOUSE_TRIPLE_CLICK: result += stringw(L"EMIE_LMOUSE_TRIPLE_CLICK"); break; case EMIE_RMOUSE_TRIPLE_CLICK: result += stringw(L"EMIE_RMOUSE_TRIPLE_CLICK"); break; case EMIE_MMOUSE_TRIPLE_CLICK: result += stringw(L"EMIE_MMOUSE_TRIPLE_CLICK"); break; default: break; } } /* Helper function to print all the state information which get from a mouse-event into a stringw */ void PrintMouseState(const SEvent& event, stringw &result) { result += stringw(L"X: "); result += stringw(event.MouseInput.X); result += stringw(L"\n"); result += stringw(L"Y: "); result += stringw(event.MouseInput.Y); result += stringw(L"\n"); result += stringw(L"Wheel: "); result += stringw(event.MouseInput.Wheel); result += stringw(L"\n"); result += stringw(L"Shift: "); if ( event.MouseInput.Shift ) result += stringw(L"true\n"); else result += stringw(L"false\n"); result += stringw(L"Control: "); if ( event.MouseInput.Control ) result += stringw(L"true\n"); else result += stringw(L"false\n"); result += stringw(L"ButtonStates: "); result += stringw(event.MouseInput.ButtonStates); result += stringw(L"\n"); result += stringw(L"isLeftPressed: "); if ( event.MouseInput.isLeftPressed() ) result += stringw(L"true\n"); else result += stringw(L"false\n"); result += stringw(L"isRightPressed: "); if ( event.MouseInput.isRightPressed() ) result += stringw(L"true\n"); else result += stringw(L"false\n"); result += stringw(L"isMiddlePressed: "); if ( event.MouseInput.isMiddlePressed() ) result += stringw(L"true\n"); else result += stringw(L"false\n"); result += stringw(L"Event: "); PrintMouseEventName(event, result); result += stringw(L"\n"); } /* A typical event receiver. */ class MyEventReceiver : public IEventReceiver { public: MyEventReceiver(SAppContext & context) : Context(context) { } virtual bool OnEvent(const SEvent& event) { if (event.EventType == EET_GUI_EVENT ) { switch ( event.GUIEvent.EventType ) { case EGET_BUTTON_CLICKED: { u32 timeNow = Context.Device->getTimer()->getTime(); TimerAction action; action.TargetTime = timeNow + DELAY_TIME; if ( event.GUIEvent.Caller == Context.ButtonSetVisible ) { action.Action = ETA_MOUSE_VISIBLE; Context.TimerActions.push_back(action); Context.ButtonSetVisible->setEnabled(false); } else if ( event.GUIEvent.Caller == Context.ButtonSetInvisible ) { action.Action = ETA_MOUSE_INVISIBLE; Context.TimerActions.push_back(action); Context.ButtonSetInvisible->setEnabled(false); } else if ( event.GUIEvent.Caller == Context.ButtonSimulateBadFps ) { Context.SimulateBadFps = Context.ButtonSimulateBadFps->isPressed(); } else if ( event.GUIEvent.Caller == Context.ButtonChangeIcon ) { /* Replace an existing cursor icon by another icon. The user has to select both - the icon which should be replaced and the icon which will replace it. */ s32 selectedCursor = Context.CursorBox->getSelected(); s32 selectedSprite = Context.SpriteBox->getSelected(); if ( selectedCursor >= 0 && selectedSprite >= 0 ) { /* This does replace the icon. */ Context.Device->getCursorControl()->changeIcon((ECURSOR_ICON)selectedCursor, Context.Sprites[selectedSprite] ); /* Do also show the new icon. */ Context.Device->getCursorControl()->setActiveIcon( ECURSOR_ICON(selectedCursor) ); } } } break; case EGET_LISTBOX_CHANGED: case EGET_LISTBOX_SELECTED_AGAIN: { if ( event.GUIEvent.Caller == Context.CursorBox ) { /* Find out which cursor the user selected */ s32 selected = Context.CursorBox->getSelected(); if ( selected >= 0 ) { /* Here we set the new cursor icon which will now be used within our window. */ Context.Device->getCursorControl()->setActiveIcon( ECURSOR_ICON(selected) ); } } } break; default: break; } } if (event.EventType == EET_MOUSE_INPUT_EVENT) { stringw infoText; PrintMouseState(event, infoText); Context.InfoStatic->setText(infoText.c_str()); if ( event.MouseInput.Event != EMIE_MOUSE_MOVED && event.MouseInput.Event != EMIE_MOUSE_WHEEL ) // no spam { infoText = L""; PrintMouseEventName(event, infoText); Context.EventBox->insertItem(0, infoText.c_str(), -1); } } return false; } private: SAppContext & Context; }; /* Use several imagefiles as animation frames for a sprite which can be used as cursor icon. The images in those files all need to have the same size. Return sprite index on success or -1 on failure */ s32 AddAnimatedIconToSpriteBank( gui::IGUISpriteBank * spriteBank, video::IVideoDriver* driver, const array< io::path >& files, u32 frameTime ) { if ( !spriteBank || !driver || !files.size() ) return -1; video::ITexture * tex = driver->getTexture( files[0] ); if ( tex ) { array< rect >& spritePositions = spriteBank->getPositions(); u32 idxRect = spritePositions.size(); spritePositions.push_back( rect(0,0, tex->getSize().Width, tex->getSize().Height) ); SGUISprite sprite; sprite.frameTime = frameTime; array< SGUISprite >& sprites = spriteBank->getSprites(); u32 startIdx = spriteBank->getTextureCount(); for ( u32 f=0; f < files.size(); ++f ) { tex = driver->getTexture( files[f] ); if ( tex ) { spriteBank->addTexture( driver->getTexture(files[f]) ); gui::SGUISpriteFrame frame; frame.rectNumber = idxRect; frame.textureNumber = startIdx+f; sprite.Frames.push_back( frame ); } } sprites.push_back( sprite ); return sprites.size()-1; } return -1; } /* Use several images within one imagefile as animation frames for a sprite which can be used as cursor icon The sizes of the icons within that file all need to have the same size Return sprite index on success or -1 on failure */ s32 AddAnimatedIconToSpriteBank( gui::IGUISpriteBank * spriteBank, video::IVideoDriver* driver, const io::path& file, const array< rect >& rects, u32 frameTime ) { if ( !spriteBank || !driver || !rects.size() ) return -1; video::ITexture * tex = driver->getTexture( file ); if ( tex ) { array< rect >& spritePositions = spriteBank->getPositions(); u32 idxRect = spritePositions.size(); u32 idxTex = spriteBank->getTextureCount(); spriteBank->addTexture( tex ); SGUISprite sprite; sprite.frameTime = frameTime; array< SGUISprite >& sprites = spriteBank->getSprites(); for ( u32 i=0; i < rects.size(); ++i ) { spritePositions.push_back( rects[i] ); gui::SGUISpriteFrame frame; frame.rectNumber = idxRect+i; frame.textureNumber = idxTex; sprite.Frames.push_back( frame ); } sprites.push_back( sprite ); return sprites.size()-1; } return -1; } /* Create a non-animated icon from the given file and position and put it into the spritebank. We can use this icon later on in a cursor. */ s32 AddIconToSpriteBank( gui::IGUISpriteBank * spriteBank, video::IVideoDriver* driver, const io::path& file, const core::rect& rect ) { if ( !spriteBank || !driver ) return -1; video::ITexture * tex = driver->getTexture( file ); if ( tex ) { core::array< core::rect >& spritePositions = spriteBank->getPositions(); spritePositions.push_back( rect ); array< SGUISprite >& sprites = spriteBank->getSprites(); spriteBank->addTexture( tex ); gui::SGUISpriteFrame frame; frame.rectNumber = spritePositions.size()-1; frame.textureNumber = spriteBank->getTextureCount()-1; SGUISprite sprite; sprite.frameTime = 0; sprite.Frames.push_back( frame ); sprites.push_back( sprite ); return sprites.size()-1; } return -1; } int main() { video::E_DRIVER_TYPE driverType = driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; IrrlichtDevice * device = createDevice(driverType, dimension2d(640, 480)); if (device == 0) return 1; // could not create selected driver. // It's sometimes of interest to know how the mouse behaves after a resize device->setResizable(true); device->setWindowCaption(L"Cursor control - Irrlicht engine tutorial"); video::IVideoDriver* driver = device->getVideoDriver(); IGUIEnvironment* env = device->getGUIEnvironment(); gui::IGUISpriteBank * SpriteBankIcons; SAppContext context; context.Device = device; rect< s32 > rectInfoStatic(10,10, 200, 200); env->addStaticText (L"Cursor state information", rectInfoStatic, true, true); rectInfoStatic.UpperLeftCorner += dimension2di(0, 15); context.InfoStatic = env->addStaticText (L"", rectInfoStatic, true, true); rect< s32 > rectEventBox(10,210, 200, 400); env->addStaticText (L"click events (new on top)", rectEventBox, true, true); rectEventBox.UpperLeftCorner += dimension2di(0, 15); context.EventBox = env->addListBox(rectEventBox); rect< s32 > rectCursorBox(210,10, 400, 250); env->addStaticText (L"cursors, click to set the active one", rectCursorBox, true, true); rectCursorBox.UpperLeftCorner += dimension2di(0, 15); context.CursorBox = env->addListBox(rectCursorBox); rect< s32 > rectSpriteBox(210,260, 400, 400); env->addStaticText (L"sprites", rectSpriteBox, true, true); rectSpriteBox.UpperLeftCorner += dimension2di(0, 15); context.SpriteBox = env->addListBox(rectSpriteBox); context.ButtonSetVisible = env->addButton( rect( 410, 20, 560, 40 ), 0, -1, L"set visible (delayed)" ); context.ButtonSetInvisible = env->addButton( rect( 410, 50, 560, 70 ), 0, -1, L"set invisible (delayed)" ); context.ButtonSimulateBadFps = env->addButton( rect( 410, 80, 560, 100 ), 0, -1, L"simulate bad FPS" ); context.ButtonSimulateBadFps->setIsPushButton(true); context.ButtonChangeIcon = env->addButton( rect( 410, 140, 560, 160 ), 0, -1, L"replace cursor icon\n(cursor+sprite must be selected)" ); // set the names for all the system cursors for ( int i=0; i < (int)gui::ECI_COUNT; ++i ) { context.CursorBox->addItem(stringw( GUICursorIconNames[i] ).c_str()); } /* Create sprites which then can be used as cursor icons. */ SpriteBankIcons = env->addEmptySpriteBank(io::path("cursor_icons")); context.SpriteBox->setSpriteBank(SpriteBankIcons); // create one animated icon from several files array< io::path > files; files.push_back( io::path("../../media/icon_crosshairs16x16bw1.png") ); files.push_back( io::path("../../media/icon_crosshairs16x16bw2.png") ); files.push_back( io::path("../../media/icon_crosshairs16x16bw3.png") ); files.push_back( io::path("../../media/icon_crosshairs16x16bw3.png") ); files.push_back( io::path("../../media/icon_crosshairs16x16bw2.png") ); SCursorSprite spriteBw; // the sprite + some additional information needed for cursors spriteBw.SpriteId = AddAnimatedIconToSpriteBank( SpriteBankIcons, driver, files, 200 ); spriteBw.SpriteBank = SpriteBankIcons; spriteBw.HotSpot = position2d(7,7); context.addIcon(L"crosshair_bw", spriteBw); // create one animated icon from one file array< rect > iconRects; iconRects.push_back( rect(0,0, 16, 16) ); iconRects.push_back( rect(16,0, 32, 16) ); iconRects.push_back( rect(0,16, 16, 32) ); iconRects.push_back( rect(0,16, 16, 32) ); iconRects.push_back( rect(16,0, 32, 16) ); SCursorSprite spriteCol; // the sprite + some additional information needed for cursors spriteCol.SpriteId = AddAnimatedIconToSpriteBank( SpriteBankIcons, driver, io::path("../../media/icon_crosshairs16x16col.png"), iconRects, 200 ); spriteCol.HotSpot = position2d(7,7); spriteCol.SpriteBank = SpriteBankIcons; context.addIcon(L"crosshair_colored", spriteCol); // Create some non-animated icons rect rectIcon; SCursorSprite spriteNonAnimated(SpriteBankIcons, 0, position2d(7,7)); rectIcon = rect(0,0, 16, 16); spriteNonAnimated.SpriteId = AddIconToSpriteBank( SpriteBankIcons, driver, io::path("../../media/icon_crosshairs16x16col.png"), rectIcon ); context.addIcon(L"crosshair_col1", spriteNonAnimated, false); rectIcon = rect(16,0, 32, 16); spriteNonAnimated.SpriteId = AddIconToSpriteBank( SpriteBankIcons, driver, io::path("../../media/icon_crosshairs16x16col.png"), rectIcon ); context.addIcon(L"crosshair_col2", spriteNonAnimated, false); rectIcon = rect(0,16, 16, 32); spriteNonAnimated.SpriteId = AddIconToSpriteBank( SpriteBankIcons, driver, io::path("../../media/icon_crosshairs16x16col.png"), rectIcon ); context.addIcon(L"crosshair_col3", spriteNonAnimated, false); MyEventReceiver receiver(context); device->setEventReceiver(&receiver); while(device->run() && driver) { // if (device->isWindowActive()) { u32 realTimeNow = device->getTimer()->getRealTime(); context.update(); driver->beginScene(true, true, SColor(0,200,200,200)); env->drawAll(); // draw custom sprite with Irrlicht functions for comparison. It should usually look the same as the cursors. if ( context.SpriteBox ) { s32 selectedSprite = context.SpriteBox->getSelected(); if ( selectedSprite >= 0 && context.Sprites[selectedSprite].SpriteId >= 0 ) { SpriteBankIcons->draw2DSprite(u32(context.Sprites[selectedSprite].SpriteId), position2di(580, 140), 0, video::SColor(255, 255, 255, 255), 0, realTimeNow); } } driver->endScene(); } // By simulating bad fps we can find out if hardware-support for cursors works or not. If it works the cursor will move as usual,while it otherwise will just update with 2 fps now. if ( context.SimulateBadFps ) { device->sleep(500); // 2 fps } else { device->sleep(10); } } device->drop(); return 0; } /* **/ irrlicht-1.8.3/examples/24.CursorControl/CursorControl_vc9.vcproj0000644000000000000000000000762012574354552023566 0ustar rootroot irrlicht-1.8.3/examples/24.CursorControl/CursorControl_vc8.vcproj0000644000000000000000000000771712574354552023574 0ustar rootroot irrlicht-1.8.3/examples/24.CursorControl/CursorControl_vc12.vcxproj0000644000000000000000000002507212574354552024031 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 24.CursorControl {02B67A37-50E1-49DB-BECF-905BC029C2FE} 24.CursorControl Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\24.CursorControl.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)CursorControl.pdb Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\24.CursorControl.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)CursorControl.pdb Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Sync Level3 Cdecl ..\..\bin\Win32-VisualStudio\24.CursorControl.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Sync Level3 Cdecl ..\..\bin\Win64-VisualStudio\24.CursorControl.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/24.CursorControl/CursorControl_vc11.vcxproj0000644000000000000000000002507112574354552024027 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 24.CursorControl {02B67A37-50E1-49DB-BECF-905BC029C2FE} 24.CursorControl Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\24.CursorControl.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)CursorControl.pdb Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\24.CursorControl.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)CursorControl.pdb Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Sync Level3 Cdecl ..\..\bin\Win32-VisualStudio\24.CursorControl.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Sync Level3 Cdecl ..\..\bin\Win64-VisualStudio\24.CursorControl.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/24.CursorControl/CursorControl_vc10.vcxproj0000644000000000000000000002507112574354552024026 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 24.CursorControl {02B67A37-50E1-49DB-BECF-905BC029C2FE} 24.CursorControl Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\24.CursorControl.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)CursorControl.pdb Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\24.CursorControl.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)CursorControl.pdb Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Sync Level3 Cdecl ..\..\bin\Win32-VisualStudio\24.CursorControl.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Sync Level3 Cdecl ..\..\bin\Win64-VisualStudio\24.CursorControl.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/24.CursorControl/CursorControl.vcproj0000644000000000000000000000671212574354552023006 0ustar rootroot irrlicht-1.8.3/examples/24.CursorControl/CursorControl.cbp0000644000000000000000000000301112574354552022234 0ustar rootroot irrlicht-1.8.3/examples/23.SMeshHandling/0000755000000000000000000000000012574354552016602 5ustar rootrootirrlicht-1.8.3/examples/23.SMeshHandling/SMeshHandling_vc9.vcproj0000644000000000000000000000770212574354552023302 0ustar rootroot irrlicht-1.8.3/examples/23.SMeshHandling/SMeshHandling_vc8.vcproj0000644000000000000000000000771712574354552023307 0ustar rootroot irrlicht-1.8.3/examples/23.SMeshHandling/SMeshHandling_vc12.vcxproj0000644000000000000000000002573012574354552023545 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 23.SMeshHandling {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7} 23.SMeshHandling Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\23.SMeshHandling.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)SMeshHandling.pdb Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\23.SMeshHandling.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)SMeshHandling.pdb Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Sync Level3 Cdecl ..\..\bin\Win32-VisualStudio\23.SMeshHandling.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Sync Level3 Cdecl ..\..\bin\Win64-VisualStudio\23.SMeshHandling.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/23.SMeshHandling/SMeshHandling_vc11.vcxproj0000644000000000000000000002572712574354552023552 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 23.SMeshHandling {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7} 23.SMeshHandling Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\23.SMeshHandling.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)SMeshHandling.pdb Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\23.SMeshHandling.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)SMeshHandling.pdb Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Sync Level3 Cdecl ..\..\bin\Win32-VisualStudio\23.SMeshHandling.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Sync Level3 Cdecl ..\..\bin\Win64-VisualStudio\23.SMeshHandling.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/23.SMeshHandling/SMeshHandling_vc10.vcxproj0000644000000000000000000002572712574354552023551 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 23.SMeshHandling {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7} 23.SMeshHandling Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\23.SMeshHandling.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)SMeshHandling.pdb Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\23.SMeshHandling.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)SMeshHandling.pdb Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Sync Level3 Cdecl ..\..\bin\Win32-VisualStudio\23.SMeshHandling.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Sync Level3 Cdecl ..\..\bin\Win64-VisualStudio\23.SMeshHandling.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/23.SMeshHandling/SMeshHandling.vcproj0000644000000000000000000000671212574354552022521 0ustar rootroot irrlicht-1.8.3/examples/23.SMeshHandling/SMeshHandling.dev0000644000000000000000000000175012574354552021771 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 23 SMeshHandling UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=23.SMeshHandling.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/23.SMeshHandling/SMeshHandling.cbp0000644000000000000000000000225412574354552021757 0ustar rootroot irrlicht-1.8.3/examples/23.SMeshHandling/Makefile0000644000000000000000000000220712574354552020243 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 23.SMeshHandling Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/23.SMeshHandling/main.cpp0000644000000000000000000002440512574354552020237 0ustar rootroot/** Example 023 SMeshBufferHandling A tutorial by geoff. In this tutorial we'll learn how to create custom meshes and deal with them with Irrlicht. We'll create an interesting heightmap with some lighting effects. With keys 1,2,3 you can choose a different mesh layout, which is put into the mesh buffers as desired. All positions, normals, etc. are updated accordingly. Ok, let's start with the headers (I think there's nothing to say about it) */ #include #include "driverChoice.h" #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif //Namespaces for the engine using namespace irr; using namespace video; using namespace core; using namespace scene; using namespace io; using namespace gui; /* This is the type of the functions which work out the colour. */ typedef SColor colour_func(f32 x, f32 y, f32 z); /* Here comes a set of functions which can be used for coloring the nodes while creating the mesh. */ // Greyscale, based on the height. SColor grey(f32, f32, f32 z) { u32 n = (u32)(255.f * z); return SColor(255, n, n, n); } // Interpolation between blue and white, with red added in one // direction and green in the other. SColor yellow(f32 x, f32 y, f32) { return SColor(255, 128 + (u32)(127.f * x), 128 + (u32)(127.f * y), 255); } // Pure white. SColor white(f32, f32, f32) { return SColor(255, 255, 255, 255); } /* The type of the functions which generate the heightmap. x and y range between -0.5 and 0.5, and s is the scale of the heightmap. */ typedef f32 generate_func(s16 x, s16 y, f32 s); // An interesting sample function :-) f32 eggbox(s16 x, s16 y, f32 s) { const f32 r = 4.f*sqrtf((f32)(x*x + y*y))/s; const f32 z = expf(-r * 2) * (cosf(0.2f * x) + cosf(0.2f * y)); return 0.25f+0.25f*z; } // A rather dumb sine function :-/ f32 moresine(s16 x, s16 y, f32 s) { const f32 xx=0.3f*(f32)x/s; const f32 yy=12*y/s; const f32 z = sinf(xx*xx+yy)*sinf(xx+yy*yy); return 0.25f + 0.25f * z; } // A simple function f32 justexp(s16 x, s16 y, f32 s) { const f32 xx=6*x/s; const f32 yy=6*y/s; const f32 z = (xx*xx+yy*yy); return 0.3f*z*cosf(xx*yy); } /* A simple class for representing heightmaps. Most of this should be obvious. */ class HeightMap { private: const u16 Width; const u16 Height; f32 s; core::array data; public: HeightMap(u16 _w, u16 _h) : Width(_w), Height(_h), s(0.f), data(0) { s = sqrtf((f32)(Width * Width + Height * Height)); data.set_used(Width * Height); } // Fill the heightmap with values generated from f. void generate(generate_func f) { u32 i=0; for(u16 y = 0; y < Height; ++y) for(u16 x = 0; x < Width; ++x) set(i++, calc(f, x, y)); } u16 height() const { return Height; } u16 width() const { return Width; } f32 calc(generate_func f, u16 x, u16 y) const { const f32 xx = (f32)x - Width*0.5f; const f32 yy = (f32)y - Height*0.5f; return f((u16)xx, (u16)yy, s); } // The height at (x, y) is at position y * Width + x. void set(u16 x, u16 y, f32 z) { data[y * Width + x] = z; } void set(u32 i, f32 z) { data[i] = z; } f32 get(u16 x, u16 y) const { return data[y * Width + x]; } /* The only difficult part. This considers the normal at (x, y) to be the cross product of the vectors between the adjacent points in the horizontal and vertical directions. s is a scaling factor, which is necessary if the height units are different from the coordinate units; for example, if your map has heights in metres and the coordinates are in units of a kilometer. */ vector3df getnormal(u16 x, u16 y, f32 s) const { const f32 zc = get(x, y); f32 zl, zr, zu, zd; if (x == 0) { zr = get(x + 1, y); zl = zc + zc - zr; } else if (x == Width - 1) { zl = get(x - 1, y); zr = zc + zc - zl; } else { zr = get(x + 1, y); zl = get(x - 1, y); } if (y == 0) { zd = get(x, y + 1); zu = zc + zc - zd; } else if (y == Height - 1) { zu = get(x, y - 1); zd = zc + zc - zu; } else { zd = get(x, y + 1); zu = get(x, y - 1); } return vector3df(s * 2 * (zl - zr), 4, s * 2 * (zd - zu)).normalize(); } }; /* A class which generates a mesh from a heightmap. */ class TMesh { private: u16 Width; u16 Height; f32 Scale; public: SMesh* Mesh; TMesh() : Mesh(0), Width(0), Height(0), Scale(1.f) { Mesh = new SMesh(); } ~TMesh() { Mesh->drop(); } // Unless the heightmap is small, it won't all fit into a single // SMeshBuffer. This function chops it into pieces and generates a // buffer from each one. void init(const HeightMap &hm, f32 scale, colour_func cf, IVideoDriver *driver) { Scale = scale; const u32 mp = driver -> getMaximalPrimitiveCount(); Width = hm.width(); Height = hm.height(); const u32 sw = mp / (6 * Height); // the width of each piece u32 i=0; for(u32 y0 = 0; y0 < Height; y0 += sw) { u16 y1 = y0 + sw; if (y1 >= Height) y1 = Height - 1; // the last one might be narrower addstrip(hm, cf, y0, y1, i); ++i; } if (igetMeshBufferCount()) { // clear the rest for (u32 j=i; jgetMeshBufferCount(); ++j) { Mesh->getMeshBuffer(j)->drop(); } Mesh->MeshBuffers.erase(i,Mesh->getMeshBufferCount()-i); } // set dirty flag to make sure that hardware copies of this // buffer are also updated, see IMesh::setHardwareMappingHint Mesh->setDirty(); Mesh->recalculateBoundingBox(); } // Generate a SMeshBuffer which represents all the vertices and // indices for values of y between y0 and y1, and add it to the // mesh. void addstrip(const HeightMap &hm, colour_func cf, u16 y0, u16 y1, u32 bufNum) { SMeshBuffer *buf = 0; if (bufNumgetMeshBufferCount()) { buf = (SMeshBuffer*)Mesh->getMeshBuffer(bufNum); } else { // create new buffer buf = new SMeshBuffer(); Mesh->addMeshBuffer(buf); // to simplify things we drop here but continue using buf buf->drop(); } buf->Vertices.set_used((1 + y1 - y0) * Width); u32 i=0; for (u16 y = y0; y <= y1; ++y) { for (u16 x = 0; x < Width; ++x) { const f32 z = hm.get(x, y); const f32 xx = (f32)x/(f32)Width; const f32 yy = (f32)y/(f32)Height; S3DVertex& v = buf->Vertices[i++]; v.Pos.set(x, Scale * z, y); v.Normal.set(hm.getnormal(x, y, Scale)); v.Color=cf(xx, yy, z); v.TCoords.set(xx, yy); } } buf->Indices.set_used(6 * (Width - 1) * (y1 - y0)); i=0; for(u16 y = y0; y < y1; ++y) { for(u16 x = 0; x < Width - 1; ++x) { const u16 n = (y-y0) * Width + x; buf->Indices[i]=n; buf->Indices[++i]=n + Width; buf->Indices[++i]=n + Width + 1; buf->Indices[++i]=n + Width + 1; buf->Indices[++i]=n + 1; buf->Indices[++i]=n; ++i; } } buf->recalculateBoundingBox(); } }; /* Our event receiver implementation, taken from tutorial 4. */ class MyEventReceiver : public IEventReceiver { public: // This is the one method that we have to implement virtual bool OnEvent(const SEvent& event) { // Remember whether each key is down or up if (event.EventType == irr::EET_KEY_INPUT_EVENT) KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; return false; } // This is used to check whether a key is being held down virtual bool IsKeyDown(EKEY_CODE keyCode) const { return KeyIsDown[keyCode]; } MyEventReceiver() { for (u32 i=0; igetVideoDriver(); ISceneManager *smgr = device->getSceneManager(); device->setWindowCaption(L"Irrlicht Example for SMesh usage."); /* Create the custom mesh and initialize with a heightmap */ TMesh mesh; HeightMap hm = HeightMap(255, 255); hm.generate(eggbox); mesh.init(hm, 50.f, grey, driver); // Add the mesh to the scene graph IMeshSceneNode* meshnode = smgr -> addMeshSceneNode(mesh.Mesh); meshnode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false); // light is just for nice effects ILightSceneNode *node = smgr->addLightSceneNode(0, vector3df(0,100,0), SColorf(1.0f, 0.6f, 0.7f, 1.0f), 500.0f); if (node) { node->getLightData().Attenuation.set(0.f, 1.f/500.f, 0.f); ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(vector3df(0,150,0),250.0f); if (anim) { node->addAnimator(anim); anim->drop(); } } ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); if (camera) { camera->setPosition(vector3df(-20.f, 150.f, -20.f)); camera->setTarget(vector3df(200.f, -80.f, 150.f)); camera->setFarValue(20000.0f); } /* Just a usual render loop with event handling. The custom mesh is a usual part of the scene graph which gets rendered by drawAll. */ while(device->run()) { if(!device->isWindowActive()) { device->sleep(100); continue; } if(receiver.IsKeyDown(irr::KEY_KEY_W)) { meshnode->setMaterialFlag(video::EMF_WIREFRAME, !meshnode->getMaterial(0).Wireframe); } else if(receiver.IsKeyDown(irr::KEY_KEY_1)) { hm.generate(eggbox); mesh.init(hm, 50.f, grey, driver); } else if(receiver.IsKeyDown(irr::KEY_KEY_2)) { hm.generate(moresine); mesh.init(hm, 50.f, yellow, driver); } else if(receiver.IsKeyDown(irr::KEY_KEY_3)) { hm.generate(justexp); mesh.init(hm, 50.f, yellow, driver); } driver->beginScene(true, true, SColor(0xff000000)); smgr->drawAll(); driver->endScene(); } device->drop(); return 0; } /* That's it! Just compile and play around with the program. **/ irrlicht-1.8.3/examples/22.MaterialViewer/0000755000000000000000000000000012574354552017035 5ustar rootrootirrlicht-1.8.3/examples/22.MaterialViewer/MaterialViewer_vc9.vcproj0000644000000000000000000001231012574354552023760 0ustar rootroot irrlicht-1.8.3/examples/22.MaterialViewer/MaterialViewer_vc8.vcproj0000644000000000000000000001221012574354552023756 0ustar rootroot irrlicht-1.8.3/examples/22.MaterialViewer/MaterialViewer_vc12.vcxproj0000644000000000000000000003331212574354552024227 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 22.MaterialViewer {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA} MaterialViewer Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/MaterialViewer.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\22.MaterialViewer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) .\Release/MaterialViewer.pdb Console .\Release/MaterialViewer.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\22.MaterialViewer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) .\Release/MaterialViewer.pdb Console .\Debug/MaterialViewer.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\22.MaterialViewer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true .\Debug/MaterialViewer.pdb Console .\Debug/MaterialViewer.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\22.MaterialViewer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true .\Debug/MaterialViewer.pdb Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/22.MaterialViewer/MaterialViewer_vc11.vcxproj0000644000000000000000000003331112574354552024225 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 22.MaterialViewer {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA} MaterialViewer Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/MaterialViewer.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\22.MaterialViewer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) .\Release/MaterialViewer.pdb Console .\Release/MaterialViewer.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\22.MaterialViewer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) .\Release/MaterialViewer.pdb Console .\Debug/MaterialViewer.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\22.MaterialViewer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true .\Debug/MaterialViewer.pdb Console .\Debug/MaterialViewer.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\22.MaterialViewer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true .\Debug/MaterialViewer.pdb Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/22.MaterialViewer/MaterialViewer_vc10.vcxproj0000644000000000000000000003331112574354552024224 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 22.MaterialViewer {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA} MaterialViewer Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/MaterialViewer.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\22.MaterialViewer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) .\Release/MaterialViewer.pdb Console .\Release/MaterialViewer.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\22.MaterialViewer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) .\Release/MaterialViewer.pdb Console .\Debug/MaterialViewer.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\22.MaterialViewer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true .\Debug/MaterialViewer.pdb Console .\Debug/MaterialViewer.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\22.MaterialViewer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true .\Debug/MaterialViewer.pdb Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/22.MaterialViewer/MaterialViewer.vcproj0000644000000000000000000001223712574354552023207 0ustar rootroot irrlicht-1.8.3/examples/22.MaterialViewer/MaterialViewer.dev0000644000000000000000000000175312574354552022463 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 22 Material Viewer UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=22.MaterialViewer.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/22.MaterialViewer/MaterialViewer.cbp0000644000000000000000000000270412574354552022446 0ustar rootroot irrlicht-1.8.3/examples/22.MaterialViewer/Makefile0000644000000000000000000000221012574354552020470 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 22.MaterialViewer Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include #CXXFLAGS = -O3 -ffast-math CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/22.MaterialViewer/main.cpp0000644000000000000000000007542512574354552020502 0ustar rootroot/** Example 022 Material Viewer This example can be used to play around with material settings and watch the results. Only the default non-shader materials are used in here. You have two nodes to make it easier to see which difference your settings will make. Additionally you have one lightscenenode and you can set the global ambient values. */ #include #include "driverChoice.h" using namespace irr; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif /* Variables within the empty namespace are globals which are restricted to this file. */ namespace { const wchar_t* const DriverTypeNames[] = { L"NULL", L"SOFTWARE", L"BURNINGSVIDEO", L"DIRECT3D8", L"DIRECT3D9", L"OPENGL", 0, }; // For the gui id's enum EGUI_IDS { GUI_ID_OPEN_TEXTURE = 1, GUI_ID_QUIT, GUI_ID_MAX }; // Name used in texture selection to clear the textures on the node const core::stringw CLEAR_TEXTURE = L"CLEAR texture"; // some useful color constants const video::SColor SCOL_BLACK = video::SColor(255, 0, 0, 0); const video::SColor SCOL_BLUE = video::SColor(255, 0, 0, 255); const video::SColor SCOL_CYAN = video::SColor(255, 0, 255, 255); const video::SColor SCOL_GRAY = video::SColor(255, 128,128, 128); const video::SColor SCOL_GREEN = video::SColor(255, 0, 255, 0); const video::SColor SCOL_MAGENTA = video::SColor(255, 255, 0, 255); const video::SColor SCOL_RED = video::SColor(255, 255, 0, 0); const video::SColor SCOL_YELLOW = video::SColor(255, 255, 255, 0); const video::SColor SCOL_WHITE = video::SColor(255, 255, 255, 255); }; // namespace /* Returns a new unique number on each call. */ s32 makeUniqueId() { static int unique = GUI_ID_MAX; ++unique; return unique; } /* Find out which vertex-type is needed for the given material type. */ video::E_VERTEX_TYPE getVertexTypeForMaterialType(video::E_MATERIAL_TYPE materialType) { using namespace video; switch ( materialType ) { case EMT_SOLID: return EVT_STANDARD; case EMT_SOLID_2_LAYER: return EVT_STANDARD; case EMT_LIGHTMAP: case EMT_LIGHTMAP_ADD: case EMT_LIGHTMAP_M2: case EMT_LIGHTMAP_M4: case EMT_LIGHTMAP_LIGHTING: case EMT_LIGHTMAP_LIGHTING_M2: case EMT_LIGHTMAP_LIGHTING_M4: return EVT_2TCOORDS; case EMT_DETAIL_MAP: return EVT_2TCOORDS; case EMT_SPHERE_MAP: return EVT_STANDARD; case EMT_REFLECTION_2_LAYER: return EVT_2TCOORDS; case EMT_TRANSPARENT_ADD_COLOR: return EVT_STANDARD; case EMT_TRANSPARENT_ALPHA_CHANNEL: return EVT_STANDARD; case EMT_TRANSPARENT_ALPHA_CHANNEL_REF: return EVT_STANDARD; case EMT_TRANSPARENT_VERTEX_ALPHA: return EVT_STANDARD; case EMT_TRANSPARENT_REFLECTION_2_LAYER: return EVT_2TCOORDS; case EMT_NORMAL_MAP_SOLID: case EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR: case EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA: case EMT_PARALLAX_MAP_SOLID: case EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR: case EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA: return EVT_TANGENTS; case EMT_ONETEXTURE_BLEND: return EVT_STANDARD; case EMT_FORCE_32BIT: return EVT_STANDARD; } return EVT_STANDARD; } /* Custom GUI-control to edit colorvalues. */ class CColorControl : public gui::IGUIElement { public: // Constructor CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2d & pos, const wchar_t *text, IGUIElement* parent, s32 id=-1 ) : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect< s32 >(pos, pos+core::dimension2d(80, 75))) , DirtyFlag(true) , ColorStatic(0) , EditAlpha(0) , EditRed(0) , EditGreen(0) , EditBlue(0) { using namespace gui; ButtonSetId = makeUniqueId(); const core::rect< s32 > rectControls(0,0,AbsoluteRect.getWidth(),AbsoluteRect.getHeight() ); IGUIStaticText * groupElement = guiEnv->addStaticText (L"", rectControls, true, false, this, -1, false); groupElement->setNotClipped(true); guiEnv->addStaticText (text, core::rect(0,0,80,15), false, false, groupElement, -1, false); EditAlpha = addEditForNumbers(guiEnv, core::position2d(0,15), L"a", -1, groupElement ); EditRed = addEditForNumbers(guiEnv, core::position2d(0,30), L"r", -1, groupElement ); EditGreen = addEditForNumbers(guiEnv, core::position2d(0,45), L"g", -1, groupElement ); EditBlue = addEditForNumbers(guiEnv, core::position2d(0,60), L"b", -1, groupElement ); ColorStatic = guiEnv->addStaticText (L"", core::rect(60,15,80,75), true, false, groupElement, -1, true); guiEnv->addButton (core::rect(60,35,80,50), groupElement, ButtonSetId, L"set"); SetEditsFromColor(Color); } // event receiver virtual bool OnEvent(const SEvent &event) { if ( event.EventType != EET_GUI_EVENT ) return false; if ( event.GUIEvent.Caller->getID() == ButtonSetId && event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) { Color = GetColorFromEdits(); SetEditsFromColor(Color); } return false; } // set the color values void setColor(const video::SColor& col) { DirtyFlag = true; Color = col; SetEditsFromColor(Color); } // get the color values const video::SColor& getColor() const { return Color; } // To reset the dirty flag void resetDirty() { DirtyFlag = false; } // when the color was changed the dirty flag is set bool isDirty() const { return DirtyFlag; }; protected: // Add a staticbox for a description + an editbox so users can enter numbers gui::IGUIEditBox* addEditForNumbers(gui::IGUIEnvironment* guiEnv, const core::position2d & pos, const wchar_t *text, s32 id, gui::IGUIElement * parent) { using namespace gui; core::rect< s32 > rect(pos, pos+core::dimension2d(10, 15)); guiEnv->addStaticText (text, rect, false, false, parent, -1, false); rect += core::position2d( 20, 0 ); rect.LowerRightCorner.X += 20; gui::IGUIEditBox* edit = guiEnv->addEditBox(L"0", rect, true, parent, id); return edit; } // Get the color value from the editfields video::SColor GetColorFromEdits() { video::SColor col; if (EditAlpha) { u32 alpha = core::strtoul10(core::stringc(EditAlpha->getText()).c_str()); if (alpha > 255) alpha = 255; col.setAlpha(alpha); } if (EditRed) { u32 red = core::strtoul10(core::stringc(EditRed->getText()).c_str()); if (red > 255) red = 255; col.setRed(red); } if (EditGreen) { u32 green = core::strtoul10(core::stringc(EditGreen->getText()).c_str()); if (green > 255) green = 255; col.setGreen(green); } if (EditBlue) { u32 blue = core::strtoul10(core::stringc(EditBlue->getText()).c_str()); if (blue > 255) blue = 255; col.setBlue(blue); } return col; } // Fill the editfields with the value for the given color void SetEditsFromColor(video::SColor col) { DirtyFlag = true; if ( EditAlpha ) EditAlpha->setText( core::stringw(col.getAlpha()).c_str() ); if ( EditRed ) EditRed->setText( core::stringw(col.getRed()).c_str() ); if ( EditGreen ) EditGreen->setText( core::stringw(col.getGreen()).c_str() ); if ( EditBlue ) EditBlue->setText( core::stringw(col.getBlue()).c_str() ); if ( ColorStatic ) ColorStatic->setBackgroundColor(col); } private: bool DirtyFlag; video::SColor Color; s32 ButtonSetId; gui::IGUIStaticText * ColorStatic; gui::IGUIEditBox * EditAlpha; gui::IGUIEditBox * EditRed; gui::IGUIEditBox * EditGreen; gui::IGUIEditBox * EditBlue; }; /* Custom GUI-control for to edit all colors typically used in materials and lights */ class CAllColorsControl : public gui::IGUIElement { public: // Constructor CAllColorsControl(gui::IGUIEnvironment* guiEnv, const core::position2d & pos, const wchar_t * description, bool hasEmissive, IGUIElement* parent, s32 id=-1) : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect(pos,pos+core::dimension2d(60,250))) , ControlAmbientColor(0), ControlDiffuseColor(0), ControlSpecularColor(0), ControlEmissiveColor(0) { core::rect rect(0, 0, 60, 15); guiEnv->addStaticText (description, rect, false, false, this, -1, false); createColorControls(guiEnv, core::position2d(0, 15), hasEmissive); } // Destructor virtual ~CAllColorsControl() { ControlAmbientColor->drop(); ControlDiffuseColor->drop(); if ( ControlEmissiveColor ) ControlEmissiveColor->drop(); ControlSpecularColor->drop(); } // Set the color values to those within the material void setColorsToMaterialColors(const video::SMaterial & material) { ControlAmbientColor->setColor(material.AmbientColor); ControlDiffuseColor->setColor(material.DiffuseColor); ControlEmissiveColor->setColor(material.EmissiveColor); ControlSpecularColor->setColor(material.SpecularColor); } // Update all changed colors in the material void updateMaterialColors(video::SMaterial & material) { if ( ControlAmbientColor->isDirty() ) material.AmbientColor = ControlAmbientColor->getColor(); if ( ControlDiffuseColor->isDirty() ) material.DiffuseColor = ControlDiffuseColor->getColor(); if ( ControlEmissiveColor->isDirty() ) material.EmissiveColor = ControlEmissiveColor->getColor(); if ( ControlSpecularColor->isDirty() ) material.SpecularColor = ControlSpecularColor->getColor(); } // Set the color values to those from the light data void setColorsToLightDataColors(const video::SLight & lightData) { ControlAmbientColor->setColor(lightData.AmbientColor.toSColor()); ControlAmbientColor->setColor(lightData.DiffuseColor.toSColor()); ControlAmbientColor->setColor(lightData.SpecularColor.toSColor()); } // Update all changed colors in the light data void updateLightColors(video::SLight & lightData) { if ( ControlAmbientColor->isDirty() ) lightData.AmbientColor = video::SColorf( ControlAmbientColor->getColor() ); if ( ControlDiffuseColor->isDirty() ) lightData.DiffuseColor = video::SColorf( ControlDiffuseColor->getColor() ); if ( ControlSpecularColor->isDirty() ) lightData.SpecularColor = video::SColorf(ControlSpecularColor->getColor() ); } // To reset the dirty flags void resetDirty() { ControlAmbientColor->resetDirty(); ControlDiffuseColor->resetDirty(); ControlSpecularColor->resetDirty(); if ( ControlEmissiveColor ) ControlEmissiveColor->resetDirty(); } protected: void createColorControls(gui::IGUIEnvironment* guiEnv, const core::position2d & pos, bool hasEmissive) { ControlAmbientColor = new CColorControl( guiEnv, pos, L"ambient", this); ControlDiffuseColor = new CColorControl( guiEnv, pos + core::position2d(0, 75), L"diffuse", this ); ControlSpecularColor = new CColorControl( guiEnv, pos + core::position2d(0, 150), L"specular", this ); if ( hasEmissive ) { ControlEmissiveColor = new CColorControl( guiEnv, pos + core::position2d(0, 225), L"emissive", this ); } } private: CColorControl* ControlAmbientColor; CColorControl* ControlDiffuseColor; CColorControl* ControlSpecularColor; CColorControl* ControlEmissiveColor; }; /* GUI-Control to offer a selection of available textures. */ class CTextureControl : public gui::IGUIElement { public: CTextureControl(gui::IGUIEnvironment* guiEnv, video::IVideoDriver * driver, const core::position2d & pos, IGUIElement* parent, s32 id=-1) : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect(pos,pos+core::dimension2d(100,15))) , DirtyFlag(true), ComboTexture(0) { core::rect rectCombo(0, 0, AbsoluteRect.getWidth(),AbsoluteRect.getHeight()); ComboTexture = guiEnv->addComboBox (rectCombo, this); updateTextures(driver); } virtual bool OnEvent(const SEvent &event) { if ( event.EventType != EET_GUI_EVENT ) return false; if ( event.GUIEvent.Caller == ComboTexture && event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED ) { DirtyFlag = true; } return false; } // Workaround for a problem with comboboxes. // We have to get in front when the combobox wants to get in front or combobox-list might be drawn below other elements. virtual bool bringToFront(IGUIElement* element) { bool result = gui::IGUIElement::bringToFront(element); if ( Parent && element == ComboTexture ) result &= Parent->bringToFront(this); return result; } // return selected texturename (if any, otherwise 0) const wchar_t * getSelectedTextureName() const { s32 selected = ComboTexture->getSelected(); if ( selected < 0 ) return 0; return ComboTexture->getItem(selected); } // reset the dirty flag void resetDirty() { DirtyFlag = false; } // when the texture was changed the dirty flag is set bool isDirty() const { return DirtyFlag; }; // Put the names of all currently loaded textures in a combobox void updateTextures(video::IVideoDriver * driver) { s32 oldSelected = ComboTexture->getSelected(); s32 selectNew = -1; core::stringw oldTextureName; if ( oldSelected >= 0 ) { oldTextureName = ComboTexture->getItem(oldSelected); } ComboTexture->clear(); for ( u32 i=0; i < driver->getTextureCount(); ++i ) { video::ITexture * texture = driver->getTextureByIndex(i); core::stringw name( texture->getName() ); ComboTexture->addItem( name.c_str() ); if ( !oldTextureName.empty() && selectNew < 0 && name == oldTextureName ) selectNew = i; } // add another name which can be used to clear the texture ComboTexture->addItem( CLEAR_TEXTURE.c_str() ); if ( CLEAR_TEXTURE == oldTextureName ) selectNew = ComboTexture->getItemCount()-1; if ( selectNew >= 0 ) ComboTexture->setSelected(selectNew); DirtyFlag = true; } private: bool DirtyFlag; gui::IGUIComboBox * ComboTexture; }; /* Control which allows setting some of the material values for a meshscenenode */ struct SMeshNodeControl { // constructor SMeshNodeControl() : Initialized(false), Driver(0), MeshManipulator(0), SceneNode(0), SceneNode2T(0), SceneNodeTangents(0) , AllColorsControl(0), ButtonLighting(0), InfoLighting(0), ComboMaterial(0), TextureControl1(0), TextureControl2(0), ControlVertexColors(0) { } // Destructor virtual ~SMeshNodeControl() { if ( TextureControl1 ) TextureControl1->drop(); if ( TextureControl2 ) TextureControl2->drop(); if ( ControlVertexColors ) ControlVertexColors->drop(); if ( AllColorsControl ) AllColorsControl->drop(); } void init(scene::IMeshSceneNode* node, IrrlichtDevice * device, const core::position2d & pos, const wchar_t * description) { if ( Initialized || !node || !device) // initializing twice or with invalid data not allowed return; Driver = device->getVideoDriver (); gui::IGUIEnvironment* guiEnv = device->getGUIEnvironment(); scene::ISceneManager* smgr = device->getSceneManager(); MeshManipulator = smgr->getMeshManipulator(); SceneNode = node; scene::IMeshManipulator * meshManip = smgr->getMeshManipulator(); scene::IMesh * mesh2T = meshManip->createMeshWith2TCoords(node->getMesh()); SceneNode2T = smgr->addMeshSceneNode(mesh2T, 0, -1, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() ); mesh2T->drop(); scene::IMesh * meshTangents = meshManip->createMeshWithTangents(node->getMesh(), false, false, false); SceneNodeTangents = smgr->addMeshSceneNode(meshTangents, 0, -1 , SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() ); meshTangents->drop(); video::SMaterial & material = SceneNode->getMaterial(0); material.Lighting = true; AllColorsControl = new CAllColorsControl(guiEnv, pos, description, true, guiEnv->getRootGUIElement()); AllColorsControl->setColorsToMaterialColors(material); core::rect rectBtn(pos + core::position2d(0, 320), core::dimension2d(60, 15)); ButtonLighting = guiEnv->addButton (rectBtn, 0, -1, L"Lighting"); ButtonLighting->setIsPushButton(true); ButtonLighting->setPressed(material.Lighting); core::rect rectInfo( rectBtn.LowerRightCorner.X, rectBtn.UpperLeftCorner.Y, rectBtn.LowerRightCorner.X+40, rectBtn.UpperLeftCorner.Y+15 ); InfoLighting = guiEnv->addStaticText(L"", rectInfo, true, false ); InfoLighting->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER ); core::rect rectCombo(pos.X, rectBtn.LowerRightCorner.Y, pos.X+100, rectBtn.LowerRightCorner.Y+15); ComboMaterial = guiEnv->addComboBox (rectCombo); for ( int i=0; i <= (int)video::EMT_ONETEXTURE_BLEND; ++i ) { ComboMaterial->addItem( core::stringw(video::sBuiltInMaterialTypeNames[i]).c_str() ); } ComboMaterial->setSelected( (s32)material.MaterialType ); core::position2d posTex(rectCombo.UpperLeftCorner.X,rectCombo.LowerRightCorner.Y); TextureControl1 = new CTextureControl(guiEnv, Driver, posTex, guiEnv->getRootGUIElement()); posTex.Y += 15; TextureControl2 = new CTextureControl(guiEnv, Driver, posTex, guiEnv->getRootGUIElement()); core::position2d posVertexColors( posTex.X, posTex.Y + 15); ControlVertexColors = new CColorControl( guiEnv, posVertexColors, L"Vertex colors", guiEnv->getRootGUIElement()); video::S3DVertex * vertices = (video::S3DVertex *)node->getMesh()->getMeshBuffer(0)->getVertices(); if ( vertices ) { ControlVertexColors->setColor(vertices[0].Color); } Initialized = true; } void update() { if ( !Initialized ) return; video::SMaterial & material = SceneNode->getMaterial(0); video::SMaterial & material2T = SceneNode2T->getMaterial(0); video::SMaterial & materialTangents = SceneNodeTangents->getMaterial(0); s32 selectedMaterial = ComboMaterial->getSelected(); if ( selectedMaterial >= (s32)video::EMT_SOLID && selectedMaterial <= (s32)video::EMT_ONETEXTURE_BLEND) { video::E_VERTEX_TYPE vertexType = getVertexTypeForMaterialType((video::E_MATERIAL_TYPE)selectedMaterial); switch ( vertexType ) { case video::EVT_STANDARD: material.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial; SceneNode->setVisible(true); SceneNode2T->setVisible(false); SceneNodeTangents->setVisible(false); break; case video::EVT_2TCOORDS: material2T.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial; SceneNode->setVisible(false); SceneNode2T->setVisible(true); SceneNodeTangents->setVisible(false); break; case video::EVT_TANGENTS: materialTangents.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial; SceneNode->setVisible(false); SceneNode2T->setVisible(false); SceneNodeTangents->setVisible(true); break; } } updateMaterial(material); updateMaterial(material2T); updateMaterial(materialTangents); if ( ButtonLighting->isPressed() ) InfoLighting->setText(L"on"); else InfoLighting->setText(L"off"); AllColorsControl->resetDirty(); TextureControl1->resetDirty(); TextureControl2->resetDirty(); ControlVertexColors->resetDirty(); } void updateTextures() { TextureControl1->updateTextures(Driver); TextureControl2->updateTextures(Driver); } protected: void updateMaterial(video::SMaterial & material) { AllColorsControl->updateMaterialColors(material); material.Lighting = ButtonLighting->isPressed(); if ( TextureControl1->isDirty() ) { material.TextureLayer[0].Texture = Driver->getTexture( io::path(TextureControl1->getSelectedTextureName()) ); } if ( TextureControl2->isDirty() ) { material.TextureLayer[1].Texture = Driver->getTexture( io::path(TextureControl2->getSelectedTextureName()) ); } if ( ControlVertexColors->isDirty() ) { MeshManipulator->setVertexColors (SceneNode->getMesh(), ControlVertexColors->getColor()); MeshManipulator->setVertexColors (SceneNode2T->getMesh(), ControlVertexColors->getColor()); MeshManipulator->setVertexColors (SceneNodeTangents->getMesh(), ControlVertexColors->getColor()); } } bool Initialized; video::IVideoDriver * Driver; scene::IMeshManipulator* MeshManipulator; scene::IMeshSceneNode* SceneNode; scene::IMeshSceneNode* SceneNode2T; scene::IMeshSceneNode* SceneNodeTangents; CAllColorsControl* AllColorsControl; gui::IGUIButton * ButtonLighting; gui::IGUIStaticText* InfoLighting; gui::IGUIComboBox * ComboMaterial; CTextureControl* TextureControl1; CTextureControl* TextureControl2; CColorControl* ControlVertexColors; }; /* Control to allow setting the color values of a lightscenenode. */ struct SLightNodeControl { // constructor SLightNodeControl() : Initialized(false), SceneNode(0), AllColorsControl(0) { } virtual ~SLightNodeControl() { if ( AllColorsControl ) AllColorsControl->drop(); } void init(scene::ILightSceneNode* node, gui::IGUIEnvironment* guiEnv, const core::position2d & pos, const wchar_t * description) { if ( Initialized || !node || !guiEnv) // initializing twice or with invalid data not allowed return; SceneNode = node; AllColorsControl = new CAllColorsControl(guiEnv, pos, description, false, guiEnv->getRootGUIElement()); const video::SLight & lightData = SceneNode->getLightData(); AllColorsControl->setColorsToLightDataColors(lightData); Initialized = true; } void update() { if ( !Initialized ) return; video::SLight & lightData = SceneNode->getLightData(); AllColorsControl->updateLightColors(lightData); } protected: bool Initialized; scene::ILightSceneNode* SceneNode; CAllColorsControl* AllColorsControl; }; /* Application configuration */ struct SConfig { SConfig() : RenderInBackground(true) , DriverType(video::EDT_BURNINGSVIDEO) , ScreenSize(640, 480) { } bool RenderInBackground; video::E_DRIVER_TYPE DriverType; core::dimension2d ScreenSize; }; /* Main application class */ class CApp : public IEventReceiver { friend int main(int argc, char *argv[]); public: // constructor CApp() : IsRunning(false) , Device(0) , Camera(0) , GlobalAmbient(0) { } // destructor ~CApp() { } // stop running - will quit at end of mainloop void stopApp() { IsRunning = false; } // Event handler virtual bool OnEvent(const SEvent &event) { if (event.EventType == EET_GUI_EVENT) { gui::IGUIEnvironment* env = Device->getGUIEnvironment(); switch(event.GUIEvent.EventType) { case gui::EGET_MENU_ITEM_SELECTED: { gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)event.GUIEvent.Caller; s32 id = menu->getItemCommandId(menu->getSelectedItem()); switch(id) { case GUI_ID_OPEN_TEXTURE: // File -> Open Texture env->addFileOpenDialog(L"Please select a texture file to open"); break; case GUI_ID_QUIT: // File -> Quit stopApp(); break; } } break; case gui::EGET_FILE_SELECTED: { // load the model file, selected in the file open dialog gui::IGUIFileOpenDialog* dialog = (gui::IGUIFileOpenDialog*)event.GUIEvent.Caller; loadTexture(io::path(dialog->getFileName()).c_str()); } break; default: break; } } return false; } protected: // Application initialization // returns true when it was successful initialized, otherwise false. bool init(int argc, char *argv[]) { // ask user for driver Config.DriverType=driverChoiceConsole(); if (Config.DriverType==video::EDT_COUNT) return false; // create the device with the settings from our config Device = createDevice(Config.DriverType, Config.ScreenSize); if (!Device) return false; Device->setWindowCaption( DriverTypeNames[Config.DriverType] ); Device->setEventReceiver(this); scene::ISceneManager* smgr = Device->getSceneManager(); video::IVideoDriver * driver = Device->getVideoDriver (); gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment(); // set a nicer font gui::IGUISkin* skin = guiEnv->getSkin(); gui::IGUIFont* font = guiEnv->getFont("../../media/fonthaettenschweiler.bmp"); if (font) skin->setFont(font); // remove some alpha value because it makes those menus harder to read otherwise video::SColor col3dHighLight( skin->getColor(gui::EGDC_APP_WORKSPACE) ); col3dHighLight.setAlpha(255); video::SColor colHighLight( col3dHighLight ); skin->setColor(gui::EGDC_HIGH_LIGHT, colHighLight ); skin->setColor(gui::EGDC_3D_HIGH_LIGHT, col3dHighLight ); // Add some textures which are useful to test material settings createDefaultTextures(driver); // create a menu gui::IGUIContextMenu * menuBar = guiEnv->addMenu(); menuBar->addItem(L"File", -1, true, true); gui::IGUIContextMenu* subMenuFile = menuBar->getSubMenu(0); subMenuFile->addItem(L"Open texture ...", GUI_ID_OPEN_TEXTURE); subMenuFile->addSeparator(); subMenuFile->addItem(L"Quit", GUI_ID_QUIT); // a static camera Camera = smgr->addCameraSceneNode (0, core::vector3df(0, 0, 0), core::vector3df(0, 0, 100), -1); // add the nodes which are used to show the materials scene::IMeshSceneNode* nodeL = smgr->addCubeSceneNode (30.0f, 0, -1, core::vector3df(-35, 0, 100), core::vector3df(0, 0, 0), core::vector3df(1.0f, 1.0f, 1.0f)); NodeLeft.init( nodeL, Device, core::position2d(10,20), L"left node" ); scene::IMeshSceneNode* nodeR = smgr->addCubeSceneNode (30.0f, 0, -1, core::vector3df(35, 0, 100), core::vector3df(0, 0, 0), core::vector3df(1.0f, 1.0f, 1.0f)); NodeRight.init( nodeR, Device, core::position2d(530,20), L"right node" ); // add one light scene::ILightSceneNode* nodeLight = smgr->addLightSceneNode(0, core::vector3df(0, 0, 0), video::SColorf(1.0f, 1.0f, 1.0f), 100.0f); LightControl.init(nodeLight, guiEnv, core::position2d(270,20), L"light" ); // one large cube around everything. That's mainly to make the light more obvious. scene::IMeshSceneNode* backgroundCube = smgr->addCubeSceneNode (200.0f, 0, -1, core::vector3df(0, 0, 0), core::vector3df(45, 0, 0), core::vector3df(1.0f, 1.0f, 1.0f)); backgroundCube->getMaterial(0).BackfaceCulling = false; // we are within the cube, so we have to disable backface culling to see it backgroundCube->getMaterial(0).EmissiveColor.set(255,50,50,50); // we keep some self lighting to keep texts visible // set the ambient light value GlobalAmbient = new CColorControl( guiEnv, core::position2d(270, 300), L"global ambient", guiEnv->getRootGUIElement()); GlobalAmbient->setColor( smgr->getAmbientLight().toSColor() ); return true; } // Update one frame bool update() { using namespace irr; video::IVideoDriver* videoDriver = Device->getVideoDriver(); if ( !Device->run() ) return false; if ( Device->isWindowActive() || Config.RenderInBackground ) { gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment(); scene::ISceneManager* smgr = Device->getSceneManager(); gui::IGUISkin * skin = guiEnv->getSkin(); // update our controls NodeLeft.update(); NodeRight.update(); LightControl.update(); // update ambient light settings if ( GlobalAmbient->isDirty() ) { smgr->setAmbientLight( GlobalAmbient->getColor() ); GlobalAmbient->resetDirty(); } // draw everything video::SColor bkColor( skin->getColor(gui::EGDC_APP_WORKSPACE) ); videoDriver->beginScene(true, true, bkColor); smgr->drawAll(); guiEnv->drawAll(); videoDriver->endScene(); } return true; } // Run the application. Our main loop. void run() { IsRunning = true; if ( !Device ) return; // main application loop while(IsRunning) { if ( !update() ) break; Device->sleep( 5 ); } } // Close down the application void quit() { IsRunning = false; GlobalAmbient->drop(); GlobalAmbient = NULL; if ( Device ) { Device->closeDevice(); Device->drop(); Device = NULL; } } // Create some useful textures. // Note that the function put readability over speed, you shouldn't use setPixel at runtime but for initialization it's nice. void createDefaultTextures(video::IVideoDriver * driver) { const u32 width = 256; const u32 height = 256; video::IImage * imageA8R8G8B8 = driver->createImage (video::ECF_A8R8G8B8, core::dimension2d(width, height)); if ( !imageA8R8G8B8 ) return; const u32 pitch = imageA8R8G8B8->getPitch(); // some nice square-pattern with 9 typical colors for ( u32 y = 0; y < height; ++ y ) { for ( u32 x = 0; x < pitch; ++x ) { if ( y < height/3 ) { if ( x < width/3 ) imageA8R8G8B8->setPixel (x, y, SCOL_BLACK); else if ( x < 2*width/3 ) imageA8R8G8B8->setPixel (x, y, SCOL_BLUE); else imageA8R8G8B8->setPixel (x, y, SCOL_CYAN); } else if ( y < 2*height/3 ) { if ( x < width/3 ) imageA8R8G8B8->setPixel (x, y, SCOL_GRAY); else if ( x < 2*width/3 ) imageA8R8G8B8->setPixel (x, y, SCOL_GREEN); else imageA8R8G8B8->setPixel (x, y, SCOL_MAGENTA); } else { if ( x < width/3 ) imageA8R8G8B8->setPixel (x, y, SCOL_RED); else if ( x < 2*width/3 ) imageA8R8G8B8->setPixel (x, y, SCOL_YELLOW); else imageA8R8G8B8->setPixel (x, y, SCOL_WHITE); } } } driver->addTexture (io::path("CARO_A8R8G8B8"), imageA8R8G8B8); // all white imageA8R8G8B8->fill(SCOL_WHITE); driver->addTexture (io::path("WHITE_A8R8G8B8"), imageA8R8G8B8); // all black imageA8R8G8B8->fill(SCOL_BLACK); driver->addTexture (io::path("BLACK_A8R8G8B8"), imageA8R8G8B8); // gray-scale for ( u32 y = 0; y < height; ++ y ) { for ( u32 x = 0; x < pitch; ++x ) { imageA8R8G8B8->setPixel (x, y, video::SColor(y, x,x,x) ); } } driver->addTexture (io::path("GRAYSCALE_A8R8G8B8"), imageA8R8G8B8); imageA8R8G8B8->drop(); } // Load a texture and make sure nodes know it when more textures are available. void loadTexture(const io::path &name) { Device->getVideoDriver()->getTexture(name); NodeLeft.updateTextures(); NodeRight.updateTextures(); } private: SConfig Config; volatile bool IsRunning; IrrlichtDevice * Device; scene::ICameraSceneNode * Camera; SMeshNodeControl NodeLeft; SMeshNodeControl NodeRight; SLightNodeControl LightControl; CColorControl * GlobalAmbient; }; /* A very short main as we do everything else in classes. */ int main(int argc, char *argv[]) { CApp APP; if ( !APP.init(argc, argv) ) { printf("init failed\n"); return 1; } APP.run(); APP.quit(); return 0; } /* **/ irrlicht-1.8.3/examples/21.Quake3Explorer/0000755000000000000000000000000012574354552016766 5ustar rootrootirrlicht-1.8.3/examples/21.Quake3Explorer/sound.h0000644000000000000000000000052612574354552020272 0ustar rootroot/*! Sound Factory. provides a sound interface */ #ifndef __QUAKE3_SOUND__H_INCLUDED__ #define __QUAKE3_SOUND__H_INCLUDED__ #include using namespace irr; void sound_init ( IrrlichtDevice *device ); void sound_shutdown (); void background_music ( const c8 * file ); #endif // __QUAKE3_SOUND__H_INCLUDED__ irrlicht-1.8.3/examples/21.Quake3Explorer/sound.cpp0000644000000000000000000000371412574354552020627 0ustar rootroot/*! Sound Factory. provides a sound interface */ #include "sound.h" //#define USE_IRRKLANG #ifdef USE_IRRKLANG #include #ifdef _IRR_WINDOWS_ #pragma comment (lib, "irrKlang.lib") #endif using namespace irrklang; struct soundfile: public IFileReader { soundfile ( io::IReadFile* f ): file (f ) {} virtual ~soundfile () { file->drop (); } virtual ik_s32 read(void* buffer, ik_u32 sizeToRead) { return file->read ( buffer, sizeToRead ); } virtual bool seek(ik_s32 finalPos, bool relativeMovement = false) { return file->seek ( finalPos, relativeMovement ); } virtual ik_s32 getSize(){ return file->getSize (); } virtual ik_s32 getPos() {return file->getPos (); } virtual const ik_c8* getFileName() { return file->getFileName (); } io::IReadFile* file; }; struct klangFactory : public irrklang::IFileFactory { klangFactory ( IrrlichtDevice *device ) { Device = device; } virtual irrklang::IFileReader* createFileReader(const ik_c8* filename) { io::IReadFile* file = Device->getFileSystem()->createAndOpenFile(filename); if ( 0 == file ) return 0; return new soundfile ( file ); } IrrlichtDevice *Device; }; ISoundEngine *engine = 0; ISound *backMusic = 0; void sound_init ( IrrlichtDevice *device ) { engine = createIrrKlangDevice (); if ( 0 == engine ) return; klangFactory *f = new klangFactory ( device ); engine->addFileFactory ( f ); } void sound_shutdown () { if ( backMusic ) backMusic->drop (); if ( engine ) engine->drop (); } void background_music ( const c8 * file ) { if ( 0 == engine ) return; if ( backMusic ) { backMusic->stop (); backMusic->drop (); } backMusic = engine->play2D ( file, true, false, true ); if ( backMusic ) { backMusic->setVolume ( 0.5f ); } } #else void sound_init ( IrrlichtDevice *device ) {} void sound_shutdown () {} void background_music ( const c8 * file ) {} #endif irrlicht-1.8.3/examples/21.Quake3Explorer/Quake3Explorer_vc9.vcproj0000644000000000000000000001032412574354552023646 0ustar rootroot irrlicht-1.8.3/examples/21.Quake3Explorer/Quake3Explorer_vc8.vcproj0000644000000000000000000001051012574354552023642 0ustar rootroot irrlicht-1.8.3/examples/21.Quake3Explorer/Quake3Explorer_vc12.vcxproj0000644000000000000000000002643512574354552024122 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 21.Quake3Explorer {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD} 21.Quake3Explorer Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\21.Quake3Explorer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)Quake3MapShader.pdb Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\21.Quake3Explorer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)Quake3MapShader.pdb Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 FastCall ..\..\bin\Win32-VisualStudio\21.Quake3Explorer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 FastCall ..\..\bin\Win64-VisualStudio\21.Quake3Explorer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/21.Quake3Explorer/Quake3Explorer_vc11.vcxproj0000644000000000000000000002643412574354552024120 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 21.Quake3Explorer {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD} 21.Quake3Explorer Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\21.Quake3Explorer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)Quake3MapShader.pdb Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\21.Quake3Explorer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)Quake3MapShader.pdb Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 FastCall ..\..\bin\Win32-VisualStudio\21.Quake3Explorer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 FastCall ..\..\bin\Win64-VisualStudio\21.Quake3Explorer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/21.Quake3Explorer/Quake3Explorer_vc10.vcxproj0000644000000000000000000002643412574354552024117 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 21.Quake3Explorer {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD} 21.Quake3Explorer Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\21.Quake3Explorer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)Quake3MapShader.pdb Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\21.Quake3Explorer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)Quake3MapShader.pdb Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 FastCall ..\..\bin\Win32-VisualStudio\21.Quake3Explorer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 FastCall ..\..\bin\Win64-VisualStudio\21.Quake3Explorer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/21.Quake3Explorer/Quake3Explorer.vcproj0000644000000000000000000000672512574354552023077 0ustar rootroot irrlicht-1.8.3/examples/21.Quake3Explorer/Quake3Explorer.dev0000644000000000000000000000313612574354552022343 0ustar rootroot[Project] FileName=Quake3Explorer.dev Name=Irrlicht Example 21 Quake3 Explorer UnitCount=5 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=21.Quake3Explorer.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 [Unit2] FileName=q3factory.cpp CompileCpp=1 Folder=Irrlicht Example 21 Quake3 Explorer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit3] FileName=q3factory.h CompileCpp=1 Folder=Irrlicht Example 21 Quake3 Explorer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit4] FileName=sound.cpp CompileCpp=1 Folder=Irrlicht Example 21 Quake3 Explorer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [Unit5] FileName=sound.h CompileCpp=1 Folder=Irrlicht Example 21 Quake3 Explorer Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= irrlicht-1.8.3/examples/21.Quake3Explorer/Quake3Explorer.cbp0000644000000000000000000000307412574354552022332 0ustar rootroot irrlicht-1.8.3/examples/21.Quake3Explorer/q3factory.h0000644000000000000000000000571512574354552021062 0ustar rootroot/*! Model Factory. create the additional scenenodes for ( bullets, health... ) Defines the Entities for Quake3 */ #ifndef __QUAKE3_FACTORY__H_INCLUDED__ #define __QUAKE3_FACTORY__H_INCLUDED__ using namespace irr; using namespace scene; using namespace gui; using namespace video; using namespace core; using namespace quake3; using namespace io; //! Defines to which group the entities belong enum eItemGroup { WEAPON, AMMO, ARMOR, HEALTH, POWERUP }; //! define a supgroup for the item. for e.q the Weapons enum eItemSubGroup { SUB_NONE = 0, GAUNTLET, MACHINEGUN, SHOTGUN, GRENADE_LAUNCHER, ROCKET_LAUNCHER, LIGHTNING, RAILGUN, PLASMAGUN, BFG, GRAPPLING_HOOK, NAILGUN, PROX_LAUNCHER, CHAINGUN, }; //! aplly a special effect to the shader enum eItemSpecialEffect { SPECIAL_SFX_NONE = 0, SPECIAL_SFX_ROTATE = 1, SPECIAL_SFX_BOUNCE = 2, SPECIAL_SFX_ROTATE_1 = 4, }; // a List for defining a model struct SItemElement { const c8 *key; const c8 *model[2]; const c8 *sound; const c8 *icon; const c8 *pickup; s32 value; eItemGroup group; eItemSubGroup sub; u32 special; }; //! Get's an entity based on it's key const SItemElement * getItemElement ( const stringc& key ); /*! Quake3 Model Factory. Takes the mesh buffers and creates scenenodes for their associated shaders */ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, IrrlichtDevice *device, IQ3LevelMesh* mesh, eQ3MeshIndex meshIndex, ISceneNode *parent, IMetaTriangleSelector *meta, bool showShaderName ); /*! Creates Model based on the entity list */ void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, IrrlichtDevice *device, IQ3LevelMesh* masterMesh, ISceneNode *parent, bool showShaderName ); /*! so we need a good starting Position in the level. we can ask the Quake3 Loader for all entities with class_name "info_player_deathmatch" */ s32 Q3StartPosition ( IQ3LevelMesh* mesh, ICameraSceneNode* camera, s32 startposIndex, const vector3df &translation ); /*! gets a accumulated force on a given surface */ vector3df getGravity ( const c8 * surface ); /* Dynamically load the Irrlicht Library */ funcptr_createDevice load_createDevice ( const c8 * filename); funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename); //! Macro for save Dropping an Element #define dropElement(x) if (x) { x->remove(); x = 0; } /* get the current collision respone camera animator */ ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * device ); //! internal Animation enum eTimeFireFlag { FIRED = 1, }; struct TimeFire { u32 flags; u32 next; u32 delta; }; void setTimeFire ( TimeFire *t, u32 delta, u32 flags = 0 ); void checkTimeFire ( TimeFire *t, u32 listSize, u32 now ); #endif // __QUAKE3_FACTORY__H_INCLUDED__ irrlicht-1.8.3/examples/21.Quake3Explorer/q3factory.cpp0000644000000000000000000004342012574354552021410 0ustar rootroot/*! Model Factory. create the additional scenenodes for ( bullets, health... ) Defines the Entities for Quake3 */ #include #include "q3factory.h" #include "sound.h" using namespace irr; using namespace scene; using namespace gui; using namespace video; using namespace core; using namespace quake3; //! This list is based on the original quake3. static const SItemElement Quake3ItemElement [] = { { "item_health", {"models/powerups/health/medium_cross.md3", "models/powerups/health/medium_sphere.md3"}, "sound/items/n_health.wav", "icons/iconh_yellow", "25 Health", 25, HEALTH, SUB_NONE, SPECIAL_SFX_BOUNCE | SPECIAL_SFX_ROTATE_1 }, { "item_health_large", "models/powerups/health/large_cross.md3", "models/powerups/health/large_sphere.md3", "sound/items/l_health.wav", "icons/iconh_red", "50 Health", 50, HEALTH, SUB_NONE, SPECIAL_SFX_BOUNCE | SPECIAL_SFX_ROTATE_1 }, { "item_health_mega", "models/powerups/health/mega_cross.md3", "models/powerups/health/mega_sphere.md3", "sound/items/m_health.wav", "icons/iconh_mega", "Mega Health", 100, HEALTH, SUB_NONE, SPECIAL_SFX_BOUNCE | SPECIAL_SFX_ROTATE_1 }, { "item_health_small", "models/powerups/health/small_cross.md3", "models/powerups/health/small_sphere.md3", "sound/items/s_health.wav", "icons/iconh_green", "5 Health", 5, HEALTH, SUB_NONE, SPECIAL_SFX_BOUNCE | SPECIAL_SFX_ROTATE_1 }, { "ammo_bullets", "models/powerups/ammo/machinegunam.md3", "", "sound/misc/am_pkup.wav", "icons/icona_machinegun", "Bullets", 50, AMMO, MACHINEGUN, SPECIAL_SFX_BOUNCE, }, { "ammo_cells", "models/powerups/ammo/plasmaam.md3", "", "sound/misc/am_pkup.wav", "icons/icona_plasma", "Cells", 30, AMMO, PLASMAGUN, SPECIAL_SFX_BOUNCE }, { "ammo_rockets", "models/powerups/ammo/rocketam.md3", "", "", "icons/icona_rocket", "Rockets", 5, AMMO, ROCKET_LAUNCHER, SPECIAL_SFX_ROTATE }, { "ammo_shells", "models/powerups/ammo/shotgunam.md3", "", "sound/misc/am_pkup.wav", "icons/icona_shotgun", "Shells", 10, AMMO, SHOTGUN, SPECIAL_SFX_ROTATE }, { "ammo_slugs", "models/powerups/ammo/railgunam.md3", "", "sound/misc/am_pkup.wav", "icons/icona_railgun", "Slugs", 10, AMMO, RAILGUN, SPECIAL_SFX_ROTATE }, { "item_armor_body", "models/powerups/armor/armor_red.md3", "", "sound/misc/ar2_pkup.wav", "icons/iconr_red", "Heavy Armor", 100, ARMOR, SUB_NONE, SPECIAL_SFX_ROTATE }, { "item_armor_combat", "models/powerups/armor/armor_yel.md3", "", "sound/misc/ar2_pkup.wav", "icons/iconr_yellow", "Armor", 50, ARMOR, SUB_NONE, SPECIAL_SFX_ROTATE }, { "item_armor_shard", "models/powerups/armor/shard.md3", "", "sound/misc/ar1_pkup.wav", "icons/iconr_shard", "Armor Shared", 5, ARMOR, SUB_NONE, SPECIAL_SFX_ROTATE }, { "weapon_gauntlet", "models/weapons2/gauntlet/gauntlet.md3", "", "sound/misc/w_pkup.wav", "icons/iconw_gauntlet", "Gauntlet", 0, WEAPON, GAUNTLET, SPECIAL_SFX_ROTATE }, { "weapon_shotgun", "models/weapons2/shotgun/shotgun.md3", "", "sound/misc/w_pkup.wav", "icons/iconw_shotgun", "Shotgun", 10, WEAPON, SHOTGUN, SPECIAL_SFX_ROTATE }, { "weapon_machinegun", "models/weapons2/machinegun/machinegun.md3", "", "sound/misc/w_pkup.wav", "icons/iconw_machinegun", "Machinegun", 40, WEAPON, MACHINEGUN, SPECIAL_SFX_ROTATE }, { "weapon_grenadelauncher", "models/weapons2/grenadel/grenadel.md3", "", "sound/misc/w_pkup.wav", "icons/iconw_grenade", "Grenade Launcher", 10, WEAPON, GRENADE_LAUNCHER, SPECIAL_SFX_ROTATE }, { "weapon_rocketlauncher", "models/weapons2/rocketl/rocketl.md3", "", "sound/misc/w_pkup.wav", "icons/iconw_rocket", "Rocket Launcher", 10, WEAPON, ROCKET_LAUNCHER, SPECIAL_SFX_ROTATE }, { "weapon_lightning", "models/weapons2/lightning/lightning.md3", "", "sound/misc/w_pkup.wav", "icons/iconw_lightning", "Lightning Gun", 100, WEAPON, LIGHTNING, SPECIAL_SFX_ROTATE }, { "weapon_railgun", "models/weapons2/railgun/railgun.md3", "", "sound/misc/w_pkup.wav", "icons/iconw_railgun", "Railgun", 10, WEAPON, RAILGUN, SPECIAL_SFX_ROTATE }, { "weapon_plasmagun", "models/weapons2/plasma/plasma.md3", "", "sound/misc/w_pkup.wav", "icons/iconw_plasma", "Plasma Gun", 50, WEAPON, PLASMAGUN, SPECIAL_SFX_ROTATE }, { "weapon_bfg", "models/weapons2/bfg/bfg.md3", "", "sound/misc/w_pkup.wav", "icons/iconw_bfg", "BFG10K", 20, WEAPON, BFG, SPECIAL_SFX_ROTATE }, { "weapon_grapplinghook", "models/weapons2/grapple/grapple.md3", "", "sound/misc/w_pkup.wav", "icons/iconw_grapple", "Grappling Hook", 0, WEAPON, GRAPPLING_HOOK, SPECIAL_SFX_ROTATE }, { 0 } }; /*! */ const SItemElement * getItemElement ( const stringc& key ) { const SItemElement *item = Quake3ItemElement; while ( item->key ) { if ( 0 == strcmp ( key.c_str(), item->key ) ) return item; item += 1; } return 0; } /*! Quake3 Model Factory. Takes the mesh buffers and creates scenenodes for their associated shaders */ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, IrrlichtDevice *device, IQ3LevelMesh* mesh, eQ3MeshIndex meshIndex, ISceneNode *parent, IMetaTriangleSelector *meta, bool showShaderName ) { if ( 0 == mesh || 0 == device ) return; IMeshSceneNode* node = 0; ISceneManager* smgr = device->getSceneManager(); ITriangleSelector * selector = 0; // the additional mesh can be quite huge and is unoptimized // Save to cast to SMesh SMesh * additional_mesh = (SMesh*) mesh->getMesh ( meshIndex ); if ( 0 == additional_mesh || additional_mesh->getMeshBufferCount() == 0) return; char buf[128]; if ( loadParam.verbose > 0 ) { loadParam.startTime = device->getTimer()->getRealTime(); if ( loadParam.verbose > 1 ) { snprintf(buf, 128, "q3shaderfactory start" ); device->getLogger()->log( buf, ELL_INFORMATION); } } IGUIFont *font = 0; if ( showShaderName ) font = device->getGUIEnvironment()->getFont("fontlucida.png"); IVideoDriver *driver = device->getVideoDriver(); // create helper textures if ( 1 ) { tTexArray tex; u32 pos = 0; getTextures ( tex, "$redimage $blueimage $whiteimage $checkerimage", pos, device->getFileSystem(), driver ); } s32 sceneNodeID = 0; for ( u32 i = 0; i!= additional_mesh->getMeshBufferCount (); ++i ) { IMeshBuffer *meshBuffer = additional_mesh->getMeshBuffer ( i ); const SMaterial &material = meshBuffer->getMaterial(); //! The ShaderIndex is stored in the second material parameter s32 shaderIndex = (s32) material.MaterialTypeParam2; // the meshbuffer can be rendered without additional support, or it has no shader IShader *shader = (IShader *) mesh->getShader ( shaderIndex ); // no shader, or mapped to existing material if ( 0 == shader ) { #if 1 // clone mesh SMesh * m = new SMesh (); m->addMeshBuffer ( meshBuffer ); SMaterial &mat = m->getMeshBuffer( 0 )->getMaterial(); if ( mat.getTexture( 0 ) == 0 ) mat.setTexture ( 0, driver->getTexture ( "$blueimage" ) ); if ( mat.getTexture( 1 ) == 0 ) mat.setTexture ( 1, driver->getTexture ( "$redimage" ) ); IMesh * store = smgr->getMeshManipulator ()->createMeshWith2TCoords ( m ); m->drop(); node = smgr->addMeshSceneNode ( store, parent, sceneNodeID ); node->setAutomaticCulling ( scene::EAC_OFF ); store->drop (); sceneNodeID += 1; #endif } else if ( 1 ) { /* stringc s; dumpShader ( s, shader ); printf ( s.c_str () ); */ // create sceneNode node = smgr->addQuake3SceneNode ( meshBuffer, shader, parent, sceneNodeID ); node->setAutomaticCulling ( scene::EAC_FRUSTUM_BOX ); sceneNodeID += 1; } // show Debug Shader Name if ( showShaderName && node ) { swprintf ( (wchar_t*) buf, 64, L"%hs:%d", node->getName(),node->getID() ); smgr->addBillboardTextSceneNode( font, (wchar_t*) buf, node, dimension2d(80.0f, 8.0f), vector3df(0, 10, 0), sceneNodeID); sceneNodeID += 1; } // create Portal Rendertargets if ( shader ) { const SVarGroup *group = shader->getGroup(1); if ( group->isDefined( "surfaceparm", "portal" ) ) { } } // add collision // find out if shader is marked as nonsolid u8 doCreate = meta !=0 ; if ( shader ) { const SVarGroup *group = shader->getGroup(1); if ( group->isDefined( "surfaceparm", "trans" ) // || group->isDefined( "surfaceparm", "sky" ) // || group->isDefined( "surfaceparm", "nonsolid" ) ) { if ( !group->isDefined( "surfaceparm", "metalsteps" ) ) { doCreate = 0; } } } if ( doCreate ) { IMesh *m = 0; //! controls if triangles are modified by the scenenode during runtime bool takeOriginal = true; if ( takeOriginal ) { m = new SMesh (); ((SMesh*) m )->addMeshBuffer (meshBuffer); } else { m = node->getMesh(); } //selector = smgr->createOctreeTriangleSelector ( m, 0, 128 ); selector = smgr->createTriangleSelector ( m, 0 ); meta->addTriangleSelector ( selector ); selector->drop (); if ( takeOriginal ) { delete m; } } } #if 0 if ( meta ) { selector = smgr->createOctreeTriangleSelector ( additional_mesh, 0 ); meta->addTriangleSelector ( selector ); selector->drop (); } #endif if ( loadParam.verbose > 0 ) { loadParam.endTime = device->getTimer()->getRealTime (); snprintf(buf, 128, "q3shaderfactory needed %04d ms to create %d shader nodes", loadParam.endTime - loadParam.startTime, sceneNodeID ); device->getLogger()->log(buf, ELL_INFORMATION); } } /*! create Items from Entity */ void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, IrrlichtDevice *device, IQ3LevelMesh* masterMesh, ISceneNode *parent, bool showShaderName ) { if ( 0 == masterMesh ) return; tQ3EntityList &entity = masterMesh->getEntityList (); ISceneManager* smgr = device->getSceneManager(); char buf[128]; const SVarGroup *group; IEntity search; s32 index; s32 lastIndex; /* stringc s; FILE *f = 0; f = fopen ( "entity.txt", "wb" ); for ( index = 0; (u32) index < entityList.size (); ++index ) { const IEntity *entity = &entityList[ index ]; s = entity->name; dumpShader ( s, entity ); fwrite ( s.c_str(), 1, s.size(), f ); } fclose ( f ); */ IAnimatedMeshMD3* model; SMD3Mesh * mesh; const SMD3MeshBuffer *meshBuffer; IMeshSceneNode* node; ISceneNodeAnimator* anim; const IShader *shader; u32 pos; vector3df p; u32 nodeCount = 0; tTexArray textureArray; IGUIFont *font = 0; if ( showShaderName ) font = device->getGUIEnvironment()->getFont("fontlucida.png"); const SItemElement *itemElement; // walk list for ( index = 0; (u32) index < entity.size(); ++index ) { itemElement = getItemElement ( entity[index].name ); if ( 0 == itemElement ) continue; pos = 0; p = getAsVector3df ( entity[index].getGroup(1)->get ( "origin" ), pos ); nodeCount += 1; for ( u32 g = 0; g < 2; ++g ) { if ( 0 == itemElement->model[g] || itemElement->model[g][0] == 0 ) continue; model = (IAnimatedMeshMD3*) smgr->getMesh( itemElement->model[g] ); if ( 0 == model ) continue; mesh = model->getOriginalMesh(); for ( u32 j = 0; j != mesh->Buffer.size (); ++j ) { meshBuffer = mesh->Buffer[j]; if ( 0 == meshBuffer ) continue; shader = masterMesh->getShader ( meshBuffer->Shader.c_str(), false ); IMeshBuffer *final = model->getMesh(0)->getMeshBuffer(j); if ( shader ) { //!TODO: Hack don't modify the vertexbuffer. make it better;-) final->getMaterial().ColorMask = 0; node = smgr->addQuake3SceneNode ( final, shader, parent ); final->getMaterial().ColorMask = 15; } else { // clone mesh SMesh * m = new SMesh (); m->addMeshBuffer ( final ); node = smgr->addMeshSceneNode ( m, parent ); m->drop(); } if ( 0 == node ) { snprintf ( buf, 128, "q3ModelFactory shader %s failed", meshBuffer->Shader.c_str() ); device->getLogger()->log ( buf ); continue; } // node was maybe centered by shaderscenenode node->setPosition ( p ); node->setName ( meshBuffer->Shader ); node->setAutomaticCulling ( scene::EAC_BOX ); // add special effects to node if ( itemElement->special & SPECIAL_SFX_ROTATE || (g == 0 && itemElement->special & SPECIAL_SFX_ROTATE_1) ) { anim = smgr->createRotationAnimator ( vector3df ( 0.f, 2.f, 0.f ) ); node->addAnimator ( anim ); anim->drop (); } if ( itemElement->special & SPECIAL_SFX_BOUNCE ) { //anim = smgr->createFlyStraightAnimator ( // p, p + vector3df ( 0.f, 60.f, 0.f ), 1000, true, true ); anim = smgr->createFlyCircleAnimator ( p + vector3df( 0.f, 20.f, 0.f ), 20.f, 0.005f, vector3df ( 1.f, 0.f, 0.f ), core::fract ( nodeCount * 0.05f ), 1.f ); node->addAnimator ( anim ); anim->drop (); } } } // show name if ( showShaderName ) { swprintf ( (wchar_t*) buf, sizeof(buf) / 2, L"%hs", itemElement->key ); smgr->addBillboardTextSceneNode( font, (wchar_t*) buf, parent, dimension2d(80.0f, 8.0f), p + vector3df(0, 30, 0), 0); } } // music search.name = "worldspawn"; index = entity.binary_search_multi ( search, lastIndex ); if ( index >= 0 ) { group = entity[ index ].getGroup(1); background_music ( group->get ( "music" ).c_str () ); } // music search.name = "worldspawn"; index = entity.binary_search_multi ( search, lastIndex ); if ( index >= 0 ) { group = entity[ index ].getGroup(1); background_music ( group->get ( "music" ).c_str () ); } //IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2"); //IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); } /*! so we need a good starting Position in the level. we can ask the Quake3 Loader for all entities with class_name "info_player_deathmatch" */ s32 Q3StartPosition ( IQ3LevelMesh* mesh, ICameraSceneNode* camera, s32 startposIndex, const vector3df &translation ) { if ( 0 == mesh ) return 0; tQ3EntityList &entityList = mesh->getEntityList (); IEntity search; search.name = "info_player_start"; // "info_player_deathmatch"; // find all entities in the multi-list s32 lastIndex; s32 index = entityList.binary_search_multi ( search, lastIndex ); if ( index < 0 ) { search.name = "info_player_deathmatch"; index = entityList.binary_search_multi ( search, lastIndex ); } if ( index < 0 ) return 0; index += core::clamp ( startposIndex, 0, lastIndex - index ); u32 parsepos; const SVarGroup *group; group = entityList[ index ].getGroup(1); parsepos = 0; vector3df pos = getAsVector3df ( group->get ( "origin" ), parsepos ); pos += translation; parsepos = 0; f32 angle = getAsFloat ( group->get ( "angle"), parsepos ); vector3df target ( 0.f, 0.f, 1.f ); target.rotateXZBy ( angle - 90.f, vector3df () ); if ( camera ) { camera->setPosition ( pos ); camera->setTarget ( pos + target ); //! New. FPSCamera and animators catches reset on animate 0 camera->OnAnimate ( 0 ); } return lastIndex - index + 1; } /*! gets a accumulated force on a given surface */ vector3df getGravity ( const c8 * surface ) { if ( 0 == strcmp ( surface, "earth" ) ) return vector3df ( 0.f, -90.f, 0.f ); if ( 0 == strcmp ( surface, "moon" ) ) return vector3df ( 0.f, -6.f / 100.f, 0.f ); if ( 0 == strcmp ( surface, "water" ) ) return vector3df ( 0.1f / 100.f, -2.f / 100.f, 0.f ); if ( 0 == strcmp ( surface, "ice" ) ) return vector3df ( 0.2f / 100.f, -9.f / 100.f, 0.3f / 100.f ); return vector3df ( 0.f, 0.f, 0.f ); } /* Dynamically load the Irrlicht Library */ #if defined(_IRR_WINDOWS_API_) #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif #include funcptr_createDevice load_createDevice ( const c8 * filename) { return (funcptr_createDevice) GetProcAddress ( LoadLibrary ( filename ), "createDevice" ); } funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename) { return (funcptr_createDeviceEx) GetProcAddress ( LoadLibrary ( filename ), "createDeviceEx" ); } #else // TODO: Dynamic Loading for other os funcptr_createDevice load_createDevice ( const c8 * filename) { return createDevice; } funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename) { return createDeviceEx; } #endif /* get the current collision response camera animator */ ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * device ) { ICameraSceneNode *camera = device->getSceneManager()->getActiveCamera(); ISceneNodeAnimatorCollisionResponse *a = 0; list::ConstIterator it = camera->getAnimators().begin(); for (; it != camera->getAnimators().end(); ++it) { a = (ISceneNodeAnimatorCollisionResponse*) (*it); if ( a->getType() == ESNAT_COLLISION_RESPONSE ) return a; } return 0; } //! internal Animation void setTimeFire ( TimeFire *t, u32 delta, u32 flags ) { t->flags = flags; t->next = 0; t->delta = delta; } void checkTimeFire ( TimeFire *t, u32 listSize, u32 now ) { u32 i; for ( i = 0; i < listSize; ++i ) { if ( now < t[i].next ) continue; t[i].next = core::max_ ( now + t[i].delta, t[i].next + t[i].delta ); t[i].flags |= FIRED; } } irrlicht-1.8.3/examples/21.Quake3Explorer/Makefile0000644000000000000000000000224012574354552020424 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 21.Quake3Explorer Sources = main.cpp sound.cpp q3factory.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include #CXXFLAGS = -O3 -ffast-math CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/21.Quake3Explorer/main.cpp0000644000000000000000000017130212574354552020422 0ustar rootroot/** Example 021 Quake3 Explorer This Tutorial shows how to load different Quake 3 maps. Features: - Load BSP Archives at Runtime from the menu - Load a Map from the menu. Showing with Screenshot - Set the VideoDriver at runtime from menu - Adjust GammaLevel at runtime - Create SceneNodes for the Shaders - Load EntityList and create Entity SceneNodes - Create Players with Weapons and with Collision Response - Play music You can download the Quake III Arena demo ( copyright id software ) at the following location: ftp://ftp.idsoftware.com/idstuff/quake3/win32/q3ademo.exe Copyright 2006-2011 Burningwater, Thomas Alten */ #include "driverChoice.h" #include #include "q3factory.h" #include "sound.h" /* Game Data is used to hold Data which is needed to drive the game */ struct GameData { GameData ( const path &startupDir) : retVal(0), StartupDir(startupDir), createExDevice(0), Device(0) { setDefault (); } void setDefault (); s32 save ( const path &filename ); s32 load ( const path &filename ); s32 debugState; s32 gravityState; s32 flyTroughState; s32 wireFrame; s32 guiActive; s32 guiInputActive; f32 GammaValue; s32 retVal; s32 sound; path StartupDir; stringw CurrentMapName; array CurrentArchiveList; vector3df PlayerPosition; vector3df PlayerRotation; tQ3EntityList Variable; Q3LevelLoadParameter loadParam; SIrrlichtCreationParameters deviceParam; funcptr_createDeviceEx createExDevice; IrrlichtDevice *Device; }; /* set default settings */ void GameData::setDefault () { debugState = EDS_OFF; gravityState = 1; flyTroughState = 0; wireFrame = 0; guiActive = 1; guiInputActive = 0; GammaValue = 1.f; // default deviceParam; #if defined ( _IRR_WINDOWS_ ) deviceParam.DriverType = EDT_DIRECT3D9; #else deviceParam.DriverType = EDT_OPENGL; #endif deviceParam.WindowSize.Width = 800; deviceParam.WindowSize.Height = 600; deviceParam.Fullscreen = false; deviceParam.Bits = 24; deviceParam.ZBufferBits = 16; deviceParam.Vsync = false; deviceParam.AntiAlias = false; // default Quake3 loadParam loadParam.defaultLightMapMaterial = EMT_LIGHTMAP; loadParam.defaultModulate = EMFN_MODULATE_1X; loadParam.defaultFilter = EMF_ANISOTROPIC_FILTER; loadParam.verbose = 2; loadParam.mergeShaderBuffer = 1; // merge meshbuffers with same material loadParam.cleanUnResolvedMeshes = 1; // should unresolved meshes be cleaned. otherwise blue texture loadParam.loadAllShaders = 1; // load all scripts in the script directory loadParam.loadSkyShader = 0; // load sky Shader loadParam.alpharef = 1; sound = 0; CurrentMapName = ""; CurrentArchiveList.clear (); // Explorer Media directory CurrentArchiveList.push_back ( StartupDir + "../../media/" ); // Add the original quake3 files before you load your custom map // Most mods are using the original shaders, models&items&weapons CurrentArchiveList.push_back("/q/baseq3/"); CurrentArchiveList.push_back(StartupDir + "../../media/map-20kdm2.pk3"); } /* Load the current game State from a typical quake3 cfg file */ s32 GameData::load ( const path &filename ) { if (!Device) return 0; // the quake3 mesh loader can also handle *.shader and *.cfg file IQ3LevelMesh* mesh = (IQ3LevelMesh*) Device->getSceneManager()->getMesh ( filename ); if (!mesh) return 0; tQ3EntityList &entityList = mesh->getEntityList (); stringc s; u32 pos; for ( u32 e = 0; e != entityList.size (); ++e ) { //dumpShader ( s, &entityList[e], false ); //printf ( s.c_str () ); for ( u32 g = 0; g != entityList[e].getGroupSize (); ++g ) { const SVarGroup *group = entityList[e].getGroup ( g ); for ( u32 index = 0; index < group->Variable.size (); ++index ) { const SVariable &v = group->Variable[index]; pos = 0; if ( v.name == "playerposition" ) { PlayerPosition = getAsVector3df ( v.content, pos ); } else if ( v.name == "playerrotation" ) { PlayerRotation = getAsVector3df ( v.content, pos ); } } } } return 1; } /* Store the current game State in a quake3 configuration file */ s32 GameData::save ( const path &filename ) { return 0; if (!Device) return 0; c8 buf[128]; u32 i; // Store current Archive for restart CurrentArchiveList.clear(); IFileSystem *fs = Device->getFileSystem(); for ( i = 0; i != fs->getFileArchiveCount(); ++i ) { CurrentArchiveList.push_back ( fs->getFileArchive(i)->getFileList()->getPath() ); } // Store Player Position and Rotation ICameraSceneNode * camera = Device->getSceneManager()->getActiveCamera (); if ( camera ) { PlayerPosition = camera->getPosition (); PlayerRotation = camera->getRotation (); } IWriteFile *file = fs->createAndWriteFile ( filename ); if (!file) return 0; snprintf ( buf, 128, "playerposition %.f %.f %.f\nplayerrotation %.f %.f %.f\n", PlayerPosition.X, PlayerPosition.Z, PlayerPosition.Y, PlayerRotation.X, PlayerRotation.Z, PlayerRotation.Y); file->write ( buf, (s32) strlen ( buf ) ); for ( i = 0; i != fs->getFileArchiveCount(); ++i ) { snprintf ( buf, 128, "archive %s\n",stringc ( fs->getFileArchive(i)->getFileList()->getPath() ).c_str () ); file->write ( buf, (s32) strlen ( buf ) ); } file->drop (); return 1; } /* Representing a player */ struct Q3Player : public IAnimationEndCallBack { Q3Player () : Device(0), MapParent(0), Mesh(0), WeaponNode(0), StartPositionCurrent(0) { animation[0] = 0; memset(Anim, 0, sizeof(TimeFire)*4); } virtual void OnAnimationEnd(IAnimatedMeshSceneNode* node); void create ( IrrlichtDevice *device, IQ3LevelMesh* mesh, ISceneNode *mapNode, IMetaTriangleSelector *meta ); void shutdown (); void setAnim ( const c8 *name ); void respawn (); void setpos ( const vector3df &pos, const vector3df& rotation ); ISceneNodeAnimatorCollisionResponse * cam() { return camCollisionResponse ( Device ); } IrrlichtDevice *Device; ISceneNode* MapParent; IQ3LevelMesh* Mesh; IAnimatedMeshSceneNode* WeaponNode; s32 StartPositionCurrent; TimeFire Anim[4]; c8 animation[64]; c8 buf[64]; }; /* End player */ void Q3Player::shutdown () { setAnim ( 0 ); dropElement (WeaponNode); if ( Device ) { ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera(); dropElement ( camera ); Device = 0; } MapParent = 0; Mesh = 0; } /* create a new player */ void Q3Player::create ( IrrlichtDevice *device, IQ3LevelMesh* mesh, ISceneNode *mapNode, IMetaTriangleSelector *meta ) { setTimeFire ( Anim + 0, 200, FIRED ); setTimeFire ( Anim + 1, 5000 ); if (!device) return; // load FPS weapon to Camera Device = device; Mesh = mesh; MapParent = mapNode; ISceneManager *smgr = device->getSceneManager (); IVideoDriver * driver = device->getVideoDriver(); ICameraSceneNode* camera = 0; SKeyMap keyMap[10]; keyMap[0].Action = EKA_MOVE_FORWARD; keyMap[0].KeyCode = KEY_UP; keyMap[1].Action = EKA_MOVE_FORWARD; keyMap[1].KeyCode = KEY_KEY_W; keyMap[2].Action = EKA_MOVE_BACKWARD; keyMap[2].KeyCode = KEY_DOWN; keyMap[3].Action = EKA_MOVE_BACKWARD; keyMap[3].KeyCode = KEY_KEY_S; keyMap[4].Action = EKA_STRAFE_LEFT; keyMap[4].KeyCode = KEY_LEFT; keyMap[5].Action = EKA_STRAFE_LEFT; keyMap[5].KeyCode = KEY_KEY_A; keyMap[6].Action = EKA_STRAFE_RIGHT; keyMap[6].KeyCode = KEY_RIGHT; keyMap[7].Action = EKA_STRAFE_RIGHT; keyMap[7].KeyCode = KEY_KEY_D; keyMap[8].Action = EKA_JUMP_UP; keyMap[8].KeyCode = KEY_KEY_J; keyMap[9].Action = EKA_CROUCH; keyMap[9].KeyCode = KEY_KEY_C; camera = smgr->addCameraSceneNodeFPS(0, 100.0f, 0.6f, -1, keyMap, 10, false, 0.6f); camera->setName ( "First Person Camera" ); //camera->setFOV ( 100.f * core::DEGTORAD ); camera->setFarValue( 20000.f ); IAnimatedMeshMD2* weaponMesh = (IAnimatedMeshMD2*) smgr->getMesh("gun.md2"); if ( 0 == weaponMesh ) return; if ( weaponMesh->getMeshType() == EAMT_MD2 ) { s32 count = weaponMesh->getAnimationCount(); for ( s32 i = 0; i != count; ++i ) { snprintf ( buf, 64, "Animation: %s", weaponMesh->getAnimationName(i) ); device->getLogger()->log(buf, ELL_INFORMATION); } } WeaponNode = smgr->addAnimatedMeshSceneNode( weaponMesh, smgr->getActiveCamera(), 10, vector3df( 0, 0, 0), vector3df(-90,-90,90) ); WeaponNode->setMaterialFlag(EMF_LIGHTING, false); WeaponNode->setMaterialTexture(0, driver->getTexture( "gun.jpg")); WeaponNode->setLoopMode ( false ); WeaponNode->setName ( "tommi the gun man" ); //create a collision auto response animator ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( meta, camera, vector3df(30,45,30), getGravity ( "earth" ), vector3df(0,40,0), 0.0005f ); camera->addAnimator( anim ); anim->drop(); if ( meta ) { meta->drop (); } respawn (); setAnim ( "idle" ); } /* so we need a good starting Position in the level. we can ask the Quake3 Loader for all entities with class_name "info_player_deathmatch" */ void Q3Player::respawn () { if (!Device) return; ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera(); Device->getLogger()->log( "respawn" ); if ( StartPositionCurrent >= Q3StartPosition ( Mesh, camera,StartPositionCurrent++, cam ()->getEllipsoidTranslation() ) ) { StartPositionCurrent = 0; } } /* set Player position from saved coordinates */ void Q3Player::setpos ( const vector3df &pos, const vector3df &rotation ) { if (!Device) return; Device->getLogger()->log( "setpos" ); ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera(); if ( camera ) { camera->setPosition ( pos ); camera->setRotation ( rotation ); //! New. FPSCamera and animators catches reset on animate 0 camera->OnAnimate ( 0 ); } } /* set the Animation of the player and weapon */ void Q3Player::setAnim ( const c8 *name ) { if ( name ) { snprintf ( animation, 64, "%s", name ); if ( WeaponNode ) { WeaponNode->setAnimationEndCallback ( this ); WeaponNode->setMD2Animation ( animation ); } } else { animation[0] = 0; if ( WeaponNode ) { WeaponNode->setAnimationEndCallback ( 0 ); } } } // Callback void Q3Player::OnAnimationEnd(IAnimatedMeshSceneNode* node) { setAnim ( 0 ); } /* GUI Elements */ struct GUI { GUI () { memset ( this, 0, sizeof ( *this ) ); } void drop() { dropElement ( Window ); dropElement ( Logo ); } IGUIComboBox* VideoDriver; IGUIComboBox* VideoMode; IGUICheckBox* FullScreen; IGUICheckBox* Bit32; IGUIScrollBar* MultiSample; IGUIButton* SetVideoMode; IGUIScrollBar* Tesselation; IGUIScrollBar* Gamma; IGUICheckBox* Collision; IGUICheckBox* Visible_Map; IGUICheckBox* Visible_Shader; IGUICheckBox* Visible_Fog; IGUICheckBox* Visible_Unresolved; IGUICheckBox* Visible_Skydome; IGUIButton* Respawn; IGUITable* ArchiveList; IGUIButton* ArchiveAdd; IGUIButton* ArchiveRemove; IGUIFileOpenDialog* ArchiveFileOpen; IGUIButton* ArchiveUp; IGUIButton* ArchiveDown; IGUIListBox* MapList; IGUITreeView* SceneTree; IGUIStaticText* StatusLine; IGUIImage* Logo; IGUIWindow* Window; }; /* CQuake3EventHandler controls the game */ class CQuake3EventHandler : public IEventReceiver { public: CQuake3EventHandler( GameData *gameData ); virtual ~CQuake3EventHandler (); void Animate(); void Render(); void AddArchive ( const path& archiveName ); void LoadMap ( const stringw& mapName, s32 collision ); void CreatePlayers(); void AddSky( u32 dome, const c8 *texture ); Q3Player *GetPlayer ( u32 index ) { return &Player[index]; } void CreateGUI(); void SetGUIActive( s32 command); bool OnEvent(const SEvent& eve); private: GameData *Game; IQ3LevelMesh* Mesh; ISceneNode* MapParent; ISceneNode* ShaderParent; ISceneNode* ItemParent; ISceneNode* UnresolvedParent; ISceneNode* BulletParent; ISceneNode* FogParent; ISceneNode * SkyNode; IMetaTriangleSelector *Meta; c8 buf[256]; Q3Player Player[2]; struct SParticleImpact { u32 when; vector3df pos; vector3df outVector; }; array Impacts; void useItem( Q3Player * player); void createParticleImpacts( u32 now ); void createTextures (); void addSceneTreeItem( ISceneNode * parent, IGUITreeViewNode* nodeParent); GUI gui; void dropMap (); }; /* Constructor */ CQuake3EventHandler::CQuake3EventHandler( GameData *game ) : Game(game), Mesh(0), MapParent(0), ShaderParent(0), ItemParent(0), UnresolvedParent(0), BulletParent(0), FogParent(0), SkyNode(0), Meta(0) { buf[0]=0; // Also use 16 Bit Textures for 16 Bit RenderDevice if ( Game->deviceParam.Bits == 16 ) { game->Device->getVideoDriver()->setTextureCreationFlag(ETCF_ALWAYS_16_BIT, true); } // Quake3 Shader controls Z-Writing game->Device->getSceneManager()->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); // create internal textures createTextures (); sound_init ( game->Device ); Game->Device->setEventReceiver ( this ); } // destructor CQuake3EventHandler::~CQuake3EventHandler () { Player[0].shutdown (); sound_shutdown (); Game->save( "explorer.cfg" ); Game->Device->drop(); } // create runtime textures smog, fog void CQuake3EventHandler::createTextures() { IVideoDriver * driver = Game->Device->getVideoDriver(); dimension2du dim(64, 64); video::IImage* image; u32 i; u32 x; u32 y; u32 * data; for ( i = 0; i != 8; ++i ) { image = driver->createImage ( video::ECF_A8R8G8B8, dim); data = (u32*) image->lock (); for ( y = 0; y != dim.Height; ++y ) { for ( x = 0; x != dim.Width; ++x ) { data [x] = 0xFFFFFFFF; } data = (u32*) ( (u8*) data + image->getPitch() ); } image->unlock(); snprintf ( buf, 64, "smoke_%02d", i ); driver->addTexture( buf, image ); image->drop (); } // fog for ( i = 0; i != 1; ++i ) { image = driver->createImage ( video::ECF_A8R8G8B8, dim); data = (u32*) image->lock (); for ( y = 0; y != dim.Height; ++y ) { for ( x = 0; x != dim.Width; ++x ) { data [x] = 0xFFFFFFFF; } data = (u32*) ( (u8*) data + image->getPitch() ); } image->unlock(); snprintf ( buf, 64, "fog_%02d", i ); driver->addTexture( buf, image ); image->drop (); } } /* create the GUI */ void CQuake3EventHandler::CreateGUI() { IGUIEnvironment *env = Game->Device->getGUIEnvironment(); IVideoDriver * driver = Game->Device->getVideoDriver(); gui.drop(); // set skin font IGUIFont* font = env->getFont("fontlucida.png"); if (font) env->getSkin()->setFont(font); env->getSkin()->setColor ( EGDC_BUTTON_TEXT, video::SColor(240,0xAA,0xAA,0xAA) ); env->getSkin()->setColor ( EGDC_3D_HIGH_LIGHT, video::SColor(240,0x22,0x22,0x22) ); env->getSkin()->setColor ( EGDC_3D_FACE, video::SColor(240,0x44,0x44,0x44) ); env->getSkin()->setColor ( EGDC_EDITABLE, video::SColor(240,0x44,0x44,0x44) ); env->getSkin()->setColor ( EGDC_FOCUSED_EDITABLE, video::SColor(240,0x54,0x54,0x54) ); env->getSkin()->setColor ( EGDC_WINDOW, video::SColor(240,0x66,0x66,0x66) ); // minimal gui size 800x600 dimension2d dim ( 800, 600 ); dimension2d vdim ( Game->Device->getVideoDriver()->getScreenSize() ); if ( vdim.Height >= dim.Height && vdim.Width >= dim.Width ) { //dim = vdim; } else { } gui.Window = env->addWindow ( rect ( 0, 0, dim.Width, dim.Height ), false, L"Quake3 Explorer" ); gui.Window->setToolTipText ( L"Quake3Explorer. Loads and show various BSP File Format and Shaders." ); gui.Window->getCloseButton()->setToolTipText ( L"Quit Quake3 Explorer" ); // add a status line help text gui.StatusLine = env->addStaticText( 0, rect( 5,dim.Height - 30,dim.Width - 5,dim.Height - 10), false, false, gui.Window, -1, true ); env->addStaticText ( L"VideoDriver:", rect( dim.Width - 400, 24, dim.Width - 310, 40 ),false, false, gui.Window, -1, false ); gui.VideoDriver = env->addComboBox(rect( dim.Width - 300, 24, dim.Width - 10, 40 ),gui.Window); gui.VideoDriver->addItem(L"Direct3D 9.0c", EDT_DIRECT3D9 ); gui.VideoDriver->addItem(L"Direct3D 8.1", EDT_DIRECT3D8 ); gui.VideoDriver->addItem(L"OpenGL 1.5", EDT_OPENGL); gui.VideoDriver->addItem(L"Software Renderer", EDT_SOFTWARE); gui.VideoDriver->addItem(L"Burning's Video (TM) Thomas Alten", EDT_BURNINGSVIDEO); gui.VideoDriver->setSelected ( gui.VideoDriver->getIndexForItemData ( Game->deviceParam.DriverType ) ); gui.VideoDriver->setToolTipText ( L"Use a VideoDriver" ); env->addStaticText ( L"VideoMode:", rect( dim.Width - 400, 44, dim.Width - 310, 60 ),false, false, gui.Window, -1, false ); gui.VideoMode = env->addComboBox(rect( dim.Width - 300, 44, dim.Width - 10, 60 ),gui.Window); gui.VideoMode->setToolTipText ( L"Supported Screenmodes" ); IVideoModeList *modeList = Game->Device->getVideoModeList(); if ( modeList ) { s32 i; for ( i = 0; i != modeList->getVideoModeCount (); ++i ) { u16 d = modeList->getVideoModeDepth ( i ); if ( d < 16 ) continue; u16 w = modeList->getVideoModeResolution ( i ).Width; u16 h = modeList->getVideoModeResolution ( i ).Height; u32 val = w << 16 | h; if ( gui.VideoMode->getIndexForItemData ( val ) >= 0 ) continue; f32 aspect = (f32) w / (f32) h; const c8 *a = ""; if ( core::equals ( aspect, 1.3333333333f ) ) a = "4:3"; else if ( core::equals ( aspect, 1.6666666f ) ) a = "15:9 widescreen"; else if ( core::equals ( aspect, 1.7777777f ) ) a = "16:9 widescreen"; else if ( core::equals ( aspect, 1.6f ) ) a = "16:10 widescreen"; else if ( core::equals ( aspect, 2.133333f ) ) a = "20:9 widescreen"; snprintf ( buf, sizeof ( buf ), "%d x %d, %s",w, h, a ); gui.VideoMode->addItem ( stringw ( buf ).c_str(), val ); } } gui.VideoMode->setSelected ( gui.VideoMode->getIndexForItemData ( Game->deviceParam.WindowSize.Width << 16 | Game->deviceParam.WindowSize.Height ) ); gui.FullScreen = env->addCheckBox ( Game->deviceParam.Fullscreen, rect( dim.Width - 400, 64, dim.Width - 300, 80 ), gui.Window,-1, L"Fullscreen" ); gui.FullScreen->setToolTipText ( L"Set Fullscreen or Window Mode" ); gui.Bit32 = env->addCheckBox ( Game->deviceParam.Bits == 32, rect( dim.Width - 300, 64, dim.Width - 240, 80 ), gui.Window,-1, L"32Bit" ); gui.Bit32->setToolTipText ( L"Use 16 or 32 Bit" ); env->addStaticText ( L"MultiSample:", rect( dim.Width - 235, 64, dim.Width - 150, 80 ),false, false, gui.Window, -1, false ); gui.MultiSample = env->addScrollBar( true, rect( dim.Width - 150, 64, dim.Width - 70, 80 ), gui.Window,-1 ); gui.MultiSample->setMin ( 0 ); gui.MultiSample->setMax ( 8 ); gui.MultiSample->setSmallStep ( 1 ); gui.MultiSample->setLargeStep ( 1 ); gui.MultiSample->setPos ( Game->deviceParam.AntiAlias ); gui.MultiSample->setToolTipText ( L"Set the MultiSample (disable, 1x, 2x, 4x, 8x )" ); gui.SetVideoMode = env->addButton (rect( dim.Width - 60, 64, dim.Width - 10, 80 ), gui.Window, -1,L"set" ); gui.SetVideoMode->setToolTipText ( L"Set Video Mode with current values" ); env->addStaticText ( L"Gamma:", rect( dim.Width - 400, 104, dim.Width - 310, 120 ),false, false, gui.Window, -1, false ); gui.Gamma = env->addScrollBar( true, rect( dim.Width - 300, 104, dim.Width - 10, 120 ), gui.Window,-1 ); gui.Gamma->setMin ( 50 ); gui.Gamma->setMax ( 350 ); gui.Gamma->setSmallStep ( 1 ); gui.Gamma->setLargeStep ( 10 ); gui.Gamma->setPos ( core::floor32 ( Game->GammaValue * 100.f ) ); gui.Gamma->setToolTipText ( L"Adjust Gamma Ramp ( 0.5 - 3.5)" ); Game->Device->setGammaRamp ( Game->GammaValue, Game->GammaValue, Game->GammaValue, 0.f, 0.f ); env->addStaticText ( L"Tesselation:", rect( dim.Width - 400, 124, dim.Width - 310, 140 ),false, false, gui.Window, -1, false ); gui.Tesselation = env->addScrollBar( true, rect( dim.Width - 300, 124, dim.Width - 10, 140 ), gui.Window,-1 ); gui.Tesselation->setMin ( 2 ); gui.Tesselation->setMax ( 12 ); gui.Tesselation->setSmallStep ( 1 ); gui.Tesselation->setLargeStep ( 1 ); gui.Tesselation->setPos ( Game->loadParam.patchTesselation ); gui.Tesselation->setToolTipText ( L"How smooth should curved surfaces be rendered" ); gui.Collision = env->addCheckBox ( true, rect( dim.Width - 400, 150, dim.Width - 300, 166 ), gui.Window,-1, L"Collision" ); gui.Collision->setToolTipText ( L"Set collision on or off ( flythrough ). \nPress F7 on your Keyboard" ); gui.Visible_Map = env->addCheckBox ( true, rect( dim.Width - 300, 150, dim.Width - 240, 166 ), gui.Window,-1, L"Map" ); gui.Visible_Map->setToolTipText ( L"Show or not show the static part the Level. \nPress F3 on your Keyboard" ); gui.Visible_Shader = env->addCheckBox ( true, rect( dim.Width - 240, 150, dim.Width - 170, 166 ), gui.Window,-1, L"Shader" ); gui.Visible_Shader->setToolTipText ( L"Show or not show the Shader Nodes. \nPress F4 on your Keyboard" ); gui.Visible_Fog = env->addCheckBox ( true, rect( dim.Width - 170, 150, dim.Width - 110, 166 ), gui.Window,-1, L"Fog" ); gui.Visible_Fog->setToolTipText ( L"Show or not show the Fog Nodes. \nPress F5 on your Keyboard" ); gui.Visible_Unresolved = env->addCheckBox ( true, rect( dim.Width - 110, 150, dim.Width - 10, 166 ), gui.Window,-1, L"Unresolved" ); gui.Visible_Unresolved->setToolTipText ( L"Show the or not show the Nodes the Engine can't handle. \nPress F6 on your Keyboard" ); gui.Visible_Skydome = env->addCheckBox ( true, rect( dim.Width - 110, 180, dim.Width - 10, 196 ), gui.Window,-1, L"Skydome" ); gui.Visible_Skydome->setToolTipText ( L"Show the or not show the Skydome." ); //Respawn = env->addButton ( rect( dim.Width - 260, 90, dim.Width - 10, 106 ), 0,-1, L"Respawn" ); env->addStaticText ( L"Archives:", rect( 5, dim.Height - 530, dim.Width - 600,dim.Height - 514 ),false, false, gui.Window, -1, false ); gui.ArchiveAdd = env->addButton ( rect( dim.Width - 725, dim.Height - 530, dim.Width - 665, dim.Height - 514 ), gui.Window,-1, L"add" ); gui.ArchiveAdd->setToolTipText ( L"Add an archive, usually packed zip-archives (*.pk3) to the Filesystem" ); gui.ArchiveRemove = env->addButton ( rect( dim.Width - 660, dim.Height - 530, dim.Width - 600, dim.Height - 514 ), gui.Window,-1, L"del" ); gui.ArchiveRemove->setToolTipText ( L"Remove the selected archive from the FileSystem." ); gui.ArchiveUp = env->addButton ( rect( dim.Width - 575, dim.Height - 530, dim.Width - 515, dim.Height - 514 ), gui.Window,-1, L"up" ); gui.ArchiveUp->setToolTipText ( L"Arrange Archive Look-up Hirachy. Move the selected Archive up" ); gui.ArchiveDown = env->addButton ( rect( dim.Width - 510, dim.Height - 530, dim.Width - 440, dim.Height - 514 ), gui.Window,-1, L"down" ); gui.ArchiveDown->setToolTipText ( L"Arrange Archive Look-up Hirachy. Move the selected Archive down" ); gui.ArchiveList = env->addTable ( rect( 5,dim.Height - 510, dim.Width - 450,dim.Height - 410 ), gui.Window ); gui.ArchiveList->addColumn ( L"Type", 0 ); gui.ArchiveList->addColumn ( L"Real File Path", 1 ); gui.ArchiveList->setColumnWidth ( 0, 60 ); gui.ArchiveList->setColumnWidth ( 1, 284 ); gui.ArchiveList->setToolTipText ( L"Show the attached Archives" ); env->addStaticText ( L"Maps:", rect( 5, dim.Height - 400, dim.Width - 450,dim.Height - 380 ),false, false, gui.Window, -1, false ); gui.MapList = env->addListBox ( rect( 5,dim.Height - 380, dim.Width - 450,dim.Height - 40 ), gui.Window, -1, true ); gui.MapList->setToolTipText ( L"Show the current Maps in all Archives.\n Double-Click the Map to start the level" ); // create a visible Scene Tree env->addStaticText ( L"Scenegraph:", rect( dim.Width - 400, dim.Height - 400, dim.Width - 5,dim.Height - 380 ),false, false, gui.Window, -1, false ); gui.SceneTree = env->addTreeView( rect( dim.Width - 400, dim.Height - 380, dim.Width - 5, dim.Height - 40 ), gui.Window, -1, true, true, false ); gui.SceneTree->setToolTipText ( L"Show the current Scenegraph" ); gui.SceneTree->getRoot()->clearChildren(); addSceneTreeItem ( Game->Device->getSceneManager()->getRootSceneNode(), gui.SceneTree->getRoot() ); IGUIImageList* imageList = env->createImageList( driver->getTexture ( "iconlist.png" ), dimension2di( 32, 32 ), true ); if ( imageList ) { gui.SceneTree->setImageList( imageList ); imageList->drop (); } // load the engine logo gui.Logo = env->addImage( driver->getTexture("irrlichtlogo3.png"), position2d(5, 16 ), true, 0 ); gui.Logo->setToolTipText ( L"The great Irrlicht Engine" ); AddArchive ( "" ); } /* Add an Archive to the FileSystems and updates the GUI */ void CQuake3EventHandler::AddArchive ( const path& archiveName ) { IFileSystem *fs = Game->Device->getFileSystem(); u32 i; if ( archiveName.size () ) { bool exists = false; for ( i = 0; i != fs->getFileArchiveCount(); ++i ) { if ( fs->getFileArchive(i)->getFileList()->getPath() == archiveName ) { exists = true; break; } } if (!exists) { fs->addFileArchive(archiveName, true, false); } } // store the current archives in game data // show the attached Archive in proper order if ( gui.ArchiveList ) { gui.ArchiveList->clearRows(); for ( i = 0; i != fs->getFileArchiveCount(); ++i ) { IFileArchive * archive = fs->getFileArchive ( i ); u32 index = gui.ArchiveList->addRow(i); core::stringw typeName; switch(archive->getType()) { case io::EFAT_ZIP: typeName = "ZIP"; break; case io::EFAT_GZIP: typeName = "gzip"; break; case io::EFAT_FOLDER: typeName = "Mount"; break; case io::EFAT_PAK: typeName = "PAK"; break; case io::EFAT_TAR: typeName = "TAR"; break; default: typeName = "archive"; } gui.ArchiveList->setCellText ( index, 0, typeName ); gui.ArchiveList->setCellText ( index, 1, archive->getFileList()->getPath() ); } } // browse the archives for maps if ( gui.MapList ) { gui.MapList->clear(); IGUISpriteBank *bank = Game->Device->getGUIEnvironment()->getSpriteBank("sprite_q3map"); if ( 0 == bank ) bank = Game->Device->getGUIEnvironment()->addEmptySpriteBank("sprite_q3map"); SGUISprite sprite; SGUISpriteFrame frame; core::rect r; bank->getSprites().clear(); bank->getPositions().clear (); gui.MapList->setSpriteBank ( bank ); u32 g = 0; core::stringw s; // browse the attached file system fs->setFileListSystem ( FILESYSTEM_VIRTUAL ); fs->changeWorkingDirectoryTo ( "/maps/" ); IFileList *fileList = fs->createFileList (); fs->setFileListSystem ( FILESYSTEM_NATIVE ); for ( i=0; i< fileList->getFileCount(); ++i) { s = fileList->getFullFileName(i); if ( s.find ( ".bsp" ) >= 0 ) { // get level screenshot. reformat texture to 128x128 path c ( s ); deletePathFromFilename ( c ); cutFilenameExtension ( c, c ); c = path ( "levelshots/" ) + c; dimension2du dim ( 128, 128 ); IVideoDriver * driver = Game->Device->getVideoDriver(); IImage* image = 0; ITexture *tex = 0; path filename; filename = c + ".jpg"; if ( fs->existFile ( filename ) ) image = driver->createImageFromFile( filename ); if ( 0 == image ) { filename = c + ".tga"; if ( fs->existFile ( filename ) ) image = driver->createImageFromFile( filename ); } if ( image ) { IImage* filter = driver->createImage ( video::ECF_R8G8B8, dim ); image->copyToScalingBoxFilter ( filter, 0 ); image->drop (); image = filter; } if ( image ) { tex = driver->addTexture ( filename, image ); image->drop (); } bank->setTexture ( g, tex ); r.LowerRightCorner.X = dim.Width; r.LowerRightCorner.Y = dim.Height; gui.MapList->setItemHeight ( r.LowerRightCorner.Y + 4 ); frame.rectNumber = bank->getPositions().size(); frame.textureNumber = g; bank->getPositions().push_back(r); sprite.Frames.set_used ( 0 ); sprite.Frames.push_back(frame); sprite.frameTime = 0; bank->getSprites().push_back(sprite); gui.MapList->addItem ( s.c_str (), g ); g += 1; } } fileList->drop (); gui.MapList->setSelected ( -1 ); IGUIScrollBar * bar = (IGUIScrollBar*)gui.MapList->getElementFromId( 0 ); if ( bar ) bar->setPos ( 0 ); } } /* clears the Map in Memory */ void CQuake3EventHandler::dropMap () { IVideoDriver * driver = Game->Device->getVideoDriver(); driver->removeAllHardwareBuffers (); driver->removeAllTextures (); Player[0].shutdown (); dropElement ( ItemParent ); dropElement ( ShaderParent ); dropElement ( UnresolvedParent ); dropElement ( FogParent ); dropElement ( BulletParent ); Impacts.clear(); if ( Meta ) { Meta = 0; } dropElement ( MapParent ); dropElement ( SkyNode ); // clean out meshes, because textures are invalid // TODO: better texture handling;-) IMeshCache *cache = Game->Device->getSceneManager ()->getMeshCache(); cache->clear (); Mesh = 0; } /* Load new map */ void CQuake3EventHandler::LoadMap ( const stringw &mapName, s32 collision ) { if ( 0 == mapName.size() ) return; dropMap (); IFileSystem *fs = Game->Device->getFileSystem(); ISceneManager *smgr = Game->Device->getSceneManager (); IReadFile* file = fs->createMemoryReadFile(&Game->loadParam, sizeof(Game->loadParam), L"levelparameter.cfg", false); // load cfg file smgr->getMesh( file ); file->drop (); // load the actual map Mesh = (IQ3LevelMesh*) smgr->getMesh(mapName); if ( 0 == Mesh ) return; /* add the geometry mesh to the Scene ( polygon & patches ) The Geometry mesh is optimised for faster drawing */ IMesh *geometry = Mesh->getMesh(E_Q3_MESH_GEOMETRY); if ( 0 == geometry || geometry->getMeshBufferCount() == 0) return; Game->CurrentMapName = mapName; //create a collision list Meta = 0; ITriangleSelector * selector = 0; if (collision) Meta = smgr->createMetaTriangleSelector(); //IMeshBuffer *b0 = geometry->getMeshBuffer(0); //s32 minimalNodes = b0 ? core::s32_max ( 2048, b0->getVertexCount() / 32 ) : 2048; s32 minimalNodes = 2048; MapParent = smgr->addOctreeSceneNode(geometry, 0, -1, minimalNodes); MapParent->setName ( mapName ); if ( Meta ) { selector = smgr->createOctreeTriangleSelector( geometry,MapParent, minimalNodes); //selector = smgr->createTriangleSelector ( geometry, MapParent ); Meta->addTriangleSelector( selector); selector->drop (); } // logical parent for the items ItemParent = smgr->addEmptySceneNode(); if ( ItemParent ) ItemParent->setName ( "Item Container" ); ShaderParent = smgr->addEmptySceneNode(); if ( ShaderParent ) ShaderParent->setName ( "Shader Container" ); UnresolvedParent = smgr->addEmptySceneNode(); if ( UnresolvedParent ) UnresolvedParent->setName ( "Unresolved Container" ); FogParent = smgr->addEmptySceneNode(); if ( FogParent ) FogParent->setName ( "Fog Container" ); // logical parent for the bullets BulletParent = smgr->addEmptySceneNode(); if ( BulletParent ) BulletParent->setName ( "Bullet Container" ); /* now construct SceneNodes for each Shader The Objects are stored in the quake mesh E_Q3_MESH_ITEMS and the Shader ID is stored in the MaterialParameters mostly dark looking skulls and moving lava.. or green flashing tubes? */ Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_ITEMS,ShaderParent, Meta, false ); Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_FOG,FogParent, 0, false ); Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_UNRESOLVED,UnresolvedParent, Meta, true ); /* Now construct Models from Entity List */ Q3ModelFactory ( Game->loadParam, Game->Device, Mesh, ItemParent, false ); } /* Adds a SceneNode with an icon to the Scene Tree */ void CQuake3EventHandler::addSceneTreeItem( ISceneNode * parent, IGUITreeViewNode* nodeParent) { IGUITreeViewNode* node; wchar_t msg[128]; s32 imageIndex; list::ConstIterator it = parent->getChildren().begin(); for (; it != parent->getChildren().end(); ++it) { switch ( (*it)->getType () ) { case ESNT_Q3SHADER_SCENE_NODE: imageIndex = 0; break; case ESNT_CAMERA: imageIndex = 1; break; case ESNT_EMPTY: imageIndex = 2; break; case ESNT_MESH: imageIndex = 3; break; case ESNT_OCTREE: imageIndex = 3; break; case ESNT_ANIMATED_MESH: imageIndex = 4; break; case ESNT_SKY_BOX: imageIndex = 5; break; case ESNT_BILLBOARD: imageIndex = 6; break; case ESNT_PARTICLE_SYSTEM: imageIndex = 7; break; case ESNT_TEXT: imageIndex = 8; break; default:imageIndex = -1; break; } if ( imageIndex < 0 ) { swprintf ( msg, 128, L"%hs,%hs", Game->Device->getSceneManager ()->getSceneNodeTypeName ( (*it)->getType () ), (*it)->getName() ); } else { swprintf ( msg, 128, L"%hs",(*it)->getName() ); } node = nodeParent->addChildBack( msg, 0, imageIndex ); // Add all Animators list::ConstIterator ait = (*it)->getAnimators().begin(); for (; ait != (*it)->getAnimators().end(); ++ait) { imageIndex = -1; swprintf ( msg, 128, L"%hs", Game->Device->getSceneManager ()->getAnimatorTypeName ( (*ait)->getType () ) ); switch ( (*ait)->getType () ) { case ESNAT_FLY_CIRCLE: case ESNAT_FLY_STRAIGHT: case ESNAT_FOLLOW_SPLINE: case ESNAT_ROTATION: case ESNAT_TEXTURE: case ESNAT_DELETION: case ESNAT_COLLISION_RESPONSE: case ESNAT_CAMERA_FPS: case ESNAT_CAMERA_MAYA: default: break; } node->addChildBack( msg, 0, imageIndex ); } addSceneTreeItem ( *it, node ); } } // Adds life! void CQuake3EventHandler::CreatePlayers() { Player[0].create ( Game->Device, Mesh, MapParent, Meta ); } // Adds a skydome to the scene void CQuake3EventHandler::AddSky( u32 dome, const c8 *texture) { ISceneManager *smgr = Game->Device->getSceneManager (); IVideoDriver * driver = Game->Device->getVideoDriver(); bool oldMipMapState = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); if ( 0 == dome ) { // irrlicht order //static const c8*p[] = { "ft", "lf", "bk", "rt", "up", "dn" }; // quake3 order static const c8*p[] = { "ft", "rt", "bk", "lf", "up", "dn" }; u32 i = 0; snprintf ( buf, 64, "%s_%s.jpg", texture, p[i] ); SkyNode = smgr->addSkyBoxSceneNode( driver->getTexture ( buf ), 0, 0, 0, 0, 0 ); if (SkyNode) { for ( i = 0; i < 6; ++i ) { snprintf ( buf, 64, "%s_%s.jpg", texture, p[i] ); SkyNode->getMaterial(i).setTexture ( 0, driver->getTexture ( buf ) ); } } } else if ( 1 == dome ) { snprintf ( buf, 64, "%s.jpg", texture ); SkyNode = smgr->addSkyDomeSceneNode( driver->getTexture( buf ), 32,32, 1.f, 1.f, 1000.f, 0, 11); } else if ( 2 == dome ) { snprintf ( buf, 64, "%s.jpg", texture ); SkyNode = smgr->addSkyDomeSceneNode( driver->getTexture( buf ), 16,8, 0.95f, 2.f, 1000.f, 0, 11); } if (SkyNode) SkyNode->setName("Skydome"); //SkyNode->getMaterial(0).ZBuffer = video::EMDF_DEPTH_LESS_EQUAL; driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); } // enable GUI elements void CQuake3EventHandler::SetGUIActive( s32 command) { bool inputState = false; ICameraSceneNode * camera = Game->Device->getSceneManager()->getActiveCamera (); switch ( command ) { case 0: Game->guiActive = 0; inputState = !Game->guiActive; break; case 1: Game->guiActive = 1; inputState = !Game->guiActive;;break; case 2: Game->guiActive ^= 1; inputState = !Game->guiActive;break; case 3: if ( camera ) inputState = !camera->isInputReceiverEnabled(); break; } if ( camera ) { camera->setInputReceiverEnabled ( inputState ); Game->Device->getCursorControl()->setVisible( !inputState ); } if ( gui.Window ) { gui.Window->setVisible ( Game->guiActive != 0 ); } if ( Game->guiActive && gui.SceneTree && Game->Device->getGUIEnvironment()->getFocus() != gui.SceneTree ) { gui.SceneTree->getRoot()->clearChildren(); addSceneTreeItem ( Game->Device->getSceneManager()->getRootSceneNode(), gui.SceneTree->getRoot() ); } Game->Device->getGUIEnvironment()->setFocus ( Game->guiActive ? gui.Window: 0 ); } /* Handle game input */ bool CQuake3EventHandler::OnEvent(const SEvent& eve) { if ( eve.EventType == EET_LOG_TEXT_EVENT ) { return false; } if ( Game->guiActive && eve.EventType == EET_GUI_EVENT ) { if ( eve.GUIEvent.Caller == gui.MapList && eve.GUIEvent.EventType == gui::EGET_LISTBOX_SELECTED_AGAIN ) { s32 selected = gui.MapList->getSelected(); if ( selected >= 0 ) { stringw loadMap = gui.MapList->getListItem ( selected ); if ( 0 == MapParent || loadMap != Game->CurrentMapName ) { printf ( "Loading map %ls\n", loadMap.c_str() ); LoadMap ( loadMap , 1 ); if ( 0 == Game->loadParam.loadSkyShader ) { AddSky ( 1, "skydome2" ); } CreatePlayers (); CreateGUI (); SetGUIActive ( 0 ); return true; } } } else if ( eve.GUIEvent.Caller == gui.ArchiveRemove && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) { Game->Device->getFileSystem()->removeFileArchive( gui.ArchiveList->getSelected() ); Game->CurrentMapName = ""; AddArchive ( "" ); } else if ( eve.GUIEvent.Caller == gui.ArchiveAdd && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) { if ( 0 == gui.ArchiveFileOpen ) { Game->Device->getFileSystem()->setFileListSystem ( FILESYSTEM_NATIVE ); gui.ArchiveFileOpen = Game->Device->getGUIEnvironment()->addFileOpenDialog ( L"Add Game Archive" , false,gui.Window ); } } else if ( eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_FILE_SELECTED ) { AddArchive ( gui.ArchiveFileOpen->getFileName() ); gui.ArchiveFileOpen = 0; } else if ( eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_DIRECTORY_SELECTED ) { AddArchive ( gui.ArchiveFileOpen->getDirectoryName() ); } else if ( eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_FILE_CHOOSE_DIALOG_CANCELLED ) { gui.ArchiveFileOpen = 0; } else if ( ( eve.GUIEvent.Caller == gui.ArchiveUp || eve.GUIEvent.Caller == gui.ArchiveDown ) && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) { s32 rel = eve.GUIEvent.Caller == gui.ArchiveUp ? -1 : 1; if ( Game->Device->getFileSystem()->moveFileArchive ( gui.ArchiveList->getSelected (), rel ) ) { s32 newIndex = core::s32_clamp ( gui.ArchiveList->getSelected() + rel, 0, gui.ArchiveList->getRowCount() - 1 ); AddArchive ( "" ); gui.ArchiveList->setSelected ( newIndex ); Game->CurrentMapName = ""; } } else if ( eve.GUIEvent.Caller == gui.VideoDriver && eve.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED ) { Game->deviceParam.DriverType = (E_DRIVER_TYPE) gui.VideoDriver->getItemData ( gui.VideoDriver->getSelected() ); } else if ( eve.GUIEvent.Caller == gui.VideoMode && eve.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED ) { u32 val = gui.VideoMode->getItemData ( gui.VideoMode->getSelected() ); Game->deviceParam.WindowSize.Width = val >> 16; Game->deviceParam.WindowSize.Height = val & 0xFFFF; } else if ( eve.GUIEvent.Caller == gui.FullScreen && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) { Game->deviceParam.Fullscreen = gui.FullScreen->isChecked(); } else if ( eve.GUIEvent.Caller == gui.Bit32 && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) { Game->deviceParam.Bits = gui.Bit32->isChecked() ? 32 : 16; } else if ( eve.GUIEvent.Caller == gui.MultiSample && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED ) { Game->deviceParam.AntiAlias = gui.MultiSample->getPos(); } else if ( eve.GUIEvent.Caller == gui.Tesselation && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED ) { Game->loadParam.patchTesselation = gui.Tesselation->getPos (); } else if ( eve.GUIEvent.Caller == gui.Gamma && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED ) { Game->GammaValue = gui.Gamma->getPos () * 0.01f; Game->Device->setGammaRamp ( Game->GammaValue, Game->GammaValue, Game->GammaValue, 0.f, 0.f ); } else if ( eve.GUIEvent.Caller == gui.SetVideoMode && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) { Game->retVal = 2; Game->Device->closeDevice(); } else if ( eve.GUIEvent.Caller == gui.Window && eve.GUIEvent.EventType == gui::EGET_ELEMENT_CLOSED ) { Game->Device->closeDevice(); } else if ( eve.GUIEvent.Caller == gui.Collision && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) { // set fly through active Game->flyTroughState ^= 1; Player[0].cam()->setAnimateTarget ( Game->flyTroughState == 0 ); printf ( "collision %d\n", Game->flyTroughState == 0 ); } else if ( eve.GUIEvent.Caller == gui.Visible_Map && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) { bool v = gui.Visible_Map->isChecked(); if ( MapParent ) { printf ( "static node set visible %d\n",v ); MapParent->setVisible ( v ); } } else if ( eve.GUIEvent.Caller == gui.Visible_Shader && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) { bool v = gui.Visible_Shader->isChecked(); if ( ShaderParent ) { printf ( "shader node set visible %d\n",v ); ShaderParent->setVisible ( v ); } } else if ( eve.GUIEvent.Caller == gui.Visible_Skydome && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) { if ( SkyNode ) { bool v = !SkyNode->isVisible(); printf ( "skynode set visible %d\n",v ); SkyNode->setVisible ( v ); } } else if ( eve.GUIEvent.Caller == gui.Respawn && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) { Player[0].respawn (); } return false; } // fire if ((eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_SPACE && eve.KeyInput.PressedDown == false) || (eve.EventType == EET_MOUSE_INPUT_EVENT && eve.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) ) { ICameraSceneNode * camera = Game->Device->getSceneManager()->getActiveCamera (); if ( camera && camera->isInputReceiverEnabled () ) { useItem( Player + 0 ); } } // gui active if ((eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_F1 && eve.KeyInput.PressedDown == false) || (eve.EventType == EET_MOUSE_INPUT_EVENT && eve.MouseInput.Event == EMIE_RMOUSE_LEFT_UP) ) { SetGUIActive ( 2 ); } // check if user presses the key if ( eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.PressedDown == false) { // Escape toggles camera Input if ( eve.KeyInput.Key == irr::KEY_ESCAPE ) { SetGUIActive ( 3 ); } else if (eve.KeyInput.Key == KEY_F11) { // screenshot are taken without gamma! IImage* image = Game->Device->getVideoDriver()->createScreenShot(); if (image) { core::vector3df pos; core::vector3df rot; ICameraSceneNode * cam = Game->Device->getSceneManager()->getActiveCamera (); if ( cam ) { pos = cam->getPosition (); rot = cam->getRotation (); } static const c8 *dName[] = { "null", "software", "burning", "d3d8", "d3d9", "opengl" }; snprintf(buf, 256, "%s_%ls_%.0f_%.0f_%.0f_%.0f_%.0f_%.0f.jpg", dName[Game->Device->getVideoDriver()->getDriverType()], Game->CurrentMapName.c_str(), pos.X, pos.Y, pos.Z, rot.X, rot.Y, rot.Z ); path filename ( buf ); filename.replace ( '/', '_' ); printf ( "screenshot : %s\n", filename.c_str() ); Game->Device->getVideoDriver()->writeImageToFile(image, filename, 100 ); image->drop(); } } else if (eve.KeyInput.Key == KEY_F9) { s32 value = EDS_OFF; Game->debugState = ( Game->debugState + 1 ) & 3; switch ( Game->debugState ) { case 1: value = EDS_NORMALS | EDS_MESH_WIRE_OVERLAY | EDS_BBOX_ALL; break; case 2: value = EDS_NORMALS | EDS_MESH_WIRE_OVERLAY | EDS_SKELETON; break; } /* // set debug map data on/off debugState = debugState == EDS_OFF ? EDS_NORMALS | EDS_MESH_WIRE_OVERLAY | EDS_BBOX_ALL: EDS_OFF; */ if ( ItemParent ) { list::ConstIterator it = ItemParent->getChildren().begin(); for (; it != ItemParent->getChildren().end(); ++it) { (*it)->setDebugDataVisible ( value ); } } if ( ShaderParent ) { list::ConstIterator it = ShaderParent->getChildren().begin(); for (; it != ShaderParent->getChildren().end(); ++it) { (*it)->setDebugDataVisible ( value ); } } if ( UnresolvedParent ) { list::ConstIterator it = UnresolvedParent->getChildren().begin(); for (; it != UnresolvedParent->getChildren().end(); ++it) { (*it)->setDebugDataVisible ( value ); } } if ( FogParent ) { list::ConstIterator it = FogParent->getChildren().begin(); for (; it != FogParent->getChildren().end(); ++it) { (*it)->setDebugDataVisible ( value ); } } if ( SkyNode ) { SkyNode->setDebugDataVisible ( value ); } } else if (eve.KeyInput.Key == KEY_F8) { // set gravity on/off Game->gravityState ^= 1; Player[0].cam()->setGravity ( getGravity ( Game->gravityState ? "earth" : "none" ) ); printf ( "gravity %s\n", Game->gravityState ? "earth" : "none" ); } else if (eve.KeyInput.Key == KEY_F7) { // set fly through active Game->flyTroughState ^= 1; Player[0].cam()->setAnimateTarget ( Game->flyTroughState == 0 ); if ( gui.Collision ) gui.Collision->setChecked ( Game->flyTroughState == 0 ); printf ( "collision %d\n", Game->flyTroughState == 0 ); } else if (eve.KeyInput.Key == KEY_F2) { Player[0].respawn (); } else if (eve.KeyInput.Key == KEY_F3) { if ( MapParent ) { bool v = !MapParent->isVisible (); printf ( "static node set visible %d\n",v ); MapParent->setVisible ( v ); if ( gui.Visible_Map ) gui.Visible_Map->setChecked ( v ); } } else if (eve.KeyInput.Key == KEY_F4) { if ( ShaderParent ) { bool v = !ShaderParent->isVisible (); printf ( "shader node set visible %d\n",v ); ShaderParent->setVisible ( v ); if ( gui.Visible_Shader ) gui.Visible_Shader->setChecked ( v ); } } else if (eve.KeyInput.Key == KEY_F5) { if ( FogParent ) { bool v = !FogParent->isVisible (); printf ( "fog node set visible %d\n",v ); FogParent->setVisible ( v ); if ( gui.Visible_Fog ) gui.Visible_Fog->setChecked ( v ); } } else if (eve.KeyInput.Key == KEY_F6) { if ( UnresolvedParent ) { bool v = !UnresolvedParent->isVisible (); printf ( "unresolved node set visible %d\n",v ); UnresolvedParent->setVisible ( v ); if ( gui.Visible_Unresolved ) gui.Visible_Unresolved->setChecked ( v ); } } } // check if user presses the key C ( for crouch) if ( eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_KEY_C ) { // crouch ISceneNodeAnimatorCollisionResponse *anim = Player[0].cam (); if ( anim && 0 == Game->flyTroughState ) { if ( false == eve.KeyInput.PressedDown ) { // stand up anim->setEllipsoidRadius ( vector3df(30,45,30) ); anim->setEllipsoidTranslation ( vector3df(0,40,0)); } else { // on your knees anim->setEllipsoidRadius ( vector3df(30,20,30) ); anim->setEllipsoidTranslation ( vector3df(0,20,0)); } return true; } } return false; } /* useItem */ void CQuake3EventHandler::useItem( Q3Player * player) { ISceneManager* smgr = Game->Device->getSceneManager(); ICameraSceneNode* camera = smgr->getActiveCamera(); if (!camera) return; SParticleImpact imp; imp.when = 0; // get line of camera vector3df start = camera->getPosition(); if ( player->WeaponNode ) { start.X += 0.f; start.Y += 0.f; start.Z += 0.f; } vector3df end = (camera->getTarget() - start); end.normalize(); start += end*20.0f; end = start + (end * camera->getFarValue()); triangle3df triangle; line3d line(start, end); // get intersection point with map scene::ISceneNode* hitNode; if (smgr->getSceneCollisionManager()->getCollisionPoint( line, Meta, end, triangle,hitNode)) { // collides with wall vector3df out = triangle.getNormal(); out.setLength(0.03f); imp.when = 1; imp.outVector = out; imp.pos = end; player->setAnim ( "pow" ); player->Anim[1].next += player->Anim[1].delta; } else { // doesnt collide with wall vector3df start = camera->getPosition(); if ( player->WeaponNode ) { //start.X += 10.f; //start.Y += -5.f; //start.Z += 1.f; } vector3df end = (camera->getTarget() - start); end.normalize(); start += end*20.0f; end = start + (end * camera->getFarValue()); } // create fire ball ISceneNode* node = 0; node = smgr->addBillboardSceneNode( BulletParent,dimension2d(10,10), start); node->setMaterialFlag(EMF_LIGHTING, false); node->setMaterialTexture(0, Game->Device->getVideoDriver()->getTexture("fireball.bmp")); node->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); node->setMaterialType(EMT_TRANSPARENT_ADD_COLOR); f32 length = (f32)(end - start).getLength(); const f32 speed = 5.8f; u32 time = (u32)(length / speed); ISceneNodeAnimator* anim = 0; // set flight line anim = smgr->createFlyStraightAnimator(start, end, time); node->addAnimator(anim); anim->drop(); snprintf ( buf, 64, "bullet: %s on %.1f,%1.f,%1.f", imp.when ? "hit" : "nohit", end.X, end.Y, end.Z ); node->setName ( buf ); anim = smgr->createDeleteAnimator(time); node->addAnimator(anim); anim->drop(); if (imp.when) { // create impact note imp.when = Game->Device->getTimer()->getTime() + (time + (s32) ( ( 1.f + Noiser::get() ) * 250.f )); Impacts.push_back(imp); } // play sound } // rendered when bullets hit something void CQuake3EventHandler::createParticleImpacts( u32 now ) { ISceneManager* sm = Game->Device->getSceneManager(); struct smokeLayer { const c8 * texture; f32 scale; f32 minparticleSize; f32 maxparticleSize; f32 boxSize; u32 minParticle; u32 maxParticle; u32 fadeout; u32 lifetime; }; smokeLayer smoke[] = { { "smoke2.jpg", 0.4f, 1.5f, 18.f, 20.f, 20, 50, 2000, 10000 }, { "smoke3.jpg", 0.2f, 1.2f, 15.f, 20.f, 10, 30, 1000, 12000 } }; u32 i; u32 g; s32 factor = 1; for ( g = 0; g != 2; ++g ) { smoke[g].minParticle *= factor; smoke[g].maxParticle *= factor; smoke[g].lifetime *= factor; smoke[g].boxSize *= Noiser::get() * 0.5f; } for ( i=0; i < Impacts.size(); ++i) { if (now < Impacts[i].when) continue; // create smoke particle system IParticleSystemSceneNode* pas = 0; for ( g = 0; g != 2; ++g ) { pas = sm->addParticleSystemSceneNode(false, BulletParent, -1, Impacts[i].pos); snprintf ( buf, 64, "bullet impact smoke at %.1f,%.1f,%1.f", Impacts[i].pos.X,Impacts[i].pos.Y,Impacts[i].pos.Z); pas->setName ( buf ); // create a flat smoke vector3df direction = Impacts[i].outVector; direction *= smoke[g].scale; IParticleEmitter* em = pas->createBoxEmitter( aabbox3d(-4.f,0.f,-4.f,20.f,smoke[g].minparticleSize,20.f), direction,smoke[g].minParticle, smoke[g].maxParticle, video::SColor(0,0,0,0),video::SColor(0,128,128,128), 250,4000, 60); em->setMinStartSize (dimension2d( smoke[g].minparticleSize, smoke[g].minparticleSize)); em->setMaxStartSize (dimension2d( smoke[g].maxparticleSize, smoke[g].maxparticleSize)); pas->setEmitter(em); em->drop(); // particles get invisible IParticleAffector* paf = pas->createFadeOutParticleAffector( video::SColor ( 0, 0, 0, 0 ), smoke[g].fadeout); pas->addAffector(paf); paf->drop(); // particle system life time ISceneNodeAnimator* anim = sm->createDeleteAnimator( smoke[g].lifetime); pas->addAnimator(anim); anim->drop(); pas->setMaterialFlag(video::EMF_LIGHTING, false); pas->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); pas->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); pas->setMaterialTexture(0, Game->Device->getVideoDriver()->getTexture( smoke[g].texture )); } // play impact sound #ifdef USE_IRRKLANG /* if (irrKlang) { audio::ISound* sound = irrKlang->play3D(impactSound, Impacts[i].pos, false, false, true); if (sound) { // adjust max value a bit to make to sound of an impact louder sound->setMinDistance(400); sound->drop(); } } */ #endif // delete entry Impacts.erase(i); i--; } } /* render */ void CQuake3EventHandler::Render() { IVideoDriver * driver = Game->Device->getVideoDriver(); if ( 0 == driver ) return; // TODO: This does not work, yet. const bool anaglyph=false; if (anaglyph) { scene::ICameraSceneNode* cameraOld = Game->Device->getSceneManager()->getActiveCamera(); driver->beginScene(true, true, SColor(0,0,0,0)); driver->getOverrideMaterial().Material.ColorMask = ECP_NONE; driver->getOverrideMaterial().EnableFlags = EMF_COLOR_MASK; driver->getOverrideMaterial().EnablePasses = ESNRP_SKY_BOX + ESNRP_SOLID + ESNRP_TRANSPARENT + ESNRP_TRANSPARENT_EFFECT + ESNRP_SHADOW; Game->Device->getSceneManager()->drawAll(); driver->clearZBuffer(); const vector3df oldPosition = cameraOld->getPosition(); const vector3df oldTarget = cameraOld->getTarget(); const matrix4 startMatrix = cameraOld->getAbsoluteTransformation(); const vector3df focusPoint = (oldTarget - cameraOld->getAbsolutePosition()).setLength(10000) + cameraOld->getAbsolutePosition() ; scene::ICameraSceneNode* camera = cameraOld;//Game->Device->getSceneManager()->addCameraSceneNode(); //Left eye... vector3df pos; matrix4 move; move.setTranslation( vector3df(-1.5f,0.0f,0.0f) ); pos=(startMatrix*move).getTranslation(); driver->getOverrideMaterial().Material.ColorMask = ECP_RED; driver->getOverrideMaterial().EnableFlags = EMF_COLOR_MASK; driver->getOverrideMaterial().EnablePasses = ESNRP_SKY_BOX|ESNRP_SOLID|ESNRP_TRANSPARENT| ESNRP_TRANSPARENT_EFFECT|ESNRP_SHADOW; camera->setPosition(pos); camera->setTarget(focusPoint); Game->Device->getSceneManager()->drawAll(); driver->clearZBuffer(); //Right eye... move.setTranslation( vector3df(1.5f,0.0f,0.0f) ); pos=(startMatrix*move).getTranslation(); driver->getOverrideMaterial().Material.ColorMask = ECP_GREEN + ECP_BLUE; driver->getOverrideMaterial().EnableFlags = EMF_COLOR_MASK; driver->getOverrideMaterial().EnablePasses = ESNRP_SKY_BOX|ESNRP_SOLID|ESNRP_TRANSPARENT| ESNRP_TRANSPARENT_EFFECT|ESNRP_SHADOW; camera->setPosition(pos); camera->setTarget(focusPoint); Game->Device->getSceneManager()->drawAll(); driver->getOverrideMaterial().Material.ColorMask=ECP_ALL; driver->getOverrideMaterial().EnableFlags=0; driver->getOverrideMaterial().EnablePasses=0; if (camera != cameraOld) { Game->Device->getSceneManager()->setActiveCamera(cameraOld); camera->remove(); } else { camera->setPosition(oldPosition); camera->setTarget(oldTarget); } } else { driver->beginScene(true, true, SColor(0,0,0,0)); Game->Device->getSceneManager()->drawAll(); } Game->Device->getGUIEnvironment()->drawAll(); driver->endScene(); } /* update the generic scene node */ void CQuake3EventHandler::Animate() { u32 now = Game->Device->getTimer()->getTime(); Q3Player * player = Player + 0; checkTimeFire ( player->Anim, 4, now ); // Query Scene Manager attributes if ( player->Anim[0].flags & FIRED ) { ISceneManager *smgr = Game->Device->getSceneManager (); wchar_t msg[128]; IVideoDriver * driver = Game->Device->getVideoDriver(); IAttributes * attr = smgr->getParameters(); #ifdef _IRR_SCENEMANAGER_DEBUG swprintf ( msg, 128, L"Q3 %s [%ls], FPS:%03d Tri:%.03fm Cull %d/%d nodes (%d,%d,%d)", Game->CurrentMapName.c_str(), driver->getName(), driver->getFPS (), (f32) driver->getPrimitiveCountDrawn( 0 ) * ( 1.f / 1000000.f ), attr->getAttributeAsInt ( "culled" ), attr->getAttributeAsInt ( "calls" ), attr->getAttributeAsInt ( "drawn_solid" ), attr->getAttributeAsInt ( "drawn_transparent" ), attr->getAttributeAsInt ( "drawn_transparent_effect" ) ); #else swprintf ( msg, 128, L"Q3 %s [%ls], FPS:%03d Tri:%.03fm", Game->CurrentMapName.c_str(), driver->getName(), driver->getFPS (), (f32) driver->getPrimitiveCountDrawn( 0 ) * ( 1.f / 1000000.f ) ); #endif Game->Device->setWindowCaption( msg ); swprintf ( msg, 128, L"%03d fps, F1 GUI on/off, F2 respawn, F3-F6 toggle Nodes, F7 Collision on/off" L", F8 Gravity on/off, Right Mouse Toggle GUI", Game->Device->getVideoDriver()->getFPS () ); if ( gui.StatusLine ) gui.StatusLine->setText ( msg ); player->Anim[0].flags &= ~FIRED; } // idle.. if ( player->Anim[1].flags & FIRED ) { if ( strcmp ( player->animation, "idle" ) ) player->setAnim ( "idle" ); player->Anim[1].flags &= ~FIRED; } createParticleImpacts ( now ); } /* The main game states */ void runGame ( GameData *game ) { if ( game->retVal >= 3 ) return; game->Device = (*game->createExDevice) ( game->deviceParam ); if ( 0 == game->Device) { // could not create selected driver. game->retVal = 0; return; } // create an event receiver based on current game data CQuake3EventHandler *eventHandler = new CQuake3EventHandler( game ); // load stored config game->load ( "explorer.cfg" ); // add our media directory and archive to the file system for ( u32 i = 0; i < game->CurrentArchiveList.size(); ++i ) { eventHandler->AddArchive ( game->CurrentArchiveList[i] ); } // Load a Map or startup to the GUI if ( game->CurrentMapName.size () ) { eventHandler->LoadMap ( game->CurrentMapName, 1 ); if ( 0 == game->loadParam.loadSkyShader ) eventHandler->AddSky ( 1, "skydome2" ); eventHandler->CreatePlayers (); eventHandler->CreateGUI (); eventHandler->SetGUIActive ( 0 ); // set player to last position on restart if ( game->retVal == 2 ) { eventHandler->GetPlayer( 0 )->setpos ( game->PlayerPosition, game->PlayerRotation ); } } else { // start up empty eventHandler->AddSky ( 1, "skydome2" ); eventHandler->CreatePlayers (); eventHandler->CreateGUI (); eventHandler->SetGUIActive ( 1 ); background_music ( "IrrlichtTheme.ogg" ); } game->retVal = 3; while( game->Device->run() ) { eventHandler->Animate (); eventHandler->Render (); //if ( !game->Device->isWindowActive() ) game->Device->yield(); } game->Device->setGammaRamp ( 1.f, 1.f, 1.f, 0.f, 0.f ); delete eventHandler; } #if defined (_IRR_WINDOWS_) && 0 #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") #endif /* The main routine, doing all setup */ int IRRCALLCONV main(int argc, char* argv[]) { path prgname(argv[0]); GameData game ( deletePathFromPath ( prgname, 1 ) ); // dynamically load irrlicht const c8 * dllName = argc > 1 ? argv[1] : "irrlicht.dll"; game.createExDevice = load_createDeviceEx ( dllName ); if ( 0 == game.createExDevice ) { game.retVal = 3; printf ( "Could not load %s.\n", dllName ); return game.retVal; // could not load dll } // start without asking for driver game.retVal = 1; do { // if driver could not created, ask for another driver if ( game.retVal == 0 ) { game.setDefault (); // ask user for driver game.deviceParam.DriverType=driverChoiceConsole(); if (game.deviceParam.DriverType==video::EDT_COUNT) game.retVal = 3; } runGame ( &game ); } while ( game.retVal < 3 ); return game.retVal; } /* **/ irrlicht-1.8.3/examples/20.ManagedLights/0000755000000000000000000000000012574354552016622 5ustar rootrootirrlicht-1.8.3/examples/20.ManagedLights/ManagedLights_vc9.vcproj0000644000000000000000000001240612574354552023342 0ustar rootroot irrlicht-1.8.3/examples/20.ManagedLights/ManagedLights_vc8.vcproj0000644000000000000000000001217612574354552023345 0ustar rootroot irrlicht-1.8.3/examples/20.ManagedLights/ManagedLights_vc12.vcxproj0000644000000000000000000003370212574354552023606 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 20.ManagedLights {16007FE2-142B-47F8-93E1-519BA3F39E71} ManagedLights Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/ManagedLights.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\Lib\Win32-visualstudio\Irrlicht.lib;%(AdditionalDependencies) ..\..\bin\Win32-VisualStudio\20.ManagedLights.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/ManagedLights.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) ..\..\bin\Win64-VisualStudio\20.ManagedLights.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/ManagedLights.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\20.ManagedLights.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/ManagedLights.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\20.ManagedLights.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/20.ManagedLights/ManagedLights_vc11.vcxproj0000644000000000000000000003370112574354552023604 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 20.ManagedLights {16007FE2-142B-47F8-93E1-519BA3F39E71} ManagedLights Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/ManagedLights.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\Lib\Win32-visualstudio\Irrlicht.lib;%(AdditionalDependencies) ..\..\bin\Win32-VisualStudio\20.ManagedLights.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/ManagedLights.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) ..\..\bin\Win64-VisualStudio\20.ManagedLights.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/ManagedLights.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\20.ManagedLights.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/ManagedLights.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\20.ManagedLights.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/20.ManagedLights/ManagedLights_vc10.vcxproj0000644000000000000000000003370112574354552023603 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 20.ManagedLights {16007FE2-142B-47F8-93E1-519BA3F39E71} ManagedLights Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/ManagedLights.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\Lib\Win32-visualstudio\Irrlicht.lib;%(AdditionalDependencies) ..\..\bin\Win32-VisualStudio\20.ManagedLights.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/ManagedLights.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) ..\..\bin\Win64-VisualStudio\20.ManagedLights.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/ManagedLights.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\20.ManagedLights.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/ManagedLights.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\20.ManagedLights.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/20.ManagedLights/ManagedLights.vcproj0000644000000000000000000001060312574354552022556 0ustar rootroot irrlicht-1.8.3/examples/20.ManagedLights/ManagedLights.dev0000644000000000000000000000175012574354552022034 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 20 ManagedLights UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=20.ManagedLights.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/20.ManagedLights/ManagedLights.cbp0000644000000000000000000000303712574354552022022 0ustar rootroot irrlicht-1.8.3/examples/20.ManagedLights/Makefile0000644000000000000000000000233412574354552020264 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 20.ManagedLights Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include #CXXFLAGS = -O3 -ffast-math CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32: CPPFLAGS += -D__GNUWIN32__ -D_WIN32 -DWIN32 -D_WINDOWS -D_MBCS -D_USRDLL all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/20.ManagedLights/main.cpp0000644000000000000000000003347412574354552020265 0ustar rootroot/** Example 020 Managed Lights Written by Colin MacDonald. This tutorial explains the use of the Light Manager of Irrlicht. It enables the use of more dynamic light sources than the actual hardware supports. Further applications of the Light Manager, such as per scene node callbacks, are left out for simplicity of the example. */ #include #include "driverChoice.h" using namespace irr; using namespace core; #if defined(_MSC_VER) #pragma comment(lib, "Irrlicht.lib") #endif // MSC_VER /* Normally, you are limited to 8 dynamic lights per scene: this is a hardware limit. If you want to use more dynamic lights in your scene, then you can register an optional light manager that allows you to to turn lights on and off at specific point during rendering. You are still limited to 8 lights, but the limit is per scene node. This is completely optional: if you do not register a light manager, then a default distance-based scheme will be used to prioritise hardware lights based on their distance from the active camera. NO_MANAGEMENT disables the light manager and shows Irrlicht's default light behaviour. The 8 lights nearest to the camera will be turned on, and other lights will be turned off. In this example, this produces a funky looking but incoherent light display. LIGHTS_NEAREST_NODE shows an implementation that turns on a limited number of lights per mesh scene node. If finds the 3 lights that are nearest to the node being rendered, and turns them on, turning all other lights off. This works, but as it operates on every light for every node, it does not scale well with many lights. The flickering you can see in this demo is due to the lights swapping their relative positions from the cubes (a deliberate demonstration of the limitations of this technique). LIGHTS_IN_ZONE shows a technique for turning on lights based on a 'zone'. Each empty scene node is considered to be the parent of a zone. When nodes are rendered, they turn off all lights, then find their parent 'zone' and turn on all lights that are inside that zone, i.e. are descendents of it in the scene graph. This produces true 'local' lighting for each cube in this example. You could use a similar technique to locally light all meshes in (e.g.) a room, without the lights spilling out to other rooms. This light manager is also an event receiver; this is purely for simplicity in this example, it's neither necessary nor recommended for a real application. */ class CMyLightManager : public scene::ILightManager, public IEventReceiver { typedef enum { NO_MANAGEMENT, LIGHTS_NEAREST_NODE, LIGHTS_IN_ZONE } LightManagementMode; LightManagementMode Mode; LightManagementMode RequestedMode; // These data represent the state information that this light manager // is interested in. scene::ISceneManager * SceneManager; core::array * SceneLightList; scene::E_SCENE_NODE_RENDER_PASS CurrentRenderPass; scene::ISceneNode * CurrentSceneNode; public: CMyLightManager(scene::ISceneManager* sceneManager) : Mode(NO_MANAGEMENT), RequestedMode(NO_MANAGEMENT), SceneManager(sceneManager), SceneLightList(0), CurrentRenderPass(scene::ESNRP_NONE), CurrentSceneNode(0) { } // The input receiver interface, which just switches light management strategy bool OnEvent(const SEvent & event) { bool handled = false; if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown) { handled = true; switch(event.KeyInput.Key) { case irr::KEY_KEY_1: RequestedMode = NO_MANAGEMENT; break; case irr::KEY_KEY_2: RequestedMode = LIGHTS_NEAREST_NODE; break; case irr::KEY_KEY_3: RequestedMode = LIGHTS_IN_ZONE; break; default: handled = false; break; } if(NO_MANAGEMENT == RequestedMode) SceneManager->setLightManager(0); // Show that it's safe to register the light manager else SceneManager->setLightManager(this); } return handled; } // This is called before the first scene node is rendered. virtual void OnPreRender(core::array & lightList) { // Update the mode; changing it here ensures that it's consistent throughout a render Mode = RequestedMode; // Store the light list. I am free to alter this list until the end of OnPostRender(). SceneLightList = &lightList; } // Called after the last scene node is rendered. virtual void OnPostRender() { // Since light management might be switched off in the event handler, we'll turn all // lights on to ensure that they are in a consistent state. You wouldn't normally have // to do this when using a light manager, since you'd continue to do light management // yourself. for (u32 i = 0; i < SceneLightList->size(); i++) (*SceneLightList)[i]->setVisible(true); } virtual void OnRenderPassPreRender(scene::E_SCENE_NODE_RENDER_PASS renderPass) { // I don't have to do anything here except remember which render pass I am in. CurrentRenderPass = renderPass; } virtual void OnRenderPassPostRender(scene::E_SCENE_NODE_RENDER_PASS renderPass) { // I only want solid nodes to be lit, so after the solid pass, turn all lights off. if (scene::ESNRP_SOLID == renderPass) { for (u32 i = 0; i < SceneLightList->size(); ++i) (*SceneLightList)[i]->setVisible(false); } } // This is called before the specified scene node is rendered virtual void OnNodePreRender(scene::ISceneNode* node) { CurrentSceneNode = node; // This light manager only considers solid objects, but you are free to manipulate // lights during any phase, depending on your requirements. if (scene::ESNRP_SOLID != CurrentRenderPass) return; // And in fact for this example, I only want to consider lighting for cube scene // nodes. You will probably want to deal with lighting for (at least) mesh / // animated mesh scene nodes as well. if (node->getType() != scene::ESNT_CUBE) return; if (LIGHTS_NEAREST_NODE == Mode) { // This is a naive implementation that prioritises every light in the scene // by its proximity to the node being rendered. This produces some flickering // when lights orbit closer to a cube than its 'zone' lights. const vector3df nodePosition = node->getAbsolutePosition(); // Sort the light list by prioritising them based on their distance from the node // that's about to be rendered. array sortingArray; sortingArray.reallocate(SceneLightList->size()); u32 i; for(i = 0; i < SceneLightList->size(); ++i) { scene::ISceneNode* lightNode = (*SceneLightList)[i]; const f64 distance = lightNode->getAbsolutePosition().getDistanceFromSQ(nodePosition); sortingArray.push_back(LightDistanceElement(lightNode, distance)); } sortingArray.sort(); // The list is now sorted by proximity to the node. // Turn on the three nearest lights, and turn the others off. for(i = 0; i < sortingArray.size(); ++i) sortingArray[i].node->setVisible(i < 3); } else if(LIGHTS_IN_ZONE == Mode) { // Empty scene nodes are used to represent 'zones'. For each solid mesh that // is being rendered, turn off all lights, then find its 'zone' parent, and turn // on all lights that are found under that node in the scene graph. // This is a general purpose algorithm that doesn't use any special // knowledge of how this particular scene graph is organised. for (u32 i = 0; i < SceneLightList->size(); ++i) { if ((*SceneLightList)[i]->getType() != scene::ESNT_LIGHT) continue; scene::ILightSceneNode* lightNode = static_cast((*SceneLightList)[i]); video::SLight & lightData = lightNode->getLightData(); if (video::ELT_DIRECTIONAL != lightData.Type) lightNode->setVisible(false); } scene::ISceneNode * parentZone = findZone(node); if (parentZone) turnOnZoneLights(parentZone); } } // Called after the specified scene node is rendered virtual void OnNodePostRender(scene::ISceneNode* node) { // I don't need to do any light management after individual node rendering. } private: // Find the empty scene node that is the parent of the specified node scene::ISceneNode * findZone(scene::ISceneNode * node) { if (!node) return 0; if (node->getType() == scene::ESNT_EMPTY) return node; return findZone(node->getParent()); } // Turn on all lights that are children (directly or indirectly) of the // specified scene node. void turnOnZoneLights(scene::ISceneNode * node) { core::list const & children = node->getChildren(); for (core::list::ConstIterator child = children.begin(); child != children.end(); ++child) { if ((*child)->getType() == scene::ESNT_LIGHT) (*child)->setVisible(true); else // Assume that lights don't have any children that are also lights turnOnZoneLights(*child); } } // A utility class to aid in sorting scene nodes into a distance order class LightDistanceElement { public: LightDistanceElement() {}; LightDistanceElement(scene::ISceneNode* n, f64 d) : node(n), distance(d) { } scene::ISceneNode* node; f64 distance; // Lower distance elements are sorted to the start of the array bool operator < (const LightDistanceElement& other) const { return (distance < other.distance); } }; }; /* */ int main(int argumentCount, char * argumentValues[]) { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; IrrlichtDevice *device = createDevice(driverType, dimension2d(640, 480), 32); if(!device) return -1; f32 const lightRadius = 60.f; // Enough to reach the far side of each 'zone' video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* guienv = device->getGUIEnvironment(); gui::IGUISkin* skin = guienv->getSkin(); if (skin) { skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255, 255, 255, 255)); gui::IGUIFont* font = guienv->getFont("../../media/fontlucida.png"); if(font) skin->setFont(font); } guienv->addStaticText(L"1 - No light management", core::rect(10,10,200,30)); guienv->addStaticText(L"2 - Closest 3 lights", core::rect(10,30,200,50)); guienv->addStaticText(L"3 - Lights in zone", core::rect(10,50,200,70)); /* Add several "zones". You could use this technique to light individual rooms, for example. */ for(f32 zoneX = -100.f; zoneX <= 100.f; zoneX += 50.f) for(f32 zoneY = -60.f; zoneY <= 60.f; zoneY += 60.f) { // Start with an empty scene node, which we will use to represent a zone. scene::ISceneNode * zoneRoot = smgr->addEmptySceneNode(); zoneRoot->setPosition(vector3df(zoneX, zoneY, 0)); // Each zone contains a rotating cube scene::IMeshSceneNode * node = smgr->addCubeSceneNode(15, zoneRoot); scene::ISceneNodeAnimator * rotation = smgr->createRotationAnimator(vector3df(0.25f, 0.5f, 0.75f)); node->addAnimator(rotation); rotation->drop(); // And each cube has three lights attached to it. The lights are attached to billboards so // that we can see where they are. The billboards are attached to the cube, so that the // lights are indirect descendents of the same empty scene node as the cube. scene::IBillboardSceneNode * billboard = smgr->addBillboardSceneNode(node); billboard->setPosition(vector3df(0, -14, 30)); billboard->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); billboard->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp")); billboard->setMaterialFlag(video::EMF_LIGHTING, false); smgr->addLightSceneNode(billboard, vector3df(0, 0, 0), video::SColorf(1, 0, 0), lightRadius); billboard = smgr->addBillboardSceneNode(node); billboard->setPosition(vector3df(-21, -14, -21)); billboard->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); billboard->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp")); billboard->setMaterialFlag(video::EMF_LIGHTING, false); smgr->addLightSceneNode(billboard, vector3df(0, 0, 0), video::SColorf(0, 1, 0), lightRadius); billboard = smgr->addBillboardSceneNode(node); billboard->setPosition(vector3df(21, -14, -21)); billboard->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); billboard->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp")); billboard->setMaterialFlag(video::EMF_LIGHTING, false); smgr->addLightSceneNode(billboard, vector3df(0, 0, 0), video::SColorf(0, 0, 1), lightRadius); // Each cube also has a smaller cube rotating around it, to show that the cubes are being // lit by the lights in their 'zone', not just lights that are their direct children. node = smgr->addCubeSceneNode(5, node); node->setPosition(vector3df(0, 21, 0)); } smgr->addCameraSceneNode(0, vector3df(0,0,-130), vector3df(0,0,0)); CMyLightManager * myLightManager = new CMyLightManager(smgr); smgr->setLightManager(0); // This is the default: we won't do light management until told to do it. device->setEventReceiver(myLightManager); int lastFps = -1; while(device->run()) { driver->beginScene(true, true, video::SColor(255,100,101,140)); smgr->drawAll(); guienv->drawAll(); driver->endScene(); int fps = driver->getFPS(); if(fps != lastFps) { lastFps = fps; core::stringw str = L"Managed Lights ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); } } myLightManager->drop(); // Drop my implicit reference device->drop(); return 0; } /* **/ irrlicht-1.8.3/examples/19.MouseAndJoystick/0000755000000000000000000000000012574354552017356 5ustar rootrootirrlicht-1.8.3/examples/19.MouseAndJoystick/MouseAndJoystick_vc9.vcproj0000644000000000000000000001233412574354552024622 0ustar rootroot irrlicht-1.8.3/examples/19.MouseAndJoystick/MouseAndJoystick_vc8.vcproj0000644000000000000000000001223412574354552024620 0ustar rootroot irrlicht-1.8.3/examples/19.MouseAndJoystick/MouseAndJoystick_vc12.vcxproj0000644000000000000000000003264612574354552025074 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 19.MouseAndJoystick {FE853A36-E0D1-4AC5-A792-B643E70D2953} MouseAndJoystick Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/MouseAndJoystick.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\19.MouseAndJoystick.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/MouseAndJoystick.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\19.MouseAndJoystick.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/MouseAndJoystick.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\19.MouseAndJoystick.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/MouseAndJoystick.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\19.MouseAndJoystick.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/19.MouseAndJoystick/MouseAndJoystick_vc11.vcxproj0000644000000000000000000003264512574354552025072 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 19.MouseAndJoystick {FE853A36-E0D1-4AC5-A792-B643E70D2953} MouseAndJoystick Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/MouseAndJoystick.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\19.MouseAndJoystick.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/MouseAndJoystick.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\19.MouseAndJoystick.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/MouseAndJoystick.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\19.MouseAndJoystick.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/MouseAndJoystick.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\19.MouseAndJoystick.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/19.MouseAndJoystick/MouseAndJoystick_vc10.vcxproj0000644000000000000000000003264512574354552025071 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 19.MouseAndJoystick {FE853A36-E0D1-4AC5-A792-B643E70D2953} MouseAndJoystick Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/MouseAndJoystick.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\19.MouseAndJoystick.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/MouseAndJoystick.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\19.MouseAndJoystick.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/MouseAndJoystick.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\19.MouseAndJoystick.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/MouseAndJoystick.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\19.MouseAndJoystick.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/19.MouseAndJoystick/MouseAndJoystick.vcproj0000644000000000000000000001054412574354552024042 0ustar rootroot irrlicht-1.8.3/examples/19.MouseAndJoystick/MouseAndJoystick.dev0000644000000000000000000000175612574354552023322 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 04 MouseAndJoystick UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=19.MouseAndJoystick.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/19.MouseAndJoystick/MouseAndJoystick.cbp0000644000000000000000000000276212574354552023306 0ustar rootroot irrlicht-1.8.3/examples/19.MouseAndJoystick/Makefile0000644000000000000000000000233712574354552021023 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 19.MouseAndJoystick Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include #CXXFLAGS = -O3 -ffast-math CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32: CPPFLAGS += -D__GNUWIN32__ -D_WIN32 -DWIN32 -D_WINDOWS -D_MBCS -D_USRDLL all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/19.MouseAndJoystick/main.cpp0000644000000000000000000002064312574354552021013 0ustar rootroot/** Example 019 Mouse and Joystick This tutorial builds on example 04.Movement which showed how to handle keyboard events in Irrlicht. Here we'll handle mouse events and joystick events, if you have a joystick connected and a device that supports joysticks. These are currently Windows, Linux and SDL devices. */ #ifdef _MSC_VER // We'll define this to stop MSVC complaining about sprintf(). #define _CRT_SECURE_NO_WARNINGS #pragma comment(lib, "Irrlicht.lib") #endif #include #include "driverChoice.h" using namespace irr; /* Just as we did in example 04.Movement, we'll store the latest state of the mouse and the first joystick, updating them as we receive events. */ class MyEventReceiver : public IEventReceiver { public: // We'll create a struct to record info on the mouse state struct SMouseState { core::position2di Position; bool LeftButtonDown; SMouseState() : LeftButtonDown(false) { } } MouseState; // This is the one method that we have to implement virtual bool OnEvent(const SEvent& event) { // Remember the mouse state if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) { switch(event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: MouseState.LeftButtonDown = true; break; case EMIE_LMOUSE_LEFT_UP: MouseState.LeftButtonDown = false; break; case EMIE_MOUSE_MOVED: MouseState.Position.X = event.MouseInput.X; MouseState.Position.Y = event.MouseInput.Y; break; default: // We won't use the wheel break; } } // The state of each connected joystick is sent to us // once every run() of the Irrlicht device. Store the // state of the first joystick, ignoring other joysticks. // This is currently only supported on Windows and Linux. if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT && event.JoystickEvent.Joystick == 0) { JoystickState = event.JoystickEvent; } return false; } const SEvent::SJoystickEvent & GetJoystickState(void) const { return JoystickState; } const SMouseState & GetMouseState(void) const { return MouseState; } MyEventReceiver() { } private: SEvent::SJoystickEvent JoystickState; }; /* The event receiver for keeping the pressed keys is ready, the actual responses will be made inside the render loop, right before drawing the scene. So lets just create an irr::IrrlichtDevice and the scene node we want to move. We also create some other additional scene nodes, to show that there are also some different possibilities to move and animate scene nodes. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device MyEventReceiver receiver; IrrlichtDevice* device = createDevice(driverType, core::dimension2d(640, 480), 16, false, false, false, &receiver); if (device == 0) return 1; // could not create selected driver. core::array joystickInfo; if(device->activateJoysticks(joystickInfo)) { std::cout << "Joystick support is enabled and " << joystickInfo.size() << " joystick(s) are present." << std::endl; for(u32 joystick = 0; joystick < joystickInfo.size(); ++joystick) { std::cout << "Joystick " << joystick << ":" << std::endl; std::cout << "\tName: '" << joystickInfo[joystick].Name.c_str() << "'" << std::endl; std::cout << "\tAxes: " << joystickInfo[joystick].Axes << std::endl; std::cout << "\tButtons: " << joystickInfo[joystick].Buttons << std::endl; std::cout << "\tHat is: "; switch(joystickInfo[joystick].PovHat) { case SJoystickInfo::POV_HAT_PRESENT: std::cout << "present" << std::endl; break; case SJoystickInfo::POV_HAT_ABSENT: std::cout << "absent" << std::endl; break; case SJoystickInfo::POV_HAT_UNKNOWN: default: std::cout << "unknown" << std::endl; break; } } } else { std::cout << "Joystick support is not enabled." << std::endl; } core::stringw tmp = L"Irrlicht Joystick Example ("; tmp += joystickInfo.size(); tmp += " joysticks)"; device->setWindowCaption(tmp.c_str()); video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); /* We'll create an arrow mesh and move it around either with the joystick axis/hat, or make it follow the mouse pointer. */ scene::ISceneNode * node = smgr->addMeshSceneNode( smgr->addArrowMesh( "Arrow", video::SColor(255, 255, 0, 0), video::SColor(255, 0, 255, 0), 16,16, 2.f, 1.3f, 0.1f, 0.6f ) ); node->setMaterialFlag(video::EMF_LIGHTING, false); scene::ICameraSceneNode * camera = smgr->addCameraSceneNode(); camera->setPosition(core::vector3df(0, 0, -10)); // As in example 04, we'll use framerate independent movement. u32 then = device->getTimer()->getTime(); const f32 MOVEMENT_SPEED = 5.f; while(device->run()) { // Work out a frame delta time. const u32 now = device->getTimer()->getTime(); const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds then = now; bool movedWithJoystick = false; core::vector3df nodePosition = node->getPosition(); if(joystickInfo.size() > 0) { f32 moveHorizontal = 0.f; // Range is -1.f for full left to +1.f for full right f32 moveVertical = 0.f; // -1.f for full down to +1.f for full up. const SEvent::SJoystickEvent & joystickData = receiver.GetJoystickState(); // We receive the full analog range of the axes, and so have to implement our // own dead zone. This is an empirical value, since some joysticks have more // jitter or creep around the center point than others. We'll use 5% of the // range as the dead zone, but generally you would want to give the user the // option to change this. const f32 DEAD_ZONE = 0.05f; moveHorizontal = (f32)joystickData.Axis[SEvent::SJoystickEvent::AXIS_X] / 32767.f; if(fabs(moveHorizontal) < DEAD_ZONE) moveHorizontal = 0.f; moveVertical = (f32)joystickData.Axis[SEvent::SJoystickEvent::AXIS_Y] / -32767.f; if(fabs(moveVertical) < DEAD_ZONE) moveVertical = 0.f; // POV hat info is only currently supported on Windows, but the value is // guaranteed to be 65535 if it's not supported, so we can check its range. const u16 povDegrees = joystickData.POV / 100; if(povDegrees < 360) { if(povDegrees > 0 && povDegrees < 180) moveHorizontal = 1.f; else if(povDegrees > 180) moveHorizontal = -1.f; if(povDegrees > 90 && povDegrees < 270) moveVertical = -1.f; else if(povDegrees > 270 || povDegrees < 90) moveVertical = +1.f; } if(!core::equals(moveHorizontal, 0.f) || !core::equals(moveVertical, 0.f)) { nodePosition.X += MOVEMENT_SPEED * frameDeltaTime * moveHorizontal; nodePosition.Y += MOVEMENT_SPEED * frameDeltaTime * moveVertical; movedWithJoystick = true; } } // If the arrow node isn't being moved with the joystick, then have it follow the mouse cursor. if(!movedWithJoystick) { // Create a ray through the mouse cursor. core::line3df ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates( receiver.GetMouseState().Position, camera); // And intersect the ray with a plane around the node facing towards the camera. core::plane3df plane(nodePosition, core::vector3df(0, 0, -1)); core::vector3df mousePosition; if(plane.getIntersectionWithLine(ray.start, ray.getVector(), mousePosition)) { // We now have a mouse position in 3d space; move towards it. core::vector3df toMousePosition(mousePosition - nodePosition); const f32 availableMovement = MOVEMENT_SPEED * frameDeltaTime; if(toMousePosition.getLength() <= availableMovement) nodePosition = mousePosition; // Jump to the final position else nodePosition += toMousePosition.normalize() * availableMovement; // Move towards it } } node->setPosition(nodePosition); // Turn lighting on and off depending on whether the left mouse button is down. node->setMaterialFlag(video::EMF_LIGHTING, receiver.GetMouseState().LeftButtonDown); driver->beginScene(true, true, video::SColor(255,113,113,133)); smgr->drawAll(); // draw the 3d scene driver->endScene(); } /* In the end, delete the Irrlicht device. */ device->drop(); return 0; } /* **/ irrlicht-1.8.3/examples/18.SplitScreen/0000755000000000000000000000000012574354552016355 5ustar rootrootirrlicht-1.8.3/examples/18.SplitScreen/SplitScreen_vc9.vcproj0000644000000000000000000000772612574354552022632 0ustar rootroot irrlicht-1.8.3/examples/18.SplitScreen/SplitScreen_vc8.vcproj0000644000000000000000000000765412574354552022631 0ustar rootroot irrlicht-1.8.3/examples/18.SplitScreen/SplitScreen_vc12.vcxproj0000644000000000000000000002602412574354552023064 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 18.SplitScreen {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0} 18.SplitScreen Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\18.SplitScreen.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)SplitScreen.pdb Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\18.SplitScreen.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)SplitScreen.pdb Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 Cdecl ..\..\bin\Win32-VisualStudio\18.SplitScreen.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 Cdecl ..\..\bin\Win64-VisualStudio\18.SplitScreen.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/18.SplitScreen/SplitScreen_vc11.vcxproj0000644000000000000000000002602312574354552023062 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 18.SplitScreen {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0} 18.SplitScreen Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\18.SplitScreen.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)SplitScreen.pdb Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\18.SplitScreen.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)SplitScreen.pdb Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 Cdecl ..\..\bin\Win32-VisualStudio\18.SplitScreen.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 Cdecl ..\..\bin\Win64-VisualStudio\18.SplitScreen.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/18.SplitScreen/SplitScreen_vc10.vcxproj0000644000000000000000000002602312574354552023061 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 18.SplitScreen {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0} 18.SplitScreen Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\18.SplitScreen.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)SplitScreen.pdb Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\18.SplitScreen.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true $(OutDir)SplitScreen.pdb Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 Cdecl ..\..\bin\Win32-VisualStudio\18.SplitScreen.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 Cdecl ..\..\bin\Win64-VisualStudio\18.SplitScreen.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/18.SplitScreen/SplitScreen.vcproj0000644000000000000000000000670212574354552022042 0ustar rootroot irrlicht-1.8.3/examples/18.SplitScreen/SplitScreen.dev0000644000000000000000000000174412574354552021316 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 18 SplitScreen UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=18.SplitScreen.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/18.SplitScreen/SplitScreen.cbp0000644000000000000000000000267312574354552021306 0ustar rootroot irrlicht-1.8.3/examples/18.SplitScreen/Makefile0000644000000000000000000000220512574354552020014 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 18.SplitScreen Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/18.SplitScreen/main.cpp0000644000000000000000000001567112574354552020017 0ustar rootroot/** Example 018 Splitscreen A tutorial by Max Winkel. In this tutorial we'll learn how to use splitscreen (e.g. for racing-games) with Irrlicht. We'll create a viewport divided into 4 parts, with 3 fixed cameras and one user-controlled. Ok, let's start with the headers (I think there's nothing to say about it) */ #include #include "driverChoice.h" #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif //Namespaces for the engine using namespace irr; using namespace core; using namespace video; using namespace scene; /* Now we'll define the resolution in a constant for use in initializing the device and setting up the viewport. In addition we set up a global variable saying splitscreen is active or not. */ //Resolution const int ResX=800; const int ResY=600; const bool fullScreen=false; //Use SplitScreen? bool SplitScreen=true; /* Now we need four pointers to our cameras which are created later: */ //cameras ICameraSceneNode *camera[4]={0,0,0,0}; /* In our event-receiver we switch the SplitScreen-variable, whenever the user press the S-key. All other events are sent to the FPS camera. */ class MyEventReceiver : public IEventReceiver { public: virtual bool OnEvent(const SEvent& event) { //Key S enables/disables SplitScreen if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.Key == KEY_KEY_S && event.KeyInput.PressedDown) { SplitScreen = !SplitScreen; return true; } //Send all other events to camera4 if (camera[3]) return camera[3]->OnEvent(event); return false; } }; /* Ok, now the main-function: First, we initialize the device, get the SourceManager and VideoDriver, load an animated mesh from .md2 and a map from .pk3. Because that's old stuff, I won't explain every step. Just take care of the maps position. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; //Instance of the EventReceiver MyEventReceiver receiver; //Initialise the engine IrrlichtDevice *device = createDevice(driverType, dimension2du(ResX,ResY), 32, fullScreen, false, false, &receiver); if (!device) return 1; ISceneManager *smgr = device->getSceneManager(); IVideoDriver *driver = device->getVideoDriver(); //Load model IAnimatedMesh *model = smgr->getMesh("../../media/sydney.md2"); if (!model) return 1; IAnimatedMeshSceneNode *model_node = smgr->addAnimatedMeshSceneNode(model); //Load texture if (model_node) { ITexture *texture = driver->getTexture("../../media/sydney.bmp"); model_node->setMaterialTexture(0,texture); model_node->setMD2Animation(scene::EMAT_RUN); //Disable lighting (we've got no light) model_node->setMaterialFlag(EMF_LIGHTING,false); } //Load map device->getFileSystem()->addFileArchive("../../media/map-20kdm2.pk3"); IAnimatedMesh *map = smgr->getMesh("20kdm2.bsp"); if (map) { ISceneNode *map_node = smgr->addOctreeSceneNode(map->getMesh(0)); //Set position map_node->setPosition(vector3df(-850,-220,-850)); } /* Now we create our four cameras. One is looking at the model from the front, one from the top and one from the side. In addition there's a FPS-camera which can be controlled by the user. */ // Create 3 fixed and one user-controlled cameras //Front camera[0] = smgr->addCameraSceneNode(0, vector3df(50,0,0), vector3df(0,0,0)); //Top camera[1] = smgr->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0)); //Left camera[2] = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0)); //User-controlled camera[3] = smgr->addCameraSceneNodeFPS(); // don't start at sydney's position if (camera[3]) camera[3]->setPosition(core::vector3df(-50,0,-50)); /* Create a variable for counting the fps and hide the mouse: */ //Hide mouse device->getCursorControl()->setVisible(false); //We want to count the fps int lastFPS = -1; /* There wasn't much new stuff - till now! Only by defining four cameras, the game won't be splitscreen. To do this you need several steps: - Set the viewport to the whole screen - Begin a new scene (Clear screen) - The following 3 steps are repeated for every viewport in the splitscreen - Set the viewport to the area you wish - Activate the camera which should be "linked" with the viewport - Render all objects - If you have a GUI: - Set the viewport the whole screen - Display the GUI - End scene Sounds a little complicated, but you'll see it isn't: */ while(device->run()) { //Set the viewpoint to the whole screen and begin scene driver->setViewPort(rect(0,0,ResX,ResY)); driver->beginScene(true,true,SColor(255,100,100,100)); //If SplitScreen is used if (SplitScreen) { //Activate camera1 smgr->setActiveCamera(camera[0]); //Set viewpoint to the first quarter (left top) driver->setViewPort(rect(0,0,ResX/2,ResY/2)); //Draw scene smgr->drawAll(); //Activate camera2 smgr->setActiveCamera(camera[1]); //Set viewpoint to the second quarter (right top) driver->setViewPort(rect(ResX/2,0,ResX,ResY/2)); //Draw scene smgr->drawAll(); //Activate camera3 smgr->setActiveCamera(camera[2]); //Set viewpoint to the third quarter (left bottom) driver->setViewPort(rect(0,ResY/2,ResX/2,ResY)); //Draw scene smgr->drawAll(); //Set viewport the last quarter (right bottom) driver->setViewPort(rect(ResX/2,ResY/2,ResX,ResY)); } //Activate camera4 smgr->setActiveCamera(camera[3]); //Draw scene smgr->drawAll(); driver->endScene(); /* As you can probably see, the image is rendered for every viewport separately. That means, that you'll loose much performance. Ok, if you're asking "How do I have to set the viewport to get this or that screen?", don't panic. It's really easy: In the rect-function you define 4 coordinates: - X-coordinate of the corner left top - Y-coordinate of the corner left top - X-coordinate of the corner right bottom - Y-coordinate of the corner right bottom That means, if you want to split the screen into 2 viewports you would give the following coordinates: - 1st viewport: 0,0,ResX/2,ResY - 2nd viewport: ResX/2,0,ResX,ResY If you didn't fully understand, just play around with the example to check out what happens. Now we just view the current fps and shut down the engine, when the user wants to: */ //Get and show fps if (driver->getFPS() != lastFPS) { lastFPS = driver->getFPS(); core::stringw tmp = L"Irrlicht SplitScreen-Example (FPS: "; tmp += lastFPS; tmp += ")"; device->setWindowCaption(tmp.c_str()); } } //Delete device device->drop(); return 0; } /* That's it! Just compile and play around with the program. Note: With the S-Key you can switch between using splitscreen and not. **/ irrlicht-1.8.3/examples/17.HelloWorld_Mobile/0000755000000000000000000000000012574354552017463 5ustar rootrootirrlicht-1.8.3/examples/17.HelloWorld_Mobile/main.cpp0000644000000000000000000003453012574354552021120 0ustar rootroot/** Example 017 Helloworld mobile This example show Hello World for Windows mobile. It compiles on other platform too. The only differences between the original examples are. You need a GUI, because otherwise you can't quit the application. You need a Filesystem, which is relative based to your executable. */ #include #if defined ( _IRR_WINDOWS_ ) #include #endif using namespace irr; using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; #pragma comment(lib, "Irrlicht.lib") class EventReceiver_basic : public IEventReceiver { private: IrrlichtDevice *Device; public: EventReceiver_basic ( IrrlichtDevice *device ): Device ( device ) {} virtual bool OnEvent(const SEvent& event) { if (event.EventType == EET_GUI_EVENT) { s32 id = event.GUIEvent.Caller->getID(); switch(event.GUIEvent.EventType) { case EGET_BUTTON_CLICKED: if (id == 2) { Device->closeDevice(); return true; } break; } } return false; } }; class CSampleSceneNode : public ISceneNode { aabbox3d Box; S3DVertex Vertices[4]; SMaterial Material; public: CSampleSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id) : ISceneNode(parent, mgr, id) { Material.Wireframe = false; Material.Lighting = false; Vertices[0] = S3DVertex(0,0,10, 1,1,0, SColor(255,0,255,255), 0, 1); Vertices[1] = S3DVertex(10,0,-10, 1,0,0, SColor(255,255,0,255), 1, 1); Vertices[2] = S3DVertex(0,20,0, 0,1,1, SColor(255,255,255,0), 1, 0); Vertices[3] = S3DVertex(-10,0,-10, 0,0,1, SColor(255,0,255,0), 0, 0); Box.reset(Vertices[0].Pos); for (s32 i=1; i<4; ++i) Box.addInternalPoint(Vertices[i].Pos); } virtual void OnRegisterSceneNode() { if (IsVisible) SceneManager->registerNodeForRendering(this); ISceneNode::OnRegisterSceneNode(); } virtual void render() { u16 indices[] = { 0,2,3, 2,1,3, 1,0,3, 2,0,1 }; IVideoDriver* driver = SceneManager->getVideoDriver(); driver->setMaterial(Material); driver->setTransform(ETS_WORLD, AbsoluteTransformation); driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 4); } virtual const aabbox3d& getBoundingBox() const { return Box; } virtual u32 getMaterialCount() { return 1; } virtual SMaterial& getMaterial(u32 i) { return Material; } }; /*! Startup a Windows Mobile Device */ IrrlichtDevice *startup() { // both software and burnings video can be used E_DRIVER_TYPE driverType = EDT_SOFTWARE; // EDT_BURNINGSVIDEO; // create device IrrlichtDevice *device = 0; #if defined (_IRR_USE_WINDOWS_CE_DEVICE_) // set to standard mobile fullscreen 240x320 device = createDevice(driverType, dimension2d(240, 320), 16, true ); #else // on PC. use window mode device = createDevice(driverType, dimension2d(240, 320), 16, false ); #endif if ( 0 == device ) return 0; IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); IGUIEnvironment* guienv = device->getGUIEnvironment(); // set the filesystem relative to the executable #if defined (_IRR_WINDOWS_) { wchar_t buf[255]; GetModuleFileNameW ( 0, buf, 255 ); io::path base = buf; base = base.subString ( 0, base.findLast ( '\\' ) + 1 ); device->getFileSystem()->addFileArchive ( base ); } #endif IGUIStaticText *text = guienv->addStaticText(L"FPS: 25", rect(140,15,200,30), false, false, 0, 100 ); guienv->addButton(core::rect(200,10,238,30), 0, 2, L"Quit"); // add irrlicht logo guienv->addImage(driver->getTexture("../../media/irrlichtlogo3.png"), core::position2d(0,-2)); return device; } /*! */ int run ( IrrlichtDevice *device ) { while(device->run()) if (device->isWindowActive()) { device->getVideoDriver()->beginScene(true, true, SColor(0,100,100,100)); device->getSceneManager()->drawAll(); device->getGUIEnvironment()->drawAll(); device->getVideoDriver()->endScene (); IGUIElement *stat = device->getGUIEnvironment()-> getRootGUIElement()->getElementFromId ( 100 ); if ( stat ) { stringw str = L"FPS: "; str += (s32)device->getVideoDriver()->getFPS(); stat->setText ( str.c_str() ); } } device->drop(); return 0; } /*! */ int example_customscenenode() { // create device IrrlichtDevice *device = startup(); if (device == 0) return 1; // could not create selected driver. // create engine and camera EventReceiver_basic receiver(device); device->setEventReceiver(&receiver); IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); IGUIEnvironment* guienv = device->getGUIEnvironment(); smgr->addCameraSceneNode(0, vector3df(0,-40,0), vector3df(0,0,0)); CSampleSceneNode *myNode = new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666); ISceneNodeAnimator* anim = smgr->createRotationAnimator(vector3df(0.8f, 0, 0.8f)); if(anim) { myNode->addAnimator(anim); anim->drop(); anim = 0; // As I shouldn't refer to it again, ensure that I can't } myNode->drop(); myNode = 0; // As I shouldn't refer to it again, ensure that I can't return run ( device ); } class EventReceiver_terrain : public IEventReceiver { public: EventReceiver_terrain(IrrlichtDevice *device, scene::ISceneNode* terrain, scene::ISceneNode* skybox, scene::ISceneNode* skydome) : Device ( device ), Terrain(terrain), Skybox(skybox), Skydome(skydome), showBox(true) { Skybox->setVisible(true); Skydome->setVisible(false); } bool OnEvent(const SEvent& event) { if (event.EventType == EET_GUI_EVENT) { s32 id = event.GUIEvent.Caller->getID(); switch(event.GUIEvent.EventType) { case EGET_BUTTON_CLICKED: if (id == 2) { Device->closeDevice(); return true; } break; } } // check if user presses the key 'W' or 'D' if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown) { switch (event.KeyInput.Key) { case irr::KEY_KEY_W: // switch wire frame mode Terrain->setMaterialFlag(video::EMF_WIREFRAME, !Terrain->getMaterial(0).Wireframe); Terrain->setMaterialFlag(video::EMF_POINTCLOUD, false); return true; case irr::KEY_KEY_P: // switch wire frame mode Terrain->setMaterialFlag(video::EMF_POINTCLOUD, !Terrain->getMaterial(0).PointCloud); Terrain->setMaterialFlag(video::EMF_WIREFRAME, false); return true; case irr::KEY_KEY_D: // toggle detail map Terrain->setMaterialType( Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ? video::EMT_DETAIL_MAP : video::EMT_SOLID); return true; case irr::KEY_KEY_S: // toggle skies showBox=!showBox; Skybox->setVisible(showBox); Skydome->setVisible(!showBox); return true; default: break; } } return false; } private: IrrlichtDevice *Device; scene::ISceneNode* Terrain; scene::ISceneNode* Skybox; scene::ISceneNode* Skydome; bool showBox; }; /* The start of the main function starts like in most other example. We ask the user for the desired renderer and start it up. This time with the advanced parameter handling. */ int example_terrain() { // create device IrrlichtDevice *device = startup(); if (device == 0) return 1; // could not create selected driver. /* First, we add standard stuff to the scene: A nice irrlicht engine logo, a small help text, a user controlled camera, and we disable the mouse cursor. */ video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); //set other font //env->getSkin()->setFont(env->getFont("../../media/fontlucida.png")); // add some help text env->addStaticText( L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map\nPress 'S' to toggle skybox/skydome", core::rect(5,250,235,320), true, true, 0, -1, true); // add camera scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0,100.0f,1.2f); camera->setPosition(core::vector3df(2700*2,255*2,2600*2)); camera->setTarget(core::vector3df(2397*2,343*2,2700*2)); camera->setFarValue(42000.0f); // disable mouse cursor device->getCursorControl()->setVisible(false); /* Here comes the terrain renderer scene node: We add it just like any other scene node to the scene using ISceneManager::addTerrainSceneNode(). The only parameter we use is a file name to the heightmap we use. A heightmap is simply a gray scale texture. The terrain renderer loads it and creates the 3D terrain from it. To make the terrain look more big, we change the scale factor of it to (40, 4.4, 40). Because we don't have any dynamic lights in the scene, we switch off the lighting, and we set the file terrain-texture.jpg as texture for the terrain and detailmap3.jpg as second texture, called detail map. At last, we set the scale values for the texture: The first texture will be repeated only one time over the whole terrain, and the second one (detail map) 20 times. */ // add terrain scene node scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode( "../../media/terrain-heightmap.bmp", 0, // parent node -1, // node id core::vector3df(0.f, 0.f, 0.f), // position core::vector3df(0.f, 0.f, 0.f), // rotation core::vector3df(40.f, 4.4f, 40.f), // scale video::SColor ( 255, 255, 255, 255 ), // vertexColor 5, // maxLOD scene::ETPS_17, // patchSize 4 // smoothFactor ); if ( terrain ) { terrain->setMaterialFlag(video::EMF_LIGHTING, false); terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg")); terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg")); terrain->setMaterialType(video::EMT_DETAIL_MAP); terrain->scaleTexture(1.0f, 20.0f); //terrain->setDebugDataVisible ( true ); /* To be able to do collision with the terrain, we create a triangle selector. If you want to know what triangle selectors do, just take a look into the collision tutorial. The terrain triangle selector works together with the terrain. To demonstrate this, we create a collision response animator and attach it to the camera, so that the camera will not be able to fly through the terrain. */ // create triangle selector for the terrain scene::ITriangleSelector* selector = smgr->createTerrainTriangleSelector(terrain, 0); terrain->setTriangleSelector(selector); // create collision response animator and attach it to the camera scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(60,100,60), core::vector3df(0,0,0), core::vector3df(0,50,0)); selector->drop(); camera->addAnimator(anim); anim->drop(); /* If you need access to the terrain data you can also do this directly via the following code fragment. */ scene::CDynamicMeshBuffer* buffer = new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); terrain->getMeshBufferForLOD(*buffer, 0); video::S3DVertex2TCoords* data = (video::S3DVertex2TCoords*)buffer->getVertexBuffer().getData(); // Work on data or get the IndexBuffer with a similar call. buffer->drop(); // When done drop the buffer again. } /* To make the user be able to switch between normal and wireframe mode, we create an instance of the event receiver from above and let Irrlicht know about it. In addition, we add the skybox which we already used in lots of Irrlicht examples and a skydome, which is shown mutually exclusive with the skybox by pressing 'S'. */ // create skybox and skydome driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); scene::ISceneNode* skybox=smgr->addSkyBoxSceneNode( driver->getTexture("../../media/irrlicht2_up.jpg"), driver->getTexture("../../media/irrlicht2_dn.jpg"), driver->getTexture("../../media/irrlicht2_lf.jpg"), driver->getTexture("../../media/irrlicht2_rt.jpg"), driver->getTexture("../../media/irrlicht2_ft.jpg"), driver->getTexture("../../media/irrlicht2_bk.jpg")); scene::ISceneNode* skydome=smgr->addSkyDomeSceneNode(driver->getTexture("../../media/skydome.jpg"),16,8,0.95f,2.0f); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true); // create event receiver EventReceiver_terrain receiver( device, terrain, skybox, skydome); device->setEventReceiver(&receiver); return run ( device ); } /* */ int example_helloworld() { // create device IrrlichtDevice *device = startup(); if (device == 0) return 1; // could not create selected driver. IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); IGUIEnvironment* guienv = device->getGUIEnvironment(); IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2"); if (!mesh) { device->drop(); return 1; } IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); /* To let the mesh look a little bit nicer, we change its material. We disable lighting because we do not have a dynamic light in here, and the mesh would be totally black otherwise. Then we set the frame loop, such that the predefined STAND animation is used. And last, we apply a texture to the mesh. Without it the mesh would be drawn using only a color. */ if (node) { node->setMaterialFlag(EMF_LIGHTING, false); node->setMD2Animation(scene::EMAT_STAND); node->setMaterialTexture( 0, driver->getTexture("../../media/sydney.bmp") ); } /* To look at the mesh, we place a camera into 3d space at the position (0, 30, -40). The camera looks from there to (0,5,0), which is approximately the place where our md2 model is. */ smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0)); EventReceiver_basic receiver(device); device->setEventReceiver(&receiver); return run ( device ); } #if defined (_IRR_USE_WINDOWS_CE_DEVICE_) #pragma comment(linker, "/subsystem:WINDOWSCE /ENTRY:main") #elif defined (_IRR_WINDOWS_) #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") #endif /* */ int main() { example_helloworld (); example_customscenenode(); //example_terrain(); } /* **/ irrlicht-1.8.3/examples/17.HelloWorld_Mobile/HelloWorld_mobile.vcproj0000644000000000000000000001641412574354552024320 0ustar rootroot irrlicht-1.8.3/examples/17.HelloWorld_Mobile/HelloWorld_mobile.sln0000644000000000000000000000551312574354552023607 0ustar rootroot Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17.HelloWorld_mobile", "HelloWorld_mobile.vcproj", "{AD95D5D7-91D2-4030-B28D-23A6FE5C0359}" ProjectSection(ProjectDependencies) = postProject {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "..\..\source\Irrlicht\Irrlicht_mobile6.vcproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Windows Mobile 6 Professional SDK (ARMV4I) = Debug|Windows Mobile 6 Professional SDK (ARMV4I) Release|Windows Mobile 6 Professional SDK (ARMV4I) = Release|Windows Mobile 6 Professional SDK (ARMV4I) EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {AD95D5D7-91D2-4030-B28D-23A6FE5C0359}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 6 Professional SDK (ARMV4I) {AD95D5D7-91D2-4030-B28D-23A6FE5C0359}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).Build.0 = Debug|Windows Mobile 6 Professional SDK (ARMV4I) {AD95D5D7-91D2-4030-B28D-23A6FE5C0359}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 6 Professional SDK (ARMV4I) {AD95D5D7-91D2-4030-B28D-23A6FE5C0359}.Release|Windows Mobile 6 Professional SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 6 Professional SDK (ARMV4I) {AD95D5D7-91D2-4030-B28D-23A6FE5C0359}.Release|Windows Mobile 6 Professional SDK (ARMV4I).Build.0 = Release|Windows Mobile 6 Professional SDK (ARMV4I) {AD95D5D7-91D2-4030-B28D-23A6FE5C0359}.Release|Windows Mobile 6 Professional SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 6 Professional SDK (ARMV4I) {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 6 Professional SDK (ARMV4I) {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).Build.0 = Debug|Windows Mobile 6 Professional SDK (ARMV4I) {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Windows Mobile 6 Professional SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 6 Professional SDK (ARMV4I) {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Windows Mobile 6 Professional SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 6 Professional SDK (ARMV4I) {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Windows Mobile 6 Professional SDK (ARMV4I).Build.0 = Release|Windows Mobile 6 Professional SDK (ARMV4I) {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Windows Mobile 6 Professional SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 6 Professional SDK (ARMV4I) EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal irrlicht-1.8.3/examples/17.HelloWorld_Mobile/17. HelloWorld for Windows Mobile on PC_vc12.vcxproj0000644000000000000000000002461412574354552030535 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 17.HelloWorld_Mobile {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B} My17HelloWorldforWindowsMobileonPC Win32Proj Application Unicode true Windows7.1SDK Application Unicode true Windows7.1SDK Application Unicode Windows7.1SDK Application Unicode Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\17.HelloWorld_Mobile.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\17.HelloWorld_Mobile.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase ..\..\bin\Win32-VisualStudio\17.HelloWorld_Mobile.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\17.HelloWorld_Mobile.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/17.HelloWorld_Mobile/17. HelloWorld for Windows Mobile on PC_vc11.vcxproj0000644000000000000000000002461312574354552030533 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 17.HelloWorld_Mobile {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B} My17HelloWorldforWindowsMobileonPC Win32Proj Application Unicode true Windows7.1SDK Application Unicode true Windows7.1SDK Application Unicode Windows7.1SDK Application Unicode Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\17.HelloWorld_Mobile.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\17.HelloWorld_Mobile.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase ..\..\bin\Win32-VisualStudio\17.HelloWorld_Mobile.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\17.HelloWorld_Mobile.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/17.HelloWorld_Mobile/17. HelloWorld for Windows Mobile on PC_vc10.vcxproj0000644000000000000000000002461312574354552030532 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 17.HelloWorld_Mobile {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B} My17HelloWorldforWindowsMobileonPC Win32Proj Application Unicode true Windows7.1SDK Application Unicode true Windows7.1SDK Application Unicode Windows7.1SDK Application Unicode Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level3 EditAndContinue ..\..\bin\Win32-VisualStudio\17.HelloWorld_Mobile.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\17.HelloWorld_Mobile.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase ..\..\bin\Win32-VisualStudio\17.HelloWorld_Mobile.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase ..\..\bin\Win64-VisualStudio\17.HelloWorld_Mobile.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/17.HelloWorld_Mobile/17. HelloWorld for Windows Mobile on PC_v9.vcproj0000644000000000000000000000756112574354552030132 0ustar rootroot irrlicht-1.8.3/examples/17.HelloWorld_Mobile/17. HelloWorld for Windows Mobile on PC_v8.vcproj0000644000000000000000000000747612574354552030136 0ustar rootroot irrlicht-1.8.3/examples/16.Quake3MapShader/0000755000000000000000000000000012574354552017036 5ustar rootrootirrlicht-1.8.3/examples/16.Quake3MapShader/Quake3MapShader_vc9.vcproj0000644000000000000000000000775212574354552023775 0ustar rootroot irrlicht-1.8.3/examples/16.Quake3MapShader/Quake3MapShader_vc8.vcproj0000644000000000000000000000772712574354552023776 0ustar rootroot irrlicht-1.8.3/examples/16.Quake3MapShader/Quake3MapShader_vc12.vcxproj0000644000000000000000000002577612574354552024245 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 16.Quake3MapShader {EB3B38EA-5CE7-4983-845B-880661E69D09} 16.Quake3MapShader Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue Cdecl ..\..\bin\Win32-VisualStudio\16.Quake3MapShader.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase Cdecl ..\..\bin\Win64-VisualStudio\16.Quake3MapShader.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 Cdecl ..\..\bin\Win32-VisualStudio\16.Quake3MapShader.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 Cdecl ..\..\bin\Win64-VisualStudio\16.Quake3MapShader.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/16.Quake3MapShader/Quake3MapShader_vc11.vcxproj0000644000000000000000000002577512574354552024243 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 16.Quake3MapShader {EB3B38EA-5CE7-4983-845B-880661E69D09} 16.Quake3MapShader Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue Cdecl ..\..\bin\Win32-VisualStudio\16.Quake3MapShader.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase Cdecl ..\..\bin\Win64-VisualStudio\16.Quake3MapShader.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 Cdecl ..\..\bin\Win32-VisualStudio\16.Quake3MapShader.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 Cdecl ..\..\bin\Win64-VisualStudio\16.Quake3MapShader.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/16.Quake3MapShader/Quake3MapShader_vc10.vcxproj0000644000000000000000000002577512574354552024242 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 16.Quake3MapShader {EB3B38EA-5CE7-4983-845B-880661E69D09} 16.Quake3MapShader Win32Proj Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK Application MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ true true ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug Level3 EditAndContinue Cdecl ..\..\bin\Win32-VisualStudio\16.Quake3MapShader.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase Cdecl ..\..\bin\Win64-VisualStudio\16.Quake3MapShader.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 Cdecl ..\..\bin\Win32-VisualStudio\16.Quake3MapShader.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) false Console true true true Speed ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreaded false Level3 Cdecl ..\..\bin\Win64-VisualStudio\16.Quake3MapShader.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) false Console true true irrlicht-1.8.3/examples/16.Quake3MapShader/Quake3MapShader.vcproj0000644000000000000000000000676412574354552023216 0ustar rootroot irrlicht-1.8.3/examples/16.Quake3MapShader/Quake3MapShader.dev0000644000000000000000000000175612574354552022465 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 16 Quake3 Map Shader UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=16.Quake3MapShader.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/16.Quake3MapShader/Quake3MapShader.cbp0000644000000000000000000000273512574354552022451 0ustar rootroot irrlicht-1.8.3/examples/16.Quake3MapShader/Makefile0000644000000000000000000000221112574354552020472 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 16.Quake3MapShader Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/16.Quake3MapShader/main.cpp0000644000000000000000000002677012574354552020502 0ustar rootroot/** Example 016 Quake3 Map Shader Support This Tutorial shows how to load a Quake 3 map into the engine, create a SceneNode for optimizing the speed of rendering and how to create a user controlled camera. Lets start like the HelloWorld example: We include the irrlicht header files and an additional file to be able to ask the user for a driver type using the console. */ #include #include "driverChoice.h" /* define which Quake3 Level should be loaded */ #define IRRLICHT_QUAKE3_ARENA //#define ORIGINAL_QUAKE3_ARENA //#define CUSTOM_QUAKE3_ARENA //#define SHOW_SHADER_NAME #ifdef ORIGINAL_QUAKE3_ARENA #define QUAKE3_STORAGE_FORMAT addFolderFileArchive #define QUAKE3_STORAGE_1 "/baseq3/" #ifdef CUSTOM_QUAKE3_ARENA #define QUAKE3_STORAGE_2 "/cf/" #define QUAKE3_MAP_NAME "maps/cf.bsp" #else #define QUAKE3_MAP_NAME "maps/q3dm8.bsp" #endif #endif #ifdef IRRLICHT_QUAKE3_ARENA #define QUAKE3_STORAGE_FORMAT addFileArchive #define QUAKE3_STORAGE_1 "../../media/map-20kdm2.pk3" #define QUAKE3_MAP_NAME "maps/20kdm2.bsp" #endif using namespace irr; using namespace scene; /* Again, to be able to use the Irrlicht.DLL file, we need to link with the Irrlicht.lib. We could set this option in the project settings, but to make it easy, we use a pragma comment lib: */ #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif /* A class to produce a series of screenshots */ class CScreenShotFactory : public IEventReceiver { public: CScreenShotFactory( IrrlichtDevice *device, const c8 * templateName, ISceneNode* node ) : Device(device), Number(0), FilenameTemplate(templateName), Node(node) { FilenameTemplate.replace ( '/', '_' ); FilenameTemplate.replace ( '\\', '_' ); } bool OnEvent(const SEvent& event) { // check if user presses the key F9 if ((event.EventType == EET_KEY_INPUT_EVENT) && event.KeyInput.PressedDown) { if (event.KeyInput.Key == KEY_F9) { video::IImage* image = Device->getVideoDriver()->createScreenShot(); if (image) { c8 buf[256]; snprintf(buf, 256, "%s_shot%04d.jpg", FilenameTemplate.c_str(), ++Number); Device->getVideoDriver()->writeImageToFile(image, buf, 85 ); image->drop(); } } else if (event.KeyInput.Key == KEY_F8) { if (Node->isDebugDataVisible()) Node->setDebugDataVisible(scene::EDS_OFF); else Node->setDebugDataVisible(scene::EDS_BBOX_ALL); } } return false; } private: IrrlichtDevice *Device; u32 Number; core::stringc FilenameTemplate; ISceneNode* Node; }; /* Ok, lets start. */ int IRRCALLCONV main(int argc, char* argv[]) { /* Like in the HelloWorld example, we create an IrrlichtDevice with createDevice(). The difference now is that we ask the user to select which hardware accelerated driver to use. The Software device would be too slow to draw a huge Quake 3 map, but just for the fun of it, we make this decision possible too. */ // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device and exit if creation failed const core::dimension2du videoDim(800,600); IrrlichtDevice *device = createDevice(driverType, videoDim, 32, false ); if (device == 0) return 1; // could not create selected driver. const char* mapname=0; if (argc>2) mapname = argv[2]; else mapname = QUAKE3_MAP_NAME; /* Get a pointer to the video driver and the SceneManager so that we do not always have to write device->getVideoDriver() and device->getSceneManager(). */ video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* gui = device->getGUIEnvironment(); //! add our private media directory to the file system device->getFileSystem()->addFileArchive("../../media/"); /* To display the Quake 3 map, we first need to load it. Quake 3 maps are packed into .pk3 files, which are nothing other than .zip files. So we add the .pk3 file to our FileSystem. After it was added, we are able to read from the files in that archive as they would directly be stored on disk. */ if (argc>2) device->getFileSystem()->QUAKE3_STORAGE_FORMAT(argv[1]); else device->getFileSystem()->QUAKE3_STORAGE_FORMAT(QUAKE3_STORAGE_1); #ifdef QUAKE3_STORAGE_2 device->getFileSystem()->QUAKE3_STORAGE_FORMAT(QUAKE3_STORAGE_2); #endif // Quake3 Shader controls Z-Writing smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); /* Now we can load the mesh by calling getMesh(). We get a pointer returned to a IAnimatedMesh. As you know, Quake 3 maps are not really animated, they are only a huge chunk of static geometry with some materials attached. Hence the IAnimated mesh consists of only one frame, so we get the "first frame" of the "animation", which is our quake level and create an Octree scene node with it, using addOctreeSceneNode(). The Octree optimizes the scene a little bit, trying to draw only geometry which is currently visible. An alternative to the Octree would be a AnimatedMeshSceneNode, which would draw always the complete geometry of the mesh, without optimization. Try it out: Write addAnimatedMeshSceneNode instead of addOctreeSceneNode and compare the primitives drawn by the video driver. (There is a getPrimitiveCountDrawed() method in the IVideoDriver class). Note that this optimization with the Octree is only useful when drawing huge meshes consisting of lots of geometry. */ scene::IQ3LevelMesh* const mesh = (scene::IQ3LevelMesh*) smgr->getMesh(mapname); /* add the geometry mesh to the Scene ( polygon & patches ) The Geometry mesh is optimised for faster drawing */ scene::ISceneNode* node = 0; if (mesh) { scene::IMesh * const geometry = mesh->getMesh(quake3::E_Q3_MESH_GEOMETRY); node = smgr->addOctreeSceneNode(geometry, 0, -1, 4096); } // create an event receiver for making screenshots CScreenShotFactory screenshotFactory(device, mapname, node); device->setEventReceiver(&screenshotFactory); /* now construct SceneNodes for each Shader The Objects are stored in the quake mesh scene::E_Q3_MESH_ITEMS and the Shader ID is stored in the MaterialParameters mostly dark looking skulls and moving lava.. or green flashing tubes? */ if ( mesh ) { // the additional mesh can be quite huge and is unoptimized const scene::IMesh * const additional_mesh = mesh->getMesh(quake3::E_Q3_MESH_ITEMS); #ifdef SHOW_SHADER_NAME gui::IGUIFont *font = device->getGUIEnvironment()->getFont("../../media/fontlucida.png"); u32 count = 0; #endif for ( u32 i = 0; i!= additional_mesh->getMeshBufferCount(); ++i ) { const IMeshBuffer* meshBuffer = additional_mesh->getMeshBuffer(i); const video::SMaterial& material = meshBuffer->getMaterial(); // The ShaderIndex is stored in the material parameter const s32 shaderIndex = (s32) material.MaterialTypeParam2; // the meshbuffer can be rendered without additional support, or it has no shader const quake3::IShader *shader = mesh->getShader(shaderIndex); if (0 == shader) { continue; } // we can dump the shader to the console in its // original but already parsed layout in a pretty // printers way.. commented out, because the console // would be full... // quake3::dumpShader ( Shader ); node = smgr->addQuake3SceneNode(meshBuffer, shader); #ifdef SHOW_SHADER_NAME count += 1; core::stringw name( node->getName() ); node = smgr->addBillboardTextSceneNode( font, name.c_str(), node, core::dimension2d(80.0f, 8.0f), core::vector3df(0, 10, 0)); #endif } } /* Now we only need a Camera to look at the Quake 3 map. And we want to create a user controlled camera. There are some different cameras available in the Irrlicht engine. For example the Maya Camera which can be controlled comparable to the camera in Maya: Rotate with left mouse button pressed, Zoom with both buttons pressed, translate with right mouse button pressed. This could be created with addCameraSceneNodeMaya(). But for this example, we want to create a camera which behaves like the ones in first person shooter games (FPS). */ scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); /* so we need a good starting Position in the level. we can ask the Quake3 Loader for all entities with class_name "info_player_deathmatch" we choose a random launch */ if ( mesh ) { quake3::tQ3EntityList &entityList = mesh->getEntityList(); quake3::IEntity search; search.name = "info_player_deathmatch"; s32 index = entityList.binary_search(search); if (index >= 0) { s32 notEndList; do { const quake3::SVarGroup *group = entityList[index].getGroup(1); u32 parsepos = 0; const core::vector3df pos = quake3::getAsVector3df(group->get("origin"), parsepos); parsepos = 0; const f32 angle = quake3::getAsFloat(group->get("angle"), parsepos); core::vector3df target(0.f, 0.f, 1.f); target.rotateXZBy(angle); camera->setPosition(pos); camera->setTarget(pos + target); ++index; /* notEndList = ( index < (s32) entityList.size () && entityList[index].name == search.name && (device->getTimer()->getRealTime() >> 3 ) & 1 ); */ notEndList = index == 2; } while ( notEndList ); } } /* The mouse cursor needs not to be visible, so we make it invisible. */ device->getCursorControl()->setVisible(false); // load the engine logo gui->addImage(driver->getTexture("irrlichtlogo2.png"), core::position2d(10, 10)); // show the driver logo const core::position2di pos(videoDim.Width - 128, videoDim.Height - 64); switch ( driverType ) { case video::EDT_BURNINGSVIDEO: gui->addImage(driver->getTexture("burninglogo.png"), pos); break; case video::EDT_OPENGL: gui->addImage(driver->getTexture("opengllogo.png"), pos); break; case video::EDT_DIRECT3D8: case video::EDT_DIRECT3D9: gui->addImage(driver->getTexture("directxlogo.png"), pos); break; } /* We have done everything, so lets draw it. We also write the current frames per second and the drawn primitives to the caption of the window. The 'if (device->isWindowActive())' line is optional, but prevents the engine render to set the position of the mouse cursor after task switching when other program are active. */ int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, video::SColor(255,20,20,40)); smgr->drawAll(); gui->drawAll(); driver->endScene(); int fps = driver->getFPS(); //if (lastFPS != fps) { io::IAttributes * const attr = smgr->getParameters(); core::stringw str = L"Q3 ["; str += driver->getName(); str += "] FPS:"; str += fps; #ifdef _IRR_SCENEMANAGER_DEBUG str += " Cull:"; str += attr->getAttributeAsInt("calls"); str += "/"; str += attr->getAttributeAsInt("culled"); str += " Draw: "; str += attr->getAttributeAsInt("drawn_solid"); str += "/"; str += attr->getAttributeAsInt("drawn_transparent"); str += "/"; str += attr->getAttributeAsInt("drawn_transparent_effect"); #endif device->setWindowCaption(str.c_str()); lastFPS = fps; } } /* In the end, delete the Irrlicht device. */ device->drop(); return 0; } /* **/ irrlicht-1.8.3/examples/15.LoadIrrFile/0000755000000000000000000000000012574354552016253 5ustar rootrootirrlicht-1.8.3/examples/15.LoadIrrFile/tutorial.html0000644000000000000000000001115712574354552021011 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 15. Load .irr File

Since version 1.1, Irrlicht is able to save and load the full scene graph into an .irr file, an xml based format. There is also an editor available to edit those files, named irrEdit on http://www.ambiera.com/irredit, which can also be used as world and particle editor. This tutorial shows how to use .irr files.



Lets start!

Lets start: Create an Irrlicht device and setup the window.

#include 
#include 
using namespace irr;

#pragma comment(lib, "Irrlicht.lib")

int main()
{
	// ask user for driver

	video::E_DRIVER_TYPE driverType;

	printf("Please select the driver you want for this example:\n"\
		" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
		" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
		" (f) NullDevice\n (otherKey) exit\n\n");

	char i;
	std::cin >> i;

	switch(i)
	{
		case 'a': driverType = video::EDT_DIRECT3D9;break;
		case 'b': driverType = video::EDT_DIRECT3D8;break;
		case 'c': driverType = video::EDT_OPENGL;   break;
		case 'd': driverType = video::EDT_SOFTWARE; break;
		case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
		case 'f': driverType = video::EDT_NULL;     break;
		default: return 1;
	}	

	// create device and exit if creation failed

	IrrlichtDevice* device =
		createDevice(driverType, core::dimension2d(640, 480));

	if (device == 0)
		return 1; // could not create selected driver.

	device->setWindowCaption(L"Load .irr file example");

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();

Now load our .irr file. .irr files can store the whole scene graph including animators, materials and particle systems. And there is also the possibility to store arbitrary user data for every scene node in that file. To keep this example simple, we are simply loading the scene here. See the documentation at ISceneManager::loadScene and ISceneManager::saveScene for more information. So to load and display a complicated huge scene, we only need a single call to loadScene().

// load the scene
smgr->loadScene("../../media/example.irr");

That was it already. Now add a camera and draw the scene.

	// add a user controlled camera

	smgr->addCameraSceneNodeFPS();

	// and draw everything.
	
	while(device->run())
	if (device->isWindowActive())
	{
		driver->beginScene(true, true, video::SColor(0,200,200,200));
		smgr->drawAll();
		driver->endScene();
	}

	device->drop();
	
	return 0;
}

 

 

 

irrlicht-1.8.3/examples/15.LoadIrrFile/Makefile0000644000000000000000000000220512574354552017712 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 15.LoadIrrFile Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/15.LoadIrrFile/main.cpp0000644000000000000000000001216112574354552017704 0ustar rootroot/** Example 015 Loading Scenes from .irr Files Since version 1.1, Irrlicht is able to save and load the full scene graph into an .irr file, an xml based format. There is an editor available to edit those files, named irrEdit (http://www.ambiera.com/irredit) which can also be used as world and particle editor. This tutorial shows how to use .irr files. Lets start: Create an Irrlicht device and setup the window. */ #include #include "driverChoice.h" using namespace irr; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif int main(int argc, char** argv) { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device and exit if creation failed IrrlichtDevice* device = createDevice(driverType, core::dimension2d(640, 480)); if (device == 0) return 1; // could not create selected driver. device->setWindowCaption(L"Load .irr file example"); video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); /* Now load our .irr file. .irr files can store the whole scene graph including animators, materials and particle systems. And there is also the possibility to store arbitrary user data for every scene node in that file. To keep this example simple, we are simply loading the scene here. See the documentation at ISceneManager::loadScene and ISceneManager::saveScene for more information. So to load and display a complicated huge scene, we only need a single call to loadScene(). */ // load the scene if (argc>1) smgr->loadScene(argv[1]); else smgr->loadScene("../../media/example.irr"); /* Now we'll create a camera, and give it a collision response animator that's built from the mesh nodes in the scene we just loaded. */ scene::ICameraSceneNode * camera = smgr->addCameraSceneNodeFPS(0, 50.f, 0.1f); // Create a meta triangle selector to hold several triangle selectors. scene::IMetaTriangleSelector * meta = smgr->createMetaTriangleSelector(); /* Now we will find all the nodes in the scene and create triangle selectors for all suitable nodes. Typically, you would want to make a more informed decision about which nodes to performs collision checks on; you could capture that information in the node name or Id. */ core::array nodes; smgr->getSceneNodesFromType(scene::ESNT_ANY, nodes); // Find all nodes for (u32 i=0; i < nodes.size(); ++i) { scene::ISceneNode * node = nodes[i]; scene::ITriangleSelector * selector = 0; switch(node->getType()) { case scene::ESNT_CUBE: case scene::ESNT_ANIMATED_MESH: // Because the selector won't animate with the mesh, // and is only being used for camera collision, we'll just use an approximate // bounding box instead of ((scene::IAnimatedMeshSceneNode*)node)->getMesh(0) selector = smgr->createTriangleSelectorFromBoundingBox(node); break; case scene::ESNT_MESH: case scene::ESNT_SPHERE: // Derived from IMeshSceneNode selector = smgr->createTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node); break; case scene::ESNT_TERRAIN: selector = smgr->createTerrainTriangleSelector((scene::ITerrainSceneNode*)node); break; case scene::ESNT_OCTREE: selector = smgr->createOctreeTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node); break; default: // Don't create a selector for this node type break; } if(selector) { // Add it to the meta selector, which will take a reference to it meta->addTriangleSelector(selector); // And drop my reference to it, so that the meta selector owns it. selector->drop(); } } /* Now that the mesh scene nodes have had triangle selectors created and added to the meta selector, create a collision response animator from that meta selector. */ scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( meta, camera, core::vector3df(5,5,5), core::vector3df(0,0,0)); meta->drop(); // I'm done with the meta selector now camera->addAnimator(anim); anim->drop(); // I'm done with the animator now // And set the camera position so that it doesn't start off stuck in the geometry camera->setPosition(core::vector3df(0.f, 20.f, 0.f)); // Point the camera at the cube node, by finding the first node of type ESNT_CUBE scene::ISceneNode * cube = smgr->getSceneNodeFromType(scene::ESNT_CUBE); if(cube) camera->setTarget(cube->getAbsolutePosition()); /* That's it. Draw everything and finish as usual. */ int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, video::SColor(0,200,200,200)); smgr->drawAll(); driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Load Irrlicht File example - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; } /* **/ irrlicht-1.8.3/examples/15.LoadIrrFile/LoadIrrFile_vc9.vcproj0000644000000000000000000001225212574354552022417 0ustar rootroot irrlicht-1.8.3/examples/15.LoadIrrFile/LoadIrrFile_vc8.vcproj0000644000000000000000000001215212574354552022415 0ustar rootroot irrlicht-1.8.3/examples/15.LoadIrrFile/LoadIrrFile_vc12.vcxproj0000644000000000000000000003276412574354552022673 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 15.LoadIrrFile {78C9F424-523C-49AC-94B7-823AA4A26BF9} LoadIrrFile Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/LoadIrrFile.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\15.LoadIrrFile.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/LoadIrrFile.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\15.LoadIrrFile.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/LoadIrrFile.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\15.LoadIrrFile.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/LoadIrrFile.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\15.LoadIrrFile.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/15.LoadIrrFile/LoadIrrFile_vc11.vcxproj0000644000000000000000000003276312574354552022671 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 15.LoadIrrFile {78C9F424-523C-49AC-94B7-823AA4A26BF9} LoadIrrFile Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/LoadIrrFile.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\15.LoadIrrFile.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/LoadIrrFile.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\15.LoadIrrFile.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/LoadIrrFile.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\15.LoadIrrFile.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/LoadIrrFile.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\15.LoadIrrFile.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/15.LoadIrrFile/LoadIrrFile_vc10.vcxproj0000644000000000000000000003276312574354552022670 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 15.LoadIrrFile {78C9F424-523C-49AC-94B7-823AA4A26BF9} LoadIrrFile Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/LoadIrrFile.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\15.LoadIrrFile.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/LoadIrrFile.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\15.LoadIrrFile.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/LoadIrrFile.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\15.LoadIrrFile.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/LoadIrrFile.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\15.LoadIrrFile.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/15.LoadIrrFile/LoadIrrFile.vcproj0000644000000000000000000001053212574354552021635 0ustar rootroot irrlicht-1.8.3/examples/15.LoadIrrFile/LoadIrrFile.dev0000644000000000000000000000174712574354552021120 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 15 Load .irr File UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=15.LoadIrrFile.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/15.LoadIrrFile/LoadIrrFile.cbp0000644000000000000000000000260712574354552021102 0ustar rootroot irrlicht-1.8.3/examples/14.Win32Window/0000755000000000000000000000000012574354552016210 5ustar rootrootirrlicht-1.8.3/examples/14.Win32Window/Win32Window_vc9.vcproj0000644000000000000000000001244212574354552022313 0ustar rootroot irrlicht-1.8.3/examples/14.Win32Window/Win32Window_vc8.vcproj0000644000000000000000000001226712574354552022317 0ustar rootroot irrlicht-1.8.3/examples/14.Win32Window/Win32Window_vc12.vcxproj0000644000000000000000000003356012574354552022561 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 14.Win32Window {772FBE05-D05A-467B-9842-BEC409EEA8D0} Win32Window Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Win32Window.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-VisualStudio\14.Win32Window.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Win32Window.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win64-VisualStudio\14.Win32Window.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Win32Window.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-VisualStudio\14.Win32Window.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Win32Window.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win64-VisualStudio\14.Win32Window.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/14.Win32Window/Win32Window_vc11.vcxproj0000644000000000000000000003355712574354552022566 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 14.Win32Window {772FBE05-D05A-467B-9842-BEC409EEA8D0} Win32Window Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Win32Window.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-VisualStudio\14.Win32Window.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Win32Window.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win64-VisualStudio\14.Win32Window.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Win32Window.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-VisualStudio\14.Win32Window.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Win32Window.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win64-VisualStudio\14.Win32Window.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/14.Win32Window/Win32Window_vc10.vcxproj0000644000000000000000000003355712574354552022565 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 14.Win32Window {772FBE05-D05A-467B-9842-BEC409EEA8D0} Win32Window Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Win32Window.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-VisualStudio\14.Win32Window.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Win32Window.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win64-VisualStudio\14.Win32Window.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Win32Window.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win32-VisualStudio\14.Win32Window.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Win32Window.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 opengl32.lib;%(AdditionalDependencies) ..\..\bin\Win64-VisualStudio\14.Win32Window.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/14.Win32Window/Win32Window.vcproj0000644000000000000000000001070712574354552021534 0ustar rootroot irrlicht-1.8.3/examples/14.Win32Window/Win32Window.dev0000644000000000000000000000174512574354552021011 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 14 Win32 Window UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=14.Win32Window.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/14.Win32Window/Win32Window.cbp0000644000000000000000000000215312574354552020771 0ustar rootroot irrlicht-1.8.3/examples/14.Win32Window/tutorial.html0000644000000000000000000002007012574354552020740 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 14. Win32 Window

This example only runs in Windows and demonstrates that Irrlicht can run inside a win32 window. MFC and .NET Windows.Forms windows are possible too.

The program which is described here will look like this:



Lets start!

In the begining, we create a windows window using the windows API. I'm not going to explain this code, because it is windows specific. See the MSDN or a windows book for details.

#include <irrlicht.h>
#include <windows.h> // this example only runs with windows

using namespace irr;

#pragma comment(lib, "irrlicht.lib")

HWND hOKButton;
HWND hWnd;

static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message,
    WPARAM wParam, LPARAM lParam)
{
	switch (message) 
	{
	case WM_COMMAND:
		{
			HWND hwndCtl = (HWND)lParam;
			int code = HIWORD(wParam);

			if (hwndCtl == hOKButton)
			{
				DestroyWindow(hWnd);
				PostQuitMessage(0);
				return 0;
			}		
		}
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	}

	return DefWindowProc(hWnd, message, wParam, lParam);
}

int main()
//int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hpre, LPSTR cmd, int cc)
{
	HINSTANCE hInstance = 0;
	// create dialog

	const char* Win32ClassName = "CIrrlichtWindowsTestDialog";

	WNDCLASSEX wcex;
	wcex.cbSize			= sizeof(WNDCLASSEX); 
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)CustomWndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= DLGWINDOWEXTRA; 
	wcex.hInstance		= hInstance;
	wcex.hIcon			= NULL;
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW);
	wcex.lpszMenuName	= 0;
	wcex.lpszClassName	= Win32ClassName;
	wcex.hIconSm		= 0;

	RegisterClassEx(&wcex);

	DWORD style = WS_SYSMENU | WS_BORDER | WS_CAPTION | 
		WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX
		| WS_MINIMIZEBOX | WS_SIZEBOX;

	int windowWidth = 440;
	int windowHeight = 380;

	hWnd = CreateWindow( Win32ClassName, "Irrlicht Win32 window example",
		style, 100, 100, windowWidth, windowHeight,
		NULL, NULL, hInstance, NULL);

	RECT clientRect;
	GetClientRect(hWnd, &clientRect);
	windowWidth = clientRect.right;
	windowHeight = clientRect.bottom;

	// create ok button

	hOKButton = CreateWindow(
	    "BUTTON", "OK - Close", WS_CHILD | WS_VISIBLE | BS_TEXT, 
		windowWidth - 160, windowHeight - 40, 150, 30, hWnd, NULL, 
		hInstance, NULL);

	// create some text
	
	CreateWindow("STATIC", 
        "This is Irrlicht running inside a standard Win32 window.\n"\
		"Also mixing with MFC and .NET Windows.Forms is possible.",
		WS_CHILD | WS_VISIBLE, 20, 20, 400, 40, hWnd, NULL, hInstance, NULL);

	// create window to put irrlicht in

	HWND hIrrlichtWindow =
CreateWindow("BUTTON", "", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 50, 80, 320, 220, hWnd, NULL, hInstance, NULL);

So now that we have some window, we can create an Irrlicht device inside of it. We use Irrlicht createEx() function for this. We only need the handle (HWND) to that window, set it as windowsID parameter and start up the engine as usual. That's it.

	// create irrlicht device in the button window

	irr::SIrrlichtCreationParameters param;
	param.WindowId = reinterpret_cast(hIrrlichtWindow); // hColorButton
	param.DriverType = video::EDT_OPENGL;

	irr::IrrlichtDevice* device = irr::createDeviceEx(param);
	
	// setup a simple 3d scene

	irr::scene::ISceneManager* smgr = device->getSceneManager();
	video::IVideoDriver* driver = device->getVideoDriver();

	scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
	cam->setTarget(core::vector3df(0,0,0));

	scene::ISceneNodeAnimator* anim =
	   smgr->createFlyCircleAnimator(core::vector3df(0,10,0), 30.0f);
	cam->addAnimator(anim);
	anim->drop();

	scene::ISceneNode* cube = smgr->addCubeSceneNode(25);
	cube->setMaterialFlag(video::EMF_LIGHTING, false);
	
	cube->setMaterialTexture(0, driver->getTexture("../../media/rockwall.bmp"));

	smgr->addSkyBoxSceneNode(
	driver->getTexture("../../media/irrlicht2_up.jpg"),
	driver->getTexture("../../media/irrlicht2_dn.jpg"),
	driver->getTexture("../../media/irrlicht2_lf.jpg"),
	driver->getTexture("../../media/irrlicht2_rt.jpg"),
	driver->getTexture("../../media/irrlicht2_ft.jpg"),
	driver->getTexture("../../media/irrlicht2_bk.jpg"));

	// show and execute dialog

	ShowWindow(hWnd , SW_SHOW);
	UpdateWindow(hWnd);

Now the only thing missing is the drawing loop using IrrlichtDevice::run(). We do this as usual. But instead of this, there is another possibility: You can also simply use your own message loop using GetMessage, DispatchMessage and whatever. Calling
Device->run() will cause Irrlicht to dispatch messages internally too. You need not call Device->run() if you want to do your own message dispatching loop, but Irrlicht will not be able to fetch user input then and you have to do it on your own using the window messages, DirectInput, or whatever.

	while (device->run())
	{
		driver->beginScene(true, true, 0);
		smgr->drawAll();
		driver->endScene();
	}

	// the alternative, own message dispatching loop without Device->run() would
	// look like this:

	/*MSG msg;
	while (true)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);

			if (msg.message == WM_QUIT)
				break;
		}
		
		// advance virtual time
		device->getTimer()->tick();

		// draw engine picture
		driver->beginScene(true, true, 0);
		smgr->drawAll();
		driver->endScene();
	}*/

	device->closeDevice();
	device->drop();

	return 0;
}

That's it, Irrlicht now runs in your own windows window.

 

irrlicht-1.8.3/examples/14.Win32Window/Makefile0000644000000000000000000000220512574354552017647 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 14.Win32Window Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/14.Win32Window/main.cpp0000644000000000000000000001603412574354552017644 0ustar rootroot/** Example 014 Win32 Window This example only runs under MS Windows and demonstrates that Irrlicht can render inside a win32 window. MFC and .NET Windows.Forms windows are possible, too. In the beginning, we create a windows window using the windows API. I'm not going to explain this code, because it is windows specific. See the MSDN or a windows book for details. */ #include #ifndef _IRR_WINDOWS_ #error Windows only example #else #include // this example only runs with windows #include #include "driverChoice.h" using namespace irr; #pragma comment(lib, "irrlicht.lib") HWND hOKButton; HWND hWnd; static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: { HWND hwndCtl = (HWND)lParam; int code = HIWORD(wParam); if (hwndCtl == hOKButton) { DestroyWindow(hWnd); PostQuitMessage(0); return 0; } } break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } /* Now ask for the driver and create the Windows specific window. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; printf("Select the render window (some dead window may exist too):\n"\ " (a) Window with button (via CreationParam)\n"\ " (b) Window with button (via beginScene)\n"\ " (c) Own Irrlicht window (default behavior)\n"\ " (otherKey) exit\n\n"); char key; std::cin >> key; if (key != 'a' && key != 'b' && key != 'c') return 1; HINSTANCE hInstance = 0; // create dialog const char* Win32ClassName = "CIrrlichtWindowsTestDialog"; WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)CustomWndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = DLGWINDOWEXTRA; wcex.hInstance = hInstance; wcex.hIcon = NULL; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW); wcex.lpszMenuName = 0; wcex.lpszClassName = Win32ClassName; wcex.hIconSm = 0; RegisterClassEx(&wcex); DWORD style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX; int windowWidth = 440; int windowHeight = 380; hWnd = CreateWindow( Win32ClassName, "Irrlicht Win32 window example", style, 100, 100, windowWidth, windowHeight, NULL, NULL, hInstance, NULL); RECT clientRect; GetClientRect(hWnd, &clientRect); windowWidth = clientRect.right; windowHeight = clientRect.bottom; // create ok button hOKButton = CreateWindow("BUTTON", "OK - Close", WS_CHILD | WS_VISIBLE | BS_TEXT, windowWidth - 160, windowHeight - 40, 150, 30, hWnd, NULL, hInstance, NULL); // create some text CreateWindow("STATIC", "This is Irrlicht running inside a standard Win32 window.\n"\ "Also mixing with MFC and .NET Windows.Forms is possible.", WS_CHILD | WS_VISIBLE, 20, 20, 400, 40, hWnd, NULL, hInstance, NULL); // create window to put irrlicht in HWND hIrrlichtWindow = CreateWindow("BUTTON", "", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 50, 80, 320, 220, hWnd, NULL, hInstance, NULL); video::SExposedVideoData videodata((key=='b')?hIrrlichtWindow:0); /* So now that we have some window, we can create an Irrlicht device inside of it. We use Irrlicht createEx() function for this. We only need the handle (HWND) to that window, set it as windowsID parameter and start up the engine as usual. That's it. */ // create irrlicht device in the button window irr::SIrrlichtCreationParameters param; param.DriverType = driverType; if (key=='a') param.WindowId = reinterpret_cast(hIrrlichtWindow); irr::IrrlichtDevice* device = irr::createDeviceEx(param); if (!device) return 1; // setup a simple 3d scene irr::scene::ISceneManager* smgr = device->getSceneManager(); video::IVideoDriver* driver = device->getVideoDriver(); if (driverType==video::EDT_OPENGL) { HDC HDc=GetDC(hIrrlichtWindow); PIXELFORMATDESCRIPTOR pfd={0}; pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR); int pf = GetPixelFormat(HDc); DescribePixelFormat(HDc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd); pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; pfd.cDepthBits=16; pf = ChoosePixelFormat(HDc, &pfd); SetPixelFormat(HDc, pf, &pfd); videodata.OpenGLWin32.HDc = HDc; videodata.OpenGLWin32.HRc=wglCreateContext(HDc); wglShareLists((HGLRC)driver->getExposedVideoData().OpenGLWin32.HRc, (HGLRC)videodata.OpenGLWin32.HRc); } scene::ICameraSceneNode* cam = smgr->addCameraSceneNode(); cam->setTarget(core::vector3df(0,0,0)); scene::ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(core::vector3df(0,15,0), 30.0f); cam->addAnimator(anim); anim->drop(); scene::ISceneNode* cube = smgr->addCubeSceneNode(20); cube->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp")); cube->setMaterialTexture(1, driver->getTexture("../../media/water.jpg")); cube->setMaterialFlag( video::EMF_LIGHTING, false ); cube->setMaterialType( video::EMT_REFLECTION_2_LAYER ); smgr->addSkyBoxSceneNode( driver->getTexture("../../media/irrlicht2_up.jpg"), driver->getTexture("../../media/irrlicht2_dn.jpg"), driver->getTexture("../../media/irrlicht2_lf.jpg"), driver->getTexture("../../media/irrlicht2_rt.jpg"), driver->getTexture("../../media/irrlicht2_ft.jpg"), driver->getTexture("../../media/irrlicht2_bk.jpg")); // show and execute dialog ShowWindow(hWnd , SW_SHOW); UpdateWindow(hWnd); // do message queue /* Now the only thing missing is the drawing loop using IrrlichtDevice::run(). We do this as usual. But instead of this, there is another possibility: You can also simply use your own message loop using GetMessage, DispatchMessage and whatever. Calling Device->run() will cause Irrlicht to dispatch messages internally too. You need not call Device->run() if you want to do your own message dispatching loop, but Irrlicht will not be able to fetch user input then and you have to do it on your own using the window messages, DirectInput, or whatever. */ while (device->run()) { driver->beginScene(true, true, 0, videodata); smgr->drawAll(); driver->endScene(); } /* The alternative, own message dispatching loop without Device->run() would look like this: */ /*MSG msg; while (true) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); if (msg.message == WM_QUIT) break; } // advance virtual time device->getTimer()->tick(); // draw engine picture driver->beginScene(true, true, 0, (key=='c')?hIrrlichtWindow:0); smgr->drawAll(); driver->endScene(); }*/ device->closeDevice(); device->drop(); return 0; } #endif // if windows /* That's it, Irrlicht now runs in your own windows window. **/ irrlicht-1.8.3/examples/13.RenderToTexture/0000755000000000000000000000000012574354552017220 5ustar rootrootirrlicht-1.8.3/examples/13.RenderToTexture/tutorial.html0000644000000000000000000002325412574354552021757 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 13. Render to Texture

This tutorial shows how to render to a texture using Irrlicht. Render to texture is a feature with which it is possible to create nice special effects. In addition, this tutorial shows how to enable specular highlights.

The program which is described here will look like this:



Lets start!

In the beginning, everything as usual. Include the needed headers, ask the user for the rendering driver, create the Irrlicht Device:

#include <irrlicht.h>
#include <iostream>

using namespace irr;

#pragma comment(lib, "Irrlicht.lib")

int main()
{
	// let user select driver type

	video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;

	printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n"); char i; std::cin >> i; switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 1;
} // create device and exit if creation failed IrrlichtDevice *device = createDevice(driverType, core::dimension2d(640, 480), 16, false, false); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment();

Now, we load an animated mesh to be displayed. As in most examples, we'll take the fairy md2 model. The difference here: We set the shininess
of the model to a value other than 0 which is the default value. This enables specular highlights on the model if dynamic lighting is on. The value influences the size of the highlights.

// load and display animated fairy mesh

	scene::IAnimatedMeshSceneNode* fairy = smgr->addAnimatedMeshSceneNode(
		smgr->getMesh("../../media/faerie.md2"));

	if (fairy)
	{
		fairy->setMaterialTexture(0, driver->getTexture("../../media/faerie2.bmp")); // set diffuse texture
		fairy->setMaterialFlag(video::EMF_LIGHTING, true); // enable dynamic lighting
		fairy->getMaterial(0).Shininess = 20.0f; // set size of specular highlights
		fairy->setPosition(core::vector3df(-10,0,-100));
	}

To make specular highlights appear on the model, we need a dynamic light in the scene. We add one directly in vicinity of the model. In addition, to make the model not that dark, we set the ambient light to gray.

	// add white light
	scene::ILightSceneNode* light = smgr->addLightSceneNode(0,
		core::vector3df(-15,5,-105), video::SColorf(1.0f, 1.0f, 1.0f));

	// set ambient light
	driver->setAmbientLight(video::SColor(0,60,60,60));

The next is just some standard stuff: Add a user controlled camera to the scene, disable mouse cursor, and add a test cube and let it rotate to make the scene more interesting.

	// add fps camera
	scene::ICameraSceneNode* fpsCamera = smgr->addCameraSceneNodeFPS();
	fpsCamera->setPosition(core::vector3df(-50,50,-150));

	// disable mouse cursor
	device->getCursorControl()->setVisible(false);

	// create test cube
	scene::ISceneNode* test = smgr->addCubeSceneNode(60);

	// let the cube rotate and set some light settings
	scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(
		core::vector3df(0.3f, 0.3f,0));

	test->setPosition(core::vector3df(-100,0,-100));
	test->setMaterialFlag(video::EMF_LIGHTING, false); // disable dynamic lighting
	test->addAnimator(anim);
	anim->drop();

	// set window caption
	device->setWindowCaption(L"Irrlicht Engine - Render to Texture and Specular Highlights example");

To test out the render to texture feature, we need a render target texture. These are not like standard textures, but need to be created first. To create one, we call IVideoDriver::createRenderTargetTexture() and specify the size of the texture. Please don't use sizes bigger than the frame buffer for this, because the render target shares the zbuffer with the frame buffer. And because we want to render the scene not from the user camera into the texture, we add another, fixed camera to the scene. But before we do all this, we check if the current running driver is able to render to textures. If it is not, we simply display a warning text.

// create render target
	video::ITexture* rt = 0;
	scene::ICameraSceneNode* fixedCam = 0;
	

	if (driver->queryFeature(video::EVDF_RENDER_TO_TARGET))
	{
		rt = driver->createRenderTargetTexture(core::dimension2d(256,256));
		test->setMaterialTexture(0, rt); // set material of cube to render target

		// add fixed camera
		fixedCam = smgr->addCameraSceneNode(0, core::vector3df(10,10,-80),
			core::vector3df(-10,10,-100));
	}
	else
	{
		// create problem text
		gui::IGUISkin* skin = env->getSkin();
		gui::IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp");
		if (font)
			skin->setFont(font);

		gui::IGUIStaticText* text = env->addStaticText(
			L"Your hardware or this renderer is not able to use the "\
			L"render to texture feature. RTT Disabled.",
			core::rect(150,20,470,60));

		text->setOverrideColor(video::SColor(100,255,255,255));
	}

Nearly finished. Now we need to draw everything. Every frame, we draw the scene twice. Once from the fixed camera into the render target texture and once as usual. When rendering into the render target, we need to disable the visibilty of the test cube, because it has the render target texture applied to it.
That's, wasn't quite complicated I hope. :)

while(device->run())
	if (device->isWindowActive())
	{
		driver->beginScene(true, true, 0);

		if (rt)
		{
			// draw scene into render target
			
			// set render target texture
			driver->setRenderTarget(rt, true, true, video::SColor(0,0,0,255));     

			// make cube invisible and set fixed camera as active camera
			test->setVisible(false);
			smgr->setActiveCamera(fixedCam);

			// draw whole scene into render buffer
			smgr->drawAll();                 

			// set back old render target
			driver->setRenderTarget(0);      

			// make the cube visible and set the user controlled camera as active one
			test->setVisible(true);
			smgr->setActiveCamera(fpsCamera);
		}
		
		// draw scene normally
		smgr->drawAll(); 
		env->drawAll();

		driver->endScene();
	}

	if (rt)
		rt->drop(); // drop render target because we created if with a create() method

	device->drop(); // drop device
	return 0;
}

 

 

irrlicht-1.8.3/examples/13.RenderToTexture/RenderToTexture_vc9.vcproj0000644000000000000000000001232212574354552024331 0ustar rootroot irrlicht-1.8.3/examples/13.RenderToTexture/RenderToTexture_vc8.vcproj0000644000000000000000000001222212574354552024327 0ustar rootroot irrlicht-1.8.3/examples/13.RenderToTexture/RenderToTexture_vc12.vcxproj0000644000000000000000000003303412574354552024576 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 13.RenderToTexture {0914E5C8-5352-467B-8421-C9EB35BD5596} RenderToTexture Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/RenderToTexture.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\13.RenderToTexture.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/RenderToTexture.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\13.RenderToTexture.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console .\Debug/RenderToTexture.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\13.RenderToTexture.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/RenderToTexture.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\13.RenderToTexture.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/13.RenderToTexture/RenderToTexture_vc11.vcxproj0000644000000000000000000003303312574354552024574 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 13.RenderToTexture {0914E5C8-5352-467B-8421-C9EB35BD5596} RenderToTexture Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/RenderToTexture.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\13.RenderToTexture.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/RenderToTexture.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\13.RenderToTexture.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console .\Debug/RenderToTexture.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\13.RenderToTexture.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/RenderToTexture.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\13.RenderToTexture.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/13.RenderToTexture/RenderToTexture_vc10.vcxproj0000644000000000000000000003303312574354552024573 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 13.RenderToTexture {0914E5C8-5352-467B-8421-C9EB35BD5596} RenderToTexture Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/RenderToTexture.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\13.RenderToTexture.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/RenderToTexture.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\13.RenderToTexture.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console .\Debug/RenderToTexture.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\13.RenderToTexture.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/RenderToTexture.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\13.RenderToTexture.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/13.RenderToTexture/RenderToTexture.vcproj0000644000000000000000000001062512574354552023554 0ustar rootroot irrlicht-1.8.3/examples/13.RenderToTexture/RenderToTexture.dev0000644000000000000000000000175612574354552023034 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 13 Render To Texture UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=13.RenderToTexture.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/13.RenderToTexture/RenderToTexture.cbp0000644000000000000000000000271012574354552023011 0ustar rootroot irrlicht-1.8.3/examples/13.RenderToTexture/Makefile0000644000000000000000000000221112574354552020654 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 13.RenderToTexture Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/13.RenderToTexture/main.cpp0000644000000000000000000001475212574354552020661 0ustar rootroot/** Example 013 Render To Texture This tutorial shows how to render to a texture using Irrlicht. Render to texture is a feature with which it is possible to create nice special effects. In addition, this tutorial shows how to enable specular highlights. In the beginning, everything as usual. Include the needed headers, ask the user for the rendering driver, create the Irrlicht Device: */ #include #include "driverChoice.h" using namespace irr; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device and exit if creation failed IrrlichtDevice *device = createDevice(driverType, core::dimension2d(640, 480), 16, false, false); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); /* Now, we load an animated mesh to be displayed. As in most examples, we'll take the fairy md2 model. The difference here: We set the shininess of the model to a value other than 0 which is the default value. This enables specular highlights on the model if dynamic lighting is on. The value influences the size of the highlights. */ // load and display animated fairy mesh scene::IAnimatedMeshSceneNode* fairy = smgr->addAnimatedMeshSceneNode( smgr->getMesh("../../media/faerie.md2")); if (fairy) { fairy->setMaterialTexture(0, driver->getTexture("../../media/faerie2.bmp")); // set diffuse texture fairy->setMaterialFlag(video::EMF_LIGHTING, true); // enable dynamic lighting fairy->getMaterial(0).Shininess = 20.0f; // set size of specular highlights fairy->setPosition(core::vector3df(-10,0,-100)); fairy->setMD2Animation ( scene::EMAT_STAND ); } /* To make specular highlights appear on the model, we need a dynamic light in the scene. We add one directly in vicinity of the model. In addition, to make the model not that dark, we set the ambient light to gray. */ // add white light smgr->addLightSceneNode(0, core::vector3df(-15,5,-105), video::SColorf(1.0f, 1.0f, 1.0f)); // set ambient light smgr->setAmbientLight(video::SColor(0,60,60,60)); /* The next is just some standard stuff: Add a test cube and let it rotate to make the scene more interesting. The user defined camera and cursor setup is made later on, right before the render loop. */ // create test cube scene::ISceneNode* test = smgr->addCubeSceneNode(60); // let the cube rotate and set some light settings scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator( core::vector3df(0.3f, 0.3f,0)); test->setPosition(core::vector3df(-100,0,-100)); test->setMaterialFlag(video::EMF_LIGHTING, false); // disable dynamic lighting test->addAnimator(anim); anim->drop(); // set window caption device->setWindowCaption(L"Irrlicht Engine - Render to Texture and Specular Highlights example"); /* To test out the render to texture feature, we need a render target texture. These are not like standard textures, but need to be created first. To create one, we call IVideoDriver::addRenderTargetTexture() and specify the size of the texture. Please don't use sizes bigger than the frame buffer for this, because the render target shares the zbuffer with the frame buffer. Because we want to render the scene not from the user camera into the texture, we add another fixed camera to the scene. But before we do all this, we check if the current running driver is able to render to textures. If it is not, we simply display a warning text. */ // create render target video::ITexture* rt = 0; scene::ICameraSceneNode* fixedCam = 0; if (driver->queryFeature(video::EVDF_RENDER_TO_TARGET)) { rt = driver->addRenderTargetTexture(core::dimension2d(256,256), "RTT1"); test->setMaterialTexture(0, rt); // set material of cube to render target // add fixed camera fixedCam = smgr->addCameraSceneNode(0, core::vector3df(10,10,-80), core::vector3df(-10,10,-100)); } else { // create problem text gui::IGUISkin* skin = env->getSkin(); gui::IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp"); if (font) skin->setFont(font); gui::IGUIStaticText* text = env->addStaticText( L"Your hardware or this renderer is not able to use the "\ L"render to texture feature. RTT Disabled.", core::rect(150,20,470,60)); text->setOverrideColor(video::SColor(100,255,255,255)); } // add fps camera scene::ICameraSceneNode* fpsCamera = smgr->addCameraSceneNodeFPS(); fpsCamera->setPosition(core::vector3df(-50,50,-150)); // disable mouse cursor device->getCursorControl()->setVisible(false); /* Nearly finished. Now we need to draw everything. Every frame, we draw the scene twice. Once from the fixed camera into the render target texture and once as usual. When rendering into the render target, we need to disable the visibility of the test cube, because it has the render target texture applied to it. That's it, wasn't too complicated I hope. :) */ int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0); if (rt) { // draw scene into render target // set render target texture driver->setRenderTarget(rt, true, true, video::SColor(0,0,0,255)); // make cube invisible and set fixed camera as active camera test->setVisible(false); smgr->setActiveCamera(fixedCam); // draw whole scene into render buffer smgr->drawAll(); // set back old render target // The buffer might have been distorted, so clear it driver->setRenderTarget(0, true, true, 0); // make the cube visible and set the user controlled camera as active one test->setVisible(true); smgr->setActiveCamera(fpsCamera); } // draw scene normally smgr->drawAll(); env->drawAll(); driver->endScene(); // display frames per second in window title int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Irrlicht Engine - Render to Texture and Specular Highlights example"; str += " FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); // drop device return 0; } /* **/ irrlicht-1.8.3/examples/12.TerrainRendering/0000755000000000000000000000000012574354552017356 5ustar rootrootirrlicht-1.8.3/examples/12.TerrainRendering/tutorial.html0000644000000000000000000002722112574354552022113 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 12. Terrain Rendering

This tutorial will briefly show how to use the terrain renderer of Irrlicht. It will also show the terrain renderer triangle selector to be able to do collision detection with terrain.

The program which is described here will look like this:


Note that the terrain renderer in Irrlicht is based the terrain renderer by Soconne and the GeoMipMapSceneNode developed by Spinz, lots of thanks go to them.


Lets start!

In the beginning there is nothing special. We include the needed header files and create an event listener to listen if the user presses the 'W' key so we can switch to wireframe mode and if he presses 'D' we toggle to material between solid and detail mapped.

#include <irrlicht.h>
#include <iostream>
using namespace irr;

#pragma comment(lib, "Irrlicht.lib")

class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(scene::ISceneNode* terrain)
{
// store pointer to terrain so we can change its drawing mode
Terrain = terrain;
}

bool OnEvent(const SEvent& event)
{
// check if user presses the key 'W' or 'D'
if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
{
switch (event.KeyInput.Key)
{
case irr::KEY_KEY_W: // switch wire frame mode
Terrain->setMaterialFlag(video::EMF_WIREFRAME, !Terrain->getMaterial(0).Wireframe);
return true;
case irr::KEY_KEY_D: // toggle detail map
Terrain->setMaterialType(
Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ?
video::EMT_DETAIL_MAP : video::EMT_SOLID);
return true;
}
}
return false;
}

private:
scene::ISceneNode* Terrain;
};

The start of the main function starts like in most other example. We ask the user for the desired renderer and start it up.

int main()
{
// let user select driver type

video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;

printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");

char i;
std::cin >> i;

switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 1;
}

// create device
IrrlichtDevice* device = createDevice(driverType, core::dimension2d<s32>(640, 480));

if (device == 0)
return 1; // could not create selected driver.

First, we add standard stuff to the scene: A nice irrlicht engine logo, a small help text, a user controlled camera, and we disable the mouse cursor.

video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
gui::IGUIEnvironment* env = device->getGUIEnvironment();

driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);

// add irrlicht logo
env->addImage(driver->getTexture("../../media/irrlichtlogoalpha.tga"),
core::position2d<s32>(10,10));
// add some help text
gui::IGUIStaticText* text = env->addStaticText(
L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map",
core::rect<s32>(10,453,200,475), true, true, 0, -1, true);
// add camera
scene::ICameraSceneNode* camera =
smgr->addCameraSceneNodeFPS(0,100.0f,1200.0f);
camera->setPosition(core::vector3df(1900*2,255*2,3700*2));
camera->setTarget(core::vector3df(2397*2,343*2,2700*2));
camera->setFarValue(12000.0f);

// disable mouse cursor
device->getCursorControl()->setVisible(false);

Here comes the terrain renderer scene node: We add it just like any other scene node to the scene using ISceneManager::addTerrainSceneNode(). The only parameter we use is a file name to the heightmap we use. A heightmap is simply a gray scale texture. The terrain renderer loads it and creates the 3D terrain from it.
To make the terrain look more big, we change the scale factor of it to (40, 4.4, 40). Because we don't have any dynamic lights in the scene, we switch off the lighting, and we set the file terrain-texture.jpg as texture for the terrain and detailmap3.jpg as second texture, called detail map. At last, we set the scale values for the texture: The first texture will be repeated only one time over the whole terrain, and the second one (detail map) 20 times.

// add terrain scene node
scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode(
"../../media/terrain-heightmap.bmp");

terrain->setScale(core::vector3df(40, 4.4f, 40));
terrain->setMaterialFlag(video::EMF_LIGHTING, false);

terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg"));
terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg"));

terrain->setMaterialType(video::EMT_DETAIL_MAP);
terrain->scaleTexture(1.0f, 20.0f);

To be able to do collision with the terrain, we create a triangle selector. If you want to know what triangle selectors do, just take a look into the collision tutorial. The terrain triangle selector works together with the terrain. To demonstrate this, we create a collision response animator and attach it to the camera, so that the camera will not be able to fly through the terrain.

// create triangle selector for the terrain	
scene::ITriangleSelector* selector =
smgr->createTerrainTriangleSelector(terrain, 0);
terrain->setTriangleSelector(selector);

// create collision response animator and attach it to the camera
scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
selector, camera, core::vector3df(60,100,60),
core::vector3df(0,0,0),
core::vector3df(0,50,0));
selector->drop();
camera->addAnimator(anim);
anim->drop();

To make the user be able to switch between normal and wireframe mode, we create an instance of the event reciever from above and let Irrlicht know about it. In addition, we add the skybox which we already used in lots of Irrlicht examples.

// create event receiver
MyEventReceiver receiver(terrain);
device->setEventReceiver(&receiver);

// create skybox
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);

smgr->addSkyBoxSceneNode(
driver->getTexture("../../media/irrlicht2_up.jpg"),
driver->getTexture("../../media/irrlicht2_dn.jpg"),
driver->getTexture("../../media/irrlicht2_lf.jpg"),
driver->getTexture("../../media/irrlicht2_rt.jpg"),
driver->getTexture("../../media/irrlicht2_ft.jpg"),
driver->getTexture("../../media/irrlicht2_bk.jpg"));
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);

That's it, draw everything. Now you know how to use terrain in Irrlicht.

	int lastFPS = -1;

while(device->run())
if (device->isWindowActive())
{
driver->beginScene(true, true, 0 );

smgr->drawAll();
env->drawAll();

driver->endScene();
// display frames per second in window title int fps = driver->getFPS();

if (lastFPS != fps)
{
core::stringw str = L"Terrain Renderer - Irrlicht Engine [";
str += driver->getName();
str += "] FPS:";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}

device->drop();

return 0;
}

 

 

irrlicht-1.8.3/examples/12.TerrainRendering/TerrainRendering_vc9.vcproj0000644000000000000000000001233412574354552024631 0ustar rootroot irrlicht-1.8.3/examples/12.TerrainRendering/TerrainRendering_vc8.vcproj0000644000000000000000000001223412574354552024627 0ustar rootroot irrlicht-1.8.3/examples/12.TerrainRendering/TerrainRendering_vc12.vcxproj0000644000000000000000000003304612574354552025076 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 12.TerrainRendering {3A5B74E5-6390-43B0-A459-2793B81FFD31} TerrainRendering Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/TerrainRendering.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\12.TerrainRendering.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/TerrainRendering.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\12.TerrainRendering.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/TerrainRendering.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\12.TerrainRendering.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/TerrainRendering.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\12.TerrainRendering.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/12.TerrainRendering/TerrainRendering_vc11.vcxproj0000644000000000000000000003304512574354552025074 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 12.TerrainRendering {3A5B74E5-6390-43B0-A459-2793B81FFD31} TerrainRendering Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/TerrainRendering.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\12.TerrainRendering.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/TerrainRendering.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\12.TerrainRendering.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/TerrainRendering.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\12.TerrainRendering.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/TerrainRendering.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\12.TerrainRendering.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/12.TerrainRendering/TerrainRendering_vc10.vcxproj0000644000000000000000000003304512574354552025073 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 12.TerrainRendering {3A5B74E5-6390-43B0-A459-2793B81FFD31} TerrainRendering Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/TerrainRendering.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\12.TerrainRendering.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/TerrainRendering.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\12.TerrainRendering.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/TerrainRendering.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\12.TerrainRendering.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/TerrainRendering.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\12.TerrainRendering.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/12.TerrainRendering/TerrainRendering.vcproj0000644000000000000000000001063612574354552024053 0ustar rootroot irrlicht-1.8.3/examples/12.TerrainRendering/TerrainRendering.dev0000644000000000000000000000175712574354552023332 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 12 Terrain Rendering UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=12.TerrainRendering.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/12.TerrainRendering/TerrainRendering.cbp0000644000000000000000000000274312574354552023314 0ustar rootroot irrlicht-1.8.3/examples/12.TerrainRendering/Makefile0000644000000000000000000000221212574354552021013 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 12.TerrainRendering Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/12.TerrainRendering/main.cpp0000644000000000000000000002260512574354552021013 0ustar rootroot/** Example 012 Terrain Rendering This tutorial will briefly show how to use the terrain renderer of Irrlicht. It will also show the terrain renderer triangle selector to be able to do collision detection with terrain. Note that the Terrain Renderer in Irrlicht is based on Spintz' GeoMipMapSceneNode, lots of thanks go to him. DeusXL provided a new elegant simple solution for building larger area on small heightmaps -> terrain smoothing. In the beginning there is nothing special. We include the needed header files and create an event listener to listen if the user presses a key: The 'W' key switches to wireframe mode, the 'P' key to pointcloud mode, and the 'D' key toggles between solid and detail mapped material. */ #include #include "driverChoice.h" using namespace irr; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif class MyEventReceiver : public IEventReceiver { public: MyEventReceiver(scene::ISceneNode* terrain, scene::ISceneNode* skybox, scene::ISceneNode* skydome) : Terrain(terrain), Skybox(skybox), Skydome(skydome), showBox(true), showDebug(false) { Skybox->setVisible(showBox); Skydome->setVisible(!showBox); } bool OnEvent(const SEvent& event) { // check if user presses the key 'W' or 'D' if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown) { switch (event.KeyInput.Key) { case irr::KEY_KEY_W: // switch wire frame mode Terrain->setMaterialFlag(video::EMF_WIREFRAME, !Terrain->getMaterial(0).Wireframe); Terrain->setMaterialFlag(video::EMF_POINTCLOUD, false); return true; case irr::KEY_KEY_P: // switch wire frame mode Terrain->setMaterialFlag(video::EMF_POINTCLOUD, !Terrain->getMaterial(0).PointCloud); Terrain->setMaterialFlag(video::EMF_WIREFRAME, false); return true; case irr::KEY_KEY_D: // toggle detail map Terrain->setMaterialType( Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ? video::EMT_DETAIL_MAP : video::EMT_SOLID); return true; case irr::KEY_KEY_S: // toggle skies showBox=!showBox; Skybox->setVisible(showBox); Skydome->setVisible(!showBox); return true; case irr::KEY_KEY_X: // toggle debug information showDebug=!showDebug; Terrain->setDebugDataVisible(showDebug?scene::EDS_BBOX_ALL:scene::EDS_OFF); return true; default: break; } } return false; } private: scene::ISceneNode* Terrain; scene::ISceneNode* Skybox; scene::ISceneNode* Skydome; bool showBox; bool showDebug; }; /* The start of the main function starts like in most other example. We ask the user for the desired renderer and start it up. This time with the advanced parameter handling. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device with full flexibility over creation parameters // you can add more parameters if desired, check irr::SIrrlichtCreationParameters irr::SIrrlichtCreationParameters params; params.DriverType=driverType; params.WindowSize=core::dimension2d(640, 480); IrrlichtDevice* device = createDeviceEx(params); if (device == 0) return 1; // could not create selected driver. /* First, we add standard stuff to the scene: A nice irrlicht engine logo, a small help text, a user controlled camera, and we disable the mouse cursor. */ video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); // add irrlicht logo env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"), core::position2d(10,10)); //set other font env->getSkin()->setFont(env->getFont("../../media/fontlucida.png")); // add some help text env->addStaticText( L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map\nPress 'S' to toggle skybox/skydome", core::rect(10,421,250,475), true, true, 0, -1, true); // add camera scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0,100.0f,1.2f); camera->setPosition(core::vector3df(2700*2,255*2,2600*2)); camera->setTarget(core::vector3df(2397*2,343*2,2700*2)); camera->setFarValue(42000.0f); // disable mouse cursor device->getCursorControl()->setVisible(false); /* Here comes the terrain renderer scene node: We add it just like any other scene node to the scene using ISceneManager::addTerrainSceneNode(). The only parameter we use is a file name to the heightmap we use. A heightmap is simply a gray scale texture. The terrain renderer loads it and creates the 3D terrain from it. To make the terrain look more big, we change the scale factor of it to (40, 4.4, 40). Because we don't have any dynamic lights in the scene, we switch off the lighting, and we set the file terrain-texture.jpg as texture for the terrain and detailmap3.jpg as second texture, called detail map. At last, we set the scale values for the texture: The first texture will be repeated only one time over the whole terrain, and the second one (detail map) 20 times. */ // add terrain scene node scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode( "../../media/terrain-heightmap.bmp", 0, // parent node -1, // node id core::vector3df(0.f, 0.f, 0.f), // position core::vector3df(0.f, 0.f, 0.f), // rotation core::vector3df(40.f, 4.4f, 40.f), // scale video::SColor ( 255, 255, 255, 255 ), // vertexColor 5, // maxLOD scene::ETPS_17, // patchSize 4 // smoothFactor ); terrain->setMaterialFlag(video::EMF_LIGHTING, false); terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg")); terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg")); terrain->setMaterialType(video::EMT_DETAIL_MAP); terrain->scaleTexture(1.0f, 20.0f); /* To be able to do collision with the terrain, we create a triangle selector. If you want to know what triangle selectors do, just take a look into the collision tutorial. The terrain triangle selector works together with the terrain. To demonstrate this, we create a collision response animator and attach it to the camera, so that the camera will not be able to fly through the terrain. */ // create triangle selector for the terrain scene::ITriangleSelector* selector = smgr->createTerrainTriangleSelector(terrain, 0); terrain->setTriangleSelector(selector); // create collision response animator and attach it to the camera scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(60,100,60), core::vector3df(0,0,0), core::vector3df(0,50,0)); selector->drop(); camera->addAnimator(anim); anim->drop(); /* If you need access to the terrain data you can also do this directly via the following code fragment. */ scene::CDynamicMeshBuffer* buffer = new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); terrain->getMeshBufferForLOD(*buffer, 0); video::S3DVertex2TCoords* data = (video::S3DVertex2TCoords*)buffer->getVertexBuffer().getData(); // Work on data or get the IndexBuffer with a similar call. buffer->drop(); // When done drop the buffer again. /* To make the user be able to switch between normal and wireframe mode, we create an instance of the event receiver from above and let Irrlicht know about it. In addition, we add the skybox which we already used in lots of Irrlicht examples and a skydome, which is shown mutually exclusive with the skybox by pressing 'S'. */ // create skybox and skydome driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); scene::ISceneNode* skybox=smgr->addSkyBoxSceneNode( driver->getTexture("../../media/irrlicht2_up.jpg"), driver->getTexture("../../media/irrlicht2_dn.jpg"), driver->getTexture("../../media/irrlicht2_lf.jpg"), driver->getTexture("../../media/irrlicht2_rt.jpg"), driver->getTexture("../../media/irrlicht2_ft.jpg"), driver->getTexture("../../media/irrlicht2_bk.jpg")); scene::ISceneNode* skydome=smgr->addSkyDomeSceneNode(driver->getTexture("../../media/skydome.jpg"),16,8,0.95f,2.0f); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true); // create event receiver MyEventReceiver receiver(terrain, skybox, skydome); device->setEventReceiver(&receiver); /* That's it, draw everything. */ int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0 ); smgr->drawAll(); env->drawAll(); driver->endScene(); // display frames per second in window title int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Terrain Renderer - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; // Also print terrain height of current camera position // We can use camera position because terrain is located at coordinate origin str += " Height: "; str += terrain->getHeight(camera->getAbsolutePosition().X, camera->getAbsolutePosition().Z); device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; } /* Now you know how to use terrain in Irrlicht. **/ irrlicht-1.8.3/examples/11.PerPixelLighting/0000755000000000000000000000000012574354552017331 5ustar rootrootirrlicht-1.8.3/examples/11.PerPixelLighting/tutorial.html0000644000000000000000000005105112574354552022064 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 11. Per pixel lighting

This tutorial shows how to use one of the built in more complex materials in irrlicht: Per pixel lighted surfaces using normal maps and parallax mapping. It will also show how to use fog and moving particle systems. And don't panic: You dont need any experience with shaders to use these materials in Irrlicht.

The program which is described here will look like this:



Lets start!

At first, we need to include all headers and do the stuff we always do, like in nearly all other tutorials.

#include <irrlicht.h>
#include <iostream>

using namespace irr;

#pragma comment(lib, "Irrlicht.lib")

For this example, we need an event receiver, to make it possible for the user to switch between the three available material types. In addition, the event receiver will create some small GUI window which displays what material is currently being used. There is nothing special done in this class, so maybe you want to skip reading it.

class MyEventReceiver : public IEventReceiver
{
public:

	MyEventReceiver(scene::ISceneNode* room, 
		gui::IGUIEnvironment* env, video::IVideoDriver* driver)
	{
		// store pointer to room so we can change its drawing mode
		Room = room;
		Driver = driver;

		// set a nicer font
		gui::IGUISkin* skin = env->getSkin();
		gui::IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp");
		if (font)
			skin->setFont(font);

		// add window and listbox
		gui::IGUIWindow* window = env->addWindow(
			core::rect(490,390,630,470), false, L"Use 'E' + 'R' to change");

		ListBox = env->addListBox(
			core::rect(2,22,135,78), window);

		ListBox->addItem(L"Diffuse");
		ListBox->addItem(L"Bump mapping");
		ListBox->addItem(L"Parallax mapping");
		ListBox->setSelected(1);

		// create problem text
		ProblemText = env->addStaticText(
			L"Your hardware or this renderer is not able to use the "\
			L"needed shaders for this material. Using fall back materials.",
			core::rect(150,20,470,60));

		ProblemText->setOverrideColor(video::SColor(100,255,255,255));

		// set start material (prefer parallax mapping if available)
		video::IMaterialRenderer* renderer = 
			Driver->getMaterialRenderer(video::EMT_PARALLAX_MAP_SOLID);
		if (renderer && renderer->getRenderCapability() == 0)
			ListBox->setSelected(2);

		// set the material which is selected in the listbox
		setMaterial();
	}

	bool OnEvent(const SEvent& event)
	{
		// check if user presses the key 'E' or 'R'
		if (event.EventType == irr::EET_KEY_INPUT_EVENT &&
			!event.KeyInput.PressedDown && Room && ListBox)
		{
			// change selected item in listbox 

			int sel = ListBox->getSelected();
			if (event.KeyInput.Key == irr::KEY_KEY_R)
				++sel;
			else
			if (event.KeyInput.Key == irr::KEY_KEY_E)
				--sel;
			else 
				return false;

			if (sel > 2) sel = 0;
			if (sel < 0) sel = 2;
			ListBox->setSelected(sel);
			
			// set the material which is selected in the listbox
			setMaterial();
		}

		return false;
	}

private:

	// sets the material of the room mesh the the one set in the 
	// list box.
	void setMaterial()
	{
		video::E_MATERIAL_TYPE type = video::EMT_SOLID;

		// change material setting
		switch(ListBox->getSelected())
		{
		case 0: type = video::EMT_SOLID;
			break;
		case 1: type = video::EMT_NORMAL_MAP_SOLID;
			break;
		case 2: type = video::EMT_PARALLAX_MAP_SOLID;
			break;
		}

		Room->setMaterialType(type);

We need to add a warning if the materials will not be able to be displayed 100% correctly. This is no problem, they will be renderered using fall back materials, but at least the user should know that it would look better on better hardware. We simply check if the material renderer is able to draw at full quality on the current hardware. The IMaterialRenderer::getRenderCapability() returns 0 if this is the case.

video::IMaterialRenderer* renderer = Driver->getMaterialRenderer(type);

		// display some problem text when problem
		if (!renderer || renderer->getRenderCapability() != 0)
			ProblemText->setVisible(true);
		else
			ProblemText->setVisible(false);
	}

private:

	gui::IGUIStaticText* ProblemText;
	gui::IGUIListBox* ListBox;

	scene::ISceneNode* Room;	
	video::IVideoDriver* Driver;
};


Now for the real fun. We create an Irrlicht Device and start to setup the scene.

int main()
{
	// let user select driver type

	video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;

printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");
char i; std::cin >> i; switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 0;
} // create device IrrlichtDevice* device = createDevice(driverType, core::dimension2d(640, 480)); if (device == 0) return 1; // could not create selected driver.

Before we start with the interesting stuff, we do some simple things: Store pointers to the most important parts of the engine (video driver,
scene manager, gui environment) to safe us from typing too much, add an irrlicht engine logo to the window and a user controlled first person shooter style camera. Also, we let the engine now that it should store all textures in 32 bit. This necessary because for parallax mapping, we need 32 bit textures.

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();
	gui::IGUIEnvironment* env = device->getGUIEnvironment();

	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);

	// add irrlicht logo
	env->addImage(driver->getTexture("../../media/irrlichtlogoalpha.tga"),
		core::position2d(10,10));
		
	// add camera
	scene::ICameraSceneNode* camera = 
		smgr->addCameraSceneNodeFPS(0,100.0f,300.0f);
	camera->setPosition(core::vector3df(-200,200,-200));

	// disable mouse cursor
	device->getCursorControl()->setVisible(false);

Because we want the whole scene to look a little bit scarier, we add some fog to it. This is done by a call to IVideoDriver::setFog(). There you can set
various fog settings. In this example, we use pixel fog, because it will work well with the materials we'll use in this example. Please note that you will have to set the material flag EMF_FOG_ENABLE to 'true' in every scene node which should be affected by this fog.

driver->setFog(video::SColor(0,138,125,81), true, 250, 1000, 0, true);

To be able to display something interesting, we load a mesh from a .3ds file which is a room I modeled with anim8or. It is the same room as
from the specialFX example. Maybe you remember from that tutorial, I am no good modeler at all and so I totally messed up the texture mapping in this model, but we can simply repair it with the IMeshManipulator::makePlanarTextureMapping() method.

	scene::IAnimatedMesh* roomMesh = smgr->getMesh(
		"../../media/room.3ds");
	scene::ISceneNode* room = 0;

	if (roomMesh)
	{
		smgr->getMeshManipulator()->makePlanarTextureMapping(
				roomMesh->getMesh(0), 0.003f);

Now for the first exciting thing: If we successfully loaded the mesh we need to apply textures to it. Because we want this room to be displayed with a very cool material, we have to do a little bit more than just set the textures. Instead of only loading a color map as usual, we also load a height map which is simply a grayscale texture. From this height map, we create a normal map which we will set as second texture of the room. If you already have a normal map, you could directly set it, but I simply didn´t find a nice normal map for this texture. The normal map texture is being generated by the makeNormalMapTexture method
of the VideoDriver. The second parameter specifies the height of the heightmap. If you set it to a bigger value, the map will look more rocky.

		video::ITexture* colorMap = driver->getTexture("../../media/rockwall.bmp");
		video::ITexture* normalMap = driver->getTexture("../../media/rockwall_height.bmp");
		
		driver->makeNormalMapTexture(normalMap, 9.0f);

But just setting color and normal map is not everything. The material we want to use needs some additional informations per vertex like tangents and binormals.
Because we are too lazy to calculate that information now, we let Irrlicht do this for us. That's why we call IMeshManipulator::createMeshWithTangents(). It
creates a mesh copy with tangents and binormals from any other mesh. After we've done that, we simply create a standard mesh scene node with this
mesh copy, set color and normal map and adjust some other material settings. Note that we set EMF_FOG_ENABLE to true to enable fog in the room.

scene::IMesh* tangentMesh = smgr->getMeshManipulator()->createMeshWithTangents(
roomMesh->getMesh(0));

room = smgr->addMeshSceneNode(tangentMesh);
room->setMaterialTexture(0, colorMap);
room->setMaterialTexture(1, normalMap);
room->getMaterial(0).SpecularColor.set(0,0,0,0);
room->setMaterialFlag(video::EMF_FOG_ENABLE, true);
room->setMaterialType(video::EMT_PARALLAX_MAP_SOLID);
room->getMaterial(0).MaterialTypeParam = 0.02f; // adjust height for parallax effect
// drop mesh because we created it with a create.. call.
tangentMesh->drop();
}

After we've created a room shaded by per pixel lighting, we add a sphere into it with the same material, but we'll make it transparent. In addition,
because the sphere looks somehow like a familiar planet, we make it rotate. The procedure is similar as before. The difference is that we are loading
the mesh from an .x file which already contains a color map so we do not need to load it manually. But the sphere is a little bit too small for our needs, so we scale it by the factor 50.

// add earth sphere

	scene::IAnimatedMesh* earthMesh = smgr->getMesh("../../media/earth.x");
	if (earthMesh)
	{
		// create mesh copy with tangent informations from original earth.x mesh
		scene::IMesh* tangentSphereMesh = 
			smgr->getMeshManipulator()->createMeshWithTangents(earthMesh->getMesh(0));

		// set the alpha value of all vertices to 200
		smgr->getMeshManipulator()->setVertexColorAlpha(tangentSphereMesh, 200);
		
		// scale the mesh by factor 50
		smgr->getMeshManipulator()->scaleMesh(
			tangentSphereMesh, core::vector3df(50,50,50));

		// create mesh scene node
		scene::ISceneNode* sphere = smgr->addMeshSceneNode(tangentSphereMesh);
		sphere->setPosition(core::vector3df(-70,130,45));

		// load heightmap, create normal map from it and set it
		video::ITexture* earthNormalMap = driver->getTexture("../../media/earthbump.bmp");
		driver->makeNormalMapTexture(earthNormalMap, 20.0f);
		sphere->setMaterialTexture(1, earthNormalMap);

		// adjust material settings
		sphere->setMaterialFlag(video::EMF_FOG_ENABLE, true);
		sphere->setMaterialType(video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA); 

		// add rotation animator
		scene::ISceneNodeAnimator* anim =
			smgr->createRotationAnimator(core::vector3df(0,0.1f,0));	
		sphere->addAnimator(anim);
		anim->drop();

		// drop mesh because we created it with a create.. call.
		tangentSphereMesh->drop();
	}

Per pixel lighted materials only look cool when there are moving lights. So we add some. And because moving lights alone are so boring, we add billboards
to them, and a whole particle system to one of them. We start with the first light which is red and has only the billboard attached.

// add light 1 (nearly red)
	scene::ILightSceneNode* light1 = 
		smgr->addLightSceneNode(0, core::vector3df(0,0,0), 
		video::SColorf(0.5f, 1.0f, 0.5f, 0.0f), 200.0f);

	// add fly circle animator to light 1
	scene::ISceneNodeAnimator* anim = 
		smgr->createFlyCircleAnimator (core::vector3df(50,300,0),190.0f, -0.003f);
	light1->addAnimator(anim);
	anim->drop();

	// attach billboard to the light
	scene::ISceneNode* bill = 
		smgr->addBillboardSceneNode(light1, core::dimension2d(60, 60));

	bill->setMaterialFlag(video::EMF_LIGHTING, false);
	bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
	bill->setMaterialTexture(0, driver->getTexture("../../media/particlered.bmp"));

Now the same again, with the second light. The difference is that we add a particle system to it too. And because the light moves, the particles of the particlesystem will follow. If you want to know more about how particle systems are created in Irrlicht, take a look at the specialFx example.
Maybe you will have noticed that we only add 2 lights, this has a simple reason: The low end version of this material was written in ps1.1 and vs1.1, which doesn't allow more lights. You could add a third light to the scene, but it won't be used to shade the walls. But of course, this will change in future versions of Irrlicht were higher versions of pixel/vertex shaders will be implemented too.

// add light 2 (gray)
	scene::ISceneNode* light2 = 
		smgr->addLightSceneNode(0, core::vector3df(0,0,0), 
		video::SColorf(1.0f, 0.2f, 0.2f, 0.0f), 200.0f);

	// add fly circle animator to light 2
	anim = smgr->createFlyCircleAnimator (core::vector3df(0,150,0),200.0f); 
	light2->addAnimator(anim);
	anim->drop();

	// attach billboard to light
	bill = smgr->addBillboardSceneNode(light2, core::dimension2d(120, 120));
	bill->setMaterialFlag(video::EMF_LIGHTING, false);
	bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
	bill->setMaterialTexture(0, driver->getTexture("../../media/particlewhite.bmp"));

	// add particle system
	scene::IParticleSystemSceneNode* ps = 
		smgr->addParticleSystemSceneNode(false, light2);

	ps->setParticleSize(core::dimension2d(30.0f, 40.0f));

	// create and set emitter
	scene::IParticleEmitter* em = ps->createBoxEmitter(
		core::aabbox3d(-3,0,-3,3,1,3), 
		core::vector3df(0.0f,0.03f,0.0f),
		80,100, 
		video::SColor(0,255,255,255), video::SColor(0,255,255,255),
		400,1100);
	ps->setEmitter(em);
	em->drop();

	// create and set affector
	scene::IParticleAffector* paf = ps->createFadeOutParticleAffector();
	ps->addAffector(paf);
	paf->drop();

	// adjust some material settings
	ps->setMaterialFlag(video::EMF_LIGHTING, false);
	ps->setMaterialTexture(0, driver->getTexture("../../media/fireball.bmp"));
	ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);


	MyEventReceiver receiver(room, env, driver);
	device->setEventReceiver(&receiver);

Finally, draw everything. That's it.

int lastFPS = -1;

	while(device->run())
	if (device->isWindowActive())
	{
		driver->beginScene(true, true, 0);

		smgr->drawAll();
		env->drawAll();

		driver->endScene();

		int fps = driver->getFPS();

		if (lastFPS != fps)
		{
		  core::stringw str = L"Per pixel lighting example - Irrlicht Engine [";
		  str += driver->getName();
		  str += "] FPS:";
		  str += fps;

		  device->setWindowCaption(str.c_str());
		  lastFPS = fps;
		}
	}

	device->drop();
	
	return 0;
}

 

irrlicht-1.8.3/examples/11.PerPixelLighting/PerPixelLighting_vc9.vcproj0000644000000000000000000001233412574354552024560 0ustar rootroot irrlicht-1.8.3/examples/11.PerPixelLighting/PerPixelLighting_vc8.vcproj0000644000000000000000000001223412574354552024556 0ustar rootroot irrlicht-1.8.3/examples/11.PerPixelLighting/PerPixelLighting_vc12.vcxproj0000644000000000000000000003304612574354552025025 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 11.PerPixelLighting {C4B42409-542D-4EFC-9E6B-44713FD47A33} PerPixelLighting Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/PerPixelLighting.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\11.PerPixelLighting.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/PerPixelLighting.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\11.PerPixelLighting.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/PerPixelLighting.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\11.PerPixelLighting.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/PerPixelLighting.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\11.PerPixelLighting.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/11.PerPixelLighting/PerPixelLighting_vc11.vcxproj0000644000000000000000000003304512574354552025023 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 11.PerPixelLighting {C4B42409-542D-4EFC-9E6B-44713FD47A33} PerPixelLighting Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/PerPixelLighting.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\11.PerPixelLighting.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/PerPixelLighting.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\11.PerPixelLighting.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/PerPixelLighting.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\11.PerPixelLighting.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/PerPixelLighting.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\11.PerPixelLighting.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/11.PerPixelLighting/PerPixelLighting_vc10.vcxproj0000644000000000000000000003304512574354552025022 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 11.PerPixelLighting {C4B42409-542D-4EFC-9E6B-44713FD47A33} PerPixelLighting Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/PerPixelLighting.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\11.PerPixelLighting.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/PerPixelLighting.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\11.PerPixelLighting.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/PerPixelLighting.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\11.PerPixelLighting.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/PerPixelLighting.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\11.PerPixelLighting.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/11.PerPixelLighting/PerPixelLighting.vcproj0000644000000000000000000001063612574354552024002 0ustar rootroot irrlicht-1.8.3/examples/11.PerPixelLighting/PerPixelLighting.dev0000644000000000000000000000176012574354552023253 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 11 Per-Pixel Lighting UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=11.PerPixelLighting.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/11.PerPixelLighting/PerPixelLighting.cbp0000644000000000000000000000300112574354552023227 0ustar rootroot irrlicht-1.8.3/examples/11.PerPixelLighting/Makefile0000644000000000000000000000221212574354552020766 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 11.PerPixelLighting Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/11.PerPixelLighting/main.cpp0000644000000000000000000003770212574354552020772 0ustar rootroot/** Example 011 Per-Pixel Lighting This tutorial shows how to use one of the built in more complex materials in irrlicht: Per pixel lighted surfaces using normal maps and parallax mapping. It will also show how to use fog and moving particle systems. And don't panic: You do not need any experience with shaders to use these materials in Irrlicht. At first, we need to include all headers and do the stuff we always do, like in nearly all other tutorials. */ #include #include "driverChoice.h" using namespace irr; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif /* For this example, we need an event receiver, to make it possible for the user to switch between the three available material types. In addition, the event receiver will create some small GUI window which displays what material is currently being used. There is nothing special done in this class, so maybe you want to skip reading it. */ class MyEventReceiver : public IEventReceiver { public: MyEventReceiver(scene::ISceneNode* room,scene::ISceneNode* earth, gui::IGUIEnvironment* env, video::IVideoDriver* driver) { // store pointer to room so we can change its drawing mode Room = room; Earth = earth; Driver = driver; // set a nicer font gui::IGUISkin* skin = env->getSkin(); gui::IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp"); if (font) skin->setFont(font); // add window and listbox gui::IGUIWindow* window = env->addWindow( core::rect(460,375,630,470), false, L"Use 'E' + 'R' to change"); ListBox = env->addListBox( core::rect(2,22,165,88), window); ListBox->addItem(L"Diffuse"); ListBox->addItem(L"Bump mapping"); ListBox->addItem(L"Parallax mapping"); ListBox->setSelected(1); // create problem text ProblemText = env->addStaticText( L"Your hardware or this renderer is not able to use the "\ L"needed shaders for this material. Using fall back materials.", core::rect(150,20,470,80)); ProblemText->setOverrideColor(video::SColor(100,255,255,255)); // set start material (prefer parallax mapping if available) video::IMaterialRenderer* renderer = Driver->getMaterialRenderer(video::EMT_PARALLAX_MAP_SOLID); if (renderer && renderer->getRenderCapability() == 0) ListBox->setSelected(2); // set the material which is selected in the listbox setMaterial(); } bool OnEvent(const SEvent& event) { // check if user presses the key 'E' or 'R' if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown && Room && ListBox) { // change selected item in listbox int sel = ListBox->getSelected(); if (event.KeyInput.Key == irr::KEY_KEY_R) ++sel; else if (event.KeyInput.Key == irr::KEY_KEY_E) --sel; else return false; if (sel > 2) sel = 0; if (sel < 0) sel = 2; ListBox->setSelected(sel); // set the material which is selected in the listbox setMaterial(); } return false; } private: // sets the material of the room mesh the the one set in the // list box. void setMaterial() { video::E_MATERIAL_TYPE type = video::EMT_SOLID; // change material setting switch(ListBox->getSelected()) { case 0: type = video::EMT_SOLID; break; case 1: type = video::EMT_NORMAL_MAP_SOLID; break; case 2: type = video::EMT_PARALLAX_MAP_SOLID; break; } Room->setMaterialType(type); // change material setting switch(ListBox->getSelected()) { case 0: type = video::EMT_TRANSPARENT_VERTEX_ALPHA; break; case 1: type = video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA; break; case 2: type = video::EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA; break; } Earth->setMaterialType(type); /* We need to add a warning if the materials will not be able to be displayed 100% correctly. This is no problem, they will be rendered using fall back materials, but at least the user should know that it would look better on better hardware. We simply check if the material renderer is able to draw at full quality on the current hardware. The IMaterialRenderer::getRenderCapability() returns 0 if this is the case. */ video::IMaterialRenderer* renderer = Driver->getMaterialRenderer(type); // display some problem text when problem if (!renderer || renderer->getRenderCapability() != 0) ProblemText->setVisible(true); else ProblemText->setVisible(false); } private: gui::IGUIStaticText* ProblemText; gui::IGUIListBox* ListBox; scene::ISceneNode* Room; scene::ISceneNode* Earth; video::IVideoDriver* Driver; }; /* Now for the real fun. We create an Irrlicht Device and start to setup the scene. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device IrrlichtDevice* device = createDevice(driverType, core::dimension2d(640, 480)); if (device == 0) return 1; // could not create selected driver. /* Before we start with the interesting stuff, we do some simple things: Store pointers to the most important parts of the engine (video driver, scene manager, gui environment) to safe us from typing too much, add an irrlicht engine logo to the window and a user controlled first person shooter style camera. Also, we let the engine know that it should store all textures in 32 bit. This necessary because for parallax mapping, we need 32 bit textures. */ video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); // add irrlicht logo env->addImage(driver->getTexture("../../media/irrlichtlogo3.png"), core::position2d(10,10)); // add camera scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); camera->setPosition(core::vector3df(-200,200,-200)); // disable mouse cursor device->getCursorControl()->setVisible(false); /* Because we want the whole scene to look a little bit scarier, we add some fog to it. This is done by a call to IVideoDriver::setFog(). There you can set various fog settings. In this example, we use pixel fog, because it will work well with the materials we'll use in this example. Please note that you will have to set the material flag EMF_FOG_ENABLE to 'true' in every scene node which should be affected by this fog. */ driver->setFog(video::SColor(0,138,125,81), video::EFT_FOG_LINEAR, 250, 1000, .003f, true, false); /* To be able to display something interesting, we load a mesh from a .3ds file which is a room I modeled with anim8or. It is the same room as from the specialFX example. Maybe you remember from that tutorial, I am no good modeler at all and so I totally messed up the texture mapping in this model, but we can simply repair it with the IMeshManipulator::makePlanarTextureMapping() method. */ scene::IAnimatedMesh* roomMesh = smgr->getMesh("../../media/room.3ds"); scene::ISceneNode* room = 0; scene::ISceneNode* earth = 0; if (roomMesh) { // The Room mesh doesn't have proper Texture Mapping on the // floor, so we can recreate them on runtime smgr->getMeshManipulator()->makePlanarTextureMapping( roomMesh->getMesh(0), 0.003f); /* Now for the first exciting thing: If we successfully loaded the mesh we need to apply textures to it. Because we want this room to be displayed with a very cool material, we have to do a little bit more than just set the textures. Instead of only loading a color map as usual, we also load a height map which is simply a grayscale texture. From this height map, we create a normal map which we will set as second texture of the room. If you already have a normal map, you could directly set it, but I simply didn't find a nice normal map for this texture. The normal map texture is being generated by the makeNormalMapTexture method of the VideoDriver. The second parameter specifies the height of the heightmap. If you set it to a bigger value, the map will look more rocky. */ video::ITexture* normalMap = driver->getTexture("../../media/rockwall_height.bmp"); if (normalMap) driver->makeNormalMapTexture(normalMap, 9.0f); /* // The Normal Map and the displacement map/height map in the alpha channel video::ITexture* normalMap = driver->getTexture("../../media/rockwall_NRM.tga"); */ /* But just setting color and normal map is not everything. The material we want to use needs some additional informations per vertex like tangents and binormals. Because we are too lazy to calculate that information now, we let Irrlicht do this for us. That's why we call IMeshManipulator::createMeshWithTangents(). It creates a mesh copy with tangents and binormals from another mesh. After we've done that, we simply create a standard mesh scene node with this mesh copy, set color and normal map and adjust some other material settings. Note that we set EMF_FOG_ENABLE to true to enable fog in the room. */ scene::IMesh* tangentMesh = smgr->getMeshManipulator()-> createMeshWithTangents(roomMesh->getMesh(0)); room = smgr->addMeshSceneNode(tangentMesh); room->setMaterialTexture(0, driver->getTexture("../../media/rockwall.jpg")); room->setMaterialTexture(1, normalMap); // Stones don't glitter.. room->getMaterial(0).SpecularColor.set(0,0,0,0); room->getMaterial(0).Shininess = 0.f; room->setMaterialFlag(video::EMF_FOG_ENABLE, true); room->setMaterialType(video::EMT_PARALLAX_MAP_SOLID); // adjust height for parallax effect room->getMaterial(0).MaterialTypeParam = 1.f / 64.f; // drop mesh because we created it with a create.. call. tangentMesh->drop(); } /* After we've created a room shaded by per pixel lighting, we add a sphere into it with the same material, but we'll make it transparent. In addition, because the sphere looks somehow like a familiar planet, we make it rotate. The procedure is similar as before. The difference is that we are loading the mesh from an .x file which already contains a color map so we do not need to load it manually. But the sphere is a little bit too small for our needs, so we scale it by the factor 50. */ // add earth sphere scene::IAnimatedMesh* earthMesh = smgr->getMesh("../../media/earth.x"); if (earthMesh) { //perform various task with the mesh manipulator scene::IMeshManipulator *manipulator = smgr->getMeshManipulator(); // create mesh copy with tangent informations from original earth.x mesh scene::IMesh* tangentSphereMesh = manipulator->createMeshWithTangents(earthMesh->getMesh(0)); // set the alpha value of all vertices to 200 manipulator->setVertexColorAlpha(tangentSphereMesh, 200); // scale the mesh by factor 50 core::matrix4 m; m.setScale ( core::vector3df(50,50,50) ); manipulator->transform( tangentSphereMesh, m ); earth = smgr->addMeshSceneNode(tangentSphereMesh); earth->setPosition(core::vector3df(-70,130,45)); // load heightmap, create normal map from it and set it video::ITexture* earthNormalMap = driver->getTexture("../../media/earthbump.jpg"); if (earthNormalMap) { driver->makeNormalMapTexture(earthNormalMap, 20.0f); earth->setMaterialTexture(1, earthNormalMap); earth->setMaterialType(video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA); } // adjust material settings earth->setMaterialFlag(video::EMF_FOG_ENABLE, true); // add rotation animator scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(core::vector3df(0,0.1f,0)); earth->addAnimator(anim); anim->drop(); // drop mesh because we created it with a create.. call. tangentSphereMesh->drop(); } /* Per pixel lighted materials only look cool when there are moving lights. So we add some. And because moving lights alone are so boring, we add billboards to them, and a whole particle system to one of them. We start with the first light which is red and has only the billboard attached. */ // add light 1 (more green) scene::ILightSceneNode* light1 = smgr->addLightSceneNode(0, core::vector3df(0,0,0), video::SColorf(0.5f, 1.0f, 0.5f, 0.0f), 800.0f); light1->setDebugDataVisible ( scene::EDS_BBOX ); // add fly circle animator to light 1 scene::ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator (core::vector3df(50,300,0),190.0f, -0.003f); light1->addAnimator(anim); anim->drop(); // attach billboard to the light scene::IBillboardSceneNode* bill = smgr->addBillboardSceneNode(light1, core::dimension2d(60, 60)); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bill->setMaterialTexture(0, driver->getTexture("../../media/particlegreen.jpg")); /* Now the same again, with the second light. The difference is that we add a particle system to it too. And because the light moves, the particles of the particlesystem will follow. If you want to know more about how particle systems are created in Irrlicht, take a look at the specialFx example. Maybe you will have noticed that we only add 2 lights, this has a simple reason: The low end version of this material was written in ps1.1 and vs1.1, which doesn't allow more lights. You could add a third light to the scene, but it won't be used to shade the walls. But of course, this will change in future versions of Irrlicht where higher versions of pixel/vertex shaders will be implemented too. */ // add light 2 (red) scene::ISceneNode* light2 = smgr->addLightSceneNode(0, core::vector3df(0,0,0), video::SColorf(1.0f, 0.2f, 0.2f, 0.0f), 800.0f); // add fly circle animator to light 2 anim = smgr->createFlyCircleAnimator(core::vector3df(0,150,0), 200.0f, 0.001f, core::vector3df(0.2f, 0.9f, 0.f)); light2->addAnimator(anim); anim->drop(); // attach billboard to light bill = smgr->addBillboardSceneNode(light2, core::dimension2d(120, 120)); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bill->setMaterialTexture(0, driver->getTexture("../../media/particlered.bmp")); // add particle system scene::IParticleSystemSceneNode* ps = smgr->addParticleSystemSceneNode(false, light2); // create and set emitter scene::IParticleEmitter* em = ps->createBoxEmitter( core::aabbox3d(-3,0,-3,3,1,3), core::vector3df(0.0f,0.03f,0.0f), 80,100, video::SColor(10,255,255,255), video::SColor(10,255,255,255), 400,1100); em->setMinStartSize(core::dimension2d(30.0f, 40.0f)); em->setMaxStartSize(core::dimension2d(30.0f, 40.0f)); ps->setEmitter(em); em->drop(); // create and set affector scene::IParticleAffector* paf = ps->createFadeOutParticleAffector(); ps->addAffector(paf); paf->drop(); // adjust some material settings ps->setMaterialFlag(video::EMF_LIGHTING, false); ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); ps->setMaterialTexture(0, driver->getTexture("../../media/fireball.bmp")); ps->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); MyEventReceiver receiver(room, earth, env, driver); device->setEventReceiver(&receiver); /* Finally, draw everything. That's it. */ int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0); smgr->drawAll(); env->drawAll(); driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Per pixel lighting example - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; } /* **/ irrlicht-1.8.3/examples/10.Shaders/0000755000000000000000000000000012574354552015503 5ustar rootrootirrlicht-1.8.3/examples/10.Shaders/tutorial.html0000644000000000000000000007600412574354552020243 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 10. Shaders

This tutorial shows how to use shaders for D3D8, D3D9 and OpenGL with the engine and how to create new material types with them. It also shows how to disable the generation of mipmaps at texture loading, and how to use text scene nodes.

This tutorial does not explain how shaders work. I would recommend to read the D3D or OpenGL documentation, to search a tutorial, or to read a book about this.

The program which is described here will look like this:



Lets start!

At first, we need to include all headers and do the stuff we always do, like in nearly all other tutorials:

#include <irrlicht.h>
#include <iostream>

using namespace irr;

#pragma comment(lib, "Irrlicht.lib")

Because we want to use some interesting shaders in this tutorials, we need to set some data for them to make them able to compute nice colors. In this example, we'll use a simple vertex shader which will calculate the color of the vertex based on the position of the camera. For this, the shader needs the following data: The inverted world matrix for transforming the normal, the clip matrix for transforming the position, the camera position and the world position of the object for the calculation of the angle of light, and the color of the light. To be able to tell the shader all this data every frame, we have to derive a class from the IShaderConstantSetCallBack interface and override its only method, namely OnSetConstants(). This method will be called every time the material is set.
The method setVertexShaderConstant() of the IMaterialRendererServices interface is used to set the data the shader needs. If the user chose to use a High Level shader language like HLSL instead of Assembler in this example, you have to set the variable name as parameter instead of the register index.

IrrlichtDevice* device = 0;
bool UseHighLevelShaders = false;

class MyShaderCallBack : public video::IShaderConstantSetCallBack
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
{
video::IVideoDriver* driver = services->getVideoDriver();

// set inverted world matrix
// if we are using highlevel shaders (the user can select this when
// starting the program), we must set the constants by name.

core::matrix4 invWorld = driver->getTransform(video::ETS_WORLD);
invWorld.makeInverse();

if (UseHighLevelShaders)
services->setVertexShaderConstant("mInvWorld", &invWorld.M[0], 16);
else
services->setVertexShaderConstant(&invWorld.M[0], 0, 4);

// set clip matrix
core::matrix4 worldViewProj;
worldViewProj = driver->getTransform(video::ETS_PROJECTION);
worldViewProj *= driver->getTransform(video::ETS_VIEW);
worldViewProj *= driver->getTransform(video::ETS_WORLD);

if (UseHighLevelShaders)
services->setVertexShaderConstant("mWorldViewProj", &worldViewProj.M[0], 16);
else
services->setVertexShaderConstant(&worldViewProj.M[0], 4, 4);

// set camera position
core::vector3df pos = device->getSceneManager()->
getActiveCamera()->getAbsolutePosition();

if (UseHighLevelShaders)
services->setVertexShaderConstant("mLightPos", reinterpret_cast<f32*>(&pos), 3);
else
services->setVertexShaderConstant(reinterpret_cast<f32*>(&pos), 8, 1);

// set light color
video::SColorf col(0.0f,1.0f,1.0f,0.0f);

if (UseHighLevelShaders)
services->setVertexShaderConstant("mLightColor", reinterpret_cast<f32*>(&col), 4);
else
services->setVertexShaderConstant(reinterpret_cast<f32*>(&col), 9, 1);

// set transposed world matrix
core::matrix4 world = driver->getTransform(video::ETS_WORLD);
world = world.getTransposed();

if (UseHighLevelShaders)
services->setVertexShaderConstant("mTransWorld", &world.M[0], 16);
else
services->setVertexShaderConstant(&world.M[0], 10, 4);
}
};

The next few lines start up the engine. Just like in most other tutorials before. But in addition, we ask the user if he wants this example to use high level shaders if he selected a driver which is capable of doing so.

int main()
{
// let user select driver type

video::E_DRIVER_TYPE driverType = video::EDT_DIRECTX9;

printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");

char i;
std::cin >> i;

switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 1;
}

// ask the user if we should use high level shaders for this example
if (driverType == video::EDT_DIRECT3D9 ||
driverType == video::EDT_OPENGL) {
printf("Please press 'y' if you want to use high level shaders.\n");
std::cin >> i;
if (i == 'y')
UseHighLevelShaders = true;
}

// create device

device = createDevice(driverType, core::dimension2d<s32>(640, 480));

if (device == 0)
{
printf("\nWas not able to create driver.\n"\
"Please restart and select another driver.\n"
);
getch();
return 1;
}

video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
gui::IGUIEnvironment* gui = device->getGUIEnvironment();

Now for the more interesting parts. If we are using Direct3D, we want to load vertex and pixel shader programs, if we have
OpenGL, we want to use ARB fragment and vertex programs. I wrote the corresponding programs down into the files d3d8.ps, d3d8.vs, d3d9.ps, d3d9.vs, opengl.ps and opengl.vs. We only need the right filenames now. This is done in the following switch. Note, that it is not necessary to write the shaders into text files, like in this example. You can even write the shaders directly as strings into the cpp source file, and use later addShaderMaterial() instead of addShaderMaterialFromFiles().

	c8* vsFileName = 0; // filename for the vertex shader
c8* psFileName = 0; // filename for the pixel shader

switch(driverType)
{
case video::EDT_DIRECT3D8:
psFileName = "../../media/d3d8.psh";
vsFileName = "../../media/d3d8.vsh";
break;
case video::EDT_DIRECT3D9:
if (UseHighLevelShaders)
{
psFileName = "../../media/d3d9.hlsl";
vsFileName = psFileName; // both shaders are in the same file
}
else
{
psFileName = "../../media/d3d9.psh";
vsFileName = "../../media/d3d9.vsh";
}
break;
case video::EDT_OPENGL:
if (UseHighLevelShaders)
{
psFileName = "../../media/opengl.frag";
vsFileName = "../../media/opengl.vert";
}
else
{
psFileName = "../../media/opengl.psh";
vsFileName = "../../media/opengl.vsh";
}
break;
}

In addition, we check if the hardware and the selected renderer is capable of executing the shaders we want. If not, we simply set the filename string to 0. This is not necessary, but useful in this example: For example, if the hardware is able to execute vertex shaders but not pixel shaders, we create a new material which only uses the vertex shader, and no pixel shader. Otherwise, if we would tell the engine to create this material and the engine sees that the hardware wouldn't be able to fullfill the request completely,
it would not create any new material at all. So in this example you would see at least the vertex shader in action, without the pixel shader.

	if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
!driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1))
{
device->getLogger()->log("WARNING: Pixel shaders disabled "\
"because of missing driver/hardware support.");
psFileName = 0;
}

if (!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
!driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1))
{
device->getLogger()->log("WARNING: Vertex shaders disabled "\
"because of missing driver/hardware support.");
vsFileName = 0;
}

Now lets create the new materials.
As you maybe know from previous examples, a material type in the Irrlicht engine is set by simply changing the MaterialType value in the SMaterial struct. And this value is just a simple 32 bit value, like video::EMT_SOLID. So we only need the engine to create a new value for us which we can set there. To do this, we get a pointer to the IGPUProgrammingServices and call addShaderMaterialFromFiles(), which returns such a new 32 bit value. That's all.
The parameters to this method are the following: First, the names of the files containing the code of the vertex and the pixel shader.
If you would use addShaderMaterial() instead, you would not need file names, then you could write the code of the shader directly as string. The following parameter is a pointer to the IShaderConstantSetCallBack class we wrote at the beginning of this tutorial. If you don't want to set constants, set this to 0. The last paramter tells the engine which material it should use as base material.
To demonstrate this, we create two materials with a different base material, one with EMT_SOLID and one with EMT_TRANSPARENT_ADD_COLOR.

	// create materials

video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();

s32 newMaterialType1 = 0;
s32 newMaterialType2 = 0;

if (gpu)
{
MyShaderCallBack* mc = new MyShaderCallBack();
// create the shaders depending on if the user wanted high level
// or low level shaders:


if (UseHighLevelShaders)
{
// create material from high level shaders (hlsl or glsl)

newMaterialType1 = gpu->addHighLevelShaderMaterialFromFiles(
vsFileName, "vertexMain", video::EVST_VS_1_1,
psFileName, "pixelMain", video::EPST_PS_1_1,
mc, video::EMT_SOLID);

newMaterialType2 = gpu->addHighLevelShaderMaterialFromFiles(
vsFileName, "vertexMain", video::EVST_VS_1_1,
psFileName, "pixelMain", video::EPST_PS_1_1,
mc, video::EMT_TRANSPARENT_ADD_COLOR);
}
else
{
// create material from low level shaders (asm or arb_asm)

newMaterialType1 = gpu->addShaderMaterialFromFiles(vsFileName,
psFileName, mc, video::EMT_SOLID);

newMaterialType2 = gpu->addShaderMaterialFromFiles(vsFileName,
psFileName, mc, video::EMT_TRANSPARENT_ADD_COLOR);
}

mc->drop();
}

Now its time for testing out the materials. We create a test cube and set the material we created. In addition, we add a text scene node to the cube and a rotatation animator, to make it look more interesting and important.


	// create test scene node 1, with the new created material type 1

	scene::ISceneNode* node = smgr->addCubeSceneNode(50);
	node->setPosition(core::vector3df(0,0,0));
	node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
	node->setMaterialFlag(video::EMF_LIGHTING, false);
	node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType1);

	smgr->addTextSceneNode(gui->getBuiltInFont(),
			L"PS & VS & EMT_SOLID",
			video::SColor(255,255,255,255),	node);

	scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(
			core::vector3df(0,0.3f,0));
	node->addAnimator(anim);
	anim->drop();

Same for the second cube, but with the second material we created.

	// create test scene node 2, with the new created material type 2

	node = smgr->addCubeSceneNode(50);
	node->setPosition(core::vector3df(0,-10,50));
	node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
	node->setMaterialFlag(video::EMF_LIGHTING, false);
	node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType2);

	smgr->addTextSceneNode(gui->getBuiltInFont(),
			L"PS & VS & EMT_TRANSPARENT",
			video::SColor(255,255,255,255),	node);

	anim = smgr->createRotationAnimator(core::vector3df(0,0.3f,0));
	node->addAnimator(anim);
	anim->drop();

Then we add a third cube without a shader on it, to be able to compare the cubes.

	// add a scene node with no shader 

	node = smgr->addCubeSceneNode(50);
	node->setPosition(core::vector3df(0,50,25));
	node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
	node->setMaterialFlag(video::EMF_LIGHTING, false);
	smgr->addTextSceneNode(gui->getBuiltInFont(), L"NO SHADER",
		video::SColor(255,255,255,255), node);
            

And last, we add a skybox and a user controlled camera to the scene. For the skybox textures, we disable mipmap generation, because we don't need mipmaps on it.

	// add a nice skybox

driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);

smgr->addSkyBoxSceneNode(
driver->getTexture("../../media/irrlicht2_up.jpg"),
driver->getTexture("../../media/irrlicht2_dn.jpg"),
driver->getTexture("../../media/irrlicht2_lf.jpg"),
driver->getTexture("../../media/irrlicht2_rt.jpg"),
driver->getTexture("../../media/irrlicht2_ft.jpg"),
driver->getTexture("../../media/irrlicht2_bk.jpg"));

driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);

// add a camera and disable the mouse cursor

scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS(0, 100.0f, 100.0f);
cam->setPosition(core::vector3df(-100,50,100));
cam->setTarget(core::vector3df(0,0,0));
device->getCursorControl()->setVisible(false);

Now draw everything. That's all.

	int lastFPS = -1;

while(device->run())
if (device->isWindowActive())
{
driver->beginScene(true, true, video::SColor(255,0,0,0));
smgr->drawAll();
driver->endScene();

int fps = driver->getFPS();

if (lastFPS != fps)
{
core::stringw str = L"Irrlicht Engine - Vertex and pixel shader example [";
str += driver->getName();
str += "] FPS:";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}

device->drop();

return 0;

Compile and run this, and I hope you have fun with your new little shader writing tool :).

Shader files

The files containing the shaders can be found in the media directory of the SDK. However, they look like this:

D3D9.HLSL
// part of the Irrlicht Engine Shader example.
// These simple Direct3D9 pixel and vertex shaders will be loaded by the shaders
// example. Please note that these example shaders don't do anything really useful. 
// They only demonstrate that shaders can be used in Irrlicht.

//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
float4x4 mWorldViewProj;  // World * View * Projection transformation
float4x4 mInvWorld;       // Inverted world matrix
float4x4 mTransWorld;     // Transposed world matrix
float3 mLightPos;         // Light position
float4 mLightColor;       // Light color


// Vertex shader output structure
struct VS_OUTPUT
{
	float4 Position   : POSITION;   // vertex position 
	float4 Diffuse    : COLOR0;     // vertex diffuse color
	float2 TexCoord   : TEXCOORD0;  // tex coords
};


VS_OUTPUT vertexMain( in float4 vPosition : POSITION,
                      in float3 vNormal   : NORMAL,
                      float2 texCoord     : TEXCOORD0 )
{
	VS_OUTPUT Output;

	// transform position to clip space 
	Output.Position = mul(vPosition, mWorldViewProj);
	
	// transform normal 
	float3 normal = mul(vNormal, mInvWorld);
	
	// renormalize normal 
	normal = normalize(normal);
	
	// position in world coodinates
	float3 worldpos = mul(mTransWorld, vPosition);
	
	// calculate light vector, vtxpos - lightpos
	float3 lightVector = worldpos - mLightPos;
	
	// normalize light vector 
	lightVector = normalize(lightVector);
	
	// calculate light color 
	float3 tmp = dot(-lightVector, normal);
	tmp = lit(tmp.x, tmp.y, 1.0);
	
	tmp = mLightColor * tmp.y;
	Output.Diffuse = float4(tmp.x, tmp.y, tmp.z, 0);
	Output.TexCoord = texCoord;
	
	return Output;
}



// Pixel shader output structure
struct PS_OUTPUT
{
    float4 RGBColor : COLOR0;  // Pixel color    
};


sampler2D tex0;
	
PS_OUTPUT pixelMain( float2 TexCoord : TEXCOORD0,
                     float4 Position : POSITION,
                     float4 Diffuse  : COLOR0 ) 
{ 
	PS_OUTPUT Output;

	float4 col = tex2D( tex0, TexCoord );  // sample color map
	
	// multiply with diffuse and do other senseless operations
	Output.RGBColor = Diffuse * col;
	Output.RGBColor *= 4.0;

	return Output;
}

D3D9.VSH
; part of the Irrlicht Engine Shader example.
; This Direct3D9 vertex shader will be loaded by the engine.
; Please note that these example shaders don't do anything really useful. 
; They only demonstrate that shaders can be used in Irrlicht.
vs.1.1 dcl_position v0; ; declare position dcl_normal v1; ; declare normal dcl_color v2; ; declare color dcl_texcoord0 v3; ; declare texture coordinate
; transpose and transform position to clip space mul r0, v0.x, c4 mad r0, v0.y, c5, r0 mad r0, v0.z, c6, r0 add oPos, c7, r0 ; transform normal dp3 r1.x, v1, c0 dp3 r1.y, v1, c1 dp3 r1.z, v1, c2 ; renormalize normal dp3 r1.w, r1, r1 rsq r1.w, r1.w mul r1, r1, r1.w ; calculate light vector m4x4 r6, v0, c10 ; vertex into world position add r2, c8, -r6 ; vtxpos - lightpos ; normalize light vector dp3 r2.w, r2, r2 rsq r2.w, r2.w mul r2, r2, r2.w ; calculate light color dp3 r3, r1, r2 ; dp3 with negative light vector lit r5, r3 ; clamp to zero if r3 < 0, r5 has diffuce component in r5.y mul oD0, r5.y, c9 ; ouput diffuse color mov oT0, v3 ; store texture coordinates

D3D9.PSH
; part of the Irrlicht Engine Shader example.
; This simple Direct3D9 pixel shader will be loaded by the engine.
; Please note that these example shaders don't do anything really useful. 
; They only demonstrate that shaders can be used in Irrlicht.
ps.1.1 tex t0 ; sample color map add r0, v0, v0 ; mulitply with color mul t0, t0, r0 ; mulitply with color add r0, t0, t0 ; make it brighter and store result

D3D8.VSH
; part of the Irrlicht Engine Shader example.
; This Direct3D9 vertex shader will be loaded by the engine.
; Please note that these example shaders don't do anything really useful. 
; They only demonstrate that shaders can be used in Irrlicht.
vs.1.1 ; transpose and transform position to clip space mul r0, v0.x, c4 mad r0, v0.y, c5, r0 mad r0, v0.z, c6, r0 add oPos, c7, r0 ; transform normal dp3 r1.x, v1, c0 dp3 r1.y, v1, c1 dp3 r1.z, v1, c2 ; renormalize normal dp3 r1.w, r1, r1 rsq r1.w, r1.w mul r1, r1, r1.w ; calculate light vector m4x4 r6, v0, c10 ; vertex into world position add r2, c8, -r6 ; vtxpos - lightpos ; normalize light vector dp3 r2.w, r2, r2 rsq r2.w, r2.w mul r2, r2, r2.w ; calculate light color dp3 r3, r1, r2 ; dp3 with negative light vector lit r5, r3 ; clamp to zero if r3 < 0, r5 has diffuce component in r5.y mul oD0, r5.y, c9 ; ouput diffuse color mov oT0, v3 ; store texture coordinates

D3D8.PSH
; part of the Irrlicht Engine Shader example.
; This simple Direct3D9 pixel shader will be loaded by the engine.
; Please note that these example shaders don't do anything really useful. 
; They only demonstrate that shaders can be used in Irrlicht.
ps.1.1 tex t0 ; sample color map mul_x2 t0, t0, v0 ; mulitply with color add r0, t0, t0 ; make it brighter and store result

OPENGL.VSH
!!ARBvp1.0
# part of the Irrlicht Engine Shader example.
# Please note that these example shaders don't do anything really useful. 
# They only demonstrate that shaders can be used in Irrlicht.
#input ATTRIB InPos = vertex.position; ATTRIB InColor = vertex.color; ATTRIB InNormal = vertex.normal; ATTRIB InTexCoord = vertex.texcoord; #output OUTPUT OutPos = result.position; OUTPUT OutColor = result.color; OUTPUT OutTexCoord = result.texcoord; PARAM MVP[4] = { state.matrix.mvp }; # modelViewProjection matrix. TEMP Temp; TEMP TempColor; TEMP TempNormal; TEMP TempPos; #transform position to clip space DP4 Temp.x, MVP[0], InPos; DP4 Temp.y, MVP[1], InPos; DP4 Temp.z, MVP[2], InPos; DP4 Temp.w, MVP[3], InPos; #transform normal DP3 TempNormal.x, InNormal.x, program.local[0]; DP3 TempNormal.y, InNormal.y, program.local[1]; DP3 TempNormal.z, InNormal.z, program.local[2]; #renormalize normal DP3 TempNormal.w, TempNormal, TempNormal; RSQ TempNormal.w, TempNormal.w; MUL TempNormal, TempNormal, TempNormal.w; # calculate light vector DP4 TempPos.x, InPos, program.local[10]; # vertex into world position DP4 TempPos.y, InPos, program.local[11]; DP4 TempPos.z, InPos, program.local[12]; DP4 TempPos.w, InPos, program.local[13]; ADD TempPos, program.local[8], -TempPos; # vtxpos - lightpos # normalize light vector DP3 TempPos.w, TempPos, TempPos; RSQ TempPos.w, TempPos.w; MUL TempPos, TempPos, TempPos.w; # calculate light color DP3 TempColor, TempNormal, TempPos; # dp3 with negative light vector LIT OutColor, TempColor; # clamp to zero if r3 < 0, r5 has diffuce component in r5.y MUL OutColor, TempColor.y, program.local[9]; # ouput diffuse color MOV OutColor.w, 1.0; # we want alpha to be always 1 MOV OutTexCoord, InTexCoord; # store texture coordinate MOV OutPos, Temp; END

OPENGL.PSH
!!ARBfp1.0
# part of the Irrlicht Engine Shader example.
# Please note that these example shaders don't do anything really useful. 
# They only demonstrate that shaders can be used in Irrlicht.
#Input ATTRIB inTexCoord = fragment.texcoord; # texture coordinates ATTRIB inColor = fragment.color.primary; # interpolated diffuse color #Output OUTPUT outColor = result.color; TEMP texelColor; TEMP tmp; TXP texelColor, inTexCoord, texture, 2D; ADD tmp, inColor, inColor; # mulitply with color MUL texelColor, texelColor, tmp; # mulitply with color ADD outColor, texelColor, texelColor; # make it brighter and store result END

 

 

 

irrlicht-1.8.3/examples/10.Shaders/Shaders_vc9.vcproj0000644000000000000000000001220212574354552021077 0ustar rootroot irrlicht-1.8.3/examples/10.Shaders/Shaders_vc8.vcproj0000644000000000000000000001210212574354552021075 0ustar rootroot irrlicht-1.8.3/examples/10.Shaders/Shaders_vc12.vcxproj0000644000000000000000000003271412574354552021353 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 10.Shaders {27158C82-CD15-4A9B-9848-35E7065B209F} Shaders Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Shaders.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\10.Shaders.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Shaders.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\10.Shaders.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Shaders.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\10.Shaders.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Shaders.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\10.Shaders.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/10.Shaders/Shaders_vc11.vcxproj0000644000000000000000000003271312574354552021351 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 10.Shaders {27158C82-CD15-4A9B-9848-35E7065B209F} Shaders Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Shaders.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\10.Shaders.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Shaders.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\10.Shaders.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Shaders.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\10.Shaders.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Shaders.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\10.Shaders.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/10.Shaders/Shaders_vc10.vcxproj0000644000000000000000000003271312574354552021350 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 10.Shaders {27158C82-CD15-4A9B-9848-35E7065B209F} Shaders Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Shaders.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\10.Shaders.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Shaders.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\10.Shaders.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Shaders.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\10.Shaders.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Shaders.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\10.Shaders.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/10.Shaders/Shaders.vcproj0000644000000000000000000001051512574354552020323 0ustar rootroot irrlicht-1.8.3/examples/10.Shaders/Shaders.dev0000644000000000000000000000173412574354552017601 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 10 Shaders UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=10.Shaders.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/10.Shaders/Shaders.cbp0000644000000000000000000000272712574354552017572 0ustar rootroot irrlicht-1.8.3/examples/10.Shaders/Makefile0000644000000000000000000000220112574354552017136 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 10.Shaders Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/10.Shaders/main.cpp0000644000000000000000000003513212574354552017137 0ustar rootroot/** Example 010 Shaders This tutorial shows how to use shaders for D3D8, D3D9, OpenGL, and Cg with the engine and how to create new material types with them. It also shows how to disable the generation of mipmaps at texture loading, and how to use text scene nodes. This tutorial does not explain how shaders work. I would recommend to read the D3D, OpenGL, or Cg documentation, to search a tutorial, or to read a book about this. At first, we need to include all headers and do the stuff we always do, like in nearly all other tutorials: */ #include #include #include "driverChoice.h" using namespace irr; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif /* Because we want to use some interesting shaders in this tutorials, we need to set some data for them to make them able to compute nice colors. In this example, we'll use a simple vertex shader which will calculate the color of the vertex based on the position of the camera. For this, the shader needs the following data: The inverted world matrix for transforming the normal, the clip matrix for transforming the position, the camera position and the world position of the object for the calculation of the angle of light, and the color of the light. To be able to tell the shader all this data every frame, we have to derive a class from the IShaderConstantSetCallBack interface and override its only method, namely OnSetConstants(). This method will be called every time the material is set. The method setVertexShaderConstant() of the IMaterialRendererServices interface is used to set the data the shader needs. If the user chose to use a High Level shader language like HLSL instead of Assembler in this example, you have to set the variable name as parameter instead of the register index. */ IrrlichtDevice* device = 0; bool UseHighLevelShaders = false; bool UseCgShaders = false; class MyShaderCallBack : public video::IShaderConstantSetCallBack { public: virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData) { video::IVideoDriver* driver = services->getVideoDriver(); // set inverted world matrix // if we are using highlevel shaders (the user can select this when // starting the program), we must set the constants by name. core::matrix4 invWorld = driver->getTransform(video::ETS_WORLD); invWorld.makeInverse(); if (UseHighLevelShaders) services->setVertexShaderConstant("mInvWorld", invWorld.pointer(), 16); else services->setVertexShaderConstant(invWorld.pointer(), 0, 4); // set clip matrix core::matrix4 worldViewProj; worldViewProj = driver->getTransform(video::ETS_PROJECTION); worldViewProj *= driver->getTransform(video::ETS_VIEW); worldViewProj *= driver->getTransform(video::ETS_WORLD); if (UseHighLevelShaders) services->setVertexShaderConstant("mWorldViewProj", worldViewProj.pointer(), 16); else services->setVertexShaderConstant(worldViewProj.pointer(), 4, 4); // set camera position core::vector3df pos = device->getSceneManager()-> getActiveCamera()->getAbsolutePosition(); if (UseHighLevelShaders) services->setVertexShaderConstant("mLightPos", reinterpret_cast(&pos), 3); else services->setVertexShaderConstant(reinterpret_cast(&pos), 8, 1); // set light color video::SColorf col(0.0f,1.0f,1.0f,0.0f); if (UseHighLevelShaders) services->setVertexShaderConstant("mLightColor", reinterpret_cast(&col), 4); else services->setVertexShaderConstant(reinterpret_cast(&col), 9, 1); // set transposed world matrix core::matrix4 world = driver->getTransform(video::ETS_WORLD); world = world.getTransposed(); if (UseHighLevelShaders) { services->setVertexShaderConstant("mTransWorld", world.pointer(), 16); // set texture, for textures you can use both an int and a float setPixelShaderConstant interfaces (You need it only for an OpenGL driver). s32 TextureLayerID = 0; if (UseHighLevelShaders) services->setPixelShaderConstant("myTexture", &TextureLayerID, 1); } else services->setVertexShaderConstant(world.pointer(), 10, 4); } }; /* The next few lines start up the engine just like in most other tutorials before. But in addition, we ask the user if he wants to use high level shaders in this example, if he selected a driver which is capable of doing so. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // ask the user if we should use high level shaders for this example if (driverType == video::EDT_DIRECT3D9 || driverType == video::EDT_OPENGL) { char i; printf("Please press 'y' if you want to use high level shaders.\n"); std::cin >> i; if (i == 'y') { UseHighLevelShaders = true; printf("Please press 'y' if you want to use Cg shaders.\n"); std::cin >> i; if (i == 'y') UseCgShaders = true; } } // create device device = createDevice(driverType, core::dimension2d(640, 480)); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* gui = device->getGUIEnvironment(); // Make sure we don't try Cg without support for it if (UseCgShaders && !driver->queryFeature(video::EVDF_CG)) { printf("Warning: No Cg support, disabling.\n"); UseCgShaders=false; } /* Now for the more interesting parts. If we are using Direct3D, we want to load vertex and pixel shader programs, if we have OpenGL, we want to use ARB fragment and vertex programs. I wrote the corresponding programs down into the files d3d8.ps, d3d8.vs, d3d9.ps, d3d9.vs, opengl.ps and opengl.vs. We only need the right filenames now. This is done in the following switch. Note, that it is not necessary to write the shaders into text files, like in this example. You can even write the shaders directly as strings into the cpp source file, and use later addShaderMaterial() instead of addShaderMaterialFromFiles(). */ io::path vsFileName; // filename for the vertex shader io::path psFileName; // filename for the pixel shader switch(driverType) { case video::EDT_DIRECT3D8: psFileName = "../../media/d3d8.psh"; vsFileName = "../../media/d3d8.vsh"; break; case video::EDT_DIRECT3D9: if (UseHighLevelShaders) { // Cg can also handle this syntax psFileName = "../../media/d3d9.hlsl"; vsFileName = psFileName; // both shaders are in the same file } else { psFileName = "../../media/d3d9.psh"; vsFileName = "../../media/d3d9.vsh"; } break; case video::EDT_OPENGL: if (UseHighLevelShaders) { if (!UseCgShaders) { psFileName = "../../media/opengl.frag"; vsFileName = "../../media/opengl.vert"; } else { // Use HLSL syntax for Cg psFileName = "../../media/d3d9.hlsl"; vsFileName = psFileName; // both shaders are in the same file } } else { psFileName = "../../media/opengl.psh"; vsFileName = "../../media/opengl.vsh"; } break; } /* In addition, we check if the hardware and the selected renderer is capable of executing the shaders we want. If not, we simply set the filename string to 0. This is not necessary, but useful in this example: For example, if the hardware is able to execute vertex shaders but not pixel shaders, we create a new material which only uses the vertex shader, and no pixel shader. Otherwise, if we would tell the engine to create this material and the engine sees that the hardware wouldn't be able to fulfill the request completely, it would not create any new material at all. So in this example you would see at least the vertex shader in action, without the pixel shader. */ if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) && !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)) { device->getLogger()->log("WARNING: Pixel shaders disabled "\ "because of missing driver/hardware support."); psFileName = ""; } if (!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) && !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)) { device->getLogger()->log("WARNING: Vertex shaders disabled "\ "because of missing driver/hardware support."); vsFileName = ""; } /* Now lets create the new materials. As you maybe know from previous examples, a material type in the Irrlicht engine is set by simply changing the MaterialType value in the SMaterial struct. And this value is just a simple 32 bit value, like video::EMT_SOLID. So we only need the engine to create a new value for us which we can set there. To do this, we get a pointer to the IGPUProgrammingServices and call addShaderMaterialFromFiles(), which returns such a new 32 bit value. That's all. The parameters to this method are the following: First, the names of the files containing the code of the vertex and the pixel shader. If you would use addShaderMaterial() instead, you would not need file names, then you could write the code of the shader directly as string. The following parameter is a pointer to the IShaderConstantSetCallBack class we wrote at the beginning of this tutorial. If you don't want to set constants, set this to 0. The last parameter tells the engine which material it should use as base material. To demonstrate this, we create two materials with a different base material, one with EMT_SOLID and one with EMT_TRANSPARENT_ADD_COLOR. */ // create materials video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices(); s32 newMaterialType1 = 0; s32 newMaterialType2 = 0; if (gpu) { MyShaderCallBack* mc = new MyShaderCallBack(); // create the shaders depending on if the user wanted high level // or low level shaders: if (UseHighLevelShaders) { // Choose the desired shader type. Default is the native // shader type for the driver, for Cg pass the special // enum value EGSL_CG const video::E_GPU_SHADING_LANGUAGE shadingLanguage = UseCgShaders ? video::EGSL_CG:video::EGSL_DEFAULT; // create material from high level shaders (hlsl, glsl or cg) newMaterialType1 = gpu->addHighLevelShaderMaterialFromFiles( vsFileName, "vertexMain", video::EVST_VS_1_1, psFileName, "pixelMain", video::EPST_PS_1_1, mc, video::EMT_SOLID, 0, shadingLanguage); newMaterialType2 = gpu->addHighLevelShaderMaterialFromFiles( vsFileName, "vertexMain", video::EVST_VS_1_1, psFileName, "pixelMain", video::EPST_PS_1_1, mc, video::EMT_TRANSPARENT_ADD_COLOR, 0 , shadingLanguage); } else { // create material from low level shaders (asm or arb_asm) newMaterialType1 = gpu->addShaderMaterialFromFiles(vsFileName, psFileName, mc, video::EMT_SOLID); newMaterialType2 = gpu->addShaderMaterialFromFiles(vsFileName, psFileName, mc, video::EMT_TRANSPARENT_ADD_COLOR); } mc->drop(); } /* Now it's time for testing the materials. We create a test cube and set the material we created. In addition, we add a text scene node to the cube and a rotation animator to make it look more interesting and important. */ // create test scene node 1, with the new created material type 1 scene::ISceneNode* node = smgr->addCubeSceneNode(50); node->setPosition(core::vector3df(0,0,0)); node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp")); node->setMaterialFlag(video::EMF_LIGHTING, false); node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType1); smgr->addTextSceneNode(gui->getBuiltInFont(), L"PS & VS & EMT_SOLID", video::SColor(255,255,255,255), node); scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator( core::vector3df(0,0.3f,0)); node->addAnimator(anim); anim->drop(); /* Same for the second cube, but with the second material we created. */ // create test scene node 2, with the new created material type 2 node = smgr->addCubeSceneNode(50); node->setPosition(core::vector3df(0,-10,50)); node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp")); node->setMaterialFlag(video::EMF_LIGHTING, false); node->setMaterialFlag(video::EMF_BLEND_OPERATION, true); node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType2); smgr->addTextSceneNode(gui->getBuiltInFont(), L"PS & VS & EMT_TRANSPARENT", video::SColor(255,255,255,255), node); anim = smgr->createRotationAnimator(core::vector3df(0,0.3f,0)); node->addAnimator(anim); anim->drop(); /* Then we add a third cube without a shader on it, to be able to compare the cubes. */ // add a scene node with no shader node = smgr->addCubeSceneNode(50); node->setPosition(core::vector3df(0,50,25)); node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp")); node->setMaterialFlag(video::EMF_LIGHTING, false); smgr->addTextSceneNode(gui->getBuiltInFont(), L"NO SHADER", video::SColor(255,255,255,255), node); /* And last, we add a skybox and a user controlled camera to the scene. For the skybox textures, we disable mipmap generation, because we don't need mipmaps on it. */ // add a nice skybox driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); smgr->addSkyBoxSceneNode( driver->getTexture("../../media/irrlicht2_up.jpg"), driver->getTexture("../../media/irrlicht2_dn.jpg"), driver->getTexture("../../media/irrlicht2_lf.jpg"), driver->getTexture("../../media/irrlicht2_rt.jpg"), driver->getTexture("../../media/irrlicht2_ft.jpg"), driver->getTexture("../../media/irrlicht2_bk.jpg")); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true); // add a camera and disable the mouse cursor scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS(); cam->setPosition(core::vector3df(-100,50,100)); cam->setTarget(core::vector3df(0,0,0)); device->getCursorControl()->setVisible(false); /* Now draw everything. That's all. */ int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, video::SColor(255,0,0,0)); smgr->drawAll(); driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Irrlicht Engine - Vertex and pixel shader example ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; } /* Compile and run this, and I hope you have fun with your new little shader writing tool :). **/ irrlicht-1.8.3/examples/09.Meshviewer/0000755000000000000000000000000012574354552016240 5ustar rootrootirrlicht-1.8.3/examples/09.Meshviewer/tutorial.html0000644000000000000000000005203112574354552020772 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 9. Mesh Viewer

This tutorial shows how to create a more complex application with the engine. We construct a simple mesh viewer using the user interface API and the scenemanagement of Irrlicht.
The tutorial shows how to create and use Buttons, Windows, Toolbars, Menus, ComboBoxes, Tabcontrols, Editboxes, Images, MessageBoxes, SkyBoxes, and how to parse XML files with the integrated XML reader of the engine.

The program which is described here will look like this:



Lets start!

We start like in most other tutorials: Include all nesessary header files, add a comment to let the engine be linked with the right .lib file in Visual Studio, and deklare some global variables. We also add two 'using namespece' statements, so we do not need to write the whole names of all classes. In this tutorial, we use a lot stuff from the gui namespace.

#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace gui;

#pragma comment(lib, "Irrlicht.lib")

IrrlichtDevice *Device = 0;
core::stringc StartUpModelFile;
core::stringw MessageText;
core::stringw Caption;
scene::IAnimatedMeshSceneNode* Model = 0;
scene::ISceneNode* SkyBox = 0;

The three following functions do several stuff used by the mesh viewer. The first function showAboutText() simply displays a messagebox with a caption and a message text. The texts will be stored in the MessageText and Caption variables at startup.

void showAboutText()
{
// create modal message box with the text
// loaded from the xml file
.
Device->getGUIEnvironment()->addMessageBox(
Caption.c_str(), MessageText.c_str());
}

The second function loadModel() loads a model and displays it using an addAnimatedMeshSceneNode and the scene manager. Nothing difficult. It also displays a short message box, if the model could not be loaded.

void loadModel(const c8* filename)
{
// load a model into the engine
if (Model)
Model->remove();
Model = 0;

scene::IAnimatedMesh* m = Device->getSceneManager()->getMesh(filename);
if (!m)
{
// model could not be loaded
if (StartUpModelFile != filename)
Device->getGUIEnvironment()->addMessageBox(
Caption.c_str(), L"The model could not be loaded. " \
L"Maybe it is not a supported file format.");
return;
}

// set default material properties
Model = Device->getSceneManager()->addAnimatedMeshSceneNode(m);
Model->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
Model->setMaterialFlag(video::EMF_LIGHTING, false);
Model->setDebugDataVisible(true);
}

Finally, the third function creates a toolbox window. In this simple mesh viewer, this toolbox only contains a tab control with three edit boxes for changing the scale of the displayed model.

void createToolBox()
{
// remove tool box if already there
IGUIEnvironment* env = Device->getGUIEnvironment();
IGUIElement* root = env->getRootGUIElement();
IGUIElement* e = root->getElementFromId(5000, true);
if (e) e->remove();

// create the toolbox window
IGUIWindow* wnd = env->addWindow(core::rect<s32>(450,25,640,480),
false, L"Toolset", 0, 5000);

// create tab control and tabs
IGUITabControl* tab = env->addTabControl(
core::rect<s32>(2,20,640-452,480-7), wnd, true, true);
IGUITab* t1 = tab->addTab(L"Scale");
IGUITab* t2 = tab->addTab(L"Empty Tab");

// add some edit boxes and a button to tab one
env->addEditBox(L"1.0", core::rect<s32>(40,50,130,70), true, t1, 901);
env->addEditBox(L"1.0", core::rect<s32>(40,80,130,100), true, t1, 902);
env->addEditBox(L"1.0", core::rect<s32>(40,110,130,130), true, t1, 903);
env->addButton(core::rect<s32>(10,150,100,190), t1, 1101, L"set");

// bring irrlicht engine logo to front, because it
// now may be below the newly created toolbox
root->bringToFront(root->getElementFromId(666, true));
}

To get all the events sent by the GUI Elements, we need to create an event receiver. This one is really simple. If an event occurs, it checks the id of the caller and the event type, and starts an action based on these values. For example, if a menu item with id 100 was selected, if opens a file-open-dialog.

class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == EET_GUI_EVENT)
{
s32 id = event.GUIEvent.Caller->getID();
IGUIEnvironment* env = Device->getGUIEnvironment();
switch(event.GUIEvent.EventType)
{
case EGET_MENU_ITEM_SELECTED:
{
// a menu item was clicked
IGUIContextMenu* menu = (IGUIContextMenu*)event.GUIEvent.Caller;
s32 id = menu->getItemCommandId(menu->getSelectedItem());

switch(id)
{
case 100: // File -> Open Model
env->addFileOpenDialog(L"Please select a model file to open");
break;
case 200: // File -> Quit
Device->closeDevice();
break;
case 300: // View -> Skybox
SkyBox->setVisible(!SkyBox->isVisible());
break;
case 400: // View -> Debug Information
if (Model)
Model->setDebugDataVisible(!Model->isDebugDataVisible());
break;
case 500: // Help->About
showAboutText();
break;
case 610: // View -> Material -> Solid
if (Model)
Model->setMaterialType(video::EMT_SOLID);
break;
case 620: // View -> Material -> Transparent
if (Model)
Model->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
break;
case 630: // View -> Material -> Reflection
if (Model)
Model->setMaterialType(video::EMT_SPHERE_MAP);
break;
}
break;
}
case EGET_FILE_SELECTED:
{
// load the model file, selected in the file open dialog
IGUIFileOpenDialog* dialog =
(IGUIFileOpenDialog*)event.GUIEvent.Caller;
loadModel(core::stringc(dialog->getFilename()).c_str());
}
case EGET_BUTTON_CLICKED:
switch(id)
{
case 1101:
{
// set scale
gui::IGUIElement* root = env->getRootGUIElement();
core::vector3df scale;
core::stringc s;
s = root->getElementFromId(901, true)->getText();
scale.X = (f32)atof(s.c_str());
s = root->getElementFromId(902, true)->getText();
scale.Y = (f32)atof(s.c_str());
s = root->getElementFromId(903, true)->getText();
scale.Z = (f32)atof(s.c_str());
if (Model)
Model->setScale(scale);
}
break;
case 1102:
env->addFileOpenDialog(L"Please select a model file to open");
break;
case 1103:
showAboutText();
break;
case 1104:
createToolBox();
break;
}
break;
}
}
return false;
}
};

Most of the hard work is done. We only need to create the Irrlicht Engine device and all the buttons, menus and toolbars. We start up the engine as usual, using createDevice(). To make our application catch events, we set our eventreceiver as parameter. The #ifdef WIN32 preprocessor commands are not necesarry, but I included them to make the tutorial use DirectX on Windows and OpenGL on all other platforms like Linux. As you can see, there is also a unusual call to IrrlichtDevice::setResizeAble(). This makes the render window resizeable, which is quite useful for a mesh viewer.

int main()
{
// ask user for driver
video::E_DRIVER_TYPE driverType;
printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");

char key;
std::cin >> key;

switch(key)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 1;
}
// create device and exit if creation failed
MyEventReceiver receiver;
Device = createDevice(driverType, core::dimension2d<s32>(640, 480),
16, false, false, false, &receiver);
if (Device == 0)
return 1; // could not create selected driver.

Device->setResizable(true);
Device->setWindowCaption(L"Irrlicht Engine - Loading...");

video::IVideoDriver* driver = Device->getVideoDriver();
IGUIEnvironment* env = Device->getGUIEnvironment();
scene::ISceneManager* smgr = Device->getSceneManager();

The next step is to read the configuration file. It is stored in the xml format and looks a little bit like this:

<?xml version="1.0"?>
<config>
<startUpModel file="some filename" />
<messageText caption="Irrlicht Engine Mesh Viewer">
Hello!
</messageText>
</config>


We need the data stored in there to be written into the global variables StartUpModelFile, MessageText and Caption. This is now done using the Irrlicht Engine integrated XML parser:

	// read configuration from xml file
io::IXMLReader* xml =
Device->getFileSystem()->createXMLReader("../../media/config.xml");
while(xml && xml->read())
{
switch(xml->getNodeType())
{
case io::EXN_TEXT:
// in this xml file, the only text which occurs is the messageText
MessageText = xml->getNodeData();
break;
case io::EXN_ELEMENT:
{
if (core::stringw("startUpModel") == xml->getNodeName())
StartUpModelFile = xml->getAttributeValue(L"file");
else
if (core::stringw("messageText") == xml->getNodeName())
Caption = xml->getAttributeValue(L"caption");
}
break;
}
}
if (xml)
xml->drop(); // don't forget to delete the xml reader

That wasn't difficult. Now we'll set a nicer font and create the Menu. It is possible to create submenus for every menu item. The call menu->addItem(L"File", -1, true, true); for example adds a new menu Item with the name "File" and the id -1. The following parameter says that the menu item should be enabled, and the last one says, that there should be a submenu. The submenu can now be accessed with menu->getSubMenu(0), because the "File" entry is the menu item with index 0.

	// set a nicer font
IGUISkin* skin = env->getSkin();
IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp");
if (font)
skin->setFont(font);

// create menu
gui::IGUIContextMenu* menu = env->addMenu();
menu->addItem(L"File", -1, true, true);
menu->addItem(L"View", -1, true, true);
menu->addItem(L"Help", -1, true, true);

gui::IGUIContextMenu* submenu;
submenu = menu->getSubMenu(0);
submenu->addItem(L"Open Model File...", 100);
submenu->addSeparator();
submenu->addItem(L"Quit", 200);

submenu = menu->getSubMenu(1);
submenu->addItem(L"toggle sky box visibility", 300);
submenu->addItem(L"toggle model debug information", 400);
submenu->addItem(L"model material", -1, true, true );

submenu = submenu->getSubMenu(2);
submenu->addItem(L"Solid", 610);
submenu->addItem(L"Transparent", 620);
submenu->addItem(L"Reflection", 630);

submenu = menu->getSubMenu(2);
submenu->addItem(L"About", 500);

We want a toolbar, onto which we can place colored buttons and important looking stuff like a senseless combobox.

	// create toolbar
gui::IGUIToolBar* bar = env->addToolBar();
bar->addButton(1102, 0, driver->getTexture("../../media/open.bmp"));
bar->addButton(1103, 0, driver->getTexture("../../media/help.bmp"));
bar->addButton(1104, 0, driver->getTexture("../../media/tools.bmp"));

// create a combobox with some senseless texts
gui::IGUIComboBox* box = env->addComboBox(core::rect<s32>(100,5,200,25), bar);
box->addItem(L"Bilinear");
box->addItem(L"Trilinear");
box->addItem(L"Anisotropic");
box->addItem(L"Isotropic");
box->addItem(L"Psychedelic");
box->addItem(L"No filtering");

To make the editor look a little bit better, we disable transparent gui elements, and add a Irrlicht Engine logo. In addition, a text, which will show the current frame per second value is created, and the window caption changed.

	// disable alpha
for (s32 i=0; i<gui::EGDC_COUNT ; ++i)
{
video::SColor col = env->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);
col.setAlpha(255);
env->getSkin()->setColor((gui::EGUI_DEFAULT_COLOR)i, col);
}

// add a tabcontrol
createToolBox();

// add the irrlicht engine logo
IGUIImage* img = env->addImage(core::rect<s32>(22,429,108,460), 0, 666);
img->setImage(driver->getTexture("../../media/irrlichtlogoaligned.jpg"));

// create fps text
IGUIStaticText* fpstext =
env->addStaticText(L"", core::rect<s32>(210,26,270,41), true);

// set window caption
Caption += " - [";
Caption += driver->getName();
Caption += "]";
Device->setWindowCaption(Caption.c_str());

That's nearly the whole application. We simply show the about message box at start up, and load the first model. To make everything look better, a skybox is created and a user controled camera, to make the application a little bit more interactive. Finally, everything is drawed in a standard drawing loop.

	// show about message box and load default model
showAboutText();
loadModel(StartUpModelFile.c_str());

// add skybox

SkyBox = smgr->addSkyBoxSceneNode(
driver->getTexture("../../media/irrlicht2_up.bmp"),
driver->getTexture("../../media/irrlicht2_dn.bmp"),
driver->getTexture("../../media/irrlicht2_lf.bmp"),
driver->getTexture("../../media/irrlicht2_rt.bmp"),
driver->getTexture("../../media/irrlicht2_ft.bmp"),
driver->getTexture("../../media/irrlicht2_bk.bmp"));

// add a camera scene node
smgr->addCameraSceneNodeMaya();

// draw everything
while(Device->run() && driver)
if (Device->isWindowActive())
{
driver->beginScene(true, true, video::SColor(150,50,50,50));
smgr->drawAll();
env->drawAll();

driver->endScene();

core::stringw str = L"FPS: ";
str += driver->getFPS();
fpstext->setText(str.c_str());
}
Device->drop();
return 0;
}

Compile and run this, and you have a fully functional 3d Mesh viewer.

 

irrlicht-1.8.3/examples/09.Meshviewer/resource.h0000644000000000000000000000070712574354552020244 0ustar rootroot//{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by 9.Meshviewer.rc // #define IDI_ICON1 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif irrlicht-1.8.3/examples/09.Meshviewer/Meshviewer_vc9.vcproj0000644000000000000000000001224012574354552022363 0ustar rootroot irrlicht-1.8.3/examples/09.Meshviewer/Meshviewer_vc8.vcproj0000644000000000000000000001214012574354552022361 0ustar rootroot irrlicht-1.8.3/examples/09.Meshviewer/Meshviewer_vc12.vcxproj0000644000000000000000000003275212574354552022637 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 09.Meshviewer {2AE24484-22FC-481B-9A40-7CD0DA5C8E06} Meshviewer Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/Meshviewer.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\09.MeshViewer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Meshviewer.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\09.MeshViewer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console .\Debug/Meshviewer.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\09.MeshViewer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Meshviewer.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\09.MeshViewer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/09.Meshviewer/Meshviewer_vc11.vcxproj0000644000000000000000000003275112574354552022635 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 09.Meshviewer {2AE24484-22FC-481B-9A40-7CD0DA5C8E06} Meshviewer Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/Meshviewer.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\09.MeshViewer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Meshviewer.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\09.MeshViewer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console .\Debug/Meshviewer.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\09.MeshViewer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Meshviewer.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\09.MeshViewer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/09.Meshviewer/Meshviewer_vc10.vcxproj0000644000000000000000000003275112574354552022634 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 09.Meshviewer {2AE24484-22FC-481B-9A40-7CD0DA5C8E06} Meshviewer Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/Meshviewer.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\09.MeshViewer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Meshviewer.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\09.MeshViewer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console .\Debug/Meshviewer.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\09.MeshViewer.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Meshviewer.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\09.MeshViewer.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/09.Meshviewer/Meshviewer.vcproj0000644000000000000000000001055012574354552021604 0ustar rootroot irrlicht-1.8.3/examples/09.Meshviewer/MeshViewer.dev0000644000000000000000000000174312574354552021023 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 09 Mesh Viewer UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=09.MeshViewer.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/09.Meshviewer/Meshviewer.cbp0000644000000000000000000000270012574354552021043 0ustar rootroot irrlicht-1.8.3/examples/09.Meshviewer/Makefile0000644000000000000000000000220412574354552017676 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 09.Meshviewer Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/09.Meshviewer/main.cpp0000644000000000000000000010016112574354552017667 0ustar rootroot/** Example 009 Mesh Viewer This tutorial show how to create a more complex application with the engine. We construct a simple mesh viewer using the user interface API and the scene management of Irrlicht. The tutorial show how to create and use Buttons, Windows, Toolbars, Menus, ComboBoxes, Tabcontrols, Editboxes, Images, MessageBoxes, SkyBoxes, and how to parse XML files with the integrated XML reader of the engine. We start like in most other tutorials: Include all necessary header files, add a comment to let the engine be linked with the right .lib file in Visual Studio, and declare some global variables. We also add two 'using namespace' statements, so we do not need to write the whole names of all classes. In this tutorial, we use a lot stuff from the gui namespace. */ #include #include "driverChoice.h" using namespace irr; using namespace gui; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif /* Some global variables used later on */ IrrlichtDevice *Device = 0; core::stringc StartUpModelFile; core::stringw MessageText; core::stringw Caption; scene::ISceneNode* Model = 0; scene::ISceneNode* SkyBox = 0; bool Octree=false; bool UseLight=false; scene::ICameraSceneNode* Camera[2] = {0, 0}; // Values used to identify individual GUI elements enum { GUI_ID_DIALOG_ROOT_WINDOW = 0x10000, GUI_ID_X_SCALE, GUI_ID_Y_SCALE, GUI_ID_Z_SCALE, GUI_ID_OPEN_MODEL, GUI_ID_SET_MODEL_ARCHIVE, GUI_ID_LOAD_AS_OCTREE, GUI_ID_SKY_BOX_VISIBLE, GUI_ID_TOGGLE_DEBUG_INFO, GUI_ID_DEBUG_OFF, GUI_ID_DEBUG_BOUNDING_BOX, GUI_ID_DEBUG_NORMALS, GUI_ID_DEBUG_SKELETON, GUI_ID_DEBUG_WIRE_OVERLAY, GUI_ID_DEBUG_HALF_TRANSPARENT, GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES, GUI_ID_DEBUG_ALL, GUI_ID_MODEL_MATERIAL_SOLID, GUI_ID_MODEL_MATERIAL_TRANSPARENT, GUI_ID_MODEL_MATERIAL_REFLECTION, GUI_ID_CAMERA_MAYA, GUI_ID_CAMERA_FIRST_PERSON, GUI_ID_POSITION_TEXT, GUI_ID_ABOUT, GUI_ID_QUIT, GUI_ID_TEXTUREFILTER, GUI_ID_SKIN_TRANSPARENCY, GUI_ID_SKIN_ANIMATION_FPS, GUI_ID_BUTTON_SET_SCALE, GUI_ID_BUTTON_SCALE_MUL10, GUI_ID_BUTTON_SCALE_DIV10, GUI_ID_BUTTON_OPEN_MODEL, GUI_ID_BUTTON_SHOW_ABOUT, GUI_ID_BUTTON_SHOW_TOOLBOX, GUI_ID_BUTTON_SELECT_ARCHIVE, GUI_ID_ANIMATION_INFO, // And some magic numbers MAX_FRAMERATE = 80, DEFAULT_FRAMERATE = 30 }; /* Toggle between various cameras */ void setActiveCamera(scene::ICameraSceneNode* newActive) { if (0 == Device) return; scene::ICameraSceneNode * active = Device->getSceneManager()->getActiveCamera(); active->setInputReceiverEnabled(false); newActive->setInputReceiverEnabled(true); Device->getSceneManager()->setActiveCamera(newActive); } /* Set the skin transparency by changing the alpha values of all skin-colors */ void setSkinTransparency(s32 alpha, irr::gui::IGUISkin * skin) { for (s32 i=0; igetColor((EGUI_DEFAULT_COLOR)i); col.setAlpha(alpha); skin->setColor((EGUI_DEFAULT_COLOR)i, col); } } /* Update the display of the model scaling */ void updateScaleInfo(scene::ISceneNode* model) { IGUIElement* toolboxWnd = Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true); if (!toolboxWnd) return; if (!model) { toolboxWnd->getElementFromId(GUI_ID_X_SCALE, true)->setText( L"-" ); toolboxWnd->getElementFromId(GUI_ID_Y_SCALE, true)->setText( L"-" ); toolboxWnd->getElementFromId(GUI_ID_Z_SCALE, true)->setText( L"-" ); } else { core::vector3df scale = model->getScale(); toolboxWnd->getElementFromId(GUI_ID_X_SCALE, true)->setText( core::stringw(scale.X).c_str() ); toolboxWnd->getElementFromId(GUI_ID_Y_SCALE, true)->setText( core::stringw(scale.Y).c_str() ); toolboxWnd->getElementFromId(GUI_ID_Z_SCALE, true)->setText( core::stringw(scale.Z).c_str() ); } } /* Function showAboutText() displays a messagebox with a caption and a message text. The texts will be stored in the MessageText and Caption variables at startup. */ void showAboutText() { // create modal message box with the text // loaded from the xml file. Device->getGUIEnvironment()->addMessageBox( Caption.c_str(), MessageText.c_str()); } /* Function loadModel() loads a model and displays it using an addAnimatedMeshSceneNode and the scene manager. Nothing difficult. It also displays a short message box, if the model could not be loaded. */ void loadModel(const c8* fn) { // modify the name if it a .pk3 file io::path filename(fn); io::path extension; core::getFileNameExtension(extension, filename); extension.make_lower(); // if a texture is loaded apply it to the current model.. if (extension == ".jpg" || extension == ".pcx" || extension == ".png" || extension == ".ppm" || extension == ".pgm" || extension == ".pbm" || extension == ".psd" || extension == ".tga" || extension == ".bmp" || extension == ".wal" || extension == ".rgb" || extension == ".rgba") { video::ITexture * texture = Device->getVideoDriver()->getTexture( filename ); if ( texture && Model ) { // always reload texture Device->getVideoDriver()->removeTexture(texture); texture = Device->getVideoDriver()->getTexture( filename ); Model->setMaterialTexture(0, texture); } return; } // if a archive is loaded add it to the FileArchive.. else if (extension == ".pk3" || extension == ".zip" || extension == ".pak" || extension == ".npk") { Device->getFileSystem()->addFileArchive(filename.c_str()); return; } // load a model into the engine if (Model) Model->remove(); Model = 0; if (extension==".irr") { core::array outNodes; Device->getSceneManager()->loadScene(filename); Device->getSceneManager()->getSceneNodesFromType(scene::ESNT_ANIMATED_MESH, outNodes); if (outNodes.size()) Model = outNodes[0]; return; } scene::IAnimatedMesh* m = Device->getSceneManager()->getMesh( filename.c_str() ); if (!m) { // model could not be loaded if (StartUpModelFile != filename) Device->getGUIEnvironment()->addMessageBox( Caption.c_str(), L"The model could not be loaded. " \ L"Maybe it is not a supported file format."); return; } // set default material properties if (Octree) Model = Device->getSceneManager()->addOctreeSceneNode(m->getMesh(0)); else { scene::IAnimatedMeshSceneNode* animModel = Device->getSceneManager()->addAnimatedMeshSceneNode(m); animModel->setAnimationSpeed(30); Model = animModel; } Model->setMaterialFlag(video::EMF_LIGHTING, UseLight); Model->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, UseLight); // Model->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false); Model->setDebugDataVisible(scene::EDS_OFF); // we need to uncheck the menu entries. would be cool to fake a menu event, but // that's not so simple. so we do it brute force gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_TOGGLE_DEBUG_INFO, true); if (menu) for(int item = 1; item < 6; ++item) menu->setItemChecked(item, false); updateScaleInfo(Model); } /* Function createToolBox() creates a toolbox window. In this simple mesh viewer, this toolbox only contains a tab control with three edit boxes for changing the scale of the displayed model. */ void createToolBox() { // remove tool box if already there IGUIEnvironment* env = Device->getGUIEnvironment(); IGUIElement* root = env->getRootGUIElement(); IGUIElement* e = root->getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true); if (e) e->remove(); // create the toolbox window IGUIWindow* wnd = env->addWindow(core::rect(600,45,800,480), false, L"Toolset", 0, GUI_ID_DIALOG_ROOT_WINDOW); // create tab control and tabs IGUITabControl* tab = env->addTabControl( core::rect(2,20,800-602,480-7), wnd, true, true); IGUITab* t1 = tab->addTab(L"Config"); // add some edit boxes and a button to tab one env->addStaticText(L"Scale:", core::rect(10,20,60,45), false, false, t1); env->addStaticText(L"X:", core::rect(22,48,40,66), false, false, t1); env->addEditBox(L"1.0", core::rect(40,46,130,66), true, t1, GUI_ID_X_SCALE); env->addStaticText(L"Y:", core::rect(22,82,40,96), false, false, t1); env->addEditBox(L"1.0", core::rect(40,76,130,96), true, t1, GUI_ID_Y_SCALE); env->addStaticText(L"Z:", core::rect(22,108,40,126), false, false, t1); env->addEditBox(L"1.0", core::rect(40,106,130,126), true, t1, GUI_ID_Z_SCALE); env->addButton(core::rect(10,134,85,165), t1, GUI_ID_BUTTON_SET_SCALE, L"Set"); // quick scale buttons env->addButton(core::rect(65,20,95,40), t1, GUI_ID_BUTTON_SCALE_MUL10, L"* 10"); env->addButton(core::rect(100,20,130,40), t1, GUI_ID_BUTTON_SCALE_DIV10, L"* 0.1"); updateScaleInfo(Model); // add transparency control env->addStaticText(L"GUI Transparency Control:", core::rect(10,200,150,225), true, false, t1); IGUIScrollBar* scrollbar = env->addScrollBar(true, core::rect(10,225,150,240), t1, GUI_ID_SKIN_TRANSPARENCY); scrollbar->setMax(255); scrollbar->setPos(255); // add framerate control env->addStaticText(L":", core::rect(10,240,150,265), true, false, t1); env->addStaticText(L"Framerate:", core::rect(12,240,75,265), false, false, t1); // current frame info env->addStaticText(L"", core::rect(75,240,200,265), false, false, t1, GUI_ID_ANIMATION_INFO); scrollbar = env->addScrollBar(true, core::rect(10,265,150,280), t1, GUI_ID_SKIN_ANIMATION_FPS); scrollbar->setMax(MAX_FRAMERATE); scrollbar->setMin(-MAX_FRAMERATE); scrollbar->setPos(DEFAULT_FRAMERATE); scrollbar->setSmallStep(1); } /* Function updateToolBox() is called each frame to update dynamic information in the toolbox. */ void updateToolBox() { IGUIEnvironment* env = Device->getGUIEnvironment(); IGUIElement* root = env->getRootGUIElement(); IGUIElement* dlg = root->getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true); if (!dlg ) return; // update the info we have about the animation of the model IGUIStaticText * aniInfo = (IGUIStaticText *)(dlg->getElementFromId(GUI_ID_ANIMATION_INFO, true)); if (aniInfo) { if ( Model && scene::ESNT_ANIMATED_MESH == Model->getType() ) { scene::IAnimatedMeshSceneNode* animatedModel = (scene::IAnimatedMeshSceneNode*)Model; core::stringw str( (s32)core::round_(animatedModel->getAnimationSpeed()) ); str += L" Frame: "; str += core::stringw((s32)animatedModel->getFrameNr()); aniInfo->setText(str.c_str()); } else aniInfo->setText(L""); } } void onKillFocus() { // Avoid that the FPS-camera continues moving when the user presses alt-tab while // moving the camera. const core::list& animators = Camera[1]->getAnimators(); core::list::ConstIterator iter = animators.begin(); while ( iter != animators.end() ) { if ( (*iter)->getType() == scene::ESNAT_CAMERA_FPS ) { // we send a key-down event for all keys used by this animator scene::ISceneNodeAnimatorCameraFPS * fpsAnimator = static_cast(*iter); const core::array& keyMap = fpsAnimator->getKeyMap(); for ( irr::u32 i=0; i< keyMap.size(); ++i ) { irr::SEvent event; event.EventType = EET_KEY_INPUT_EVENT; event.KeyInput.Key = keyMap[i].KeyCode; event.KeyInput.PressedDown = false; fpsAnimator->OnEvent(event); } } ++iter; } } /* Function hasModalDialog() checks if we currently have a modal dialog open. */ bool hasModalDialog() { if ( !Device ) return false; IGUIEnvironment* env = Device->getGUIEnvironment(); IGUIElement * focused = env->getFocus(); while ( focused ) { if ( focused->isVisible() && focused->hasType(EGUIET_MODAL_SCREEN) ) return true; focused = focused->getParent(); } return false; } /* To get all the events sent by the GUI Elements, we need to create an event receiver. This one is really simple. If an event occurs, it checks the id of the caller and the event type, and starts an action based on these values. For example, if a menu item with id GUI_ID_OPEN_MODEL was selected, it opens a file-open-dialog. */ class MyEventReceiver : public IEventReceiver { public: virtual bool OnEvent(const SEvent& event) { // Escape swaps Camera Input if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown == false) { if ( OnKeyUp(event.KeyInput.Key) ) return true; } if (event.EventType == EET_GUI_EVENT) { s32 id = event.GUIEvent.Caller->getID(); IGUIEnvironment* env = Device->getGUIEnvironment(); switch(event.GUIEvent.EventType) { case EGET_MENU_ITEM_SELECTED: // a menu item was clicked OnMenuItemSelected( (IGUIContextMenu*)event.GUIEvent.Caller ); break; case EGET_FILE_SELECTED: { // load the model file, selected in the file open dialog IGUIFileOpenDialog* dialog = (IGUIFileOpenDialog*)event.GUIEvent.Caller; loadModel(core::stringc(dialog->getFileName()).c_str()); } break; case EGET_SCROLL_BAR_CHANGED: // control skin transparency if (id == GUI_ID_SKIN_TRANSPARENCY) { const s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos(); setSkinTransparency(pos, env->getSkin()); } // control animation speed else if (id == GUI_ID_SKIN_ANIMATION_FPS) { const s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos(); if (scene::ESNT_ANIMATED_MESH == Model->getType()) ((scene::IAnimatedMeshSceneNode*)Model)->setAnimationSpeed((f32)pos); } break; case EGET_COMBO_BOX_CHANGED: // control anti-aliasing/filtering if (id == GUI_ID_TEXTUREFILTER) { OnTextureFilterSelected( (IGUIComboBox*)event.GUIEvent.Caller ); } break; case EGET_BUTTON_CLICKED: switch(id) { case GUI_ID_BUTTON_SET_SCALE: { // set scale gui::IGUIElement* root = env->getRootGUIElement(); core::vector3df scale; core::stringc s; s = root->getElementFromId(GUI_ID_X_SCALE, true)->getText(); scale.X = (f32)atof(s.c_str()); s = root->getElementFromId(GUI_ID_Y_SCALE, true)->getText(); scale.Y = (f32)atof(s.c_str()); s = root->getElementFromId(GUI_ID_Z_SCALE, true)->getText(); scale.Z = (f32)atof(s.c_str()); if (Model) Model->setScale(scale); updateScaleInfo(Model); } break; case GUI_ID_BUTTON_SCALE_MUL10: if (Model) Model->setScale(Model->getScale()*10.f); updateScaleInfo(Model); break; case GUI_ID_BUTTON_SCALE_DIV10: if (Model) Model->setScale(Model->getScale()*0.1f); updateScaleInfo(Model); break; case GUI_ID_BUTTON_OPEN_MODEL: env->addFileOpenDialog(L"Please select a model file to open"); break; case GUI_ID_BUTTON_SHOW_ABOUT: showAboutText(); break; case GUI_ID_BUTTON_SHOW_TOOLBOX: createToolBox(); break; case GUI_ID_BUTTON_SELECT_ARCHIVE: env->addFileOpenDialog(L"Please select your game archive/directory"); break; } break; default: break; } } return false; } /* Handle key-up events */ bool OnKeyUp(irr::EKEY_CODE keyCode) { // Don't handle keys if we have a modal dialog open as it would lead // to unexpected application behaviour for the user. if ( hasModalDialog() ) return false; if (keyCode == irr::KEY_ESCAPE) { if (Device) { scene::ICameraSceneNode * camera = Device->getSceneManager()->getActiveCamera(); if (camera) { camera->setInputReceiverEnabled( !camera->isInputReceiverEnabled() ); } return true; } } else if (keyCode == irr::KEY_F1) { if (Device) { IGUIElement* elem = Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_POSITION_TEXT); if (elem) elem->setVisible(!elem->isVisible()); } } else if (keyCode == irr::KEY_KEY_M) { if (Device) Device->minimizeWindow(); } else if (keyCode == irr::KEY_KEY_L) { UseLight=!UseLight; if (Model) { Model->setMaterialFlag(video::EMF_LIGHTING, UseLight); Model->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, UseLight); } } return false; } /* Handle "menu item clicked" events. */ void OnMenuItemSelected( IGUIContextMenu* menu ) { s32 id = menu->getItemCommandId(menu->getSelectedItem()); IGUIEnvironment* env = Device->getGUIEnvironment(); switch(id) { case GUI_ID_OPEN_MODEL: // FilOnButtonSetScalinge -> Open Model env->addFileOpenDialog(L"Please select a model file to open"); break; case GUI_ID_SET_MODEL_ARCHIVE: // File -> Set Model Archive env->addFileOpenDialog(L"Please select your game archive/directory"); break; case GUI_ID_LOAD_AS_OCTREE: // File -> LoadAsOctree Octree = !Octree; menu->setItemChecked(menu->getSelectedItem(), Octree); break; case GUI_ID_QUIT: // File -> Quit Device->closeDevice(); break; case GUI_ID_SKY_BOX_VISIBLE: // View -> Skybox menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); SkyBox->setVisible(!SkyBox->isVisible()); break; case GUI_ID_DEBUG_OFF: // View -> Debug Information menu->setItemChecked(menu->getSelectedItem()+1, false); menu->setItemChecked(menu->getSelectedItem()+2, false); menu->setItemChecked(menu->getSelectedItem()+3, false); menu->setItemChecked(menu->getSelectedItem()+4, false); menu->setItemChecked(menu->getSelectedItem()+5, false); menu->setItemChecked(menu->getSelectedItem()+6, false); if (Model) Model->setDebugDataVisible(scene::EDS_OFF); break; case GUI_ID_DEBUG_BOUNDING_BOX: // View -> Debug Information menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); if (Model) Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX)); break; case GUI_ID_DEBUG_NORMALS: // View -> Debug Information menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); if (Model) Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_NORMALS)); break; case GUI_ID_DEBUG_SKELETON: // View -> Debug Information menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); if (Model) Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_SKELETON)); break; case GUI_ID_DEBUG_WIRE_OVERLAY: // View -> Debug Information menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); if (Model) Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_MESH_WIRE_OVERLAY)); break; case GUI_ID_DEBUG_HALF_TRANSPARENT: // View -> Debug Information menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); if (Model) Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_HALF_TRANSPARENCY)); break; case GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES: // View -> Debug Information menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); if (Model) Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX_BUFFERS)); break; case GUI_ID_DEBUG_ALL: // View -> Debug Information menu->setItemChecked(menu->getSelectedItem()-1, true); menu->setItemChecked(menu->getSelectedItem()-2, true); menu->setItemChecked(menu->getSelectedItem()-3, true); menu->setItemChecked(menu->getSelectedItem()-4, true); menu->setItemChecked(menu->getSelectedItem()-5, true); menu->setItemChecked(menu->getSelectedItem()-6, true); if (Model) Model->setDebugDataVisible(scene::EDS_FULL); break; case GUI_ID_ABOUT: // Help->About showAboutText(); break; case GUI_ID_MODEL_MATERIAL_SOLID: // View -> Material -> Solid if (Model) Model->setMaterialType(video::EMT_SOLID); break; case GUI_ID_MODEL_MATERIAL_TRANSPARENT: // View -> Material -> Transparent if (Model) Model->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); break; case GUI_ID_MODEL_MATERIAL_REFLECTION: // View -> Material -> Reflection if (Model) Model->setMaterialType(video::EMT_SPHERE_MAP); break; case GUI_ID_CAMERA_MAYA: setActiveCamera(Camera[0]); break; case GUI_ID_CAMERA_FIRST_PERSON: setActiveCamera(Camera[1]); break; } } /* Handle the event that one of the texture-filters was selected in the corresponding combobox. */ void OnTextureFilterSelected( IGUIComboBox* combo ) { s32 pos = combo->getSelected(); switch (pos) { case 0: if (Model) { Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, false); Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, false); } break; case 1: if (Model) { Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, true); Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, false); } break; case 2: if (Model) { Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, true); } break; case 3: if (Model) { Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, true); } break; case 4: if (Model) { Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, false); } break; } } }; /* Most of the hard work is done. We only need to create the Irrlicht Engine device and all the buttons, menus and toolbars. We start up the engine as usual, using createDevice(). To make our application catch events, we set our eventreceiver as parameter. As you can see, there is also a call to IrrlichtDevice::setResizeable(). This makes the render window resizeable, which is quite useful for a mesh viewer. */ int main(int argc, char* argv[]) { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device and exit if creation failed MyEventReceiver receiver; Device = createDevice(driverType, core::dimension2d(800, 600), 16, false, false, false, &receiver); if (Device == 0) return 1; // could not create selected driver. Device->setResizable(true); Device->setWindowCaption(L"Irrlicht Engine - Loading..."); video::IVideoDriver* driver = Device->getVideoDriver(); IGUIEnvironment* env = Device->getGUIEnvironment(); scene::ISceneManager* smgr = Device->getSceneManager(); smgr->getParameters()->setAttribute(scene::COLLADA_CREATE_SCENE_INSTANCES, true); driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); smgr->addLightSceneNode(0, core::vector3df(200,200,200), video::SColorf(1.0f,1.0f,1.0f),2000); smgr->setAmbientLight(video::SColorf(0.3f,0.3f,0.3f)); // add our media directory as "search path" Device->getFileSystem()->addFileArchive("../../media/"); /* The next step is to read the configuration file. It is stored in the xml format and looks a little bit like this: @verbatim Hello! @endverbatim We need the data stored in there to be written into the global variables StartUpModelFile, MessageText and Caption. This is now done using the Irrlicht Engine integrated XML parser: */ // read configuration from xml file io::IXMLReader* xml = Device->getFileSystem()->createXMLReader( L"config.xml"); while(xml && xml->read()) { switch(xml->getNodeType()) { case io::EXN_TEXT: // in this xml file, the only text which occurs is the // messageText MessageText = xml->getNodeData(); break; case io::EXN_ELEMENT: { if (core::stringw("startUpModel") == xml->getNodeName()) StartUpModelFile = xml->getAttributeValue(L"file"); else if (core::stringw("messageText") == xml->getNodeName()) Caption = xml->getAttributeValue(L"caption"); } break; default: break; } } if (xml) xml->drop(); // don't forget to delete the xml reader if (argc > 1) StartUpModelFile = argv[1]; /* That wasn't difficult. Now we'll set a nicer font and create the Menu. It is possible to create submenus for every menu item. The call menu->addItem(L"File", -1, true, true); for example adds a new menu Item with the name "File" and the id -1. The following parameter says that the menu item should be enabled, and the last one says, that there should be a submenu. The submenu can now be accessed with menu->getSubMenu(0), because the "File" entry is the menu item with index 0. */ // set a nicer font IGUISkin* skin = env->getSkin(); IGUIFont* font = env->getFont("fonthaettenschweiler.bmp"); if (font) skin->setFont(font); // create menu gui::IGUIContextMenu* menu = env->addMenu(); menu->addItem(L"File", -1, true, true); menu->addItem(L"View", -1, true, true); menu->addItem(L"Camera", -1, true, true); menu->addItem(L"Help", -1, true, true); gui::IGUIContextMenu* submenu; submenu = menu->getSubMenu(0); submenu->addItem(L"Open Model File & Texture...", GUI_ID_OPEN_MODEL); submenu->addItem(L"Set Model Archive...", GUI_ID_SET_MODEL_ARCHIVE); submenu->addItem(L"Load as Octree", GUI_ID_LOAD_AS_OCTREE); submenu->addSeparator(); submenu->addItem(L"Quit", GUI_ID_QUIT); submenu = menu->getSubMenu(1); submenu->addItem(L"sky box visible", GUI_ID_SKY_BOX_VISIBLE, true, false, true); submenu->addItem(L"toggle model debug information", GUI_ID_TOGGLE_DEBUG_INFO, true, true); submenu->addItem(L"model material", -1, true, true ); submenu = submenu->getSubMenu(1); submenu->addItem(L"Off", GUI_ID_DEBUG_OFF); submenu->addItem(L"Bounding Box", GUI_ID_DEBUG_BOUNDING_BOX); submenu->addItem(L"Normals", GUI_ID_DEBUG_NORMALS); submenu->addItem(L"Skeleton", GUI_ID_DEBUG_SKELETON); submenu->addItem(L"Wire overlay", GUI_ID_DEBUG_WIRE_OVERLAY); submenu->addItem(L"Half-Transparent", GUI_ID_DEBUG_HALF_TRANSPARENT); submenu->addItem(L"Buffers bounding boxes", GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES); submenu->addItem(L"All", GUI_ID_DEBUG_ALL); submenu = menu->getSubMenu(1)->getSubMenu(2); submenu->addItem(L"Solid", GUI_ID_MODEL_MATERIAL_SOLID); submenu->addItem(L"Transparent", GUI_ID_MODEL_MATERIAL_TRANSPARENT); submenu->addItem(L"Reflection", GUI_ID_MODEL_MATERIAL_REFLECTION); submenu = menu->getSubMenu(2); submenu->addItem(L"Maya Style", GUI_ID_CAMERA_MAYA); submenu->addItem(L"First Person", GUI_ID_CAMERA_FIRST_PERSON); submenu = menu->getSubMenu(3); submenu->addItem(L"About", GUI_ID_ABOUT); /* Below the menu we want a toolbar, onto which we can place colored buttons and important looking stuff like a senseless combobox. */ // create toolbar gui::IGUIToolBar* bar = env->addToolBar(); video::ITexture* image = driver->getTexture("open.png"); bar->addButton(GUI_ID_BUTTON_OPEN_MODEL, 0, L"Open a model",image, 0, false, true); image = driver->getTexture("tools.png"); bar->addButton(GUI_ID_BUTTON_SHOW_TOOLBOX, 0, L"Open Toolset",image, 0, false, true); image = driver->getTexture("zip.png"); bar->addButton(GUI_ID_BUTTON_SELECT_ARCHIVE, 0, L"Set Model Archive",image, 0, false, true); image = driver->getTexture("help.png"); bar->addButton(GUI_ID_BUTTON_SHOW_ABOUT, 0, L"Open Help", image, 0, false, true); // create a combobox for texture filters gui::IGUIComboBox* box = env->addComboBox(core::rect(250,4,350,23), bar, GUI_ID_TEXTUREFILTER); box->addItem(L"No filtering"); box->addItem(L"Bilinear"); box->addItem(L"Trilinear"); box->addItem(L"Anisotropic"); box->addItem(L"Isotropic"); /* To make the editor look a little bit better, we disable transparent gui elements, and add an Irrlicht Engine logo. In addition, a text showing the current frames per second value is created and the window caption is changed. */ // disable alpha for (s32 i=0; igetSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i); col.setAlpha(255); env->getSkin()->setColor((gui::EGUI_DEFAULT_COLOR)i, col); } // add a tabcontrol createToolBox(); // create fps text IGUIStaticText* fpstext = env->addStaticText(L"", core::rect(400,4,570,23), true, false, bar); IGUIStaticText* postext = env->addStaticText(L"", core::rect(10,50,470,80),false, false, 0, GUI_ID_POSITION_TEXT); postext->setVisible(false); // set window caption Caption += " - ["; Caption += driver->getName(); Caption += "]"; Device->setWindowCaption(Caption.c_str()); /* That's nearly the whole application. We simply show the about message box at start up, and load the first model. To make everything look better, a skybox is created and a user controlled camera, to make the application a little bit more interactive. Finally, everything is drawn in a standard drawing loop. */ // show about message box and load default model if (argc==1) showAboutText(); loadModel(StartUpModelFile.c_str()); // add skybox SkyBox = smgr->addSkyBoxSceneNode( driver->getTexture("irrlicht2_up.jpg"), driver->getTexture("irrlicht2_dn.jpg"), driver->getTexture("irrlicht2_lf.jpg"), driver->getTexture("irrlicht2_rt.jpg"), driver->getTexture("irrlicht2_ft.jpg"), driver->getTexture("irrlicht2_bk.jpg")); // add a camera scene node Camera[0] = smgr->addCameraSceneNodeMaya(); Camera[0]->setFarValue(20000.f); // Maya cameras reposition themselves relative to their target, so target the location // where the mesh scene node is placed. Camera[0]->setTarget(core::vector3df(0,30,0)); Camera[1] = smgr->addCameraSceneNodeFPS(); Camera[1]->setFarValue(20000.f); Camera[1]->setPosition(core::vector3df(0,0,-70)); Camera[1]->setTarget(core::vector3df(0,30,0)); setActiveCamera(Camera[0]); // load the irrlicht engine logo IGUIImage *img = env->addImage(driver->getTexture("irrlichtlogo2.png"), core::position2d(10, driver->getScreenSize().Height - 128)); // lock the logo's edges to the bottom left corner of the screen img->setAlignment(EGUIA_UPPERLEFT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); // remember state so we notice when the window does lose the focus bool hasFocus = Device->isWindowFocused(); // draw everything while(Device->run() && driver) { // Catch focus changes (workaround until Irrlicht has events for this) bool focused = Device->isWindowFocused(); if ( hasFocus && !focused ) onKillFocus(); hasFocus = focused; if (Device->isWindowActive()) { driver->beginScene(true, true, video::SColor(150,50,50,50)); smgr->drawAll(); env->drawAll(); driver->endScene(); // update information about current frame-rate core::stringw str(L"FPS: "); str.append(core::stringw(driver->getFPS())); str += L" Tris: "; str.append(core::stringw(driver->getPrimitiveCountDrawn())); fpstext->setText(str.c_str()); // update information about the active camera scene::ICameraSceneNode* cam = Device->getSceneManager()->getActiveCamera(); str = L"Pos: "; str.append(core::stringw(cam->getPosition().X)); str += L" "; str.append(core::stringw(cam->getPosition().Y)); str += L" "; str.append(core::stringw(cam->getPosition().Z)); str += L" Tgt: "; str.append(core::stringw(cam->getTarget().X)); str += L" "; str.append(core::stringw(cam->getTarget().Y)); str += L" "; str.append(core::stringw(cam->getTarget().Z)); postext->setText(str.c_str()); // update the tool dialog updateToolBox(); } else Device->yield(); } Device->drop(); return 0; } /* **/ irrlicht-1.8.3/examples/09.Meshviewer/icon.ico0000644000000000000000000000427612574354552017675 0ustar rootroot ¨( @€€€€€€€€€ÀÀÀÀÜÀðʦ """)))UUUMMMBBB999€|ÿPPÿ“ÖÿìÌÆÖïÖçç©­3f™Ì3333f3™3Ì3ÿff3fff™fÌfÿ™™3™f™™™Ì™ÿÌÌ3ÌfÌ™ÌÌÌÿÿfÿ™ÿÌ3333f3™3Ì3ÿ3333333f33™33Ì33ÿ3f3f33ff3f™3fÌ3fÿ3™3™33™f3™™3™Ì3™ÿ3Ì3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿff3fff™fÌfÿf3f33f3ff3™f3Ìf3ÿffff3fffff™ffÌf™f™3f™ff™™f™Ìf™ÿfÌfÌ3fÌ™fÌÌfÌÿfÿfÿ3fÿ™fÿÌÌÿÿÌ™™™3™™™™Ì™™33™f™3Ì™ÿ™f™f3™3f™f™™fÌ™3ÿ™™3™™f™™™™™Ì™™ÿ™Ì™Ì3fÌf™Ì™™ÌÌ™Ìÿ™ÿ™ÿ3™Ìf™ÿ™™ÿÌ™ÿÿÌ™3ÌfÌ™ÌÌ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌfÌf3™ffÌf™ÌfÌ™fÿ̙̙3Ì™fÌ™™Ì™ÌÌ™ÿÌÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÿÌÿ3™ÿfÌÿ™ÌÿÌÌÿÿÌ3ÿfÿ™Ì3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿfÿf3Ìffÿf™ÿfÌÌfÿÿ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÿ3Ìÿfÿÿ™ÿÿÌffÿfÿffÿÿÿffÿfÿÿÿf!¥___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøðûÿ¤  €€€ÿÿÿÿÿÿÿÿÿÿÿÿ mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿmmìêêêê’ììñÿðìmì¼ôóm÷óÿììòÿôììñÿmm CìC ïð mðÿôôCômmïñòó÷÷ð÷ì êðÿôôômmôÿÿ’ ¼ôô¼ðð ì÷ôôômmôÿÿ’ mðÿÿÿÿò ôôômmôÿÿ’¼ÿôï¼ñ êïðCôôômmôÿÿïmììì¼ êðÿïïCìïêmCôÿÿêCñðmðÿCmñ¼òÿÿÿñ¼òÿô’÷ðóô¼ðóÿñ¼ò¼ïïïêmÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿmCCCCCCCCCCCCC®®®®®®®®®®®®®®®®®f Cµ÷®µµ®®®µµ®µ®®®®µ"KLK Cñð®ðð®®µô÷íô÷®®ðóDRzytQ Còðêðñê®óñ®íô’®µô÷CDtz  ™tKD Còðêðñ®¼ó쮵ô÷íô¼®Dy     ztKD Còðêðÿÿÿô﮵ôÿÿÿñìJy     šzuLDCòðêðòìíôìíôïìíñðCDy     ztKD Còðêðñ®®µôííô÷®®ðóCDtzz zyKD Còð®ðÿÿÿÿñ®íôÿÿÿÿ÷CDLuztKD Cµí®íµííí®®®µííí®®DKKK C®®®®®®®®®®®®®®®®®f#" CCCCCCCCCCCCCCCCC irrlicht-1.8.3/examples/09.Meshviewer/9.Meshviewer.rc0000644000000000000000000000402112574354552021050 0ustar rootroot// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // German (Austria) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEA) #ifdef _WIN32 LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN #pragma code_page(1252) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDI_ICON1 ICON "icon.ico" #endif // German (Austria) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED irrlicht-1.8.3/examples/08.SpecialFX/0000755000000000000000000000000012574354552015737 5ustar rootrootirrlicht-1.8.3/examples/08.SpecialFX/tutorial.html0000644000000000000000000004117312574354552020476 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 8. Special Effects

This tutorials describes how to do special effects. It shows how to use stencil buffer shadows, the particle system, billboards, dynamic light and the water surface scene node.

The program which is described here will look like this:



Lets start!

We start like in some tutorials before. Please note that this time, the 'shadows' flag in createDevice() is set to true, for we want to have a dynamic shadow casted from an animated character. If your this example runs to slow, set it to false. The Irrlicht Engine checks if your hardware doesn't support the stencil buffer, and disables shadows by itself, but just in case the demo runs slow on your hardware.

#include <irrlicht.h>
#include <iostream>
using namespace irr; #pragma comment(lib, "Irrlicht.lib") int main() { // ask user for driver
video::E_DRIVER_TYPE driverType;
printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");

char i;
std::cin >> i;

switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 1;
} // create device and exit if creation failed
IrrlichtDevice *device = createDevice(driverType, core::dimension2d<s32>(640, 480), 16, false, true); if (device == 0) return 1; video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager();

For our environment, we load a .3ds file. It is a small room I modelled with Anim8or and exported it into the 3ds format because the Irrlicht Engine did not support the .an8 format when I wrote this tutorial. I am a very bad 3d graphic artist, and so the texture mapping is not very nice in this model. Luckily I am a better programmer than artist, and so the Irrlicht Engine is able to create a cool texture mapping for me: Just use the mesh manipulator and create a planar texture mapping for the mesh. If you want to see the mapping I made with Anim8or, uncomment this line. I also did not figure out how to
set the material right in Anim8or, it has a specular light color which I don't really
like. I'll switch it off too with this code.

	scene::IAnimatedMesh* mesh = smgr->getMesh(
		"../../media/room.3ds");

	smgr->getMeshManipulator()->makePlanarTextureMapping(
		mesh->getMesh(0), 0.008f);

	scene::ISceneNode* node = 0;

	node = smgr->addAnimatedMeshSceneNode(mesh);
	node->setMaterialTexture(0,	driver->getTexture("../../media/wall.jpg"));
	node->getMaterial(0).SpecularColor.set(0,0,0,0);

Now, for the first special effect: Animated water. It works like this: The WaterSurfaceSceneNode takes a mesh as input and makes it wave like a water surface. And if we let this scene node use a nice material like the MT_REFLECTION_2_LAYER, it looks really cool. We are doing this with the next few lines of code. As input mesh, we create a hill plane mesh, without hills. But any other mesh could be used for this, you could even use the room.3ds (which would look really strange) if you wanted to.

	mesh = smgr->addHillPlaneMesh("myHill",
		core::dimension2d<f32>(20,20),
		core::dimension2d<s32>(40,40), 0, 0,
		core::dimension2d<f32>(0,0),
		core::dimension2d<f32>(10,10));

	node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0), 3.0f, 300.0f, 30.0f);
	node->setPosition(core::vector3df(0,7,0));

	node->setMaterialTexture(0,	driver->getTexture("../../media/stones.jpg"));
	node->setMaterialTexture(1,	driver->getTexture("../../media/water.jpg"));

	node->setMaterialType(video::EMT_REFLECTION_2_LAYER);

The second special effect is very basic, I bet you saw it already in some Irrlicht Engine demos: A transparent billboard combined with a dynamic light. We simply create a light scene node, let it fly around, an to make it look more cool, we attach a billboard scene node to it.

	// create light

	node = smgr->addLightSceneNode(0, core::vector3df(0,0,0), 
		video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 600.0f);
	scene::ISceneNodeAnimator* anim = 0;
	anim = smgr->createFlyCircleAnimator (core::vector3df(0,150,0),250.0f);
	node->addAnimator(anim);
	anim->drop();

	// attach billboard to light

	node = smgr->addBillboardSceneNode(node, core::dimension2d<f32>(50, 50));
	node->setMaterialFlag(video::EMF_LIGHTING, false);
	node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
	node->setMaterialTexture(0,	driver->getTexture("../../media/particlewhite.bmp"));

The next special effect is a lot more interesting: A particle system. The particle system in the Irrlicht Engine is quit modular and extensible and yet easy to use. There is a particle system scene node into which you can put particle emitters, which make particles come out of nothing. These emitters are quite flexible and usually have lots of parameters like direction, amount and color of the particles they should create.
There are different emitters, for example a point emitter which lets particles pop out at a fixed point. If the particle emitters available in the engine are not enough for you, you can easily create your own ones, you'll simply have to create a class derived from the IParticleEmitter interface and attach it to the particle system using setEmitter().
In this example we create a box particle emitter, which creates particles randomly inside a box. The parameters define the box, direction of the particles, minimal and maximal new particles per second, color and minimal and maximal livetime of the particles.

Because only with emitters particle system would be a little bit boring, there are particle affectors, which modify particles during they fly around. They can be added to the particle system, simulating additional effects like gravity or wind. The particle affector we use in this example is an affector, which modifies the color of the particles: It lets them fade out. Like the particle emitters, additional particle affectors can also be implemented by you, simply derive a class from IParticleAffector and add it with addAffector(). After we set a nice material to the particle system, we have a cool looking camp fire. By adjusting material, texture, particle emitter and affector parameters, it is also easily possible to create smoke, rain, explosions, snow, and so on.

	scene::IParticleSystemSceneNode* ps = 0;
	ps = smgr->addParticleSystemSceneNode(false);
	ps->setPosition(core::vector3df(-70,60,40));
	ps->setScale(core::vector3df(2,2,2));

	ps->setParticleSize(core::dimension2d<f32>(20.0f, 10.0f));

	scene::IParticleEmitter* em = ps->createBoxEmitter(
		core::aabbox3d<f32>(-7,0,-7,7,1,7), 
		core::vector3df(0.0f,0.03f,0.0f),
		80,100, 
		video::SColor(0,255,255,255), video::SColor(0,255,255,255),
		800,2000);

	ps->setEmitter(em);
	em->drop();

	scene::IParticleAffector* paf = 
		ps->createFadeOutParticleAffector();

	ps->addAffector(paf);
	paf->drop();

	ps->setMaterialFlag(video::EMF_LIGHTING, false);
	ps->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp"));
	ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);

As our last special effect, we want a dynamic shadow be casted from an animated character. For this we load a DirectX .x model and place it into our world. For creating the shadow, we simply need to call addShadowVolumeSceneNode(). The color of shadows is only adjustable globally for all shadows, by calling ISceneManager::setShadowColor(). Voila, here is our dynamic shadow.
Because the character is a little bit too small for this scene, we make it bigger using setScale(). And because the character is lighted by a dynamic light, we need to normalize the normals to make the lighting on it correct. This is always necessary if the scale of a dynamic lighted model is not (1,1,1). Otherwise it would get too dark or too bright because the normals will be scaled too.

	mesh = smgr->getMesh("../../media/dwarf.x");
	scene::IAnimatedMeshSceneNode* anode = 0;

	anode = smgr->addAnimatedMeshSceneNode(mesh);
	anode->setPosition(core::vector3df(-50,20,-60));
	anode->setAnimationSpeed(15);

	// add shadow
	anode->addShadowVolumeSceneNode();	
	smgr->setShadowColor(video::SColor(220,0,0,0));

	// make the model a little bit bigger and normalize its normals 
// because of this for correct lighting

anode->setScale(core::vector3df(2,2,2));
anode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);

Finally we simply have to draw everything, that's all.

	scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();
	camera->setPosition(core::vector3df(-50,50,-150));


	int lastFPS = -1;

	while(device->run())
	{
		driver->beginScene(true, true, 0);

		smgr->drawAll();

		driver->endScene();

		int fps = driver->getFPS();

		if (lastFPS != fps)
		{
		  core::stringw str = L"Irrlicht Engine - SpecialFX example [";
str += driver->getName();
str += "] FPS:";
str += fps;

device->setWindowCaption(str.c_str());
lastFPS = fps;
} } device->drop(); return 0; }

 

 

 

 

irrlicht-1.8.3/examples/08.SpecialFX/SpecialFX_vc9.vcproj0000644000000000000000000001222612574354552021566 0ustar rootroot irrlicht-1.8.3/examples/08.SpecialFX/SpecialFX_vc8.vcproj0000644000000000000000000001212612574354552021564 0ustar rootroot irrlicht-1.8.3/examples/08.SpecialFX/SpecialFX_vc12.vcxproj0000644000000000000000000003274012574354552022033 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 08.SpecialFX {C869BF55-B9D6-4980-BC92-60FA0CF8411A} SpecialFX Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/SpecialFX.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\08.SpecialFx.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/SpecialFX.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\08.SpecialFx.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console .\Debug/SpecialFX.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\08.SpecialFx.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/SpecialFX.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\08.SpecialFx.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/08.SpecialFX/SpecialFX_vc11.vcxproj0000644000000000000000000003273712574354552022040 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 08.SpecialFX {C869BF55-B9D6-4980-BC92-60FA0CF8411A} SpecialFX Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/SpecialFX.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\08.SpecialFx.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/SpecialFX.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\08.SpecialFx.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console .\Debug/SpecialFX.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\08.SpecialFx.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/SpecialFX.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\08.SpecialFx.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/08.SpecialFX/SpecialFX_vc10.vcxproj0000644000000000000000000003273712574354552022037 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 08.SpecialFX {C869BF55-B9D6-4980-BC92-60FA0CF8411A} SpecialFX Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/SpecialFX.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\08.SpecialFx.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/SpecialFX.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\08.SpecialFx.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console .\Debug/SpecialFX.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\08.SpecialFx.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/SpecialFX.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\08.SpecialFx.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/08.SpecialFX/SpecialFX.vcproj0000644000000000000000000001053712574354552021010 0ustar rootroot irrlicht-1.8.3/examples/08.SpecialFX/SpecialFX.dev0000644000000000000000000000174612574354552020265 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 08 Special Effects UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=08.SpecialFX.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/08.SpecialFX/SpecialFX.cbp0000644000000000000000000000260312574354552020244 0ustar rootroot irrlicht-1.8.3/examples/08.SpecialFX/Makefile0000644000000000000000000000220312574354552017374 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 08.SpecialFX Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/08.SpecialFX/main.cpp0000644000000000000000000002574012574354552017377 0ustar rootroot/** Example 008 SpecialFX This tutorials describes how to do special effects. It shows how to use stencil buffer shadows, the particle system, billboards, dynamic light, and the water surface scene node. We start like in some tutorials before. Please note that this time, the 'shadows' flag in createDevice() is set to true, for we want to have a dynamic shadow casted from an animated character. If this example runs too slow, set it to false. The Irrlicht Engine checks if your hardware doesn't support the stencil buffer, and disables shadows by itself, but just in case the demo runs slow on your hardware. */ #include #include #include "driverChoice.h" using namespace irr; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif int main() { // ask if user would like shadows char i; printf("Please press 'y' if you want to use realtime shadows.\n"); std::cin >> i; const bool shadows = (i == 'y'); // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; /* Create device and exit if creation failed. We make the stencil flag optional to avoid slow screen modes for runs without shadows. */ IrrlichtDevice *device = createDevice(driverType, core::dimension2d(640, 480), 16, false, shadows); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); /* For our environment, we load a .3ds file. It is a small room I modelled with Anim8or and exported into the 3ds format because the Irrlicht Engine does not support the .an8 format. I am a very bad 3d graphic artist, and so the texture mapping is not very nice in this model. Luckily I am a better programmer than artist, and so the Irrlicht Engine is able to create a cool texture mapping for me: Just use the mesh manipulator and create a planar texture mapping for the mesh. If you want to see the mapping I made with Anim8or, uncomment this line. I also did not figure out how to set the material right in Anim8or, it has a specular light color which I don't really like. I'll switch it off too with this code. */ scene::IAnimatedMesh* mesh = smgr->getMesh("../../media/room.3ds"); smgr->getMeshManipulator()->makePlanarTextureMapping(mesh->getMesh(0), 0.004f); scene::ISceneNode* node = 0; node = smgr->addAnimatedMeshSceneNode(mesh); node->setMaterialTexture(0, driver->getTexture("../../media/wall.jpg")); node->getMaterial(0).SpecularColor.set(0,0,0,0); /* Now, for the first special effect: Animated water. It works like this: The WaterSurfaceSceneNode takes a mesh as input and makes it wave like a water surface. And if we let this scene node use a nice material like the EMT_REFLECTION_2_LAYER, it looks really cool. We are doing this with the next few lines of code. As input mesh, we create a hill plane mesh, without hills. But any other mesh could be used for this, you could even use the room.3ds (which would look really strange) if you want to. */ mesh = smgr->addHillPlaneMesh( "myHill", core::dimension2d(20,20), core::dimension2d(40,40), 0, 0, core::dimension2d(0,0), core::dimension2d(10,10)); node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0), 3.0f, 300.0f, 30.0f); node->setPosition(core::vector3df(0,7,0)); node->setMaterialTexture(0, driver->getTexture("../../media/stones.jpg")); node->setMaterialTexture(1, driver->getTexture("../../media/water.jpg")); node->setMaterialType(video::EMT_REFLECTION_2_LAYER); /* The second special effect is very basic, I bet you saw it already in some Irrlicht Engine demos: A transparent billboard combined with a dynamic light. We simply create a light scene node, let it fly around, and to make it look more cool, we attach a billboard scene node to it. */ // create light node = smgr->addLightSceneNode(0, core::vector3df(0,0,0), video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 800.0f); scene::ISceneNodeAnimator* anim = 0; anim = smgr->createFlyCircleAnimator (core::vector3df(0,150,0),250.0f); node->addAnimator(anim); anim->drop(); // attach billboard to light node = smgr->addBillboardSceneNode(node, core::dimension2d(50, 50)); node->setMaterialFlag(video::EMF_LIGHTING, false); node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); node->setMaterialTexture(0, driver->getTexture("../../media/particlewhite.bmp")); /* The next special effect is a lot more interesting: A particle system. The particle system in the Irrlicht Engine is quite modular and extensible, but yet easy to use. There is a particle system scene node into which you can put a particle emitter, which makes particles come out of nothing. These emitters are quite flexible and usually have lots of parameters like direction, amount, and color of the particles they create. There are different emitters, for example a point emitter which lets particles pop out at a fixed point. If the particle emitters available in the engine are not enough for you, you can easily create your own ones, you'll simply have to create a class derived from the IParticleEmitter interface and attach it to the particle system using setEmitter(). In this example we create a box particle emitter, which creates particles randomly inside a box. The parameters define the box, direction of the particles, minimal and maximal new particles per second, color, and minimal and maximal lifetime of the particles. Because only with emitters particle system would be a little bit boring, there are particle affectors which modify particles while they fly around. Affectors can be added to a particle system for simulating additional effects like gravity or wind. The particle affector we use in this example is an affector which modifies the color of the particles: It lets them fade out. Like the particle emitters, additional particle affectors can also be implemented by you, simply derive a class from IParticleAffector and add it with addAffector(). After we set a nice material to the particle system, we have a cool looking camp fire. By adjusting material, texture, particle emitter, and affector parameters, it is also easily possible to create smoke, rain, explosions, snow, and so on. */ // create a particle system scene::IParticleSystemSceneNode* ps = smgr->addParticleSystemSceneNode(false); scene::IParticleEmitter* em = ps->createBoxEmitter( core::aabbox3d(-7,0,-7,7,1,7), // emitter size core::vector3df(0.0f,0.06f,0.0f), // initial direction 80,100, // emit rate video::SColor(0,255,255,255), // darkest color video::SColor(0,255,255,255), // brightest color 800,2000,0, // min and max age, angle core::dimension2df(10.f,10.f), // min size core::dimension2df(20.f,20.f)); // max size ps->setEmitter(em); // this grabs the emitter em->drop(); // so we can drop it here without deleting it scene::IParticleAffector* paf = ps->createFadeOutParticleAffector(); ps->addAffector(paf); // same goes for the affector paf->drop(); ps->setPosition(core::vector3df(-70,60,40)); ps->setScale(core::vector3df(2,2,2)); ps->setMaterialFlag(video::EMF_LIGHTING, false); ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); ps->setMaterialTexture(0, driver->getTexture("../../media/fire.bmp")); ps->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); /* Next we add a volumetric light node, which adds a glowing fake area light to the scene. Like with the billboards and particle systems we also assign a texture for the desired effect, though this time we'll use a texture animator to create the illusion of a magical glowing area effect. */ scene::IVolumeLightSceneNode * n = smgr->addVolumeLightSceneNode(0, -1, 32, // Subdivisions on U axis 32, // Subdivisions on V axis video::SColor(0, 255, 255, 255), // foot color video::SColor(0, 0, 0, 0)); // tail color if (n) { n->setScale(core::vector3df(56.0f, 56.0f, 56.0f)); n->setPosition(core::vector3df(-120,50,40)); // load textures for animation core::array textures; for (s32 g=7; g > 0; --g) { core::stringc tmp; tmp = "../../media/portal"; tmp += g; tmp += ".bmp"; video::ITexture* t = driver->getTexture( tmp.c_str() ); textures.push_back(t); } // create texture animator scene::ISceneNodeAnimator* glow = smgr->createTextureAnimator(textures, 150); // add the animator n->addAnimator(glow); // drop the animator because it was created with a create() function glow->drop(); } /* As our last special effect, we want a dynamic shadow be casted from an animated character. For this we load a DirectX .x model and place it into our world. For creating the shadow, we simply need to call addShadowVolumeSceneNode(). The color of shadows is only adjustable globally for all shadows, by calling ISceneManager::setShadowColor(). Voila, here is our dynamic shadow. Because the character is a little bit too small for this scene, we make it bigger using setScale(). And because the character is lighted by a dynamic light, we need to normalize the normals to make the lighting on it correct. This is always necessary if the scale of a dynamic lighted model is not (1,1,1). Otherwise it would get too dark or too bright because the normals will be scaled too. */ // add animated character mesh = smgr->getMesh("../../media/dwarf.x"); scene::IAnimatedMeshSceneNode* anode = 0; anode = smgr->addAnimatedMeshSceneNode(mesh); anode->setPosition(core::vector3df(-50,20,-60)); anode->setAnimationSpeed(15); // add shadow anode->addShadowVolumeSceneNode(); smgr->setShadowColor(video::SColor(150,0,0,0)); // make the model a little bit bigger and normalize its normals // because of the scaling, for correct lighting anode->setScale(core::vector3df(2,2,2)); anode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true); /* Finally we simply have to draw everything, that's all. */ scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); camera->setPosition(core::vector3df(-50,50,-150)); camera->setFarValue(10000.0f); // this increase a shadow visible range. // disable mouse cursor device->getCursorControl()->setVisible(false); s32 lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0); smgr->drawAll(); driver->endScene(); const s32 fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Irrlicht Engine - SpecialFX example ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; } /* **/ irrlicht-1.8.3/examples/07.Collision/0000755000000000000000000000000012574354552016053 5ustar rootrootirrlicht-1.8.3/examples/07.Collision/tutorial.html0000644000000000000000000004217512574354552020615 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 7. Collision detection and response

In this tutorial, I will show how to collision detection with the Irrlicht Engine. I will describe 3 methods: Automatic collision detection for moving through 3d worlds with stair climbing and sliding, manual triangle picking and manual scene node picking.

The program which is described here will look like this:



Lets start!

To start, we take the program from tutorial 2, which loaded and displayed a quake 3 level. We will use the level to walk in it and to pick triangles from it. In addition we'll place 3 animated models into it for scene node picking. The following code starts up the engine and loads a quake 3 level. I will not explain it, because it should already be known from tutorial 2.

#include <irrlicht.h>
#include <iostream>
using namespace irr; #pragma comment(lib, "Irrlicht.lib") int main() { // let user select driver type
video::E_DRIVER_TYPE driverType;

printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");

char i;
std::cin >> i;

switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 0;
}
// create device
  IrrlichtDevice *device = createDevice(driverType,
     core::dimension2d<s32>(640, 480), 16, false);
if (device == 0)
return 1; // could not create selected driver.

video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();

device->getFileSystem()->addZipFileArchive
("../../media/map-20kdm2.pk3"); scene::IAnimatedMesh* q3levelmesh = smgr->getMesh("20kdm2.bsp"); scene::ISceneNode* q3node = 0; if (q3levelmesh) q3node = smgr->addOctTreeSceneNode(q3levelmesh->getMesh(0));

So far so good, we've loaded the quake 3 level like in tutorial 2. Now, here comes something different: We create a triangle selector. A triangle selector is a class which can fetch the triangles from scene nodes for doing different things with them, for example collision detection. There are different triangle selectors, and all can be created with the ISceneManager. In this example, we create an OctTreeTriangleSelector, which optimizes the triangle output a little bit by reducing it like an octree. This is very useful for huge meshes like quake 3 levels.
Afte we created the triangle selector, we attach it to the q3node. This is not necessary, but in this way, we do not need to care for the selector, for example dropping it after we do not need it anymore.

scene::ITriangleSelector* selector = 0;
	
	if (q3node)
	{		
		q3node->setPosition(core::vector3df(-1370,-130,-1400));

		selector = smgr->createOctTreeTriangleSelector(
            q3levelmesh->getMesh(0), q3node, 128);
		q3node->setTriangleSelector(selector);
	}

We add a first person shooter camera to the scene for being able to move in the quake 3 level like in tutorial 2. But this, time, we add a special animator to the camera: A Collision Response animator. This thing modifies the scene node to which it is attached to in that way, that it may no more move through walls and is affected by gravity. The only thing we have to tell the animator is how the world looks like, how big the scene node is, how gravity and so on. After the collision response animator is attached to the camera, we do not have to do anything more for collision detection, anything is done automaticly, all other collision detection code below is for picking. And please note another cool feature: The collsion response animator can be attached also to all other scene nodes, not only to cameras. And it can be mixed with other scene node animators. In this way, collision detection and response in the Irrlicht
engine is really, really easy.
Now we'll take a closer look on the parameters of createCollisionResponseAnimator(). The first parameter is the TriangleSelector, which specifies how the world, against collision detection is done looks like. The second parameter is the scene node, which is the object, which is affected by collision detection, in our case it is the camera. The third defines how big the object is, it is the radius of an ellipsoid. Try it out and change the radius to smaller values, the camera will be able to move closer to walls after this. The next parameter is the direction and speed of gravity. You could set it to (0,0,0) to disable gravity. And the last value is just a translation: Without this, the ellipsoid with which collision detection is done would be around the camera, and the camera would be in the middle of the ellipsoid. But as human beings, we are used to have our eyes on top of the body, with which we collide with our world, not in the middle of it. So we place the scene node 50 units over the center of the ellipsoid with this parameter. And that's it, collision detection works now.

	scene::ICameraSceneNode* camera = 	
camera = smgr->addCameraSceneNodeFPS(0,100.0f,300.0f); camera->setPosition(core::vector3df(-100,50,-150)); scene::ISceneNodeAnimator* anim =
smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(30,50,30), core::vector3df(0,-3,0), core::vector3df(0,50,0));
selector->drop();
camera->addAnimator(anim); anim->drop();

Because collision detection is no big deal in irrlicht, I'll describe how to do two different types of picking in the next section. But before this, I'll prepare the scene a little. I need three animated characters which we
could pick later, a dynamic light for lighting them, a billboard for drawing where we found an intersection, and, yes, I need to get rid of this mouse cursor. :)

	// disable mouse cursor

	device->getCursorControl()->setVisible(false);

	// add billboard

	scene::IBillboardSceneNode * bill = smgr->addBillboardSceneNode();
	bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR );
	bill->setMaterialTexture(0, driver->getTexture(
"../../media/particle.bmp")); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setSize(core::dimension2d<f32>(20.0f, 20.0f)); // add 3 animated faeries. video::SMaterial material; material.Texture1 = driver->getTexture(
"../../media/faerie2.bmp"
); material.Lighting = true; scene::IAnimatedMeshSceneNode* node = 0; scene::IAnimatedMesh* faerie = smgr->getMesh(
"../../media/faerie.md2"); if (faerie) { node = smgr->addAnimatedMeshSceneNode(faerie); node->setPosition(core::vector3df(-70,0,-90)); node->setMD2Animation(scene::EMAT_RUN); node->getMaterial(0) = material; node = smgr->addAnimatedMeshSceneNode(faerie); node->setPosition(core::vector3df(-70,0,-30)); node->setMD2Animation(scene::EMAT_SALUTE); node->getMaterial(0) = material; node = smgr->addAnimatedMeshSceneNode(faerie); node->setPosition(core::vector3df(-70,0,-60)); node->setMD2Animation(scene::EMAT_JUMP); node->getMaterial(0) = material; } material.Texture1 = 0; material.Lighting = false; // Add a light smgr->addLightSceneNode(0, core::vector3df(-60,100,400), video::SColorf(1.0f,1.0f,1.0f,1.0f), 600.0f);

For not making it to complicated, I'm doing picking inside the drawing loop. We take two pointers for storing the current and the last selected scene node and start the loop.

	scene::ISceneNode* selectedSceneNode = 0;
	scene::ISceneNode* lastSelectedSceneNode = 0;

	
	int lastFPS = -1;

	while(device->run())
if (device->isWindowActive()) { driver->beginScene(true, true, 0); smgr->drawAll();

After we've drawn the whole scene whit smgr->drawAll(), we'll do the first picking: We want to know which triangle of the world we are looking at. In addition, we want the exact point of the quake 3 level we are looking at. For this, we create a 3d line starting at the position of the camera and going through the lookAt-target of it. Then we ask the collision manager if this line collides with a triangle of the world stored in the triangle selector. If yes, we draw the 3d triangle and set the position of the billboard to the intersection point.

		core::line3d<f32> line;
		line.start = camera->getPosition();
		line.end = line.start +
         (camera->getTarget() - line.start).normalize() * 1000.0f;

		core::vector3df intersection;
		core::triangle3df tri;

		if (smgr->getSceneCollisionManager()->getCollisionPoint(
			line, selector, intersection, tri))
		{
			bill->setPosition(intersection);
				
			driver->setTransform(video::ETS_WORLD, core::matrix4());
			driver->setMaterial(material);
			driver->draw3DTriangle(tri, video::SColor(0,255,0,0));
		}

Another type of picking supported by the Irrlicht Engine is scene node picking based on bouding boxes. Every scene node has got a bounding box, and because of that, it's very fast for example to get the scene node which the camera looks
at. Again, we ask the collision manager for this, and if we've got a scene node, we highlight it by disabling Lighting in its material, if it is not the billboard or the quake 3 level.

		selectedSceneNode = smgr->getSceneCollisionManager()->
          getSceneNodeFromCameraBB(camera);

		if (lastSelectedSceneNode)
			lastSelectedSceneNode->setMaterialFlag(
                video::EMF_LIGHTING, true);

		if (selectedSceneNode == q3node ||
           selectedSceneNode == bill)
			selectedSceneNode = 0;

		if (selectedSceneNode)
			selectedSceneNode->setMaterialFlag(
               video::EMF_LIGHTING, false);

		lastSelectedSceneNode = selectedSceneNode;

That's it, we just have to finish drawing.

		driver->endScene();

		int fps = driver->getFPS();

		if (lastFPS != fps)
		{
		  core::stringw str = L"Collision detection example - Irrlicht Engine [";
str += driver->getName();
str += "] FPS:";
str += fps;

device->setWindowCaption(str.c_str());
lastFPS = fps;
} } device->drop(); return 0; }

 

 

 

irrlicht-1.8.3/examples/07.Collision/Makefile0000644000000000000000000000220312574354552017510 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 07.Collision Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/07.Collision/main.cpp0000644000000000000000000003265012574354552017511 0ustar rootroot/** Example 007 Collision We will describe 2 methods: Automatic collision detection for moving through 3d worlds with stair climbing and sliding, and manual scene node and triangle picking using a ray. In this case, we will use a ray coming out from the camera, but you can use any ray. To start, we take the program from tutorial 2, which loads and displays a quake 3 level. We will use the level to walk in it and to pick triangles from. In addition we'll place 3 animated models into it for triangle picking. The following code starts up the engine and loads the level, as per tutorial 2. */ #include #include "driverChoice.h" using namespace irr; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif enum { // I use this ISceneNode ID to indicate a scene node that is // not pickable by getSceneNodeAndCollisionPointFromRay() ID_IsNotPickable = 0, // I use this flag in ISceneNode IDs to indicate that the // scene node can be picked by ray selection. IDFlag_IsPickable = 1 << 0, // I use this flag in ISceneNode IDs to indicate that the // scene node can be highlighted. In this example, the // homonids can be highlighted, but the level mesh can't. IDFlag_IsHighlightable = 1 << 1 }; int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device IrrlichtDevice *device = createDevice(driverType, core::dimension2d(640, 480), 16, false); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); device->getFileSystem()->addFileArchive("../../media/map-20kdm2.pk3"); scene::IAnimatedMesh* q3levelmesh = smgr->getMesh("20kdm2.bsp"); scene::IMeshSceneNode* q3node = 0; // The Quake mesh is pickable, but doesn't get highlighted. if (q3levelmesh) q3node = smgr->addOctreeSceneNode(q3levelmesh->getMesh(0), 0, IDFlag_IsPickable); /* So far so good, we've loaded the quake 3 level like in tutorial 2. Now, here comes something different: We create a triangle selector. A triangle selector is a class which can fetch the triangles from scene nodes for doing different things with them, for example collision detection. There are different triangle selectors, and all can be created with the ISceneManager. In this example, we create an OctreeTriangleSelector, which optimizes the triangle output a little bit by reducing it like an octree. This is very useful for huge meshes like quake 3 levels. After we created the triangle selector, we attach it to the q3node. This is not necessary, but in this way, we do not need to care for the selector, for example dropping it after we do not need it anymore. */ scene::ITriangleSelector* selector = 0; if (q3node) { q3node->setPosition(core::vector3df(-1350,-130,-1400)); selector = smgr->createOctreeTriangleSelector( q3node->getMesh(), q3node, 128); q3node->setTriangleSelector(selector); // We're not done with this selector yet, so don't drop it. } /* We add a first person shooter camera to the scene so that we can see and move in the quake 3 level like in tutorial 2. But this, time, we add a special animator to the camera: A Collision Response animator. This animator modifies the scene node to which it is attached to in order to prevent it moving through walls, and to add gravity to it. The only thing we have to tell the animator is how the world looks like, how big the scene node is, how much gravity to apply and so on. After the collision response animator is attached to the camera, we do not have to do anything more for collision detection, anything is done automatically. The rest of the collision detection code below is for picking. And please note another cool feature: The collision response animator can be attached also to all other scene nodes, not only to cameras. And it can be mixed with other scene node animators. In this way, collision detection and response in the Irrlicht engine is really easy. Now we'll take a closer look on the parameters of createCollisionResponseAnimator(). The first parameter is the TriangleSelector, which specifies how the world, against collision detection is done looks like. The second parameter is the scene node, which is the object, which is affected by collision detection, in our case it is the camera. The third defines how big the object is, it is the radius of an ellipsoid. Try it out and change the radius to smaller values, the camera will be able to move closer to walls after this. The next parameter is the direction and speed of gravity. We'll set it to (0, -10, 0), which approximates to realistic gravity, assuming that our units are metres. You could set it to (0,0,0) to disable gravity. And the last value is just a translation: Without this, the ellipsoid with which collision detection is done would be around the camera, and the camera would be in the middle of the ellipsoid. But as human beings, we are used to have our eyes on top of the body, with which we collide with our world, not in the middle of it. So we place the scene node 50 units over the center of the ellipsoid with this parameter. And that's it, collision detection works now. */ // Set a jump speed of 3 units per second, which gives a fairly realistic jump // when used with the gravity of (0, -10, 0) in the collision response animator. scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0, 100.0f, .3f, ID_IsNotPickable, 0, 0, true, 3.f); camera->setPosition(core::vector3df(50,50,-60)); camera->setTarget(core::vector3df(-70,30,-60)); if (selector) { scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(30,50,30), core::vector3df(0,-10,0), core::vector3df(0,30,0)); selector->drop(); // As soon as we're done with the selector, drop it. camera->addAnimator(anim); anim->drop(); // And likewise, drop the animator when we're done referring to it. } // Now I create three animated characters which we can pick, a dynamic light for // lighting them, and a billboard for drawing where we found an intersection. // First, let's get rid of the mouse cursor. We'll use a billboard to show // what we're looking at. device->getCursorControl()->setVisible(false); // Add the billboard. scene::IBillboardSceneNode * bill = smgr->addBillboardSceneNode(); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); bill->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp")); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialFlag(video::EMF_ZBUFFER, false); bill->setSize(core::dimension2d(20.0f, 20.0f)); bill->setID(ID_IsNotPickable); // This ensures that we don't accidentally ray-pick it /* Add 3 animated hominids, which we can pick using a ray-triangle intersection. They all animate quite slowly, to make it easier to see that accurate triangle selection is being performed. */ scene::IAnimatedMeshSceneNode* node = 0; video::SMaterial material; // Add an MD2 node, which uses vertex-based animation. node = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/faerie.md2"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-90,-15,-140)); // Put its feet on the floor. node->setScale(core::vector3df(1.6f)); // Make it appear realistically scaled node->setMD2Animation(scene::EMAT_POINT); node->setAnimationSpeed(20.f); material.setTexture(0, driver->getTexture("../../media/faerie2.bmp")); material.Lighting = true; material.NormalizeNormals = true; node->getMaterial(0) = material; // Now create a triangle selector for it. The selector will know that it // is associated with an animated node, and will update itself as necessary. selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); // We're done with this selector, so drop it now. // And this B3D file uses skinned skeletal animation. node = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/ninja.b3d"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setScale(core::vector3df(10)); node->setPosition(core::vector3df(-75,-66,-80)); node->setRotation(core::vector3df(0,90,0)); node->setAnimationSpeed(8.f); node->getMaterial(0).NormalizeNormals = true; node->getMaterial(0).Lighting = true; // Just do the same as we did above. selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); // This X files uses skeletal animation, but without skinning. node = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/dwarf.x"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-70,-66,-30)); // Put its feet on the floor. node->setRotation(core::vector3df(0,-90,0)); // And turn it towards the camera. node->setAnimationSpeed(20.f); node->getMaterial(0).Lighting = true; selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); // And this mdl file uses skinned skeletal animation. node = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/yodan.mdl"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-90,-25,20)); node->setScale(core::vector3df(0.8f)); node->getMaterial(0).Lighting = true; node->setAnimationSpeed(20.f); // Just do the same as we did above. selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); material.setTexture(0, 0); material.Lighting = false; // Add a light, so that the unselected nodes aren't completely dark. scene::ILightSceneNode * light = smgr->addLightSceneNode(0, core::vector3df(-60,100,400), video::SColorf(1.0f,1.0f,1.0f,1.0f), 600.0f); light->setID(ID_IsNotPickable); // Make it an invalid target for selection. // Remember which scene node is highlighted scene::ISceneNode* highlightedSceneNode = 0; scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager(); int lastFPS = -1; // draw the selection triangle only as wireframe material.Wireframe=true; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0); smgr->drawAll(); // Unlight any currently highlighted scene node if (highlightedSceneNode) { highlightedSceneNode->setMaterialFlag(video::EMF_LIGHTING, true); highlightedSceneNode = 0; } // All intersections in this example are done with a ray cast out from the camera to // a distance of 1000. You can easily modify this to check (e.g.) a bullet // trajectory or a sword's position, or create a ray from a mouse click position using // ISceneCollisionManager::getRayFromScreenCoordinates() core::line3d ray; ray.start = camera->getPosition(); ray.end = ray.start + (camera->getTarget() - ray.start).normalize() * 1000.0f; // Tracks the current intersection point with the level or a mesh core::vector3df intersection; // Used to show with triangle has been hit core::triangle3df hitTriangle; // This call is all you need to perform ray/triangle collision on every scene node // that has a triangle selector, including the Quake level mesh. It finds the nearest // collision point/triangle, and returns the scene node containing that point. // Irrlicht provides other types of selection, including ray/triangle selector, // ray/box and ellipse/triangle selector, plus associated helpers. // See the methods of ISceneCollisionManager scene::ISceneNode * selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay( ray, intersection, // This will be the position of the collision hitTriangle, // This will be the triangle hit in the collision IDFlag_IsPickable, // This ensures that only nodes that we have // set up to be pickable are considered 0); // Check the entire scene (this is actually the implicit default) // If the ray hit anything, move the billboard to the collision position // and draw the triangle that was hit. if(selectedSceneNode) { bill->setPosition(intersection); // We need to reset the transform before doing our own rendering. driver->setTransform(video::ETS_WORLD, core::matrix4()); driver->setMaterial(material); driver->draw3DTriangle(hitTriangle, video::SColor(0,255,0,0)); // We can check the flags for the scene node that was hit to see if it should be // highlighted. The animated nodes can be highlighted, but not the Quake level mesh if((selectedSceneNode->getID() & IDFlag_IsHighlightable) == IDFlag_IsHighlightable) { highlightedSceneNode = selectedSceneNode; // Highlighting in this case means turning lighting OFF for this node, // which means that it will be drawn with full brightness. highlightedSceneNode->setMaterialFlag(video::EMF_LIGHTING, false); } } // We're all done drawing, so end the scene. driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Collision detection example - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; } /* **/ irrlicht-1.8.3/examples/07.Collision/Collision_vc9.vcproj0000644000000000000000000001222612574354552022017 0ustar rootroot irrlicht-1.8.3/examples/07.Collision/Collision_vc8.vcproj0000644000000000000000000001212612574354552022015 0ustar rootroot irrlicht-1.8.3/examples/07.Collision/Collision_vc12.vcxproj0000644000000000000000000003274012574354552022264 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 07.Collision {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E} Collision Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Collision.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\07.Collision.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Collision.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\07.Collision.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Collision.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\07.Collision.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Collision.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\07.Collision.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/07.Collision/Collision_vc11.vcxproj0000644000000000000000000003273712574354552022271 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 07.Collision {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E} Collision Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Collision.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\07.Collision.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Collision.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\07.Collision.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Collision.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\07.Collision.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Collision.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\07.Collision.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/07.Collision/Collision_vc10.vcxproj0000644000000000000000000003273712574354552022270 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 07.Collision {3E30297B-5BE3-4A5C-B31E-08A28ADDB29E} Collision Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Collision.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\07.Collision.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Collision.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\07.Collision.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Collision.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\07.Collision.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Collision.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\07.Collision.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/07.Collision/Collision.vcproj0000644000000000000000000001053712574354552021241 0ustar rootroot irrlicht-1.8.3/examples/07.Collision/Collision.dev0000644000000000000000000000174012574354552020510 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 07 Collision UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=07.Collision.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/07.Collision/Collision.cbp0000644000000000000000000000266412574354552020504 0ustar rootroot irrlicht-1.8.3/examples/06.2DGraphics/0000755000000000000000000000000012574354552016045 5ustar rootrootirrlicht-1.8.3/examples/06.2DGraphics/tutorial.html0000644000000000000000000002314012574354552020576 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 6. 2D Graphics

This Tutorial shows how to do 2d graphics with the Irrlicht Engine. It shows how to draw images, keycolor based sprites, transparent rectangles and different fonts. You will may consider this useful if you want to make a 2d game with the engine, or if you want to draw a cool interface or head up display for your 3d game.

The program which is described here will look like this:



Lets start!

As always, I include the header files, use the irr namespace, and tell the linker to link with the .lib file.

#include <irrlicht.h>
#include <iostream>

using namespace irr;
#pragma comment(lib, "Irrlicht.lib")
               

At first, we let the user select the driver type, then start up the engine, set a caption, and get a pointer to the video driver.

int main()
{
// let user select driver type
video::E_DRIVER_TYPE driverType;

printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");

char i;
std::cin >> i;

switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 0;
}

// create device
  IrrlichtDevice *device = createDevice(driverType,
         core::dimension2d<s32>(512, 384));
  if (device == 0)
      return 1;
 
device->setWindowCaption(L"Irrlicht Engine - 2D Graphics Demo");
  video::IVideoDriver* driver = device->getVideoDriver();

All 2d graphics in this example are put together into one texture, 2ddemo.bmp. Because we want to draw colorkey based sprites, we need to load this texture and tell the engine, which part of it should be transparent based on a colorkey. In this example, we don't tell it the color directly, we just say "Hey Irrlicht Engine, you'll find the color I want at position (0,0) on the texture.". Instead, it would be also possible to call driver->makeColorKeyTexture(images, video::SColor(0,0,0,0)), to make e.g. all black pixels transparent. Please note, that makeColorKeyTexture just creates an alpha channel based on the color.

video::ITexture* images = driver->getTexture("../../media/2ddemo.bmp");
driver->makeColorKeyTexture(images, core::position2d<s32>(0,0));

To be able to draw some text with two different fonts, we load them. Ok, we load just one, as first font we just use the default font which is built into the engine.
Also, we define two rectangles, which specify the position of the images of the red imps (little flying creatures) in the texture.

gui::IGUIFont* font = device->getGUIEnvironment()->getBuiltInFont();
gui::IGUIFont* font2 = device->getGUIEnvironment()->getFont( "../../media/fonthaettenschweiler.bmp");
core::rect<s32> imp1(349,15,385,78);
core::rect<s32> imp2(387,15,423,78);

Everything is prepared, now we can draw everything in the draw loop, between the begin scene and end scene calls. In this example, we are just doing 2d graphics, but it would be no problem to mix them with 3d graphics. Just try it out, and draw some 3d vertices or set up a scene with the scene manager and draw it.

while(device->run() && driver)
{
if (device->isWindowActive())
{
u32 time = device->getTimer()->getTime();
driver->beginScene(true, true, video::SColor(0,120,102,136));

First, we draw 3 sprites, using the alpha channel we created with makeColorKeyTexture. The last parameter specifiys that the drawing method should use thiw alpha channel. The parameter before the last one specifies a color, with wich the sprite should be colored. (255,255,255,255) is full white, so the sprite will look like the original. The third sprite is drawed colored based on the time.

// draw fire & dragons background world
driver->draw2DImage(images, core::position2d<s32>(50,50),
core::rect<s32>(0,0,342,224), 0,
video::SColor(255,255,255,255), true);
// draw flying imp 
driver->draw2DImage(images, core::position2d<s32>(164,125),
  (time/500 % 2) ? imp1 : imp2, 0, 
   video::SColor(255,255,255,255), true);
// draw second flying imp with colorcylce
driver->draw2DImage(images, core::position2d<s32>(270,105),
  (time/500 % 2) ? imp1 : imp2, 0, 
  video::SColor(255,(time) % 255,255,255), true);

Drawing text is really simple. The code should be self explanatory.

// draw some text
if (font)
font->draw(L"This is some text.",
core::rect<s32>(130,10,300,50),
video::SColor(255,255,255,255));
// draw some other text
if (font2)
   font2->draw(L"This is some other text.", 
       core::rect<s32>(130,20,300,60),
       video::SColor(255,time % 255,time % 255,255));

At last, we draw the Irrlicht Engine logo (without using a color or an alpha channel) and a transparent 2d Rectangle at the position of the mouse cursor.

    // draw logo
driver->draw2DImage(images, core::position2d<s32>(10,10),
core::rect<s32>(354,87,442,118));
    // draw transparent rect under cursor
    core::position2d<s32> m = device->getCursorControl()->getPosition();
    driver->draw2DRectangle(video::SColor(100,255,255,255),
          core::rect<s32>(m.X-20, m.Y-20, m.X+20, m.Y+20));
    driver->endScene();
  }
}

That's all, it was not really difficult, I hope.

   device->drop();
   return 0;
}

 

 

irrlicht-1.8.3/examples/06.2DGraphics/Makefile0000644000000000000000000000220412574354552017503 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 06.2DGraphics Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/06.2DGraphics/main.cpp0000644000000000000000000001273112574354552017501 0ustar rootroot/** Example 006 2D Graphics This Tutorial shows how to do 2d graphics with the Irrlicht Engine. It shows how to draw images, keycolor based sprites, transparent rectangles, and different fonts. You may consider this useful if you want to make a 2d game with the engine, or if you want to draw a cool interface or head up display for your 3d game. As always, I include the header files, use the irr namespace, and tell the linker to link with the .lib file. */ #include #include "driverChoice.h" using namespace irr; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif /* At first, we let the user select the driver type, then start up the engine, set a caption, and get a pointer to the video driver. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device IrrlichtDevice *device = createDevice(driverType, core::dimension2d(512, 384)); if (device == 0) return 1; // could not create selected driver. device->setWindowCaption(L"Irrlicht Engine - 2D Graphics Demo"); video::IVideoDriver* driver = device->getVideoDriver(); /* All 2d graphics in this example are put together into one texture, 2ddemo.png. Because we want to draw colorkey based sprites, we need to load this texture and tell the engine, which part of it should be transparent based on a colorkey. In this example, we don't tell it the color directly, we just say "Hey Irrlicht Engine, you'll find the color I want at position (0,0) on the texture.". Instead, it would be also possible to call driver->makeColorKeyTexture(images, video::SColor(0,0,0,0)), to make e.g. all black pixels transparent. Please note that makeColorKeyTexture just creates an alpha channel based on the color. */ video::ITexture* images = driver->getTexture("../../media/2ddemo.png"); driver->makeColorKeyTexture(images, core::position2d(0,0)); /* To be able to draw some text with two different fonts, we first load them. Ok, we load just one. As the first font we just use the default font which is built into the engine. Also, we define two rectangles which specify the position of the images of the red imps (little flying creatures) in the texture. */ gui::IGUIFont* font = device->getGUIEnvironment()->getBuiltInFont(); gui::IGUIFont* font2 = device->getGUIEnvironment()->getFont("../../media/fonthaettenschweiler.bmp"); core::rect imp1(349,15,385,78); core::rect imp2(387,15,423,78); /* Prepare a nicely filtering 2d render mode for special cases. */ driver->getMaterial2D().TextureLayer[0].BilinearFilter=true; driver->getMaterial2D().AntiAliasing=video::EAAM_FULL_BASIC; /* Everything is prepared, now we can draw everything in the draw loop, between the begin scene and end scene calls. In this example, we are just doing 2d graphics, but it would be no problem to mix them with 3d graphics. Just try it out, and draw some 3d vertices or set up a scene with the scene manager and draw it. */ while(device->run() && driver) { if (device->isWindowActive()) { u32 time = device->getTimer()->getTime(); driver->beginScene(true, true, video::SColor(255,120,102,136)); /* First, we draw 3 sprites, using the alpha channel we created with makeColorKeyTexture. The last parameter specifies that the drawing method should use this alpha channel. The last-but-one parameter specifies a color, with which the sprite should be colored. (255,255,255,255) is full white, so the sprite will look like the original. The third sprite is drawn with the red channel modulated based on the time. */ // draw fire & dragons background world driver->draw2DImage(images, core::position2d(50,50), core::rect(0,0,342,224), 0, video::SColor(255,255,255,255), true); // draw flying imp driver->draw2DImage(images, core::position2d(164,125), (time/500 % 2) ? imp1 : imp2, 0, video::SColor(255,255,255,255), true); // draw second flying imp with colorcylce driver->draw2DImage(images, core::position2d(270,105), (time/500 % 2) ? imp1 : imp2, 0, video::SColor(255,(time) % 255,255,255), true); /* Drawing text is really simple. The code should be self explanatory. */ // draw some text if (font) font->draw(L"This demo shows that Irrlicht is also capable of drawing 2D graphics.", core::rect(130,10,300,50), video::SColor(255,255,255,255)); // draw some other text if (font2) font2->draw(L"Also mixing with 3d graphics is possible.", core::rect(130,20,300,60), video::SColor(255,time % 255,time % 255,255)); /* Next, we draw the Irrlicht Engine logo (without using a color or an alpha channel). Since we slightly scale the image we use the prepared filter mode. */ driver->enableMaterial2D(); driver->draw2DImage(images, core::rect(10,10,108,48), core::rect(354,87,442,118)); driver->enableMaterial2D(false); /* Finally draw a half-transparent rect under the mouse cursor. */ core::position2d m = device->getCursorControl()->getPosition(); driver->draw2DRectangle(video::SColor(100,255,255,255), core::rect(m.X-20, m.Y-20, m.X+20, m.Y+20)); driver->endScene(); } } device->drop(); return 0; } /* That's all. I hope it was not too difficult. **/ irrlicht-1.8.3/examples/06.2DGraphics/2DGraphics_vc9.vcproj0000644000000000000000000001224012574354552022000 0ustar rootroot irrlicht-1.8.3/examples/06.2DGraphics/2DGraphics_vc8.vcproj0000644000000000000000000001214012574354552021776 0ustar rootroot irrlicht-1.8.3/examples/06.2DGraphics/2DGraphics_vc12.vcxproj0000644000000000000000000003275212574354552022254 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 06.2DGraphics {E71B6F18-10DC-4101-A541-F6D33F71B2BD} 2DGraphics Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/2DGraphics.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\06.2DGraphics.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/2DGraphics.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\06.2DGraphics.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console .\Debug/2DGraphics.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\06.2DGraphics.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/2DGraphics.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\06.2DGraphics.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/06.2DGraphics/2DGraphics_vc11.vcxproj0000644000000000000000000003275112574354552022252 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 06.2DGraphics {E71B6F18-10DC-4101-A541-F6D33F71B2BD} 2DGraphics Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/2DGraphics.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\06.2DGraphics.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/2DGraphics.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\06.2DGraphics.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console .\Debug/2DGraphics.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\06.2DGraphics.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/2DGraphics.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\06.2DGraphics.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/06.2DGraphics/2DGraphics_vc10.vcxproj0000644000000000000000000003275112574354552022251 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 06.2DGraphics {E71B6F18-10DC-4101-A541-F6D33F71B2BD} 2DGraphics Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/2DGraphics.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\06.2DGraphics.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/2DGraphics.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\06.2DGraphics.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console .\Debug/2DGraphics.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\06.2DGraphics.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/2DGraphics.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\06.2DGraphics.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/06.2DGraphics/2DGraphics.vcproj0000644000000000000000000001055012574354552021221 0ustar rootroot irrlicht-1.8.3/examples/06.2DGraphics/2DGraphics.dev0000644000000000000000000000174312574354552020500 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 06 2D Graphics UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=06.2DGraphics.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/06.2DGraphics/2DGraphics.cbp0000644000000000000000000000267012574354552020466 0ustar rootroot irrlicht-1.8.3/examples/05.UserInterface/0000755000000000000000000000000012574354552016655 5ustar rootrootirrlicht-1.8.3/examples/05.UserInterface/UserInterface_vc9.vcproj0000644000000000000000000001227612574354552023432 0ustar rootroot irrlicht-1.8.3/examples/05.UserInterface/UserInterface_vc8.vcproj0000644000000000000000000001217612574354552023430 0ustar rootroot irrlicht-1.8.3/examples/05.UserInterface/UserInterface_vc12.vcxproj0000644000000000000000000003301012574354552023661 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 05.UserInterface {622C9DD7-0391-49FF-AF53-24F9D5A8EC53} UserInterface Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/UserInterface.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\05.UserInterface.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/UserInterface.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\05.UserInterface.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/UserInterface.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\05.UserInterface.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/UserInterface.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\05.UserInterface.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/05.UserInterface/UserInterface_vc11.vcxproj0000644000000000000000000003300712574354552023666 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 05.UserInterface {622C9DD7-0391-49FF-AF53-24F9D5A8EC53} UserInterface Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/UserInterface.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\05.UserInterface.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/UserInterface.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\05.UserInterface.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/UserInterface.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\05.UserInterface.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/UserInterface.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\05.UserInterface.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/05.UserInterface/UserInterface_vc10.vcxproj0000644000000000000000000003300712574354552023665 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 05.UserInterface {622C9DD7-0391-49FF-AF53-24F9D5A8EC53} UserInterface Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/UserInterface.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\05.UserInterface.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/UserInterface.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\05.UserInterface.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/UserInterface.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\05.UserInterface.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/UserInterface.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\05.UserInterface.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/05.UserInterface/UserInterface.vcproj0000644000000000000000000001060312574354552022641 0ustar rootroot irrlicht-1.8.3/examples/05.UserInterface/UserInterface.dev0000644000000000000000000000175112574354552022120 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 05 User Interface UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=05.UserInterface.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/05.UserInterface/UserInterface.cbp0000644000000000000000000000270112574354552022102 0ustar rootroot irrlicht-1.8.3/examples/05.UserInterface/tutorial.html0000644000000000000000000002700512574354552021412 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 5.User Interface

This tutorial shows how to use the built in User Interface of the Irrlicht Engine. It will give a brief overview and show how to create and use windows, buttons, scroll bars, static texts and list boxes.

The program which is described here will look like this:



Lets start!

As always, we include the header files (conio and curses for getting user input from the console), and use the irrlicht namespaces. We also store a pointer to the Irrlicht device, a counter variable for changing the creation position of a window, and a pointer to a listbox.

#include <irrlicht.h>
#include <iostream>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#pragma comment(lib, "Irrlicht.lib")
IrrlichtDevice *device = 0;
s32 cnt = 0;
IGUIListBox* listbox = 0;

The Event Receiver is not only capable of getting keyboard and mouse input events, but also events of the graphical user interface (gui). There are events for almost everything: Button click, Listbox selection change, events that say that a element was hovered and so on. To be able to react to some of these events, we create
an event receiver. We only react to gui events, and if it's such an event, we get the id of the caller (the gui element which caused the event) and get the pointer to the gui environment.

class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == EET_GUI_EVENT)
{
s32 id = event.GUIEvent.Caller->getID();
IGUIEnvironment* env = device->getGUIEnvironment();
            switch(event.GUIEvent.EventType)
            {

If a scrollbar changed its scroll position, and it is 'our' scrollbar (the one with id 104), then we change the
transparency of all gui elements. This is a very easy task: There is a skin object, in which all color settings are stored. We simply go through all colors stored in the skin and change their alpha value.

case EGET_SCROLL_BAR_CHANGED:
if (id == 104)
{
s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();

for (s32 i=0; i<EGDC_COUNT ; ++i)
{
SColor col = env->getSkin()->getColor((EGUI_DEFAULT_COLOR)i);
col.setAlpha(pos);
env->getSkin()->setColor((EGUI_DEFAULT_COLOR)i, col);
}
}
break;

If a button was clicked, it could be one of 'our' three buttons. If it is the first, we shut down the engine.
If it is the second, we create a little window with some text on it. We also add a string to the list box to log
what happened. And if it is the third button, we create a file open dialog, and add also this as string to the list box.
That's all for the event receiver.

       case EGET_BUTTON_CLICKED:
              if (id == 101)
              {
                 device->closeDevice();
                 return true;
              }
              if (id == 102)
              {
                 listbox->addItem(L"Window created");
                 cnt += 30;
                 if (cnt > 200) 
                   cnt = 0;
                 IGUIWindow* window = env->addWindow(
                       rect<s32>(100 + cnt, 100 + cnt, 300 + cnt, 200 + cnt), 
false, // modal? L"Test window");
                 env->addStaticText(L"Please close me", 
                       rect<s32>(35,35,140,50),
                       true, // border?,
                       false, // wordwrap?
                       window);

                 return true;
              }
              if (id == 103)
              {
                 listbox->addItem(L"File open");
                 env->addFileOpenDialog(L"Please choose a file.");
                 return true;
              }
              break;
          }
       }
       return false;
    }
 };

Ok, now for the more interesting part. First, create the Irrlicht device. As in some examples before, we ask the user which driver he wants to use for this example:

int main()
{
  // ask user for driver
  video::E_DRIVER_TYPE driverType;


  printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");

char i;
std::cin >> i;
switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 1;
} // create device and exit if creation failed device = createDevice(driverType, core::dimension2d<s32>(640, 480));
if (device == 0) return 1;

The creation was successful, now we set the event receiver and store pointers to the driver and to the gui environment.

MyEventReceiver receiver;
device->setEventReceiver(&receiver);
device->setWindowCaption(L"Irrlicht Engine - User Inferface Demo");
video::IVideoDriver* driver = device->getVideoDriver();
IGUIEnvironment* env = device->getGUIEnvironment();

We add three buttons. The first one closes the engine. The second creates a window and the third opens a file open dialog. The third parameter is the id of the button, with which we can easily identify the button in the event receiver.

env->addButton(rect<s32>(10,240,100,270), 0, 101, L"Quit");
env->addButton(rect<s32>(10,280,100,320), 0, 102, L"New Window");
env->addButton(rect<s32>(10,330,100,370), 0, 103, L"File Open");

Now, we add a static text and a scrollbar, which modifies the transparency of all gui elements. We set the maximum value of the scrollbar to 255, because that's the maximal value for a color value.
Then we create an other static text and a list box.

env->addStaticText(L"Transparent Control:", rect<s32>(150,20,350,40), true);
IGUIScrollBar* scrollbar = env->addScrollBar(true, rect<s32>(150, 45, 350, 60), 0, 104);
scrollbar->setMax(255);
env->addStaticText(L"Logging ListBox:", rect<s32>(50,110,250,130), true);
listbox = env->addListBox(rect<s32>(50, 140, 250, 210));

To make the font a little bit nicer, we load an external font and set it as new font in the skin. An at last, we create a nice Irrlicht Engine logo in the top left corner.

IGUISkin* skin = env->getSkin();
IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp");
if (font)
skin->setFont(font);
IGUIImage* img = env->addImage(
driver->getTexture("../../media/irrlichtlogoalpha.tga"),
position2d<int>(10,10));

That's all, we only have to draw everything.

  while(device->run() && driver)
if (device->isWindowActive())
{
driver->beginScene(true, true, SColor(0,122,65,171)); env->drawAll(); driver->endScene(); } device->drop();
  return 0;
}

 

irrlicht-1.8.3/examples/05.UserInterface/Makefile0000644000000000000000000000220712574354552020316 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 05.UserInterface Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/05.UserInterface/main.cpp0000644000000000000000000002067212574354552020314 0ustar rootroot/** Example 005 User Interface This tutorial shows how to use the built in User Interface of the Irrlicht Engine. It will give a brief overview and show how to create and use windows, buttons, scroll bars, static texts, and list boxes. As always, we include the header files, and use the irrlicht namespaces. We also store a pointer to the Irrlicht device, a counter variable for changing the creation position of a window, and a pointer to a listbox. */ #include #include "driverChoice.h" using namespace irr; using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; #ifdef _IRR_WINDOWS_ #pragma comment(lib, "Irrlicht.lib") #endif // Declare a structure to hold some context for the event receiver so that it // has it available inside its OnEvent() method. struct SAppContext { IrrlichtDevice *device; s32 counter; IGUIListBox* listbox; }; // Define some values that we'll use to identify individual GUI controls. enum { GUI_ID_QUIT_BUTTON = 101, GUI_ID_NEW_WINDOW_BUTTON, GUI_ID_FILE_OPEN_BUTTON, GUI_ID_TRANSPARENCY_SCROLL_BAR }; /* Set the skin transparency by changing the alpha values of all skin-colors */ void setSkinTransparency(s32 alpha, irr::gui::IGUISkin * skin) { for (s32 i=0; igetColor((EGUI_DEFAULT_COLOR)i); col.setAlpha(alpha); skin->setColor((EGUI_DEFAULT_COLOR)i, col); } } /* The Event Receiver is not only capable of getting keyboard and mouse input events, but also events of the graphical user interface (gui). There are events for almost everything: Button click, Listbox selection change, events that say that a element was hovered and so on. To be able to react to some of these events, we create an event receiver. We only react to gui events, and if it's such an event, we get the id of the caller (the gui element which caused the event) and get the pointer to the gui environment. */ class MyEventReceiver : public IEventReceiver { public: MyEventReceiver(SAppContext & context) : Context(context) { } virtual bool OnEvent(const SEvent& event) { if (event.EventType == EET_GUI_EVENT) { s32 id = event.GUIEvent.Caller->getID(); IGUIEnvironment* env = Context.device->getGUIEnvironment(); switch(event.GUIEvent.EventType) { /* If a scrollbar changed its scroll position, and it is 'our' scrollbar (the one with id GUI_ID_TRANSPARENCY_SCROLL_BAR), then we change the transparency of all gui elements. This is a very easy task: There is a skin object, in which all color settings are stored. We simply go through all colors stored in the skin and change their alpha value. */ case EGET_SCROLL_BAR_CHANGED: if (id == GUI_ID_TRANSPARENCY_SCROLL_BAR) { s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos(); setSkinTransparency(pos, env->getSkin()); } break; /* If a button was clicked, it could be one of 'our' three buttons. If it is the first, we shut down the engine. If it is the second, we create a little window with some text on it. We also add a string to the list box to log what happened. And if it is the third button, we create a file open dialog, and add also this as string to the list box. That's all for the event receiver. */ case EGET_BUTTON_CLICKED: switch(id) { case GUI_ID_QUIT_BUTTON: Context.device->closeDevice(); return true; case GUI_ID_NEW_WINDOW_BUTTON: { Context.listbox->addItem(L"Window created"); Context.counter += 30; if (Context.counter > 200) Context.counter = 0; IGUIWindow* window = env->addWindow( rect(100 + Context.counter, 100 + Context.counter, 300 + Context.counter, 200 + Context.counter), false, // modal? L"Test window"); env->addStaticText(L"Please close me", rect(35,35,140,50), true, // border? false, // wordwrap? window); } return true; case GUI_ID_FILE_OPEN_BUTTON: Context.listbox->addItem(L"File open"); // There are some options for the file open dialog // We set the title, make it a modal window, and make sure // that the working directory is restored after the dialog // is finished. env->addFileOpenDialog(L"Please choose a file.", true, 0, -1, true); return true; default: return false; } break; case EGET_FILE_SELECTED: { // show the model filename, selected in the file dialog IGUIFileOpenDialog* dialog = (IGUIFileOpenDialog*)event.GUIEvent.Caller; Context.listbox->addItem(dialog->getFileName()); } break; default: break; } } return false; } private: SAppContext & Context; }; /* Ok, now for the more interesting part. First, create the Irrlicht device. As in some examples before, we ask the user which driver he wants to use for this example: */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device and exit if creation failed IrrlichtDevice * device = createDevice(driverType, core::dimension2d(640, 480)); if (device == 0) return 1; // could not create selected driver. /* The creation was successful, now we set the event receiver and store pointers to the driver and to the gui environment. */ device->setWindowCaption(L"Irrlicht Engine - User Interface Demo"); device->setResizable(true); video::IVideoDriver* driver = device->getVideoDriver(); IGUIEnvironment* env = device->getGUIEnvironment(); /* To make the font a little bit nicer, we load an external font and set it as the new default font in the skin. To keep the standard font for tool tip text, we set it to the built-in font. */ IGUISkin* skin = env->getSkin(); IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp"); if (font) skin->setFont(font); skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP); /* We add three buttons. The first one closes the engine. The second creates a window and the third opens a file open dialog. The third parameter is the id of the button, with which we can easily identify the button in the event receiver. */ env->addButton(rect(10,240,110,240 + 32), 0, GUI_ID_QUIT_BUTTON, L"Quit", L"Exits Program"); env->addButton(rect(10,280,110,280 + 32), 0, GUI_ID_NEW_WINDOW_BUTTON, L"New Window", L"Launches a new Window"); env->addButton(rect(10,320,110,320 + 32), 0, GUI_ID_FILE_OPEN_BUTTON, L"File Open", L"Opens a file"); /* Now, we add a static text and a scrollbar, which modifies the transparency of all gui elements. We set the maximum value of the scrollbar to 255, because that's the maximal value for a color value. Then we create an other static text and a list box. */ env->addStaticText(L"Transparent Control:", rect(150,20,350,40), true); IGUIScrollBar* scrollbar = env->addScrollBar(true, rect(150, 45, 350, 60), 0, GUI_ID_TRANSPARENCY_SCROLL_BAR); scrollbar->setMax(255); scrollbar->setPos(255); setSkinTransparency( scrollbar->getPos(), env->getSkin()); // set scrollbar position to alpha value of an arbitrary element scrollbar->setPos(env->getSkin()->getColor(EGDC_WINDOW).getAlpha()); env->addStaticText(L"Logging ListBox:", rect(50,110,250,130), true); IGUIListBox * listbox = env->addListBox(rect(50, 140, 250, 210)); env->addEditBox(L"Editable Text", rect(350, 80, 550, 100)); // Store the appropriate data in a context structure. SAppContext context; context.device = device; context.counter = 0; context.listbox = listbox; // Then create the event receiver, giving it that context structure. MyEventReceiver receiver(context); // And tell the device to use our custom event receiver. device->setEventReceiver(&receiver); /* And at last, we create a nice Irrlicht Engine logo in the top left corner. */ env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"), position2d(10,10)); /* That's all, we only have to draw everything. */ while(device->run() && driver) if (device->isWindowActive()) { driver->beginScene(true, true, SColor(0,200,200,200)); env->drawAll(); driver->endScene(); } device->drop(); return 0; } /* **/ irrlicht-1.8.3/examples/04.Movement/0000755000000000000000000000000012574354552015707 5ustar rootrootirrlicht-1.8.3/examples/04.Movement/tutorial.html0000644000000000000000000002411312574354552020441 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 4.Movement

This Tutorial shows how to move and animate SceneNodes. The basic concept of SceneNodeAnimators is shown as well as manual movement of nodes using the keyboard.

The program which is described here will look like this:



Lets start!

As always, I include the header files, use the irr namespace, and tell the linker to link with the .lib file.

#include <stdio.h>
#include <wchar.h>
#include <irrlicht.h>
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")

In this tutorial, one of our goals is to move a scene node using some keys on the keyboard. We store a pointer to the scene node we want to move with the keys here.
The other pointer is a pointer to the Irrlicht Device, which we need int the EventReceiver to manipulate the scene node and to get the active camera.

scene::ISceneNode* node = 0;
IrrlichtDevice* device = 0;

To get events like mouse and keyboard input, or GUI events like "the OK button has been clicked", we need an object wich is derived from the IEventReceiver object. There is only one method to override: OnEvent. This method will be called by the engine when an event happened. We will use this input to move the scene node with the keys W and S.

class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(const SEvent& event)
{

If the key 'W' or 'S' was left up, we get the position of the scene node, and modify the Y coordinate a little bit. So if you press 'W', the node moves up, and if you press 'S' it moves down.

if (node != 0 && event.EventType == irr::EET_KEY_INPUT_EVENT&&
!event.KeyInput.PressedDown)
{
switch(event.KeyInput.Key)
{
case KEY_KEY_W:
case KEY_KEY_S:
{
core::vector3df v = node->getPosition();
v.Y += event.KeyInput.Key == KEY_KEY_W ? 2.0f : -2.0f;
node->setPosition(v);
}
return true;
}
} return false;
}
};

The event receiver for moving a scene node is ready. So lets just create an Irrlicht Device and the scene node we want to move. We also create some other additional scene nodes, to show that there are also some different possibilities to move and animate scene nodes.

int main()
{
MyEventReceiver receiver; device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(640, 480), 16, false, false, false, &receiver);
   video::IVideoDriver* driver = device->getVideoDriver();
   scene::ISceneManager* smgr = device->getSceneManager();

Create the node for moving it with the 'W' and 'S' key. We create a sphere node, which is a built in geometric primitive scene node. We place the node at (0,0,30) and assign a texture to it to let it look a little bit more interesting.

node = smgr->addSphereSceneNode();
node->setPosition(core::vector3df(0,0,30));
node->setMaterialFlag(video::EMF_LIGHTING, false);
node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));

Now we create another node, moving using a scene node animator. Scene node animators modify scene nodes and can be attached to any scene node like
mesh scene nodes, billboards, lights and even camera scene nodes. Scene node animators are not only able to modify the position of a scene node, they can
also animate the textures of an object for example. We create a test scene node again an attach a 'fly circle' scene node to it, letting this node fly around our first test scene node.

scene::ISceneNode* n = smgr->addCubeSceneNode();
n->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg"));
n->setMaterialFlag(video::EMF_LIGHTING, false);
scene::ISceneNodeAnimator* anim = 
	smgr->createFlyCircleAnimator(core::vector3df(0,0,30), 20.0f);
n->addAnimator(anim);
anim->drop();

The last scene node we add to show possibilities of scene node animators is a md2 model, which uses a 'fly straight' animator to run between to points.

scene::IAnimatedMeshSceneNode* anms = smgr->addAnimatedMeshSceneNode(
smgr->getMesh("../../media/sydney.md2")); if (n)
{
anim = smgr->createFlyStraightAnimator(core::vector3df(100,0,60),
core::vector3df(-100,0,60), 10000, true);
anms->addAnimator(anim);
anim->drop();

To make to model look right we set the frames between which the animation should loop, rotate the model around 180 degrees, and adjust the animation speed and the texture.
To set the right animation (frames and speed), we would also be able to just call "anms->setMD2Animation(scene::EMAT_RUN)" for the 'run' animation instead of "setFrameLoop" and "setAnimationSpeed", but this only works with MD2 animations, and so you know how to start other animations.

   anms->setMaterialFlag(video::EMF_LIGHTING, false);
anms->setFrameLoop(320, 360); anms->setAnimationSpeed(30);
anms->setRotation(core::vector3df(0,180.0f,0));
anms->setMaterialTexture(0, driver->getTexture("../../media/sydney.bmp"));
}

To be able to look at and move around in this scene, we create a first person shooter style camera and make the mouse cursor invisible.

smgr->addCameraSceneNodeFPS(0, 100.0f, 100.0f);
device->getCursorControl()->setVisible(false);

We have done everything, so lets draw it. We also write the current frames per second and the name of the driver to the caption of the window.

int lastFPS = -1;
while(device->run())
{
     driver->beginScene(true, true, video::SColor(255,90,90,156));
     smgr->drawAll();
     driver->endScene();
     int fps = driver->getFPS();
     if (lastFPS != fps)
     {
        wchar_t tmp[1024];
        swprintf(tmp, 1024, L"Movement Example - Irrlicht Engine (%ls)(fps:%d)",
driver->getName(), fps);
       device->setWindowCaption(tmp);
       lastFPS = fps;
     }
}

device->drop();
return 0;
}

That's it. Compile and play around with the program.

 

 

irrlicht-1.8.3/examples/04.Movement/Movement_vc9.vcproj0000644000000000000000000001221412574354552021507 0ustar rootroot irrlicht-1.8.3/examples/04.Movement/Movement_vc8.vcproj0000644000000000000000000001211412574354552021505 0ustar rootroot irrlicht-1.8.3/examples/04.Movement/Movement_vc12.vcxproj0000644000000000000000000003272612574354552021763 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 04.Movement {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF} Movement Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Movement.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\04.Movement.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Movement.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\04.Movement.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Movement.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\04.Movement.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Movement.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\04.Movement.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/04.Movement/Movement_vc11.vcxproj0000644000000000000000000003272512574354552021761 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 04.Movement {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF} Movement Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Movement.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\04.Movement.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Movement.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\04.Movement.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Movement.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\04.Movement.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Movement.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\04.Movement.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/04.Movement/Movement_vc10.vcxproj0000644000000000000000000003272512574354552021760 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 04.Movement {7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF} Movement Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Movement.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\04.Movement.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Movement.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\04.Movement.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Movement.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\04.Movement.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Movement.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\04.Movement.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/04.Movement/Movement.vcproj0000644000000000000000000001052612574354552020732 0ustar rootroot irrlicht-1.8.3/examples/04.Movement/Movement.dev0000644000000000000000000000173612574354552020210 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 04 Movement UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=04.Movement.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/04.Movement/Movement.cbp0000644000000000000000000000266612574354552020201 0ustar rootroot irrlicht-1.8.3/examples/04.Movement/Makefile0000644000000000000000000000232712574354552017353 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 04.Movement Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32: CPPFLAGS += -D__GNUWIN32__ -D_WIN32 -DWIN32 -D_WINDOWS -D_MBCS -D_USRDLL all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/04.Movement/main.cpp0000644000000000000000000002011112574354552017332 0ustar rootroot/** Example 004 Movement This Tutorial shows how to move and animate SceneNodes. The basic concept of SceneNodeAnimators is shown as well as manual movement of nodes using the keyboard. We'll demonstrate framerate independent movement, which means moving by an amount dependent on the duration of the last run of the Irrlicht loop. Example 19.MouseAndJoystick shows how to handle those kinds of input. As always, I include the header files, use the irr namespace, and tell the linker to link with the .lib file. */ #ifdef _MSC_VER // We'll also define this to stop MSVC complaining about sprintf(). #define _CRT_SECURE_NO_WARNINGS #pragma comment(lib, "Irrlicht.lib") #endif #include #include "driverChoice.h" using namespace irr; /* To receive events like mouse and keyboard input, or GUI events like "the OK button has been clicked", we need an object which is derived from the irr::IEventReceiver object. There is only one method to override: irr::IEventReceiver::OnEvent(). This method will be called by the engine once when an event happens. What we really want to know is whether a key is being held down, and so we will remember the current state of each key. */ class MyEventReceiver : public IEventReceiver { public: // This is the one method that we have to implement virtual bool OnEvent(const SEvent& event) { // Remember whether each key is down or up if (event.EventType == irr::EET_KEY_INPUT_EVENT) KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; return false; } // This is used to check whether a key is being held down virtual bool IsKeyDown(EKEY_CODE keyCode) const { return KeyIsDown[keyCode]; } MyEventReceiver() { for (u32 i=0; i(640, 480), 16, false, false, false, &receiver); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); /* Create the node which will be moved with the WSAD keys. We create a sphere node, which is a built-in geometry primitive. We place the node at (0,0,30) and assign a texture to it to let it look a little bit more interesting. Because we have no dynamic lights in this scene we disable lighting for each model (otherwise the models would be black). */ scene::ISceneNode * node = smgr->addSphereSceneNode(); if (node) { node->setPosition(core::vector3df(0,0,30)); node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp")); node->setMaterialFlag(video::EMF_LIGHTING, false); } /* Now we create another node, movable using a scene node animator. Scene node animators modify scene nodes and can be attached to any scene node like mesh scene nodes, billboards, lights and even camera scene nodes. Scene node animators are not only able to modify the position of a scene node, they can also animate the textures of an object for example. We create a cube scene node and attach a 'fly circle' scene node animator to it, letting this node fly around our sphere scene node. */ scene::ISceneNode* n = smgr->addCubeSceneNode(); if (n) { n->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg")); n->setMaterialFlag(video::EMF_LIGHTING, false); scene::ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(core::vector3df(0,0,30), 20.0f); if (anim) { n->addAnimator(anim); anim->drop(); } } /* The last scene node we add to show possibilities of scene node animators is a b3d model, which uses a 'fly straight' animator to run between to points. */ scene::IAnimatedMeshSceneNode* anms = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/ninja.b3d")); if (anms) { scene::ISceneNodeAnimator* anim = smgr->createFlyStraightAnimator(core::vector3df(100,0,60), core::vector3df(-100,0,60), 3500, true); if (anim) { anms->addAnimator(anim); anim->drop(); } /* To make the model look right we disable lighting, set the frames between which the animation should loop, rotate the model around 180 degrees, and adjust the animation speed and the texture. To set the right animation (frames and speed), we would also be able to just call "anms->setMD2Animation(scene::EMAT_RUN)" for the 'run' animation instead of "setFrameLoop" and "setAnimationSpeed", but this only works with MD2 animations, and so you know how to start other animations. But a good advice is to not use hardcoded frame-numbers... */ anms->setMaterialFlag(video::EMF_LIGHTING, false); anms->setFrameLoop(0, 13); anms->setAnimationSpeed(15); // anms->setMD2Animation(scene::EMAT_RUN); anms->setScale(core::vector3df(2.f,2.f,2.f)); anms->setRotation(core::vector3df(0,-90,0)); // anms->setMaterialTexture(0, driver->getTexture("../../media/sydney.bmp")); } /* To be able to look at and move around in this scene, we create a first person shooter style camera and make the mouse cursor invisible. */ smgr->addCameraSceneNodeFPS(); device->getCursorControl()->setVisible(false); /* Add a colorful irrlicht logo */ device->getGUIEnvironment()->addImage( driver->getTexture("../../media/irrlichtlogoalpha2.tga"), core::position2d(10,20)); gui::IGUIStaticText* diagnostics = device->getGUIEnvironment()->addStaticText( L"", core::rect(10, 10, 400, 20)); diagnostics->setOverrideColor(video::SColor(255, 255, 255, 0)); /* We have done everything, so lets draw it. We also write the current frames per second and the name of the driver to the caption of the window. */ int lastFPS = -1; // In order to do framerate independent movement, we have to know // how long it was since the last frame u32 then = device->getTimer()->getTime(); // This is the movemen speed in units per second. const f32 MOVEMENT_SPEED = 5.f; while(device->run()) { // Work out a frame delta time. const u32 now = device->getTimer()->getTime(); const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds then = now; /* Check if keys W, S, A or D are being held down, and move the sphere node around respectively. */ core::vector3df nodePosition = node->getPosition(); if(receiver.IsKeyDown(irr::KEY_KEY_W)) nodePosition.Y += MOVEMENT_SPEED * frameDeltaTime; else if(receiver.IsKeyDown(irr::KEY_KEY_S)) nodePosition.Y -= MOVEMENT_SPEED * frameDeltaTime; if(receiver.IsKeyDown(irr::KEY_KEY_A)) nodePosition.X -= MOVEMENT_SPEED * frameDeltaTime; else if(receiver.IsKeyDown(irr::KEY_KEY_D)) nodePosition.X += MOVEMENT_SPEED * frameDeltaTime; node->setPosition(nodePosition); driver->beginScene(true, true, video::SColor(255,113,113,133)); smgr->drawAll(); // draw the 3d scene device->getGUIEnvironment()->drawAll(); // draw the gui environment (the logo) driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw tmp(L"Movement Example - Irrlicht Engine ["); tmp += driver->getName(); tmp += L"] fps: "; tmp += fps; device->setWindowCaption(tmp.c_str()); lastFPS = fps; } } /* In the end, delete the Irrlicht device. */ device->drop(); return 0; } /* That's it. Compile and play around with the program. **/ irrlicht-1.8.3/examples/03.CustomSceneNode/0000755000000000000000000000000012574354552017152 5ustar rootrootirrlicht-1.8.3/examples/03.CustomSceneNode/tutorial.html0000644000000000000000000002716012574354552021711 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 3.CustomSceneNode

This Tutorial is a tutorial for more advanced developers. If you are currently just playing around with the Irrlicht engine, please look at other examples first. This tutorial shows how to create a custom scene node and how to use it in the engine. A custom scene node is needed, if you want to implement a render technique, the Irrlicht Engine is currently not supporting. For example you can write a indoor portal based renderer or a advanced terrain scene node with it. With creating custom scene nodes, you can easily extend the Irrlicht Engine and adapt it to your needs.

I will keep the tutorial simple: Keep everything very short, everything in one .cpp file, and I'll use the engine here as in all other tutorials. At the end of the tutorial, the result will look like the image below. This looks not very exciting, but it is a complete customized scene node and a good point to start from creating you own scene nodes.



Lets start!

To start, I include the header files, use the irr namespace, and tell the linker to link with the .lib file.

#include <irrlicht.h>
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")

Here comes the most sophisticated part of this tutorial: The class of our very own custom scene node. To keep it simple,
our scene node will not be an indoor portal renderer nor a terrain scene node, but a simple tetraeder, a 3d object consiting of 4 connected vertices, which only draws itself and does nothing more.

To let our scene node be able to be inserted into the Irrlicht Engine scene, the class we create needs only be derived from the ISceneNode class and has to override some methods.

class CSampleSceneNode : public scene::ISceneNode
{

First, we declare some member variables, to hold data for our tetraeder: The bounding box, 4 vertices, and
the material of the tetraeder.

core::aabbox3d<f32> Box;
video::S3DVertex Vertices[4];
video::SMaterial Material;

The parameters of the constructor specify the parent of the scene node, a pointer to the scene manager, and an id of the scene node. In the constructor itself, we call the parent classes constructor, set some properties of the material we use to draw the scene node and create the 4 vertices of the tetraeder we will draw later.

public:
CSampleSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id)
 : scene::ISceneNode(parent, mgr, id)
{ 
  Material.Wireframe = false;
  Material.Lighting = false;
  Vertices[0] = video::S3DVertex(0,0,10, 1,1,0,video::SColor(255,0,255,255),0,1);
  Vertices[1] = video::S3DVertex(10,0,-10, 1,0,0,video::SColor(255,255,0,255),1,1); 
  Vertices[2] = video::S3DVertex(0,20,0, 0,1,1,video::SColor(255,255,255,0),1,0);
  Vertices[3] = video::S3DVertex(-10,0,-10, 0,0,1,video::SColor(255,0,255,0),0,0);

The Irrlicht Engine needs to know the bounding box of your scene node. It will use it for doing automatic culling and other things. Hence we need to create a bounding box from the 4 vertices we use. If you do not want the engine to use the box for automatic culling, and/or don't want to create the box, you could also write
AutomaticCullingEnabled = false;.

  Box.reset(Vertices[0].Pos);
for (s32 i=1; i<4; ++i)
Box.addInternalPoint(Vertices[i].Pos); }

Before it is drawn, the OnPreRender() method of every scene node in the scene is called by the scene manager. If the scene node wishes to draw itself, it may register itself in the scene manager to be drawn. This is necessary to tell the scene manager when it should call the ::render method. For example normal scene nodes render their content one after another, while stencil buffer shadows would like to be drawn after all other scene nodes. And camera or light scene nodes need to be rendered before all other scene nodes (if at all).
So here we simply register the scene node to get rendered normally. If we would like to let it be rendered like cameras or light, we would have to call SceneManager->registerNodeForRendering(this, SNRT_LIGHT_AND_CAMERA);
After this, we call the OnPreRender-method of the base class ISceneNode, which simply lets also all the child scene nodes of this node register themselves.

virtual void OnPreRender()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this); ISceneNode::OnPreRender(); }

In the render() method most of the interresting stuff happenes: The Scene node renders itself. We override this method and draw the tetraeder.

virtual void render()
{
u16 indices[] = { 0,2,3, 2,1,3, 1,0,3, 2,0,1 }; video::IVideoDriver* driver = SceneManager->getVideoDriver();
  driver->setMaterial(Material);
  driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
  driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 4);
}

At least, we create three small additional methods. GetBoundingBox() returns the bounding box of this scene node,
GetMaterialCount() returns the amount of materials in this scene node (our tetraeder only has one material), and getMaterial() returns the material at an index. Because we have only one material here, we can return the only one material, assuming that no one ever calls getMaterial() with an index greater than 0.

  virtual const core::aabbox3d<f32>& getBoundingBox() const
{
return Box;
}
  virtual u32 getMaterialCount()
  {
    return 1;
  }
  virtual video::SMaterial& getMaterial(u32 i)
  {
    return Material;
  } 
};

That's it. The Scene node is done. Now we simply have to start the engine, create the scene node and a camera, and look at the result.

int main()
{ IrrlichtDevice *device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(640, 480), 16, false);
  device->setWindowCaption(L"Custom Scene Node - Irrlicht Engine Demo");
  video::IVideoDriver* driver = device->getVideoDriver();
           scene::ISceneManager* smgr = device->getSceneManager();
  smgr->addCameraSceneNode(0, core::vector3df(0,-40,0), core::vector3df(0,0,0));
                   

Create our scene node. Note that it is dropped (->drop()) instantly after we create it. This is possible because the scene manager now takes care of it. This is not nessecary, it would also be possible to drop it at the end of the program.

CSampleSceneNode *myNode = 
new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666); myNode->drop();

To animate something in this boring scene consisting only of one tetraeder, and to show, that you now can use your scene node like any other scene node in the engine, we add an animator to the scene node, which rotates the node a little bit.

scene::ISceneNodeAnimator* anim = 
smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f)); myNode->addAnimator(anim); anim->drop();

Now draw everything and finish.

  while(device->run())
{
driver->beginScene(true, true, video::SColor(0,100,100,100)); smgr->drawAll(); driver->endScene(); } device->drop(); return 0; }

That's it. Compile and play around with the program.

 

irrlicht-1.8.3/examples/03.CustomSceneNode/Makefile0000644000000000000000000000221112574354552020606 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 03.CustomSceneNode Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 irrlicht-1.8.3/examples/03.CustomSceneNode/main.cpp0000644000000000000000000002151212574354552020603 0ustar rootroot/** Example 003 Custom SceneNode This Tutorial is more advanced than the previous ones. If you are currently just playing around with the Irrlicht engine, you may want to look at other examples first. This tutorials shows how to create a custom scene node and how to use it in the engine. A custom scene node is needed if you want to implement a render technique the Irrlicht Engine currently does not support. For example, you can write an indoor portal based renderer or an advanced terrain scene node with it. By creating custom scene nodes, you can easily extend the Irrlicht Engine and adapt it to your own needs. I will keep the tutorial simple: Keep everything very short, everything in one .cpp file, and I'll use the engine here as in all other tutorials. To start, I include the header files, use the irr namespace, and tell the linker to link with the .lib file. */ #include #include "driverChoice.h" using namespace irr; #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif /* Here comes the more sophisticated part of this tutorial: The class of our very own custom scene node. To keep it simple, our scene node will not be an indoor portal renderer nor a terrain scene node, but a simple tetraeder, a 3d object consisting of 4 connected vertices, which only draws itself and does nothing more. Note that this scenario does not require a custom scene node in Irrlicht. Instead one would create a mesh from the geometry and pass it to a irr::scene::IMeshSceneNode. This example just illustrates creation of a custom scene node in a very simple setting. To let our scene node be able to be inserted into the Irrlicht Engine scene, the class we create needs to be derived from the irr::scene::ISceneNode class and has to override some methods. */ class CSampleSceneNode : public scene::ISceneNode { /* First, we declare some member variables: The bounding box, 4 vertices, and the material of the tetraeder. */ core::aabbox3d Box; video::S3DVertex Vertices[4]; video::SMaterial Material; /* The parameters of the constructor specify the parent of the scene node, a pointer to the scene manager, and an id of the scene node. In the constructor we call the parent class' constructor, set some properties of the material, and create the 4 vertices of the tetraeder we will draw later. */ public: CSampleSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id) : scene::ISceneNode(parent, mgr, id) { Material.Wireframe = false; Material.Lighting = false; Vertices[0] = video::S3DVertex(0,0,10, 1,1,0, video::SColor(255,0,255,255), 0, 1); Vertices[1] = video::S3DVertex(10,0,-10, 1,0,0, video::SColor(255,255,0,255), 1, 1); Vertices[2] = video::S3DVertex(0,20,0, 0,1,1, video::SColor(255,255,255,0), 1, 0); Vertices[3] = video::S3DVertex(-10,0,-10, 0,0,1, video::SColor(255,0,255,0), 0, 0); /* The Irrlicht Engine needs to know the bounding box of a scene node. It will use it for automatic culling and other things. Hence, we need to create a bounding box from the 4 vertices we use. If you do not want the engine to use the box for automatic culling, and/or don't want to create the box, you could also call irr::scene::ISceneNode::setAutomaticCulling() with irr::scene::EAC_OFF. */ Box.reset(Vertices[0].Pos); for (s32 i=1; i<4; ++i) Box.addInternalPoint(Vertices[i].Pos); } /* Before it is drawn, the irr::scene::ISceneNode::OnRegisterSceneNode() method of every scene node in the scene is called by the scene manager. If the scene node wishes to draw itself, it may register itself in the scene manager to be drawn. This is necessary to tell the scene manager when it should call irr::scene::ISceneNode::render(). For example, normal scene nodes render their content one after another, while stencil buffer shadows would like to be drawn after all other scene nodes. And camera or light scene nodes need to be rendered before all other scene nodes (if at all). So here we simply register the scene node to render normally. If we would like to let it be rendered like cameras or light, we would have to call SceneManager->registerNodeForRendering(this, SNRT_LIGHT_AND_CAMERA); After this, we call the actual irr::scene::ISceneNode::OnRegisterSceneNode() method of the base class, which simply lets also all the child scene nodes of this node register themselves. */ virtual void OnRegisterSceneNode() { if (IsVisible) SceneManager->registerNodeForRendering(this); ISceneNode::OnRegisterSceneNode(); } /* In the render() method most of the interesting stuff happens: The Scene node renders itself. We override this method and draw the tetraeder. */ virtual void render() { u16 indices[] = { 0,2,3, 2,1,3, 1,0,3, 2,0,1 }; video::IVideoDriver* driver = SceneManager->getVideoDriver(); driver->setMaterial(Material); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); driver->drawVertexPrimitiveList(&Vertices[0], 4, &indices[0], 4, video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT); } /* And finally we create three small additional methods. irr::scene::ISceneNode::getBoundingBox() returns the bounding box of this scene node, irr::scene::ISceneNode::getMaterialCount() returns the amount of materials in this scene node (our tetraeder only has one material), and irr::scene::ISceneNode::getMaterial() returns the material at an index. Because we have only one material here, we can return the only one material, assuming that no one ever calls getMaterial() with an index greater than 0. */ virtual const core::aabbox3d& getBoundingBox() const { return Box; } virtual u32 getMaterialCount() const { return 1; } virtual video::SMaterial& getMaterial(u32 i) { return Material; } }; /* That's it. The Scene node is done. Now we simply have to start the engine, create the scene node and a camera, and look at the result. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device IrrlichtDevice *device = createDevice(driverType, core::dimension2d(640, 480), 16, false); if (device == 0) return 1; // could not create selected driver. // create engine and camera device->setWindowCaption(L"Custom Scene Node - Irrlicht Engine Demo"); video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); smgr->addCameraSceneNode(0, core::vector3df(0,-40,0), core::vector3df(0,0,0)); /* Create our scene node. I don't check the result of calling new, as it should throw an exception rather than returning 0 on failure. Because the new node will create itself with a reference count of 1, and then will have another reference added by its parent scene node when it is added to the scene, I need to drop my reference to it. Best practice is to drop it only *after* I have finished using it, regardless of what the reference count of the object is after creation. */ CSampleSceneNode *myNode = new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666); /* To animate something in this boring scene consisting only of one tetraeder, and to show that you now can use your scene node like any other scene node in the engine, we add an animator to the scene node, which rotates the node a little bit. irr::scene::ISceneManager::createRotationAnimator() could return 0, so should be checked. */ scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f)); if(anim) { myNode->addAnimator(anim); /* I'm done referring to anim, so must irr::IReferenceCounted::drop() this reference now because it was produced by a createFoo() function. As I shouldn't refer to it again, ensure that I can't by setting to 0. */ anim->drop(); anim = 0; } /* I'm done with my CSampleSceneNode object, and so must drop my reference. This won't delete the object, yet, because it is still attached to the scene graph, which prevents the deletion until the graph is deleted or the custom scene node is removed from it. */ myNode->drop(); myNode = 0; // As I shouldn't refer to it again, ensure that I can't /* Now draw everything and finish. */ u32 frames=0; while(device->run()) { driver->beginScene(true, true, video::SColor(0,100,100,100)); smgr->drawAll(); driver->endScene(); if (++frames==100) { core::stringw str = L"Irrlicht Engine ["; str += driver->getName(); str += L"] FPS: "; str += (s32)driver->getFPS(); device->setWindowCaption(str.c_str()); frames=0; } } device->drop(); return 0; } /* That's it. Compile and play around with the program. **/ irrlicht-1.8.3/examples/03.CustomSceneNode/CustomSceneNode_vc9.vcproj0000644000000000000000000001232212574354552024216 0ustar rootroot irrlicht-1.8.3/examples/03.CustomSceneNode/CustomSceneNode_vc8.vcproj0000644000000000000000000001222212574354552024214 0ustar rootroot irrlicht-1.8.3/examples/03.CustomSceneNode/CustomSceneNode_vc12.vcxproj0000644000000000000000000003456212574354552024472 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 03.CustomSceneNode {171CCDFA-C140-4956-8EB7-F0168F4521D3} CustomSceneNode Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/CustomSceneNode.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\03.CustomSceneNode.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/CustomSceneNode.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\03.CustomSceneNode.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/CustomSceneNode.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true .\Release/CustomSceneNode.pch .\Release/ .\Release/ .\Release/ Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\03.CustomSceneNode.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) .\Release/CustomSceneNode.pdb Console false .\Release/CustomSceneNode.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true .\Release/CustomSceneNode.pch .\Release/ .\Release/ .\Release/ Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\03.CustomSceneNode.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) .\Release/CustomSceneNode.pdb Console false Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/03.CustomSceneNode/CustomSceneNode_vc11.vcxproj0000644000000000000000000003456112574354552024470 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 03.CustomSceneNode {171CCDFA-C140-4956-8EB7-F0168F4521D3} CustomSceneNode Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/CustomSceneNode.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\03.CustomSceneNode.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/CustomSceneNode.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\03.CustomSceneNode.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/CustomSceneNode.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true .\Release/CustomSceneNode.pch .\Release/ .\Release/ .\Release/ Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\03.CustomSceneNode.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) .\Release/CustomSceneNode.pdb Console false .\Release/CustomSceneNode.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true .\Release/CustomSceneNode.pch .\Release/ .\Release/ .\Release/ Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\03.CustomSceneNode.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) .\Release/CustomSceneNode.pdb Console false Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/03.CustomSceneNode/CustomSceneNode_vc10.vcxproj0000644000000000000000000003456112574354552024467 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 03.CustomSceneNode {171CCDFA-C140-4956-8EB7-F0168F4521D3} CustomSceneNode Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/CustomSceneNode.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\03.CustomSceneNode.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/CustomSceneNode.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\03.CustomSceneNode.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/CustomSceneNode.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true .\Release/CustomSceneNode.pch .\Release/ .\Release/ .\Release/ Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\03.CustomSceneNode.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) .\Release/CustomSceneNode.pdb Console false .\Release/CustomSceneNode.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true .\Release/CustomSceneNode.pch .\Release/ .\Release/ .\Release/ Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\03.CustomSceneNode.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) .\Release/CustomSceneNode.pdb Console false Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/03.CustomSceneNode/CustomSceneNode.vcproj0000644000000000000000000001062512574354552023441 0ustar rootroot irrlicht-1.8.3/examples/03.CustomSceneNode/CustomSceneNode.dev0000644000000000000000000000175612574354552022721 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 03 Custom Scene Node UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=03.CustomSceneNode.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/03.CustomSceneNode/CustomSceneNode.cbp0000644000000000000000000000311512574354552022676 0ustar rootroot irrlicht-1.8.3/examples/02.Quake3Map/0000755000000000000000000000000012574354552015702 5ustar rootrootirrlicht-1.8.3/examples/02.Quake3Map/tutorial.html0000644000000000000000000002564212574354552020444 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 2.Quake3Map

This Tutorial shows how to load a Quake 3 map into the engine, create a SceneNode for optimizing the speed of rendering and how to create a user controlled camera. Please note that you should know the basics of the engine before starting this tutorial, just take a short look at the first tutorial, 1.HelloWorld, if you haven't done this yet.
The result of this example will look like this:



Lets start!

Lets start like the HelloWorld example: We include the irrlicht header files and an additional file to be able
to ask the user for a driver type using the console.

#include <irrlicht.h>
#include <iostream>

As already written in the HelloWorld example, in the Irrlicht Engine, everything can be found in the namespace 'irr'. To get rid of the irr:: in front of the name of every class, we tell the compiler that we use that namespace from now on, and we will not have to write that 'irr::'.
There are 5 other sub namespaces 'core', 'scene', 'video', 'io' and 'gui'. Unlike in the HelloWorld example, we do not a 'using namespace' for these 5 other namespaces because in this way you will see what can be found in which namespace. But if you like, you can also include the namespaces like in the previous example. Code just like you want to.

using namespace irr;

Again, to be able to use the Irrlicht.DLL file, we need to link with the Irrlicht.lib. We could set this option in the project settings, but to make it easy, we use a pragma comment lib:

#pragma comment(lib, "Irrlicht.lib")

Ok, lets start. Again, we use the main() method as start, not the WinMain(), because its shorter to write.

int main()
{

Like in the HelloWorld example, we create an IrrlichtDevice with createDevice(). The difference now is that we ask the user to select which hardware accelerated driver to use. The Software device would be too slow to draw a huge Quake 3 map, but just for the fun of it, we make this decision possible too.

// ask user for driver

video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;

printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");
char i;
std::cin >> i;

switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 1;
}

// create device and exit if creation failed

IrrlichtDevice *device =
createDevice(driverType, core::dimension2d<s32>(640, 480));

if (device == 0)
return 1;

Get a pointer to the video driver and the SceneManager so that we do not always have to write device->getVideoDriver() and device->getSceneManager().

video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();

To display the Quake 3 map, we first need to load it. Quake 3 maps are packed into .pk3 files wich are nothing other than .zip files. So we add the .pk3 file to our FileSystem. After it was added, we are able to read from the files in that archive as they would directly be stored on disk.

device->getFileSystem()->addZipFileArchive("../../media/map-20kdm2.pk3");

Now we can load the mesh by calling getMesh(). We get a pointer returned to a IAnimatedMesh. As you know, Quake 3 maps are not really animated, they are only a huge chunk of static geometry with some materials attached. Hence the IAnimated mesh consists of only one frame,
so we get the "first frame" of the "animation", which is our quake level and create an OctTree scene node with it, using addOctTreeSceneNode(). The OctTree optimizes the scene a little bit, trying to draw only geometry which is currently visible. An alternative to the OctTree would be a AnimatedMeshSceneNode, which would draw always the complete geometry of the mesh, without optimization. Try it out: Write addAnimatedMeshSceneNode instead of addOctTreeSceneNode and compare the primitives drawed by the video driver. (There is a getPrimitiveCountDrawed() method in the IVideoDriver class). Note that this optimization with the Octree is only useful when drawing huge meshes consiting of lots of geometry.

scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp");
scene::ISceneNode* node = 0; if (mesh)
node = smgr->addOctTreeSceneNode(mesh->getMesh(0));

Because the level was modelled not around the origin (0,0,0), we translate the whole level a little bit.

if (node)
node->setPosition(core::vector3df(-1300,-144,-1249));

Now we only need a Camera to look at the Quake 3 map. And we want to create a user controlled camera. There are some different cameras available in the Irrlicht engine. For example the Maya Camera which can be controlled compareable to the camera in Maya: Rotate with left mouse button pressed, Zoom with both buttons pressed,
translate with right mouse button pressed. This could be created with addCameraSceneNodeMaya(). But for this example, we want to create a camera which behaves like the ones in first person shooter games (FPS):

smgr->addCameraSceneNodeFPS();

The mouse cursor needs not to be visible, so we make it invisible.

device->getCursorControl()->setVisible(false);

We have done everything, so lets draw it. We also write the current frames per second and the drawn primitives to the caption of the window. The 'if (device->isWindowActive())' line is optional, but prevents the engine render to set the position of the mouse cursor after task switching when other program are active.

int lastFPS = -1;
while(device->run())
{
  driver->beginScene(true, true, video::SColor(0,200,200,200));
  smgr->drawAll();
  driver->endScene();
  int fps = driver->getFPS();
  if (lastFPS != fps)
  {
     core::stringw str = L"Irrlicht Engine - Quake 3 Map example [";
str += driver->getName();
str += "] FPS:";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps; } }

In the end, delete the Irrlicht device.

  device->drop();
return 0;
}

That's it. Compile and play around with the program.

 

 

irrlicht-1.8.3/examples/02.Quake3Map/Quake3Map_vc9.vcproj0000644000000000000000000001222612574354552021502 0ustar rootroot irrlicht-1.8.3/examples/02.Quake3Map/Quake3Map_vc8.vcproj0000644000000000000000000001212612574354552021500 0ustar rootroot irrlicht-1.8.3/examples/02.Quake3Map/Quake3Map_vc12.vcxproj0000644000000000000000000003274012574354552021747 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 02.Quake3Map {D1A464A2-D479-458C-98A2-60965D823CD1} Quake3Map Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Quake3Map.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\02.Quake3Map.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Quake3Map.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\02.Quake3Map.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Quake3Map.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\02.Quake3Map.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Quake3Map.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\02.Quake3Map.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/02.Quake3Map/Quake3Map_vc11.vcxproj0000644000000000000000000003273712574354552021754 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 02.Quake3Map {D1A464A2-D479-458C-98A2-60965D823CD1} Quake3Map Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Quake3Map.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\02.Quake3Map.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Quake3Map.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\02.Quake3Map.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Quake3Map.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\02.Quake3Map.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Quake3Map.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\02.Quake3Map.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/02.Quake3Map/Quake3Map_vc10.vcxproj0000644000000000000000000003273712574354552021753 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 02.Quake3Map {D1A464A2-D479-458C-98A2-60965D823CD1} Quake3Map Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/Quake3Map.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\02.Quake3Map.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/Quake3Map.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\02.Quake3Map.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/Quake3Map.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\02.Quake3Map.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/Quake3Map.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\02.Quake3Map.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/02.Quake3Map/Quake3Map.vcproj0000644000000000000000000001045012574354552020716 0ustar rootroot irrlicht-1.8.3/examples/02.Quake3Map/Quake3Map.dev0000644000000000000000000000174012574354552020173 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 02 Quake3Map UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput=obj OverrideOutput=1 OverrideOutputName=02.Quake3Map.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/02.Quake3Map/Quake3Map.cbp0000644000000000000000000000264612574354552020167 0ustar rootroot irrlicht-1.8.3/examples/02.Quake3Map/Makefile0000644000000000000000000000243012574354552017341 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler Target = 02.Quake3Map Sources = main.cpp # general compiler settings CPPFLAGS = -I../../include -I/usr/X11R6/include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall #default target is Linux all: all_linux ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif # target specific settings all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht static_win32: LDFLAGS += -lgdi32 -lopengl32 -ld3dx9d -lwinmm -lm static_win32: CPPFLAGS += -D_IRR_STATIC_LIB_ static_win32 all_win32 clean_win32: SYSTEM=Win32-gcc static_win32 all_win32 clean_win32: SUF=.exe # name of the binary - only valid for targets which set SYSTEM DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) all_linux all_win32 static_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 clean clean_linux clean_win32 static_win32 irrlicht-1.8.3/examples/02.Quake3Map/main.cpp0000644000000000000000000001651012574354552017335 0ustar rootroot/** Example 002 Quake3Map This Tutorial shows how to load a Quake 3 map into the engine, create a SceneNode for optimizing the speed of rendering, and how to create a user controlled camera. Please note that you should know the basics of the engine before starting this tutorial. Just take a short look at the first tutorial, if you haven't done this yet: http://irrlicht.sourceforge.net/tut001.html Lets start like the HelloWorld example: We include the irrlicht header files and an additional file to be able to ask the user for a driver type using the console. */ #include #include /* As already written in the HelloWorld example, in the Irrlicht Engine everything can be found in the namespace 'irr'. To get rid of the irr:: in front of the name of every class, we tell the compiler that we use that namespace from now on, and we will not have to write that 'irr::'. There are 5 other sub namespaces 'core', 'scene', 'video', 'io' and 'gui'. Unlike in the HelloWorld example, we do not call 'using namespace' for these 5 other namespaces, because in this way you will see what can be found in which namespace. But if you like, you can also include the namespaces like in the previous example. */ using namespace irr; /* Again, to be able to use the Irrlicht.DLL file, we need to link with the Irrlicht.lib. We could set this option in the project settings, but to make it easy, we use a pragma comment lib: */ #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #endif /* Ok, lets start. Again, we use the main() method as start, not the WinMain(). */ int main() { /* Like in the HelloWorld example, we create an IrrlichtDevice with createDevice(). The difference now is that we ask the user to select which video driver to use. The Software device might be too slow to draw a huge Quake 3 map, but just for the fun of it, we make this decision possible, too. Instead of copying this whole code into your app, you can simply include driverChoice.h from Irrlicht's include directory. The function driverChoiceConsole does exactly the same. */ // ask user for driver video::E_DRIVER_TYPE driverType; printf("Please select the driver you want for this example:\n"\ " (a) OpenGL 1.5\n (b) Direct3D 9.0c\n (c) Direct3D 8.1\n"\ " (d) Burning's Software Renderer\n (e) Software Renderer\n"\ " (f) NullDevice\n (otherKey) exit\n\n"); char i; std::cin >> i; switch(i) { case 'a': driverType = video::EDT_OPENGL; break; case 'b': driverType = video::EDT_DIRECT3D9;break; case 'c': driverType = video::EDT_DIRECT3D8;break; case 'd': driverType = video::EDT_BURNINGSVIDEO;break; case 'e': driverType = video::EDT_SOFTWARE; break; case 'f': driverType = video::EDT_NULL; break; default: return 1; } // create device and exit if creation failed IrrlichtDevice *device = createDevice(driverType, core::dimension2d(640, 480)); if (device == 0) return 1; // could not create selected driver. /* Get a pointer to the video driver and the SceneManager so that we do not always have to call irr::IrrlichtDevice::getVideoDriver() and irr::IrrlichtDevice::getSceneManager(). */ video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); /* To display the Quake 3 map, we first need to load it. Quake 3 maps are packed into .pk3 files which are nothing else than .zip files. So we add the .pk3 file to our irr::io::IFileSystem. After it was added, we are able to read from the files in that archive as if they are directly stored on the disk. */ device->getFileSystem()->addFileArchive("../../media/map-20kdm2.pk3"); /* Now we can load the mesh by calling irr::scene::ISceneManager::getMesh(). We get a pointer returned to an irr::scene::IAnimatedMesh. As you might know, Quake 3 maps are not really animated, they are only a huge chunk of static geometry with some materials attached. Hence the IAnimatedMesh consists of only one frame, so we get the "first frame" of the "animation", which is our quake level and create an Octree scene node with it, using irr::scene::ISceneManager::addOctreeSceneNode(). The Octree optimizes the scene a little bit, trying to draw only geometry which is currently visible. An alternative to the Octree would be a irr::scene::IMeshSceneNode, which would always draw the complete geometry of the mesh, without optimization. Try it: Use irr::scene::ISceneManager::addMeshSceneNode() instead of addOctreeSceneNode() and compare the primitives drawn by the video driver. (There is a irr::video::IVideoDriver::getPrimitiveCountDrawn() method in the irr::video::IVideoDriver class). Note that this optimization with the Octree is only useful when drawing huge meshes consisting of lots of geometry. */ scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp"); scene::ISceneNode* node = 0; if (mesh) node = smgr->addOctreeSceneNode(mesh->getMesh(0), 0, -1, 1024); // node = smgr->addMeshSceneNode(mesh->getMesh(0)); /* Because the level was not modelled around the origin (0,0,0), we translate the whole level a little bit. This is done on irr::scene::ISceneNode level using the methods irr::scene::ISceneNode::setPosition() (in this case), irr::scene::ISceneNode::setRotation(), and irr::scene::ISceneNode::setScale(). */ if (node) node->setPosition(core::vector3df(-1300,-144,-1249)); /* Now we only need a camera to look at the Quake 3 map. We want to create a user controlled camera. There are some cameras available in the Irrlicht engine. For example the MayaCamera which can be controlled like the camera in Maya: Rotate with left mouse button pressed, Zoom with both buttons pressed, translate with right mouse button pressed. This could be created with irr::scene::ISceneManager::addCameraSceneNodeMaya(). But for this example, we want to create a camera which behaves like the ones in first person shooter games (FPS) and hence use irr::scene::ISceneManager::addCameraSceneNodeFPS(). */ smgr->addCameraSceneNodeFPS(); /* The mouse cursor needs not be visible, so we hide it via the irr::IrrlichtDevice::ICursorControl. */ device->getCursorControl()->setVisible(false); /* We have done everything, so lets draw it. We also write the current frames per second and the primitives drawn into the caption of the window. The test for irr::IrrlichtDevice::isWindowActive() is optional, but prevents the engine to grab the mouse cursor after task switching when other programs are active. The call to irr::IrrlichtDevice::yield() will avoid the busy loop to eat up all CPU cycles when the window is not active. */ int lastFPS = -1; while(device->run()) { if (device->isWindowActive()) { driver->beginScene(true, true, video::SColor(255,200,200,200)); smgr->drawAll(); driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Irrlicht Engine - Quake 3 Map example ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } else device->yield(); } /* In the end, delete the Irrlicht device. */ device->drop(); return 0; } /* That's it. Compile and play around with the program. **/ irrlicht-1.8.3/examples/01.HelloWorld/0000755000000000000000000000000012574354552016165 5ustar rootrootirrlicht-1.8.3/examples/01.HelloWorld/tutorial.html0000644000000000000000000005620712574354552020730 0ustar rootroot Irrlicht Engine Tutorial
Tutorial 1.HelloWorld

This Tutorial shows how to set up the IDE for using the Irrlicht Engine and how to write a simple HelloWorld program with it. The program will show how to use the basics of the VideoDriver, the GUIEnvironment and the SceneManager.
The result of this example will look like this:



Setting up the IDE

To use the engine, we will have to include the header file <irrlicht.h>, which can be found in the Irrlicht Engine SDK directory \include. To let the compiler find this header file, the directory where it is located should be specified somewhere. This is different for every IDE and compiler. I will explain how to do this in Microsoft Visual Studio C++ 6.0 and .NET:

  • If you use Version 6.0, select the Menu Extras -> Options. Select the directories tab, and select the 'Include' Item in the combo box. Add the \include directory of the Irrlicht Engine folder to the list of directories. Now the compiler will find the Irrlicht.h header file. We also need the location of irrlicht.lib to be listed, so select the 'Libraries' tab and add the \lib\VisualStudio directory.

      
     
  • If your IDE is Visual Studio .NET, select Tools -> Options. Select the Projects entry and then select VC++ directories. Select 'show directories for include files' in the combo box, and add the \include directory of the Irrlicht Engine folder to the list of directories so the compiler will find the Irrlicht.h header file. We also need the irrlicht.lib to be found, so select 'show directories for Library files' and add the \lib\VisualStudio directory.


 


Lets start!

After we have set up the IDE, the compiler will know where to find the Irrlicht Engine header files so we can include it now into our code.

#include <irrlicht.h>

In the Irrlicht Engine, everything can be found in the namespace 'irr'. So if you want to use a class of the engine, you'll have to type an irr:: before the name of the class. For example, to use the IrrlichtDevice, write: irr::IrrlichtDevice. To avoid having to put irr:: before of the name of every class, we tell the compiler that we use that namespace.

using namespace irr;

There are 5 sub-namespaces in the Irrlicht Engine. Take a look at them: you can read a detailed description of them in the documentation by clicking on the top menu item 'Namespace List'. To keep this example simple, we don't want to have to specify the name spaces, Hence:

using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

To be able to use the Irrlicht.DLL file, we need to link with the Irrlicht.lib. We could set this option in the project settings, but to make it easy we use a pragma comment:

#pragma comment(lib, "Irrlicht.lib")

Now the main method: to keep this example simple we use int main(), which can be used on any platform. However, on Windows platforms, we could also use the WinMain method if we would want to get rid of the console window which pops up when starting a program with main().

int main()
{

The most important function of the engine is the 'createDevice' function. The Irrlicht Device, which is the root object for doing everything with the engine, can be created with it. createDevice() has 7 parameters:

  • deviceType: Type of the device. This can currently be the Null device, the Software device, Direct3D8, Direct3D9, or OpenGL. In this example we use EDT_SOFTWARE, but, to try them out, you might want to change it to EDT_NULL, EDT_DIRECT3D8, EDT_DIRECT3D9 or EDT_OPENGL.
  • windowSize: Size of the window or full screen mode to be created. In this example we use 512x384.
  • bits: Number of bits per pixel when in full screen mode. This should be 16 or 32. This parameter is ignored when running in windowed mode.
  • fullscreen: Specifies if we want the device to run in full screen mode or not.
  • stencilbuffer: Specifies if we want to use the stencil buffer for drawing shadows.
  • vsync: Specifies if we want to have vsync enabled. This is only useful in full screen mode.
  • eventReceiver: An object to receive events. We do not want to use this parameter here, and set it to 0.
IrrlichtDevice *device =
createDevice(EDT_SOFTWARE, dimension2d<s32>(512, 384), 16,
false, false, false, 0);

Now we set the caption of the window to some nice text. Note that there is a 'L' in front of the string: the Irrlicht Engine uses wide character strings when displaying text.

device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo");

Now we store a pointer to the video driver, the SceneManager, and the graphical user interface environment so that we do not always have to write device->getVideoDriver(), device->getSceneManager(), and device->getGUIEnvironment().

IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();

We add a hello world label to the window using the GUI environment. The text is placed at the position (10,10) as top left corner and (200,22) as lower right corner.

guienv->addStaticText(L"Hello World! This is the Irrlicht Software engine!",
rect<s32>(10,10,200,22), true);

To display something interesting, we load a Quake 2 model and display it. We only have to get the Mesh from the Scene Manager with getMesh() and add a SceneNode to display the mesh with addAnimatedMeshSceneNode(). Instead of loading a Quake2 file (.md2), it is also possible to load a Maya object file (.obj), a complete Quake3 map (.bsp), or a Milshape file (.ms3d).
By the way, that cool Quake 2 model called sydney.md2 was modelled by Brian Collins.

IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2");
IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh );

To make the mesh look a little bit nicer, we change its material a little bit: we disable lighting because we do not have a dynamic light in here and the mesh would be totally black. Then we set the frame loop so that the animation is looped between the frames 0 and 310. Then, at last, we apply a texture to the mesh. Without it the mesh would be drawn using only a solid color.

if (node)
{
node->setMaterialFlag(EMF_LIGHTING, false);
node->setFrameLoop(0, 310);
node->setMaterialTexture( 0, driver->getTexture("../../media/sydney.bmp") );
}

To look at the mesh, we place a camera into 3d space at the position (0, 10, -40). The camera looks from there to (0,5,0).

smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0));

Ok. Now that we have set up the scene, let's draw everything: we run the device in a while() loop until the device does not want to run any more. This would be when the user closes the window or presses ALT+F4 in Windows.

while(device->run())
{

Everything must be drawn between a beginScene() and an endScene() call. The beginScene clears the screen with a color and also the depth buffer, if desired. Then we let the Scene Manager and the GUI environment draw their content. With the endScene() call, everything is presented on the screen.

	driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll(); guienv->drawAll();
	driver->endScene();
}

After we are finished, we have to delete the Irrlicht Device created earlier with createDevice(). With the Irrlicht Engine, you should delete all objects you created with a method or function that starts with 'create'. The object is deleted simply by calling ->drop(). See the documentation for more information.

	device->drop();
return 0; }

That's it. Compile and run.

 


Possible Errors or Problems

Visual Studio
While trying to compile the tutorial, if you get the error:

fatal error C1083: Cannot open include file: 'irrlicht.h': No such file or directory

Solution: You may have set the include directory improperly in the Visual Studio options. See above for information on setting it.

LINK : LNK6004: HelloWorld.exe not found or not built by the last incremental link; performing full link
LINK : fatal error LNK1104: cannot open file "Irrlicht.lib"
Error executing link.exe

Solution: You may have set the library directory improperly. See above for information on setting it.

Compiler independent problems
If the tutorial compiles successfully but gives the error:

This application has failed to start because Irrlicht.dll was not found. Re-installing the application may fix this problem

Solution: You may have forgotten to copy the Irrlicht.dll file from Irrlicht\bin\VisualStudio to the directory the tutorial's project file is in.

If the tutorial compiles and runs successfully but produces errors in the console like:

Could not load mesh, because file could not be opened.: ../media/sydney.md2

Or:

Could not open file of texture: stones.jpg
Could not load texture: stones.jpg

Solution: The file listed in the error message cannot be found. Ensure that the directory specified in the main.cpp exists and is where the file is located.

 

irrlicht-1.8.3/examples/01.HelloWorld/Makefile0000644000000000000000000000425412574354552017632 0ustar rootroot# Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler # Name of the executable created (.exe will be added automatically if necessary) Target := 01.HelloWorld # List of source files, separated by spaces Sources := main.cpp # Path to Irrlicht directory, should contain include/ and lib/ IrrlichtHome := ../.. # Path for the executable. Note that Irrlicht.dll should usually also be there for win32 systems BinPath = ../../bin/$(SYSTEM) # general compiler settings (might need to be set when compiling the lib, too) # preprocessor flags, e.g. defines and include paths USERCPPFLAGS = # compiler flags such as optimization flags USERCXXFLAGS = -O3 -ffast-math #USERCXXFLAGS = -g -Wall # linker flags such as additional libraries and link paths USERLDFLAGS = #### #no changes necessary below this line #### CPPFLAGS = -I$(IrrlichtHome)/include -I/usr/X11R6/include $(USERCPPFLAGS) CXXFLAGS = $(USERCXXFLAGS) LDFLAGS = $(USERLDFLAGS) #default target is Linux all: all_linux # target specific settings all_linux all_win32 static_win32: LDFLAGS += -L$(IrrlichtHome)/lib/$(SYSTEM) -lIrrlicht all_linux: LDFLAGS += -L/usr/X11R6/lib$(LIBSELECT) -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux clean_linux: SYSTEM=Linux all_win32 clean_win32 static_win32: SYSTEM=Win32-gcc all_win32 clean_win32 static_win32: SUF=.exe static_win32: CPPFLAGS += -D_IRR_STATIC_LIB_ all_win32: LDFLAGS += -lopengl32 -lm static_win32: LDFLAGS += -lgdi32 -lwinspool -lcomdlg32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -lopengl32 # name of the binary - only valid for targets which set SYSTEM DESTPATH = $(BinPath)/$(Target)$(SUF) all_linux all_win32 static_win32: $(warning Building...) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) clean: clean_linux clean_win32 $(warning Cleaning...) clean_linux clean_win32: @$(RM) $(DESTPATH) .PHONY: all all_win32 static_win32 clean clean_linux clean_win32 #multilib handling ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif #solaris real-time features ifeq ($(HOSTTYPE), sun4) LDFLAGS += -lrt endif irrlicht-1.8.3/examples/01.HelloWorld/main.cpp0000644000000000000000000002173312574354552017623 0ustar rootroot/** Example 001 HelloWorld This Tutorial shows how to set up the IDE for using the Irrlicht Engine and how to write a simple HelloWorld program with it. The program will show how to use the basics of the VideoDriver, the GUIEnvironment, and the SceneManager. Microsoft Visual Studio is used as an IDE, but you will also be able to understand everything if you are using a different one or even another operating system than windows. You have to include the header file in order to use the engine. The header file can be found in the Irrlicht Engine SDK directory \c include. To let the compiler find this header file, the directory where it is located has to be specified. This is different for every IDE and compiler you use. Let's explain shortly how to do this in Microsoft Visual Studio: - If you use Version 6.0, select the Menu Extras -> Options. Select the directories tab, and select the 'Include' Item in the combo box. Add the \c include directory of the irrlicht engine folder to the list of directories. Now the compiler will find the Irrlicht.h header file. We also need the irrlicht.lib to be found, so stay in that dialog, select 'Libraries' in the combo box and add the \c lib/VisualStudio directory. \image html "vc6optionsdir.jpg" \image latex "vc6optionsdir.jpg" \image html "vc6include.jpg" \image latex "vc6include.jpg" - If your IDE is Visual Studio .NET, select Tools -> Options. Select the projects entry and then select VC++ directories. Select 'show directories for include files' in the combo box, and add the \c include directory of the irrlicht engine folder to the list of directories. Now the compiler will find the Irrlicht.h header file. We also need the irrlicht.lib to be found, so stay in that dialog, select 'show directories for Library files' and add the \c lib/VisualStudio directory. \image html "vcnetinclude.jpg" \image latex "vcnetinclude.jpg" That's it. With your IDE set up like this, you will now be able to develop applications with the Irrlicht Engine. Lets start! After we have set up the IDE, the compiler will know where to find the Irrlicht Engine header files so we can include it now in our code. */ #include /* In the Irrlicht Engine, everything can be found in the namespace 'irr'. So if you want to use a class of the engine, you have to write irr:: before the name of the class. For example to use the IrrlichtDevice write: irr::IrrlichtDevice. To get rid of the irr:: in front of the name of every class, we tell the compiler that we use that namespace from now on, and we will not have to write irr:: anymore. */ using namespace irr; /* There are 5 sub namespaces in the Irrlicht Engine. Take a look at them, you can read a detailed description of them in the documentation by clicking on the top menu item 'Namespace List' or by using this link: http://irrlicht.sourceforge.net/docu/namespaces.html Like the irr namespace, we do not want these 5 sub namespaces now, to keep this example simple. Hence, we tell the compiler again that we do not want always to write their names. */ using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; /* To be able to use the Irrlicht.DLL file, we need to link with the Irrlicht.lib. We could set this option in the project settings, but to make it easy, we use a pragma comment lib for VisualStudio. On Windows platforms, we have to get rid of the console window, which pops up when starting a program with main(). This is done by the second pragma. We could also use the WinMain method, though losing platform independence then. */ #ifdef _IRR_WINDOWS_ #pragma comment(lib, "Irrlicht.lib") #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") #endif /* This is the main method. We can now use main() on every platform. */ int main() { /* The most important function of the engine is the createDevice() function. The IrrlichtDevice is created by it, which is the root object for doing anything with the engine. createDevice() has 7 parameters: - deviceType: Type of the device. This can currently be the Null-device, one of the two software renderers, D3D8, D3D9, or OpenGL. In this example we use EDT_SOFTWARE, but to try out, you might want to change it to EDT_BURNINGSVIDEO, EDT_NULL, EDT_DIRECT3D8, EDT_DIRECT3D9, or EDT_OPENGL. - windowSize: Size of the Window or screen in FullScreenMode to be created. In this example we use 640x480. - bits: Amount of color bits per pixel. This should be 16 or 32. The parameter is often ignored when running in windowed mode. - fullscreen: Specifies if we want the device to run in fullscreen mode or not. - stencilbuffer: Specifies if we want to use the stencil buffer (for drawing shadows). - vsync: Specifies if we want to have vsync enabled, this is only useful in fullscreen mode. - eventReceiver: An object to receive events. We do not want to use this parameter here, and set it to 0. Always check the return value to cope with unsupported drivers, dimensions, etc. */ IrrlichtDevice *device = createDevice( video::EDT_SOFTWARE, dimension2d(640, 480), 16, false, false, false, 0); if (!device) return 1; /* Set the caption of the window to some nice text. Note that there is an 'L' in front of the string. The Irrlicht Engine uses wide character strings when displaying text. */ device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo"); /* Get a pointer to the VideoDriver, the SceneManager and the graphical user interface environment, so that we do not always have to write device->getVideoDriver(), device->getSceneManager(), or device->getGUIEnvironment(). */ IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); IGUIEnvironment* guienv = device->getGUIEnvironment(); /* We add a hello world label to the window, using the GUI environment. The text is placed at the position (10,10) as top left corner and (260,22) as lower right corner. */ guienv->addStaticText(L"Hello World! This is the Irrlicht Software renderer!", rect(10,10,260,22), true); /* To show something interesting, we load a Quake 2 model and display it. We only have to get the Mesh from the Scene Manager with getMesh() and add a SceneNode to display the mesh with addAnimatedMeshSceneNode(). We check the return value of getMesh() to become aware of loading problems and other errors. Instead of writing the filename sydney.md2, it would also be possible to load a Maya object file (.obj), a complete Quake3 map (.bsp) or any other supported file format. By the way, that cool Quake 2 model called sydney was modelled by Brian Collins. */ IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2"); if (!mesh) { device->drop(); return 1; } IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); /* To let the mesh look a little bit nicer, we change its material. We disable lighting because we do not have a dynamic light in here, and the mesh would be totally black otherwise. Then we set the frame loop, such that the predefined STAND animation is used. And last, we apply a texture to the mesh. Without it the mesh would be drawn using only a color. */ if (node) { node->setMaterialFlag(EMF_LIGHTING, false); node->setMD2Animation(scene::EMAT_STAND); node->setMaterialTexture( 0, driver->getTexture("../../media/sydney.bmp") ); } /* To look at the mesh, we place a camera into 3d space at the position (0, 30, -40). The camera looks from there to (0,5,0), which is approximately the place where our md2 model is. */ smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0)); /* Ok, now we have set up the scene, lets draw everything: We run the device in a while() loop, until the device does not want to run any more. This would be when the user closes the window or presses ALT+F4 (or whatever keycode closes a window). */ while(device->run()) { /* Anything can be drawn between a beginScene() and an endScene() call. The beginScene() call clears the screen with a color and the depth buffer, if desired. Then we let the Scene Manager and the GUI Environment draw their content. With the endScene() call everything is presented on the screen. */ driver->beginScene(true, true, SColor(255,100,101,140)); smgr->drawAll(); guienv->drawAll(); driver->endScene(); } /* After we are done with the render loop, we have to delete the Irrlicht Device created before with createDevice(). In the Irrlicht Engine, you have to delete all objects you created with a method or function which starts with 'create'. The object is simply deleted by calling ->drop(). See the documentation at irr::IReferenceCounted::drop() for more information. */ device->drop(); return 0; } /* That's it. Compile and run. **/ irrlicht-1.8.3/examples/01.HelloWorld/HelloWorld_vc9.vcproj0000644000000000000000000001224012574354552022245 0ustar rootroot irrlicht-1.8.3/examples/01.HelloWorld/HelloWorld_vc8.vcproj0000644000000000000000000001214012574354552022243 0ustar rootroot irrlicht-1.8.3/examples/01.HelloWorld/HelloWorld_vc12.vcxproj0000644000000000000000000003275212574354552022521 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 01.HelloWorld {5AD4C95C-BA38-4692-BA4B-8C25A86208F9} HelloWorld Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win32-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/HelloWorld.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\01.HelloWorld.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/HelloWorld.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\01.HelloWorld.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/HelloWorld.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\01.HelloWorld.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/HelloWorld.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\01.HelloWorld.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/01.HelloWorld/HelloWorld_vc11.vcxproj0000644000000000000000000003275112574354552022517 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 01.HelloWorld {5AD4C95C-BA38-4692-BA4B-8C25A86208F9} HelloWorld Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win32-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/HelloWorld.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\01.HelloWorld.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/HelloWorld.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\01.HelloWorld.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/HelloWorld.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\01.HelloWorld.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/HelloWorld.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\01.HelloWorld.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/01.HelloWorld/HelloWorld_vc10.vcxproj0000644000000000000000000003257512574354552022522 0ustar rootroot Debug Win32 Debug x64 Release Win32 Release x64 01.HelloWorld {5AD4C95C-BA38-4692-BA4B-8C25A86208F9} HelloWorld Application false MultiByte Application false MultiByte Application false MultiByte Windows7.1SDK Application false MultiByte Windows7.1SDK <_ProjectFileVersion>10.0.30319.1 ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win64-VisualStudio\ ..\..\bin\Win32-VisualStudio\ ..\..\bin\Win32-VisualStudio\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/HelloWorld.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\01.HelloWorld.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) true Console .\Debug/HelloWorld.tlb Disabled ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\01.HelloWorld.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) true Console .\Release/HelloWorld.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win32-VisualStudio\01.HelloWorld.exe ..\..\lib\Win32-visualstudio;%(AdditionalLibraryDirectories) Console .\Release/HelloWorld.tlb MaxSpeed OnlyExplicitInline ..\..\include;%(AdditionalIncludeDirectories) WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded true Level3 NDEBUG;%(PreprocessorDefinitions) 0x0c07 ..\..\bin\Win64-VisualStudio\01.HelloWorld.exe ..\..\lib\Win64-visualstudio;%(AdditionalLibraryDirectories) Console Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) irrlicht-1.8.3/examples/01.HelloWorld/HelloWorld.vcproj0000644000000000000000000001055012574354552021466 0ustar rootroot irrlicht-1.8.3/examples/01.HelloWorld/HelloWorld.dev0000644000000000000000000000173712574354552020750 0ustar rootroot[Project] FileName=example.dev Name=Irrlicht Example 01 HelloWorld UnitCount=1 Type=1 Ver=1 ObjFiles= Includes=..\..\include Libs= PrivateResource= ResourceIncludes= MakeIncludes= Compiler= CppCompiler= Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ IsCpp=1 Icon= ExeOutput=../../bin/Win32-gcc ObjectOutput= OverrideOutput=1 OverrideOutputName=01.HelloWorld.exe HostApplication= Folders= CommandLine= IncludeVersionInfo=0 SupportXPThemes=0 CompilerSet=0 CompilerSettings=0000000000000000000000 UseCustomMakefile=0 CustomMakefile= [Unit1] FileName=main.cpp CompileCpp=1 Folder=Projekt1 Compile=1 Link=1 Priority=1000 OverrideBuildCmd=0 BuildCmd= [VersionInfo] Major=0 Minor=1 Release=1 Build=1 LanguageID=1033 CharsetID=1252 CompanyName= FileVersion= FileDescription=Irrlicht Engine example compiled using DevCpp and gcc InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion= AutoIncBuildNr=0 irrlicht-1.8.3/examples/01.HelloWorld/HelloWorld.cbp0000644000000000000000000000265312574354552020734 0ustar rootroot irrlicht-1.8.3/doc/0000755000000000000000000000000012574354552012622 5ustar rootrootirrlicht-1.8.3/doc/upgrade-guide.txt0000644000000000000000000035414312574354552016117 0ustar rootrootThis file contains API changes between consecutive versions. You can get the relevant information about all changes to the public Irrlicht API needed for upgrading your code (esp. custom scene nodes and GUI elements) to a new Irrlicht version. Since all changes are incremental you should skip forward to the version you use right now and check each note until you reach the desired version. Please note that the changes described here do not contain functional changes, but only syntactical ones. Also, new methods are not documented here and have to be looked up in the API documentation instead. Basically, all changes have to be reflected in user code where used. Removed and renamed methods are obviously not existant anymore. A hint is usually given for such changes on how to remedy the situation. Changed signatures of methods might go unnoticed. That need not be a bad thing, e.g. for changes from s32 to u32 the parameters are usually automatically converted by the compiler. However, one should be careful when writing custom scene nodes or GUI elements. It might happen that the methods are not properly chosen as candidates for virtual overloading. So always check that methods in the user code have the proper signatures just as the interface versions. The change hint will help to identify necessary changes. Changes for Version 1.2 ----------------------- Removed compile flag (always used where available) _IRR_LINUX_OPENGL_USE_EXTENSIONS_ IAnimatedMeshB3d: Removed (no replacement available) virtual void AddMatrixToJoint(s32 jointNumber, core::matrix4* matrix) = 0; IGUIElement.h Changed signatures (made const) IGUIElement* getParent() const core::rect getRelativePosition() const IGUITabControl.h Changed signatures (const param) virtual IGUITab* addTab(const wchar_t* caption, s32 id=-1) = 0; IImage.h Changed signatures (made const) virtual ECOLOR_FORMAT getColorFormat() const = 0; IParticleAffector.h Changed inheritance (from irr:IUnknown) class IParticleAffector : public virtual io::IAttributeExchangingObject IParticleEmitter.h Changed inheritance (from irr:IUnknown) class IParticleEmitter : public virtual io::IAttributeExchangingObject IParticleSystemSceneNode.h Changed signatures (const param) virtual IParticleEmitter* createPointEmitter( const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, video::SColor minStartColor = video::SColor(255,0,0,0), virtual IParticleEmitter* createBoxEmitter( const core::aabbox3df& box = core::aabbox3df(-10,28,-10,10,30,10), const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, video::SColor minStartColor = video::SColor(255,0,0,0), virtual IParticleAffector* createGravityAffector( const core::vector3df& gravity = core::vector3df(0.0f,-0.03f,0.0f), u32 timeForceLost = 1000) = 0; ISceneManager.h Changed signatures (additional param) virtual ISceneNodeAnimator* createFlyCircleAnimator(const core::vector3df& center, f32 radius, f32 speed=0.001f, const core::vector3df& direction= core::vector3df ( 0.f, 1.f, 0.f ) ) = 0; ITexture.h Changed signatures (made const) virtual ECOLOR_FORMAT getColorFormat() const = 0; IVideoDriver.h Changed signatures (changed default param, use ECF_A1R5G5B5 explicitly for old behavior) virtual ITexture* addTexture(const core::dimension2d& size, const c8* name, ECOLOR_FORMAT format = ECF_A8R8G8B8) = 0; Changed signatures (made const) virtual ITexture* createRenderTargetTexture(const core::dimension2d& size) = 0; matrix4.h Changed signatures (swapped parameter, it was (col, row) before although the names did not represent this) f32& operator()(s32 row, s32 col); const f32& operator()(s32 row, s32 col) const; S3DVertex.h Changed signatures (unconst param) S3DVertex(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv); S3DVertex(const core::vector3df& pos, const core::vector3df& normal, SColor color, const core::vector2d& tcoords); S3DVertex2TCoords(f32 x, f32 y, f32 z, SColor c, f32 tu, f32 tv, f32 tu2, f32 tv2); S3DVertex2TCoords(const core::vector3df& pos, SColor color, const core::vector2d& tcoords, const core::vector2d& tcoords2); S3DVertex2TCoords(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv); S3DVertex2TCoords(const core::vector3df& pos, const core::vector3df& normal, SColor color, const core::vector2d& tcoords); S3DVertexTangents(const core::vector3df& pos, const core::vector2df& tcoords, SColor c); SColor.h Changed signatures (changed param types from signed to unsigned) inline u16 RGBA16(u32 r, u32 g, u32 b, u32 a); inline u16 RGB16(u32 r, u32 g, u32 b); inline u16 X8R8G8B8toA1R5G5B5(u32 color); inline u32 A1R5G5B5toA8R8G8B8(u32 color); inline u32 R5G6B5toA8R8G8B8(u16 color); inline u16 R5G6B5toA1R5G5B5(u16 color); inline u16 A1R5G5B5toR5G6B5(u16 color); inline u32 getAlpha(u16 color); inline u32 getRed(u16 color); inline u32 getGreen(u16 color); inline u32 getBlue(u16 color); inline u32 getLuminance(u16 color); inline SColor (u32 a, u32 r, u32 g, u32 b); inline SColor(u32 clr); inline u32 getAlpha() const inline u32 getRed() const inline u32 getGreen() const inline u32 getBlue() const inline void setAlpha(u32 a); inline void setRed(u32 r); inline void setGreen(u32 g); inline void setBlue(u32 b); inline u16 toA1R5G5B5() const inline void toOpenGLColor(u8* dest) const inline void set(u32 a, u32 r, u32 g, u32 b); inline void set(u32 col); Changed signatures (const param) inline SColor getInterpolated(const SColor &other, f32 d) const Changed public member (type changed) u32 color; Changes for Version 1.3 ----------------------- Globally renamed Frustrum to Frustum in all signatures and code parts IAnimatedMeshB3d.h Renamed methods (small first letter) virtual void setInterpolationMode(s32 mode) = 0; virtual void setAnimateMode(s32 mode) = 0; IAnimatedMeshSceneNode.h changed signature (changed types) virtual void setAnimationSpeed(f32 framesPerSecond) = 0; ICameraSceneNode.h Renamed methods and changed signature (changed types, frustum renaming) virtual const SViewFrustum* getViewFrustum() const = 0; IFileSystem.h Renamed method (from addUnZipFileArchive) virtual bool addFolderFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true) = 0; IGUIContextMenu.h Changed signature (added param) virtual s32 addItem(const wchar_t* text, s32 commandId=-1, bool enabled=true, bool hasSubMenu=false, bool checked=false) = 0; IGUIElement.h Changed inheritance class IGUIElement : public virtual io::IAttributeExchangingObject, public IEventReceiver Changed signature (made const) core::rect getAbsolutePosition() const IGUIEnvironment.h Changed signature (added param) virtual IGUIButton* addButton(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0, const wchar_t* tooltiptext = 0) = 0; IGUIListBox.h Removed method (Using sprite bank now) virtual void setIconFont(IGUIFont* font) = 0; Change signature (changed types, due to sprite bank) virtual s32 addItem(const wchar_t* text, s32 icon) = 0; IGUISkin.h Changed inheritance class IGUISkin : public virtual io::IAttributeExchangingObject IGUIToolbar.h Changed signature (Added param for tooltips) virtual IGUIButton* addButton(s32 id=-1, const wchar_t* text=0, const wchar_t* tooltiptext=0, video::ITexture* img=0, video::ITexture* pressedimg=0, bool isPushButton=false, bool useAlphaChannel=false) = 0; IImage.h Changed signature (made const) virtual u32 getPitch() const = 0; IImageWriter.h Changed signature (additional param) virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param = 0) = 0; IMeshBuffer.h Changed signature (changed return type) virtual u32 getVertexCount() const = 0; virtual u32 getIndexCount() const = 0; Removed method (use setBoundingBox instead) virtual core::aabbox3df& getBoundingBox() = 0; IMesh.h Changed signature (changed types, made const) virtual u32 getMeshBufferCount() const = 0; virtual IMeshBuffer* getMeshBuffer(u32 nr) const = 0; Removed method (use setBoundingBox instead) virtual core::aabbox3d& getBoundingBox() = 0; IReadFile.h Changed signature (changed types) virtual s32 read(void* buffer, u32 sizeToRead) = 0; irrArray.h Changed signature (made const) s32 binary_search(const T& element, s32 left, s32 right) const irrMath.h Constant changed const f32 PI = 3.14159265359f; Constants removed (use RADTODEG64 or DEGTORAD64 instead) const f64 GRAD_PI = 180.0 / PI64; const f64 GRAD_PI2 = PI64 / 180.0; Changed signature (added tolerance parameter) inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_32) irrString.h Changed signature (const param) template string(const B* const c, u32 length); template string(const B* const c); template string& operator=(const B* const c); template string operator+(const B* const c) const bool operator ==(const T* const str) const bool operator !=(const T* const str) const bool equalsn(const T* const str, int len) const void append(const T* const other); s32 findFirstChar(const T* const c, u32 count) const template s32 findFirstCharNotInList(const B* const c, u32 count) const template s32 findLastCharNotInList(const B* const c, u32 count) const template s32 find(const B* const str) const void operator += (const T* const c); Changed signature (changed type from signed) T& operator [](const u32 index) const u32 size() const void append(const string& other, u32 length); void reserve(u32 count); s32 findNext(T c, u32 startPos) const string subString(u32 begin, s32 length) const void erase(u32 index); void reallocate(u32 new_size); Changed signature (added param) s32 findLast(T c, s32 start = -1) const ISceneManager.h Changed signature (changed default param from 128 minimalPolysPerNode) virtual ISceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; virtual ISceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; Changed signature (added param) virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, f32 rotateSpeed = 100.0f, f32 moveSpeed = 500.0f, s32 id=-1, SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, f32 jumpSpeed = 0.f) = 0; virtual IBillboardSceneNode* addBillboardSceneNode(ISceneNode* parent = 0, const core::dimension2d& size = core::dimension2d(10.0f, 10.0f), const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1, video::SColor shade_top = 0xFFFFFFFF, video::SColor shade_down = 0xFFFFFFFF) = 0; virtual ITerrainSceneNode* addTerrainSceneNode( const c8* heightMapFileName, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), video::SColor vertexColor = video::SColor(255,255,255,255), s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0) = 0; virtual ITerrainSceneNode* addTerrainSceneNode( io::IReadFile* heightMapFile, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), video::SColor vertexColor = video::SColor(255,255,255,255), s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0) = 0; Changed signature (changed return type) virtual u32 registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS pass = ESNRP_AUTOMATIC) = 0; ISceneNodeAnimatorCollisionResponse.h Changed signature (made const) virtual void setEllipsoidTranslation(const core::vector3df &translation) = 0; ISceneNode.h Renamed method (from OnPreRender) virtual void OnRegisterSceneNode(); Renamed method (from OnPostRender) virtual void OnAnimate(u32 timeMs); Changed signature (made const) virtual const core::aabbox3d getTransformedBoundingBox() const const core::matrix4& getAbsoluteTransformation() const virtual bool isVisible() const virtual s32 getID() const scene::ISceneNode* getParent() const virtual ESCENE_NODE_TYPE getType() const Changed signature (changed type) virtual video::SMaterial& getMaterial(u32 num); void setMaterialTexture(u32 textureLayer, video::ITexture* texture); void setAutomaticCulling( E_CULLING_TYPE state); virtual void setDebugDataVisible(E_DEBUG_SCENE_TYPE visible); Changed signature (changed return type) virtual u32 getMaterialCount(); virtual const core::vector3df& getRotation() const E_CULLING_TYPE getAutomaticCulling() const Changed signature (changed return type, made const) E_DEBUG_SCENE_TYPE isDebugDataVisible() const ITerrainSceneNode.h Changed signature (changed return type) virtual u32 getIndexCount() = 0; ITexture.h Changed signature (changed return type, made const) virtual u32 getPitch() const = 0; Removed method (Available in SMaterial now) core::matrix4& getTransformation(); IVideoDriver.h Changed signature (changed types) virtual ITexture* getTextureByIndex(u32 index) = 0; virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType) = 0; virtual void drawIndexedTriangleList(const S3DVertex* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) = 0; virtual void drawIndexedTriangleList(const S3DVertex2TCoords* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) = 0; virtual void drawIndexedTriangleList(const S3DVertexTangents* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) = 0; virtual void drawIndexedTriangleFan(const S3DVertex* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) = 0; virtual void drawIndexedTriangleFan(const S3DVertex2TCoords* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) = 0; virtual const SLight& getDynamicLight(u32 idx) = 0; virtual IMaterialRenderer* getMaterialRenderer(u32 idx) = 0; virtual const c8* getMaterialRendererName(u32 idx) = 0; Changed signature (const param) virtual void drawMeshBuffer( const scene::IMeshBuffer* mb) = 0; virtual io::IAttributes* createAttributesFromMaterial(const video::SMaterial& material) = 0; Changed signature (added param) virtual u32 getPrimitiveCountDrawn( u32 param = 0 ) = 0; virtual bool writeImageToFile(IImage* image, const c8* filename, u32 param = 0) = 0; virtual IImage* createImageFromData(ECOLOR_FORMAT format, const core::dimension2d& size, void *data, bool ownForeignMemory=false, bool deleteMemory = true) = 0; Changed signature (changed return types) virtual u32 getMaximalDynamicLightAmount() = 0; virtual u32 getDynamicLightCount() = 0; virtual u32 getMaximalPrimitiveCount() = 0; virtual u32 getMaterialRendererCount() = 0; matrix4.h Changed signature (added param) matrix4( eConstructor constructor = EM4CONST_IDENTITY ); Changed signature (const param) f32& operator()(const s32 row, const s32 col); const f32& operator()(const s32 row, const s32 col) const Changed signature (param order) void transformVect( vector3df& out, const vector3df& in ) const; quaternion.h Changed signature (changed return type) void slerp( quaternion q1, const quaternion q2, f32 interpolate ); SColor.h Renamed method (from getLuminance), changed types inline s32 getAverage(s16 color); Changed signature (changed return types) inline f32 getLuminance() const Changed signature (const param) inline SColorf getInterpolated(const SColorf &other, f32 d) const SMaterial.h Constant type changed const u32 MATERIAL_MAX_TEXTURES = 4; Type changed class SMaterial Public members removed (use Textures[] instead) ITexture* Texture1; ITexture* Texture2; ITexture* Texture3; ITexture* Texture4; Public members removed (use setFlag()/getFlag() instead) Flags[] Public members changed (type changed) u32 ZBuffer; Changed signature (made const) inline bool operator!=(const SMaterial& b) const SMeshBuffer.h Changed signature (changed param) virtual u32 getVertexCount() const virtual u32 getIndexCount() const Removed method (use setBoundingBox instead) virtual core::aabbox3d& getBoundingBox(); SMeshBufferLightMap.h Changed signature (changed param) virtual u32 getVertexCount() const virtual u32 getIndexCount() const Removed method (use setBoundingBox instead) virtual core::aabbox3d& getBoundingBox(); SMeshBufferTangents.h Changed signature (changed param) virtual u32 getVertexCount() const virtual u32 getIndexCount() const Removed method (use setBoundingBox instead) virtual core::aabbox3d& getBoundingBox(); SMesh.h Changed signature (changed param, made const) virtual u32 getMeshBufferCount() const virtual IMeshBuffer* getMeshBuffer(u32 nr) const Removed method (use setBoundingBox instead); virtual core::aabbox3d& getBoundingBox(); vector3d.h Changed signature (changed return type) T getLength() const Changed signature (changed type) vector3d getInterpolated(const vector3d& other, const T d) const Changes for Version 1.3.1 ------------------------- Changed types: SMeshBuffer* types are now template typedefs from CMeshBuffer dimension2d.h Changed signature (const param) dimension2d(const T& width, const T& height); dimension2d operator/(const T& scale); dimension2d operator*(const T& scale); IAnimatedMeshSceneNode.h Changed signature (made const) virtual s32 getFrameNr() const = 0; virtual s32 getStartFrame() const = 0; virtual s32 getEndFrame() const = 0; Renamed method (from getAbsoluteTransformation) virtual const SMD3QuaterionTag& getMD3TagTransformation( const core::stringc & tagname) = 0; IGUIButton.h Renamed method (from getUseAlphaChannel) virtual bool isAlphaChannelUsed() = 0; IGUIElementFactory.h Changed signature (made const) EGUI_ELEMENT_TYPE getType() const virtual const c8* getTypeName() const IGUIEnvironment.h Changed signature (added param) virtual bool saveGUI(const c8* filename, IGUIElement* start=0) = 0; virtual bool saveGUI(io::IWriteFile* file, IGUIElement* start=0) = 0; virtual bool loadGUI(const c8* filename, IGUIElement* parent=0) = 0; virtual bool loadGUI(io::IReadFile* file, IGUIElement* parent=0) = 0; IGUIFontBitmap.h Changed signature (made const) virtual EGUI_FONT_TYPE getType() const { return EGFT_BITMAP; } IGUIFont.h Changed signature (made const) virtual EGUI_FONT_TYPE getType() const { return EGFT_CUSTOM; } IGUISkin.h Changed signature (added param) virtual IGUIFont* getFont(EGUI_DEFAULT_FONT which=EGDF_DEFAULT) = 0; virtual void setFont(IGUIFont* font, EGUI_DEFAULT_FONT which=EGDF_DEFAULT) = 0; Changed signature (made const) virtual EGUI_SKIN_TYPE getType() const { return EGST_UNKNOWN; }; IImage.h Changed signature (made const) virtual const core::dimension2d& getDimension() const = 0; virtual u32 getRedMask() const = 0; virtual u32 getGreenMask() const = 0; virtual u32 getBlueMask() const = 0; virtual u32 getAlphaMask() const = 0; Changed signature (changed return type, made const) virtual u32 getBitsPerPixel() const = 0; virtual u32 getBytesPerPixel() const = 0; virtual u32 getImageDataSizeInBytes() const = 0; virtual u32 getImageDataSizeInPixels() const = 0; Changed signature (changed param type, made const) virtual SColor getPixel(u32 x, u32 y) const = 0; IMeshCache.h Changed signature (const param) virtual void removeMesh(const IAnimatedMesh* const mesh) = 0; Changed signature (const param, made const) virtual s32 getMeshIndex(const IAnimatedMesh* const mesh) const = 0; virtual const c8* getMeshFilename(const IAnimatedMesh* const mesh) const = 0; virtual const c8* getMeshFilename(const IMesh* const mesh) const = 0; Changed signature (changed return type, made const) virtual u32 getMeshCount() const = 0; Changed signature (changed param type) virtual IAnimatedMesh* getMeshByIndex(u32 index) = 0; Changed signature (made const) virtual const c8* getMeshFilename(u32 index) const = 0; IParticleAffector.h Changed signature (made const) virtual E_PARTICLE_AFFECTOR_TYPE getType() const = 0; IParticleEmitter.h Changed signature (made const) virtual E_PARTICLE_EMITTER_TYPE getType() const = 0; irrString.h Changed signature (const param) string(const double number); Changed signature (changed return type) string& operator += (T c); string& operator += (const string& other); Changed signature (changed return type, const param) string& operator += (const T* const c); string& operator += (const int i); string& operator += (const double i); ISceneManager.h Changed signature (added param) virtual ITerrainSceneNode* addTerrainSceneNode( const c8* heightMapFileName, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), video::SColor vertexColor = video::SColor(255,255,255,255), s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0, bool addAlsoIfHeightmapEmpty = false) = 0; virtual ITerrainSceneNode* addTerrainSceneNode( io::IReadFile* heightMapFile, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& scale = core::vector3df(1.0f,1.0f,1.0f), video::SColor vertexColor = video::SColor(255,255,255,255), s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0, bool addAlsoIfHeightmapEmpty = false) = 0; virtual ISceneManager* createNewSceneManager(bool cloneContent=false) = 0; ISceneNodeAnimator.h Changed signature (made const) virtual ESCENE_NODE_ANIMATOR_TYPE getType() const ITexture.h Changed signature (made const) virtual bool hasMipMaps() const IVideoDriver.h Changed signature (reference param) virtual void draw3DBox(const core::aabbox3d& box, SColor color = SColor(255,255,255,255)) = 0; Changed signature (added defaults for param) virtual void draw2DImage(video::ITexture* texture, const core::position2d& pos, const core::array >& sourceRects, const core::array& indices, s32 kerningWidth=0, const core::rect* clipRect=0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) = 0; Changed signature (changed return type) virtual const SExposedVideoData& getExposedVideoData() = 0; line3d.h Changed signature (changed return type) T getLength() const matrix4.h Changed type to template class template class CMatrix4 typedef CMatrix4 matrix4; Changed signature (changed return type) T& operator()(const s32 row, const s32 col); const T& operator()(const s32 row, const s32 col) const T& operator[](u32 index); const T& operator[](u32 index) const Changed signature (changed param type) inline CMatrix4& operator=(const T& scalar); const T* pointer() const T* pointer(); CMatrix4 operator*(const T& scalar) const; CMatrix4& operator*=(const T& scalar); void transformVect(T *out,const core::vector3df &in) const; void rotateVect(T *out,const core::vector3df &in) const; void multiplyWith1x4Matrix(T* matrix) const; CMatrix4 interpolate(const core::CMatrix4& b, f32 time) const; plane3d.h Renamed method (from existsInterSection) bool existsIntersection(const plane3d& other) const quaternion.h Changed signature (unconst param) void slerp( quaternion q1, quaternion q2, f32 interpolate ); SExposedVideoData.h Removed public member (replaced by X11Display and X11Window) OpenGLLinux.Window; SIrrCreationParameters.h Changed public member (changed type for 64bit system support) void* WindowId; triangle3d.h Changed method to private bool isOnSameSide(const vector3d& p1, const vector3d& p2, const vector3d& a, const vector3d& b) const vector2d.h Changed signature (changed return value) T getLength() const T getDistanceFrom(const vector2d& other) const vector3d.h Changed signature (changed return value) T getDistanceFrom(const vector3d& other) const Changes for Version 1.4 ----------------------- This release had many changes in API method signatures. Many methods have been made const, also several parameter types were changed. The two most noticeable changes (which almost every user of the Irrlicht API will come across) are the renaming of IUnknown to IReferenceCounted and const-ref change of the SEvent structure of the OnEvent method. Another important change: DirectX8 support is now by default disabled, enable the define in IrrCompileConfig.h to restore the old behavior. IReferenceCounted.h Renamed Type (from IUnknown). This changed most classes in Irrlicht class IReferenceCounted IEventReceiver.h Changed signature (made const) virtual bool OnEvent(const SEvent& event) = 0; IrrCompileConfig.h DirectX8 support is now by default disabled CMeshBuffer.h Removed method virtual u32 getVertexPitch() const fast_atof.h Changed signature to allow optional second parameter u32 strtol10(const char* in, const char** out=0) IAnimatedMesh.h Changed inheritance (instead of IReferenceCounted) class IAnimatedMesh : public IMesh Changed signature (made const) virtual u32 getFrameCount() const = 0; IAnimatedMeshSceneNode.h Changed signature (changed param type) virtual void setCurrentFrame(f32 frame) = 0; Replaced methods (generalized method getJointNode available) virtual ISceneNode* getMS3DJointNode(const c8* jointName) = 0; virtual ISceneNode* getXJointNode(const c8* jointName) = 0; virtual ISceneNode* getB3DJointNode(const c8* jointName) = 0; Changed signature (changed return type) virtual f32 getFrameNr() const = 0; Changed signature (made const) virtual bool isReadOnlyMaterials() const = 0; IAttributeExchangingObject.h Changed signature (made const) virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const {} IAttributes.h Changed signature (made const, changed param type) virtual u32 getAttributeCount() const = 0; Changed signature (added param) virtual bool read(io::IXMLReader* reader, bool readCurrentElementOnly=false, const wchar_t* elementName=0) = 0; virtual bool write(io::IXMLWriter* writer, bool writeXMLHeader=false, const wchar_t* elementName=0) = 0; Changed signature (made const-ref param) virtual void addMatrix(const c8* attributeName, const core::matrix4& v) = 0; virtual void setAttribute(const c8* attributeName, const core::matrix4& v) = 0; virtual void setAttribute(s32 index, const core::matrix4& v) = 0; IBillboardSceneNode.h Changed signature (made const) virtual const core::dimension2d& getSize() const = 0; virtual void getColor(video::SColor & topColor, video::SColor & bottomColor) const = 0; ICameraSceneNode.h Changed signature (made const) virtual const core::matrix4& getProjectionMatrix() const = 0; virtual const core::matrix4& getViewMatrix() const = 0; virtual bool OnEvent(const SEvent& event) = 0; virtual f32 getNearValue() const = 0; virtual f32 getFarValue() const = 0; virtual f32 getAspectRatio() const = 0; virtual f32 getFOV() const = 0; virtual bool isInputReceiverEnabled() const = 0; virtual bool isOrthogonal() const ICursorControl.h Changed signature (made const) virtual bool isVisible() const = 0; IFileList.h Changed signature (made const, changed param or return types) virtual u32 getFileCount() const = 0; virtual const c8* getFileName(u32 index) const = 0; virtual const c8* getFullFileName(u32 index) = 0; virtual bool isDirectory(u32 index) const = 0; IFileSystem.h 2007-09-17 09:53:10.000000000 +0200 Changed signature (made const method and const-ref param) virtual core::stringc getAbsolutePath(const core::stringc& filename) const = 0; virtual core::stringc getFileDir(const core::stringc& filename) const = 0; Changed signature (made const) virtual IFileList* createFileList() const = 0; virtual bool existFile(const c8* filename) const = 0; IGUIButton.h Changed signature (made const) virtual bool isPressed() const = 0; virtual bool isAlphaChannelUsed() const = 0; virtual bool isPushButton() const = 0; virtual bool isDrawingBorder() const = 0; IGUICheckBox.h Changed signature (made const) virtual bool isChecked() const = 0; IGUIComboBox.h Changed signature (made const, changed param or return types) virtual u32 getItemCount() const = 0; virtual const wchar_t* getItem(u32 idx) const = 0; virtual s32 getSelected() const = 0; Changed signature (changed param or return types) virtual u32 addItem(const wchar_t* text) = 0; virtual void removeItem(u32 id) = 0; IGUIContextMenu.h Changed signature (changed param or return types) virtual u32 getItemCount() const = 0; virtual u32 addItem(const wchar_t* text, s32 commandId=-1, bool enabled=true, bool hasSubMenu=false, bool checked=false) = 0; virtual void setItemText(u32 idx, const wchar_t* text) = 0; virtual void setItemEnabled(u32 idx, bool enabled) = 0; virtual void setItemChecked(u32 idx, bool enabled) = 0; virtual void removeItem(u32 idx) = 0; virtual void setItemCommandId(u32 idx, s32 id) = 0; Changed signature (made const, changed param or return types) virtual const wchar_t* getItemText(u32 idx) const = 0; virtual bool isItemEnabled(u32 idx) const = 0; virtual bool isItemChecked(u32 idx) const = 0; virtual s32 getSelectedItem() const = 0; virtual s32 getItemCommandId(u32 idx) const = 0; virtual IGUIContextMenu* getSubMenu(u32 idx) const = 0; IGUIEditBox.h Changed signature (changed param or return types) virtual void setMax(u32 max) = 0; Changed signature (made const, changed param or return types) virtual u32 getMax() const = 0; IGUIElementFactory.h Changed signature (made const) virtual s32 getCreatableGUIElementTypeCount() const = 0; virtual EGUI_ELEMENT_TYPE getCreateableGUIElementType(s32 idx) const = 0; virtual const c8* getCreateableGUIElementTypeName(s32 idx) const = 0; virtual const c8* getCreateableGUIElementTypeName(EGUI_ELEMENT_TYPE type) const = 0; IGUIElement.h Changed signature (made const) bool isNotClipped() const virtual bool isVisible() const virtual bool isSubElement() const virtual bool isEnabled() const virtual const wchar_t* getText() const virtual s32 getID() const virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const Changed signature (made const-ref param or return type) virtual const core::stringw& getToolTipText() const virtual bool OnEvent(const SEvent& event) IGUIEnvironment.h Changed signature (changed return type) virtual bool setFocus(IGUIElement* element) = 0; virtual bool removeFocus(IGUIElement* element) = 0; Changed signature (made const) virtual IGUIElement* getFocus() const = 0; virtual bool hasFocus(IGUIElement* element) const = 0; virtual video::IVideoDriver* getVideoDriver() const = 0; virtual io::IFileSystem* getFileSystem() const = 0; virtual IOSOperator* getOSOperator() const = 0; virtual IGUISkin* getSkin() const = 0; virtual IGUIFont* getBuiltInFont() const = 0; virtual IGUIElementFactory* getDefaultGUIElementFactory() const = 0; virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const =0; Changed signature (made const-ref param or return type) virtual bool postEventFromUser(const SEvent& event) = 0; Changed signature (made const, changed param or return types) virtual u32 getRegisteredGUIElementFactoryCount() const = 0; virtual IGUIElementFactory* getGUIElementFactory(u32 index) const = 0; IGUIFileOpenDialog.h Changed signature (made const) virtual const wchar_t* getFileName() const = 0; IGUIFontBitmap.h Changed signature (made const) virtual IGUISpriteBank* getSpriteBank() const = 0; virtual u32 getSpriteNoFromChar(const wchar_t *c) const = 0; virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const = 0; IGUIFont.h Changed signature (made const) virtual core::dimension2d getDimension(const wchar_t* text) const = 0; virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const = 0; virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const = 0; virtual s32 getKerningHeight() const = 0; IGUIListBox.h Changed signature (made const, changed param or return types) virtual u32 getItemCount() const = 0; virtual const wchar_t* getListItem(u32 id) const = 0; virtual s32 getIcon(u32 index) const = 0; Changed signature (changed param or return types) virtual u32 addItem(const wchar_t* text) = 0; virtual u32 addItem(const wchar_t* text, s32 icon) = 0; virtual void removeItem(u32 index) = 0; Changed signature (made const) virtual s32 getSelected() const = 0; IGUIMeshViewer.h Changed signature (made const) virtual const video::SMaterial& getMaterial() const = 0; IGUIScrollBar.h Changed signature (made const) virtual s32 getMax() const = 0; virtual s32 getSmallStep() const = 0; virtual s32 getPos() const = 0; IGUISkin.h Changed signature (made const) virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const = 0; virtual s32 getSize(EGUI_DEFAULT_SIZE size) const = 0; virtual const wchar_t* getDefaultText(EGUI_DEFAULT_TEXT text) const = 0; virtual IGUIFont* getFont(EGUI_DEFAULT_FONT which=EGDF_DEFAULT) const = 0; virtual IGUISpriteBank* getSpriteBank() const = 0; virtual u32 getIcon(EGUI_DEFAULT_ICON icon) const = 0; IGUISpriteBank.h Changed signature (made const) virtual u32 getTextureCount() const = 0; virtual video::ITexture* getTexture(u32 index) const = 0; IGUIStaticText.h Changed signature (made const) virtual IGUIFont* getOverrideFont(void) const = 0; virtual video::SColor const& getOverrideColor(void) const = 0; virtual bool isOverrideColorEnabled(void) const = 0; virtual bool isWordWrapEnabled(void) const = 0; virtual s32 getTextHeight() const = 0; virtual s32 getTextWidth(void) const = 0; IGUITabControl.h Changed signature (made const) virtual s32 getNumber() const = 0; virtual s32 getTabCount() const = 0; virtual IGUITab* getTab(s32 idx) const = 0; virtual s32 getActiveTab() const = 0; IGUIWindow.h Changed signature (made const) virtual IGUIButton* getCloseButton() const = 0; virtual IGUIButton* getMinimizeButton() const = 0; virtual IGUIButton* getMaximizeButton() const = 0; IImageLoader.h Changed signature (made const) virtual bool isALoadableFileExtension(const c8* fileName) const = 0; virtual bool isALoadableFileFormat(io::IReadFile* file) const = 0; virtual IImage* loadImage(io::IReadFile* file) const = 0; IImageWriter.h Changed signature (made const) virtual bool isAWriteableFileExtension(const c8* fileName) const = 0; virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param = 0) const = 0; ILogger.h Changed signature (made const) virtual ELOG_LEVEL getLogLevel() const = 0; IMaterialRenderer.h Changed signature (made const-ref param) virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) {}; Changed signature (made const) virtual bool isTransparent() const { return false; } virtual s32 getRenderCapability() const { return 0; } IMesh.h Changed signature (made const) virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const = 0; IMeshLoader.h Changed signature (made const) virtual bool isALoadableFileExtension(const c8* fileName) const = 0; IMeshManipulator.h Removed method (now in IMeshBuffer) virtual void recalculateBoundingBox(scene::IMeshBuffer* buffer) const IMeshSceneNode.h Changed signature (made const) virtual bool isReadOnlyMaterials() const = 0; IOSOperator.h Changed signature (made const) virtual const wchar_t* getOperationSystemVersion() const = 0; virtual void copyToClipboard(const c8* text) const = 0; virtual c8* getTextFromClipboard() const = 0; virtual bool getProcessorSpeedMHz(u32* MHz) const = 0; virtual bool getSystemMemory(u32* Total, u32* Avail) const = 0; IParticleAffector.h Changed signature (made const) virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const {} IParticleEmitter.h Changed signature (made const) virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const {} IParticleSystemSceneNode.h Changed signature (changed return type, changed param types) virtual IParticlePointEmitter* createPointEmitter( const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0) = 0; virtual IParticleEmitter* createBoxEmitter( const core::aabbox3df& box = core::aabbox3df(-10,28,-10,10,30,10), const core::vector3df& direction = core::vector3df(0.0f,0.03f,0.0f), u32 minParticlesPerSecond = 5, u32 maxParticlesPerSecond = 10, const video::SColor& minStartColor = video::SColor(255,0,0,0), const video::SColor& maxStartColor = video::SColor(255,255,255,255), u32 lifeTimeMin=2000, u32 lifeTimeMax=4000, s32 maxAngleDegrees=0) = 0; virtual IParticleFadeOutAffector* createFadeOutParticleAffector( const video::SColor& targetColor = video::SColor(0,0,0,0), u32 timeNeededToFadeOut = 1000) = 0; virtual IParticleGravityAffector* createGravityAffector( const core::vector3df& gravity = core::vector3df(0.0f,-0.03f,0.0f), u32 timeForceLost = 1000) = 0; IQ3Shader.h Removed method bool operator < ( const SVariable &other ) const IReadFile.h Changed param types (adapt the correct C-API for file positions) virtual bool seek(long finalPos, bool relativeMovement = false) = 0; virtual long getSize() const = 0; virtual long getPos() const = 0; IReadFile* createLimitReadFile(const c8* fileName, IReadFile* alreadyOpenedFile, long areaSize); IReadFile* createMemoryReadFile(void* memory, long size, const c8* fileName, bool deleteMemoryWhenDropped); Changed signature (made const) virtual const c8* getFileName() const = 0; IrrlichtDevice.h Changed signature (made const) virtual bool isWindowActive() const = 0; virtual const c8* getVersion() const = 0; Changed signature (made const-ref param) virtual void postEventFromUser(const SEvent& event) = 0; irrList.h Changed some structures in order to incorporate a ConstIterator class. Iterator begin() ConstIterator begin() const Iterator end() ConstIterator end() const Iterator getLast() ConstIterator getLast() const void insert_after(const Iterator& it, const T& element) void insert_before(const Iterator& it, const T& element) irrMath.h Changed signature (Use const references for better class handling) inline const T& min_(const T& a, const T& b) inline const T& min_(const T& a, const T& b, const T& c) inline const T& max_(const T& a, const T& b) inline const T& max_(const T& a, const T& b, const T& c) inline T abs_(const T& a) inline T lerp(const T& a, const T& b, const f32 t) inline const T clamp (const T& value, const T& low, const T& high) irrString.h Changed signature (made proper const method) T& operator [](const u32 index) const T& operator [](const u32 index) const irrXML.h Changed signature (adapt the correct C-API for file positions, made const) virtual long getSize() const = 0; Changed signature (changed param types) virtual unsigned int getAttributeCount() const = 0; ISceneManager.h Changed signature (changed param types) virtual IAnimatedMesh* addHillPlaneMesh(const c8* name, const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material = 0, f32 hillHeight = 0.0f, const core::dimension2d& countHills = core::dimension2d(0.0f, 0.0f), const core::dimension2d& textureRepeatCount = core::dimension2d(1.0f, 1.0f)) = 0; Changed signature (changed param types and order) virtual IAnimatedMesh* addArrowMesh(const c8* name, video::SColor vtxColor0=0xFFFFFFFF, video::SColor vtxColor1=0xFFFFFFFF, u32 tesselationCylinder=4, u32 tesselationCone=8, f32 height=1.f, f32 cylinderHeight=0.6f, f32 width0=0.05f, f32 width1=0.3f) = 0; Changed signature (changed param types) virtual bool postEventFromUser(const SEvent& event) = 0; virtual ISceneNodeFactory* getSceneNodeFactory(u32 index) = 0; virtual ISceneNodeAnimatorFactory* getSceneNodeAnimatorFactory(u32 index) = 0; Changed signature (made const) virtual E_SCENE_NODE_RENDER_PASS getSceneNodeRenderPass() const = 0; Changed signature (changed param types, made const) virtual u32 getRegisteredSceneNodeFactoryCount() const = 0; virtual u32 getRegisteredSceneNodeAnimatorFactoryCount() const = 0; virtual const video::SColorf& getAmbientLight() const = 0; ISceneNodeAnimatorCollisionResponse.h Changed signature (made const) virtual bool isFalling() const = 0; ISceneNodeAnimatorFactory.h Changed signature (changed param types, made const) virtual u32 getCreatableSceneNodeAnimatorTypeCount() const = 0; virtual ESCENE_NODE_ANIMATOR_TYPE getCreateableSceneNodeAnimatorType(u32 idx) const = 0; virtual const c8* getCreateableSceneNodeAnimatorTypeName(u32 idx) const = 0; Changed signature (made const) virtual const c8* getCreateableSceneNodeAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const = 0; ISceneNodeFactory.h Changed signature (changed param types, made const) virtual u32 getCreatableSceneNodeTypeCount() const = 0; virtual ESCENE_NODE_TYPE getCreateableSceneNodeType(u32 idx) const = 0; virtual const c8* getCreateableSceneNodeTypeName(u32 idx) const = 0; Changed signature (made const) virtual const c8* getCreateableSceneNodeTypeName(ESCENE_NODE_TYPE type) const = 0; ISceneNode.h Changed signature (made const) virtual u32 getMaterialCount() const bool isDebugObject() const virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const IShadowVolumeSceneNode.h Changed signature (made const param) virtual void setMeshToRenderFrom(const IMesh* mesh) = 0; ITerrainSceneNode.h Changed signature (made const) virtual u32 getIndexCount() const = 0; virtual void getMeshBufferForLOD(SMeshBufferLightMap& mb, s32 LOD) const = 0; virtual s32 getCurrentLODOfPatches(core::array& LODs) const = 0; virtual f32 getHeight( f32 x, f32 y ) const = 0; Changed signature (made const, made const-ref param) virtual const core::vector3df& getTerrainCenter() const = 0; ITexture.h Changed signature (made const) virtual const core::dimension2d& getOriginalSize() const = 0; virtual const core::dimension2d& getSize() const = 0; virtual E_DRIVER_TYPE getDriverType() const = 0; const core::stringc& getName() const { return Name; } ITimer.h Changed signature (made const) virtual u32 getRealTime() const = 0; virtual u32 getTime() const = 0; virtual f32 getSpeed() const = 0; virtual bool isStopped() const = 0; ITriangleSelector.h Changed signature (made const) virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::matrix4* transform=0) const = 0; virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::aabbox3d& box, const core::matrix4* transform=0) const = 0; virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform=0) const = 0; IVideoDriver.h Changed signature (made const, changed param type) virtual u32 getTextureCount() const = 0; Changed signature (made const param) in all draw2DImage methods virtual void draw2DImage(const video::ITexture* texture, Changed signature (made const-ref param, made const) virtual const core::dimension2d& getScreenSize() const = 0; virtual const core::dimension2d& getCurrentRenderTargetSize() const = 0; Changed signature (made const) virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const = 0; virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const = 0; virtual ITexture* createRenderTargetTexture(const core::dimension2d& size, const c8* name = 0) = 0; virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor color) const = 0; virtual void makeColorKeyTexture(video::ITexture* texture, core::position2d colorKeyPixelPos) const = 0; virtual void makeNormalMapTexture(video::ITexture* texture, f32 amplitude=1.0f) const = 0; virtual s32 getFPS() const = 0; virtual u32 getPrimitiveCountDrawn( u32 param = 0 ) const = 0; virtual u32 getMaximalDynamicLightAmount() const = 0; virtual u32 getDynamicLightCount() const = 0; virtual const SLight& getDynamicLight(u32 idx) const = 0; virtual const wchar_t* getName() const = 0; virtual u32 getMaximalPrimitiveCount() const = 0; virtual bool getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const = 0; virtual u32 getMaterialRendererCount() const = 0; virtual const c8* getMaterialRendererName(u32 idx) const = 0; virtual E_DRIVER_TYPE getDriverType() const = 0; IWriteFile.h Changed signature (changed param type) virtual s32 write(const void* buffer, u32 sizeToWrite) = 0; virtual bool seek(long finalPos, bool relativeMovement = false) = 0; Changed signature (changed param type, made const) virtual long getPos() const = 0; Changed signature (made const) virtual const c8* getFileName() const = 0; line2d.h Changed signature (made const) vector2d getUnitVector() const f64 getAngleWith(const line2d& l) const T getPointOrientation(const vector2d& point) const bool isPointOnLine(const vector2d& point) const matrix4.h Changed signature (made template param) void setTranslation( const vector3d& translation ); vector3d getTranslation() const; void setInverseTranslation( const vector3d& translation ); inline void setRotationRadians( const vector3d& rotation ); void setRotationDegrees( const vector3d& rotation ); core::vector3d getRotationDegrees() const; inline void setInverseRotationRadians( const vector3d& rotation ); void setInverseRotationDegrees( const vector3d& rotation ); void setScale( const vector3d& scale ); core::vector3d getScale() const; rect.h Changed signature (made non-const ref param, C++ conformance) rect& operator+=(const position2d& pos) rect& operator-=(const position2d& pos) S3DVertex.h Changed inheritance (S3DVertex is now base class of other vertex types) struct S3DVertex2TCoords : public S3DVertex struct S3DVertexTangents : public S3DVertex SAnimatedMesh.h Changed signature (changed param type, made const) virtual u32 getFrameCount() const SColor.h Changed signature (changed param type) inline u32 A1R5G5B5toA8R8G8B8(u16 color) SLight.h Removed attribute (use LightSceneNode position instead) core::vector3df Position; SMaterial.h Changed attribute structure (texture layer properties are now in thenew TextureLayer array). This changes access to Textures, TextureMatrix, TextureWrap, and the filter settings, which are also per-layer now. SMaterialLayer TextureLayer[MATERIAL_MAX_TEXTURES]; vector3d.h Changed signature (made template param) bool equals(const vector3d& other, const T tolerance = (T)ROUNDING_ERROR_32 ) const Changes for Version 1.4.1 ------------------------- Since this version is a backward compatible bugfix release, the API changes are only a few. None of them should result in uncompilable code. Newly found warnings might point out wrongly used variables, additional casts or type changes in the app should easily fix that. The only change which might go unnoticed by the compiler, but affect the application is the changed initialization in SColorf. This was done to synchronize with other constructors from SColorf and SColor, though, so the expectations are now much better met. Also, OSX users have to adjust the defines in IrrCompileConfig, as we now also have OSX defines in Irrlicht style. It's now even possible to build with X11 support under OSX without changes in the device code. SColor.h Changed signature (SColorf is now default initialized to alpha=1.0f) SColorf(f32 r=0.f, f32 g=0.f, f32 b=0.f, f32 a=1.f) : r(r), g(g), b(b), a(a) {} IrrCompileConfig.h Split the OSX define into platform and device (from old MACOSX define) _IRR_OSX_PLATFORM_ for Apple systems running OSX _IRR_USE_OSX_DEVICE_ for Cocoa native windowing on OSX ISceneManager.h Added new overload for getMesh with IReadFile instead of filename. virtual IAnimatedMesh* getMesh(io::IReadFile* file) = 0; irrMath.h Renamed method setbit REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask ) ISceneNode.h Changed signature (because the debug data enum values can be OR'ed to enable multiple debug data types) virtual void setDebugDataVisible(s32 state) s32 isDebugDataVisible() const s32 DebugDataVisible; matrix4.h Changed signature (Added return values to some methods) inline CMatrix4& setbyproduct(const CMatrix4& other_a,const CMatrix4& other_b ); CMatrix4& setbyproduct_nocheck(const CMatrix4& other_a,const CMatrix4& other_b ); inline CMatrix4& makeIdentity(); CMatrix4& setTranslation( const vector3d& translation ); CMatrix4& setInverseTranslation( const vector3d& translation ); inline CMatrix4& setRotationRadians( const vector3d& rotation ); CMatrix4& setRotationDegrees( const vector3d& rotation ); inline CMatrix4& setInverseRotationRadians( const vector3d& rotation ); CMatrix4& setInverseRotationDegrees( const vector3d& rotation ); CMatrix4& setScale( const vector3d& scale ); CMatrix4& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar); CMatrix4& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar); CMatrix4& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); CMatrix4& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); CMatrix4& buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); CMatrix4& buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); CMatrix4& buildCameraLookAtMatrixLH(...) CMatrix4& buildCameraLookAtMatrixRH(...) CMatrix4& buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f); CMatrix4& buildNDCToDCMatrix( const core::rect& area, f32 zScale); CMatrix4& setTextureScale( f32 sx, f32 sy ); CMatrix4& setTextureRotationCenter( f32 radAngle ); CMatrix4& setTextureScaleCenter( f32 sx, f32 sy ); CMatrix4& setTextureTranslate( f32 x, f32 y ); CMatrix4& setM(const T* data); Added overload (for one scale value for all axes) CMatrix4& setScale( const T scale ) { return setScale(core::vector3d(scale,scale,scale)); } S3DVertex.h Added operator bool operator<(const S3DVertex& other) const bool operator<(const S3DVertex2TCoords& other) const bool operator<(const S3DVertexTangents& other) const irrString.h Changed signature (int->u32, negative length didn't make sense) bool equalsn(const string& other, u32 n) const bool equalsn(const T* const str, u32 n) const New overload/missing method (completing the findLast... and find...Char methods) s32 findLastChar(const T* const c, u32 count) const Changed signature (Added return value) string& trim() Changes for Version 1.4.2 ------------------------- This is once more a bugfix release of the 1.4 branch, and hence pretty API-consistent and backward compatible. The major reason to publish this release is the OpenGL bug, which made several OpenGL 2.x drivers run in SW emulation. However, we also introduced some driver consistency fixes, which might affect your application's behavior. So read through the next points thoroughly. SceneParameters.h (and general video driver behavior) The way Irrlicht handles zbuffer writing with transparent materials has changed. This was an issue ever since, because the default behavior in Irrlicht is to disable writing to the z-buffer for all really transparent, i.e. blending materials. This avoids problems with intersecting faces, but can also break renderings. And this is now consistent for both OpenGL and Direct3D. If transparent materials should use the SMaterial flag for ZWriteEnable just as other material types use the newly introduced attribute scene::ALLOW_ZWRITE_ON_TRANSPARENT like this: SceneManager->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); All transparent materials will henceforth work as specified by the material flag, until the scenemanager attribute is set to false. SMaterialLayer.h The texture matrix now uses irrAllocator for memory handling. This shouldn't be noticeable from the user application (besides fixed heap corruptions on Windows machines), but is still mentioned for completeness. ISceneNode.h Documentation error. The docs said that children of a scene node are not visible if the node itself is set to visible. This is of course wrong, children inherit non-visibility of the parent and are hence invisible if the parent is. If the parent is visible, the visibility flag of the child determines its status. SColor.h Removed methods (use the unsigned versions and cast in your app if necessary) inline s32 getRedSigned(u16 color) inline s32 getGreenSigned(u16 color) inline s32 getBlueSigned(u16 color) IParticleSystemSceneNode.h Changed default values (the old direction default was no real direction) virtual IParticleAnimatedMeshSceneNodeEmitter* createAnimatedMeshSceneNodeEmitter(...) virtual IParticleCylinderEmitter* createCylinderEmitter(...) virtual IParticleMeshEmitter* createMeshEmitter(...) IBoneSceneNode.h Changed signature (Made const) virtual E_BONE_SKINNING_SPACE getSkinningSpace() const=0; IrrlichtDevice.h Changed signature (Return value bool instead of void). Returns whether the event has been handled somewhere. virtual bool postEventFromUser(const SEvent& event) = 0; Changes for Version 1.5 ----------------------- Another major release, so expect API breaks at several places. The changes herein are described as a difference to Irrlicht 1.4.2. The most noticeable changes are the speed factor of the FPS camera (now units/ms instead of units/s, so divide the parameter by 1000.f) and the new interfaces of the camera nodes, based on scene node animators. Custom camera nodes should be adpated to this new scheme, although they might still work. Also, particle sizes are now set and handled by the emitters, which requires a change of the particle system constructor call or adaption of the setParticleSize method to work on the emitters. A deprecation method is issued if the old scheme is used. Light setting has also changed, the SLight struct is used in even less situations than before, instead use methods in ILightSceneNode. Other changes did change major parts of the underlying structures, but might go unnoticed on the user level. This includes 32bit indices and Vertex Buffer Objects. However, VBOs require the user to call setDirty on Meshes or MeshBuffers after changes to the vertex or index data. The all need only to be done once before the next render call, but again after subsequent changes later on. All Mesh types and MeshBuffers: New methods for VBO support. Once VBOs are enabled for a meshbuffer, changes will only be effective after a call to setDirty(). VBOs are enabled by default for some scene nodes. virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX); All MeshBuffers: Due to the 32bit support, it might happen that indices are stored as 32bit integers. The actual index type can be queried from a mesh buffer. virtual video::E_INDEX_TYPE getIndexType() const IrrCompileConfig.h Some new defines for configuring Irrlicht _IRR_USE_WINDOWS_CE_DEVICE_ for Windows CE API based device _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ to enable joystick support (enabled by default) _IRR_COMPILE_WITH_LWO_LOADER_ to enable the LWO mesh loader (enabled by default) _IRR_COMPILE_WITH_OBJ_WRITER_ to enable the OBJ mesh writer (enabled by default) _IRR_COMPILE_WITH_WAL_LOADER_ to enable the WAL image loader (enabled by default) _IRR_USE_NVIDIA_PERFHUD_ for support of the PerfHUD tool (disabled by default) SceneParameters.h New parameter scene::OBJ_LOADER_IGNORE_GROUPS, which allows to ignore the group structure of obj files. It's disabled by default, meaning obj groups will be represented by separate meshbuffers. SColor.h Renamed method names of the SColorHSL class void fromRGB(const SColor &color); void toRGB(SColor &color) const; ITexture.h Added new parameter virtual void* lock(bool readOnly = false) = 0; IMeshManipulator.h Renamed methods (the old ones still exist, but are deprecated). The new methods also work on meshbuffers, not just meshes. (renamed from scaleMesh) virtual void scale(IMesh* mesh, const core::vector3df& factor) const = 0; (renamed from transformMesh) virtual void transform(IMesh* mesh, const core::matrix4& m) const = 0; Changed signature (Added new parameters to adjust the algorithm) virtual IMesh* createMeshWithTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false) const = 0; IBillboardTextSceneNode.h New interface replacing the multiple inheritance from bliiboard and text scene node previously used by the billboard text scene node. IParticleSystemSceneNode.h All emitters have minStartSize and maxStartSize parameters now, since partice size is handled by the emitters now. Default value added virtual void setParticlesAreGlobal(bool global=true) = 0; fast_atof.h Signature change (return value changed from u32) inline s32 strtol10(const char* in, const char** out=0) Signature change (parameter changed from float) inline const char* fast_atof_move( const char * in, f32 & out) IAnimatedMeshSceneNode.h Added new parameter (dummy node used for simplifying shadow calculation) virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh=0, s32 id=-1, bool zfailmethod=true, f32 infinity=10000.0f) = 0; ISceneManager.h Removed extra render passes for quake shaders Changed scene node from ISceneNode to IMeshSceneNode virtual IMeshSceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1, ...) virtual IMeshSceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ...) Changed default value (from 256 to 512, for efficiency on common gfx hardware) virtual ISceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) = 0; Changed default value (from 500.f, to adapt the changed speed scale) virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, f32 rotateSpeed = 100.0f, f32 moveSpeed = .5f, s32 id=-1, ...) Added default values virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, u32 horiRes=16, u32 vertRes=8, f64 texturePercentage=0.9, f64 spherePercentage=2.0, ISceneNode* parent=0, s32 id=-1) = 0; Changed return value (from ITextSceneNode, due to changed inheritance) virtual IBillboardTextSceneNode* addBillboardTextSceneNode( gui::IGUIFont* font, const wchar_t* text, ...) Changed default value (gravity, from -100.f) virtual ISceneNodeAnimatorCollisionResponse* createCollisionResponseAnimator( ITriangleSelector* world, ISceneNode* sceneNode, const core::vector3df& ellipsoidRadius = core::vector3df(30,60,30), const core::vector3df& gravityPerSecond = core::vector3df(0,-10.0f,0), const core::vector3df& ellipsoidTranslation = core::vector3df(0,0,0), f32 slidingValue = 0.0005f) = 0; ISceneNodeAnimator.h Changed inheritance (for interactive animators) class ISceneNodeAnimator : public io::IAttributeExchangingObject, public IEventReceiver Changed to pure virtual (bug fix) virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0) = 0; IVideoModeList.h Changed return value (constification) virtual const core::dimension2d& getDesktopResolution() const = 0; IBoneSceneNode.h Deprecation: Use getName instead. virtual const c8* getBoneName() const; vector3d.h Changed return value (return *this) vector3d& set(const T nx, const T ny, const T nz) {X=nx; Y=ny; Z=nz; return *this;} vector3d& set(const vector3d& p) {X=p.X; Y=p.Y; Z=p.Z;return *this;} vector3d& setLength(T newlength) vector3d& invert() Added default value void rotateXZBy(f64 degrees, const vector3d& center=vector3d()) void rotateXYBy(f64 degrees, const vector3d& center=vector3d()) void rotateYZBy(f64 degrees, const vector3d& center=vector3d()) Changed parameter type (interpolation factor must not be integral) vector3d getInterpolated(const vector3d& other, f64 d) const vector3d getInterpolated_quadratic(const vector3d& v2, const vector3d& v3, f64 d) const Method made const vector3d getHorizontalAngle() const SLight.h Attenuation can be overridden by ILightSceneMethod setRadius() Attenuation will change to (0,1.f/radius,0). Can be overridden after radius was set. The following members are read-only now: f32 Radius; E_LIGHT_TYPE Type; bool CastShadows; ITerrainSceneNode.h Parameter type changed (diue to possible 32bit indices) virtual void getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD=0) const =0; Added dafault value (highest detail) virtual void setLODOfPatch(s32 patchX, s32 patchZ, s32 LOD=0) =0; SExposedVideoData.h Changed member attributes (from s32, to fix 64bit architecture problems) void* HWnd; void* HDc; void* HRc; void* HWnd; IAnimatedMeshMD3.h Changed return value (constification) const SMD3QuaterionTag& operator[](u32 index) const IQ3Shader.h Changed default q3 shader values (from LIGHTMAP_M2) const video::E_MATERIAL_TYPE defaultMaterialType = video::EMT_LIGHTMAP_M4; const video::E_MODULATE_FUNC defaultModulate = video::EMFN_MODULATE_4X; ISceneNode.h Method made virtual virtual const core::matrix4& getAbsoluteTransformation() const Changed return value (constified) virtual const core::vector3df& getScale() const virtual const core::vector3df& getPosition() const IEventReceiver.h Removed member from UserEvent f32 UserData3; SMaterial.h Changed member type (from u32) char ZBuffer; IGUISkin.h Added parameter (for alignment) virtual void draw3DTabButton(IGUIElement* element, bool active, const core::rect& rect, const core::rect* clip=0, gui::EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT) = 0; virtual void draw3DTabBody(IGUIElement* element, bool border, bool background, const core::rect& rect, const core::rect* clip=0, s32 tabHeight=-1, gui::EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT ) = 0; quaternion.h Renamed method (from getDotProduct) inline f32 dotProduct(const quaternion& other) const; Changed return value (return *this) quaternion& set(f32 x, f32 y, f32 z, f32 w); quaternion& set(f32 x, f32 y, f32 z); quaternion& set(const core::vector3df& vec); quaternion& makeInverse(); quaternion& slerp( quaternion q1, quaternion q2, f32 interpolate ); quaternion& fromAngleAxis (f32 angle, const vector3df& axis); quaternion& makeIdentity(); quaternion& rotationFromTo(const vector3df& from, const vector3df& to); IVideoDriver.h Added parameters (moved from endScene) and added default values virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), void* windowId=0, core::rect* sourceRect=0) = 0; Removed parameter (move to beginScene) virtual bool endScene() = 0; Renamed method (note, also affects ReferenceCount behavior!) Use addRenderTargetTexture instead of createRenderTargetTexture virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const c8* name=0) =0; Changed parameters (for 32bit index support) virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) = 0; Changed parameter (colors are const pointers now) virtual void draw2DImage(const video::ITexture* texture, const core::rect& destRect, const core::rect& sourceRect, const core::rect* clipRect = 0, const video::SColor * const colors=0, bool useAlphaChannelOfTexture=false) = 0; IQ3LevelMesh.h Added default value virtual const quake3::SShader* getShader( const c8* filename, bool fileNameIsValid=true ) = 0; ICameraSceneNode.h Added method parameter (required to set orthogonal together with projection to avoid inconsistencies) virtual void setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal = false) = 0; Removed method (use new parameter in setProjectionMatrix) void setIsOrthogonal( bool orthogonal ) Constified return value virtual const core::vector3df& getTarget() const = 0; virtual const core::vector3df& getUpVector() const = 0; matrix4.h Removed method (use transformPlane) void transformPlane_new( core::plane3d &plane) const; Changed qulifications (to enable use under Win32 systems, too) IRRLICHT_API extern const matrix4 IdentityMatrix; SIrrCreationParameters.h Changed member attribute types u8 Bits; const c8* const SDK_version_do_not_use; IGUIElement.h Renamed method from setRelativePosition (to distinguish rather different parameter interpretation) void setRelativePositionProportional(const core::rect& r) irrString.h Constructors made explicit (use core::stringc(var) in places where var was used before) explicit string(const double number) explicit string(int number) explicit string(unsigned int number) Added parameter (allows use of method for stringw, and other things) string& trim(const string & whitespace = " \t\n\r") vector2d.h Changed return value (return *this) vector2d& set(T nx, T ny) {X=nx; Y=ny; return *this; } vector2d& set(const vector2d& p) { X=p.X; Y=p.Y; return *this; } Added default value vector2d& rotateBy(f64 degrees, const vector2d& center=vector2d()) Changed parameter type (interpolation factor must not be int) vector2d getInterpolated(const vector2d& other, f64 d) const vector2d getInterpolated_quadratic(const vector2d& v2, const vector2d& v3, f64 d) const vector2d& interpolate(const vector2d& a, const vector2d& b, f64 d) Changes for Version 1.5.1 ------------------------- This release is a pure bugfixes release, with almost no visible API changes. All changes should be backward compatible (as it's just a minor release), but you have to recompile the app due to changes in the virtual method tables. dimension2d.h Fixed a bug in the operator+=, added operator-= and changed comparison to equal() method. dimension2d& operator-=(const dimension2d& other) IrrCompileConfig.h Added defines to check for the Irrlicht version in the code. IRRLICHT_VERSION_MAJOR IRRLICHT_VERSION_MINOR IRRLICHT_VERSION_REVISION IRRLICHT_VERSION_SVN // only defined if you're using a version from SVN, i.e. not officially released one IrrlichtDevice.h Added static method isDriverSupported which checks the driver support of the library static bool isDriverSupported(video::E_DRIVER_TYPE driver) irrMath.h Added iszero specialization for f64 bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_64) irrXML.h Added deleteCallback flag for cleanup of the ReadCallback. IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback, bool deleteCallback = false); IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback, bool deleteCallback = false); IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback, bool deleteCallback = false); ISceneNode.h Added getSceneManager to get the currently used scene manager of the node. ISceneManager* getSceneManager(void) const IVideoDriver.h Added default values for vType, pType, and iType virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primCount, E_VERTEX_TYPE vType=EVT_STANDARD, scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, E_INDEX_TYPE iType=EIT_16BIT) Added method to draw 2d rectangle outline void draw2DRectangleOutline(const core::recti& pos, SColor color=SColor(255,255,255,255)) matrix4.h Added method to get transposedInverse CMatrix4 transposedInverse(*this, EM4CONST_INVERSE_TRANSPOSED) rect.h Added typedefs typedef rect rectf; typedef rect recti; SSharedMeshBuffer.h Split hardware mapping hint into vertex and index part E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const E_HARDWARE_MAPPING getHardwareMappingHint_Index() const void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX ) vector2d.h Fix angle calculation for integer vectors Changes for Version 1.5.2 ------------------------- Even less visible changes have been made in this version. Only the automatic Solaris OS recognition has changed, so make sure you have all things defined properly if you compile for Solaris. And the float parser bugfix is a visible change, though non-interfering for existing code. Changes for Version 1.6.0 ------------------------- This releases has many changes in method signatures. The most obvious ones are signedness changes from s32 to u32. Since many templates won't accept both types, you need to change the types manually in your code. The other major change is from many different types of strings to the new class io::path. These changes should be transparent to the app, unless you need proper overrides in derived classes. Finally, some deprecated methods have been removed, and some were simply renamed. Just check the API if some methods is not found anymore. IMeshSceneNode.h Added default parameters for identity transformation IMeshSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1,1,1)) path.h This is a new type, which handles stuff with UTF file systems. typedef core::string io::path; ESceneNodeTypes.h New scene node identifiers ESNT_SKY_DOME = MAKE_IRR_ID('s','k','y','d'), ESNT_Q3SHADER_SCENE_NODE = MAKE_IRR_ID('q','3','s','h'), ESNT_VOLUME_LIGHT = MAKE_IRR_ID('v','o','l','l'), IGUIListBox.h New methods virtual void setSelected(const wchar_t *item) = 0; virtual void setItemHeight( s32 height ) = 0; virtual void setDrawBackground(bool draw) = 0; ITexture.h New texture generation flag for burnings video driver //! Allow the Driver to use Non-Power-2-Textures ETCF_ALLOW_NON_POWER_2 = 0x00000040, Parameter change (now using path type instead of C-strings) ITexture(const io::path& name) Signedness change virtual const core::dimension2d& getOriginalSize() const = 0; virtual const core::dimension2d& getSize() const = 0; New method virtual bool hasAlpha() const Parameter change (now using path type instead of stringc) const io::path& getName() const ILightManager.h This is a new interface for the light manager class ILightManager : public IReferenceCounted IGUIEditBox.h Signedness change virtual core::dimension2du getTextDimension() = 0; ITriangleSelector.h New method virtual const ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const = 0; IMeshManipulator.h New methods virtual void makePlanarTextureMapping(scene::IMeshBuffer* meshbuffer, f32 resolution=0.001f) const =0; virtual void makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const =0; virtual IMesh* createMeshWith1TCoords(IMesh* mesh) const = 0; SceneParameters.h Removed parameter const c8* const DMF_USE_MATERIALS_DIRS = "DMF_MaterialsDir"; New parameters const c8* const DMF_IGNORE_MATERIALS_DIRS = "DMF_IgnoreMaterialsDir"; const c8* const OBJ_LOADER_IGNORE_MATERIAL_FILES = "OBJ_IgnoreMaterialFiles"; const c8* const B3D_LOADER_IGNORE_MIPMAP_FLAG = "B3D_IgnoreMipmapFlag"; const c8* const DEBUG_NORMAL_LENGTH = "DEBUG_Normal_Length"; const c8* const DEBUG_NORMAL_COLOR = "DEBUG_Normal_Color"; SViewFrustum.h Removed method (use getTransform) void setTransformState( video::E_TRANSFORMATION_STATE state); New methods core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state); const core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state) const; bool clipLine(core::line3d& line) const; IFileList.h Changed parameters (to io::path) virtual const io::path& getFileName(u32 index) const = 0; virtual const io::path& getFullFileName(u32 index) const = 0; New methods virtual u32 getFileSize(u32 index) const = 0; virtual s32 findFile(const io::path& filename, bool isFolder=false) const = 0; virtual const io::path& getPath() const = 0; coreutil.h New methods s32 isFileExtension(const io::path& filename, const io::path& ext0, const io::path& ext1, const io::path& ext2) bool hasFileExtension(const io::path& filename, const io::path& ext0, const io::path& ext1 = "", const io::path& ext2 = "") stringw& cutFilenameExtension ( stringw &dest, const stringw &source ) core::stringw& deletePathFromFilename(core::stringw& filename) core::stringc& deletePathFromFilename(core::stringc& filename) io::path& deletePathFromPath(io::path& filename, s32 pathCount) s32 isInSameDirectory ( const io::path& path, const io::path& file ) IGUIComboBox.h New methods virtual u32 getItemData(u32 idx) const = 0; virtual s32 getIndexForItemData(u32 data ) const = 0; New parameter virtual u32 addItem(const wchar_t* text, u32 data = 0) = 0; irrArray.h New allocation scheme member array() Use overload instead of different name s32 binary_search(const T& element) const New method void setAllocStrategy ( eAllocStrategy newStrategy = ALLOC_STRATEGY_DOUBLE ) s32 binary_search_multi(const T& element, s32 &last) IrrCompileConfig.h New compiler flags #define _IRR_MATERIAL_MAX_TEXTURES_ 4 //! Define _IRR_D3D_USE_LEGACY_HLSL_COMPILER to enable the old HLSL compiler in recent DX SDKs #define BURNINGVIDEO_RENDERER_CE #define IGNORE_DEPRECATED_WARNING #define _IRR_COMPILE_WITH_PLY_LOADER_ #define _IRR_COMPILE_WITH_PLY_WRITER_ #define _IRR_COMPILE_WITH_RGB_LOADER_ #define __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ #define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ #define __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ #define __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ //! _IRR_WINDOWS_CE_PLATFORM_ for Windows CE //! _IRR_COMPILE_WITH_WINDOWS_DEVICE_ for Windows API based device //! _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ for Windows CE API based device //! _IRR_COMPILE_WITH_OSX_DEVICE_ for Cocoa native windowing on OSX //! _IRR_COMPILE_WITH_X11_DEVICE_ for Linux X11 based device //! _IRR_COMPILE_WITH_SDL_DEVICE_ for platform independent SDL framework //! _IRR_COMPILE_WITH_CONSOLE_DEVICE_ for no windowing system, used as a fallback Removed compiler flags //! _IRR_USE_SDL_DEVICE_ for platform independent SDL framework //! _IRR_USE_WINDOWS_DEVICE_ for Windows API based device //! _IRR_USE_WINDOWS_CE_DEVICE_ for Windows CE API based device //! _IRR_USE_LINUX_DEVICE_ for X11 based device //! _IRR_USE_OSX_DEVICE_ for Cocoa native windowing on OSX Old compilers rejected # error "Only Microsoft Visual Studio 7.0 and later are supported." Force symbol export in shared libraries built with gcc. #define IRRLICHT_API __attribute__ ((visibility("default"))) IGUIFileOpenDialog.h New method virtual const io::path& getDirectoryName() = 0; EDeviceTypes.h New enum for multi-device support enum E_DEVICE_TYPE IMeshLoader.h Changed parameter to use io::path instead of C strings virtual bool isALoadableFileExtension(const io::path& filename) const = 0; IAnimatedMeshSceneNode.h Changed return value to pointer type virtual const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname) = 0; ISceneManager.h New enum values and numbering enum E_SCENE_NODE_RENDER_PASS ESNRP_NONE =0, ESNRP_TRANSPARENT =16, ESNRP_TRANSPARENT_EFFECT =32, Changed parameter to use io::path instead of C strings virtual IAnimatedMesh* getMesh(const io::path& filename) = 0; New methods virtual io::IFileSystem* getFileSystem() = 0; virtual ITriangleSelector* createTriangleSelector(IAnimatedMeshSceneNode* node) = 0; virtual const c8* getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) = 0; virtual ISkinnedMesh* createSkinnedMesh() = 0; virtual void setLightManager(ILightManager* lightManager) = 0; virtual const IGeometryCreator* getGeometryCreator(void) const = 0; virtual bool isCulled(const ISceneNode* node) const =0; Changed return type to IMeshSceneNode virtual IMeshSceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) = 0; virtual IMeshSceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; virtual IMeshSceneNode* addQuake3SceneNode(IMeshBuffer* meshBuffer, const quake3::IShader * shader, ISceneNode* parent=0, s32 id=-1) = 0; New parameter invertMouse virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, f32 rotateSpeed = 100.0f, f32 moveSpeed = 0.5f, s32 id=-1, SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, f32 jumpSpeed = 0.f, bool invertMouse=false) = 0; New parameter radius virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, u32 horiRes=16, u32 vertRes=8, f32 texturePercentage=0.9, f32 spherePercentage=2.0,f32 radius = 1000.f, ISceneNode* parent=0, s32 id=-1) = 0; Changed to use io::path instead of C strings virtual ITerrainSceneNode* addTerrainSceneNode( const io::path& heightMapFileName, ISceneNode* parent=0, s32 id=-1, virtual IAnimatedMesh* addHillPlaneMesh(const io::path& name, const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material = 0, f32 hillHeight = 0.0f, const core::dimension2d& countHills = core::dimension2d(0.0f, 0.0f), const core::dimension2d& textureRepeatCount = core::dimension2d(1.0f, 1.0f)) = 0; virtual IAnimatedMesh* addArrowMesh(const io::path& name, video::SColor vtxColor0=0xFFFFFFFF, video::SColor vtxColor1=0xFFFFFFFF, u32 tesselationCylinder=4, u32 tesselationCone=8, virtual IAnimatedMesh* addSphereMesh(const io::path& name, f32 radius=5.f, u32 polyCountX = 16, u32 polyCountY = 16) = 0; virtual bool saveScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0) = 0; virtual bool loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0) = 0; Changed to use io::path instead of C strings and signedness change virtual IAnimatedMesh* addTerrainMesh(const io::path& meshname, video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize = core::dimension2d(10.0f,10.0f), f32 maxHeight=200.0f, const core::dimension2d& defaultVertexBlockSize = core::dimension2d(64,64)) = 0; New method virtual IAnimatedMesh* addVolumeLightMesh(const io::path& name, const u32 SubdivideU = 32, const u32 SubdivideV = 32, const video::SColor FootColor = video::SColor(51, 0, 230, 180), const video::SColor TailColor = video::SColor(0, 0, 0, 0)) = 0; Constification of method virtual ICameraSceneNode* getActiveCamera() const =0; New parameters virtual ISceneNodeAnimator* createFlyCircleAnimator( const core::vector3df& center=core::vector3df(0.f,0.f,0.f), f32 radius=100.f, f32 speed=0.001f, const core::vector3df& direction=core::vector3df(0.f, 1.f, 0.f), f32 startPosition = 0.f, f32 radiusEllipsoid = 0.f) = 0; virtual ISceneNodeAnimator* createFlyStraightAnimator(const core::vector3df& startPoint, const core::vector3df& endPoint, u32 timeForWay, bool loop=false, bool pingpong = false) = 0; ISceneNodeAnimatorCollisionResponse.h New interface class ICollisionCallback : public virtual IReferenceCounted New methods for ISceneNodeAnimatorCollisionResponse virtual void setAnimateTarget ( bool enable ) = 0; virtual bool getAnimateTarget () const = 0; virtual void setTargetNode(ISceneNode * node) = 0; virtual ISceneNode* getTargetNode(void) const = 0; virtual bool collisionOccurred() const = 0; virtual const core::vector3df & getCollisionPoint() const = 0; virtual const core::triangle3df & getCollisionTriangle() const = 0; virtual const core::vector3df & getCollisionResultPosition(void) const = 0; virtual const ISceneNode* getCollisionNode(void) const = 0; virtual void setCollisionCallback(ICollisionCallback* callback) = 0; ILightSceneNode.h New methods virtual void setVisible(bool isVisible) = 0; EMeshWriterEnums.h New enums EMWT_PLY = MAKE_IRR_ID('p','l','y',0) EMWF_WRITE_BINARY = 0x4 ISceneNodeAnimator.h New method virtual bool hasFinished(void) const SMaterialLayer.h Changed types u8 TextureWrap; bool BilinearFilter:1; bool TrilinearFilter:1; u8 AnisotropicFilter; New member s8 LODBias; IVideoModeList.h Signedness change virtual core::dimension2d getVideoModeResolution(s32 modeNumber) const = 0; virtual core::dimension2d getVideoModeResolution(const core::dimension2d& minSize, const core::dimension2d& maxSize) const = 0; virtual const core::dimension2d& getDesktopResolution() const = 0; EMaterialFlags.h Enum values changed (all renumbered) ISkinnedMesh.h Renamed methods (was create... before, but these methods grab the things they create) virtual SSkinMeshBuffer* addMeshBuffer() = 0; virtual SJoint* addJoint(SJoint *parent=0) = 0; virtual SWeight* addWeight(SJoint *joint) = 0; virtual SPositionKey* addPositionKey(SJoint *joint) = 0; virtual SScaleKey* addScaleKey(SJoint *joint) = 0; virtual SRotationKey* addRotationKey(SJoint *joint) = 0; SLight.h Type change bool CastShadows:1; IGUITreeView.h New element // written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de class IGUITreeView : public IGUIElement IAnimatedMeshMD3.h Renamed class (from SMD3QuaterionTag) struct SMD3QuaternionTag IGUIEnvironment.h New methods virtual IGUIImageList* createImageList( video::ITexture* texture, core::dimension2d imageSize, bool useAlphaChannel ) = 0; virtual IGUITreeView* addTreeView(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, bool drawBackground=false, bool scrollBarVertical = true, bool scrollBarHorizontal = false) = 0; Changed parameters to use io::path (instead of C strings) virtual IGUIFont* getFont(const io::path& filename) = 0; virtual IGUISpriteBank* getSpriteBank(const io::path& filename) = 0; virtual IGUISpriteBank* addEmptySpriteBank(const io::path& name) = 0; virtual bool saveGUI(const io::path& filename, IGUIElement* start=0) = 0; virtual bool loadGUI(const io::path& filename, IGUIElement* parent=0) = 0; New parameter "border" virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect& rectangle, bool border=true,IGUIElement* parent=0, s32 id=-1) = 0; IQ3Shader.h Made non-const static core::stringc irrEmptyStringc(""); New enum values enum eQ3MeshIndex E_Q3_MESH_FOG, E_Q3_MESH_UNRESOLVED, IGeometryCreator.h New interface class IGeometryCreator : public IReferenceCounted IFileArchive.h New interfaces class IFileArchive : public virtual IReferenceCounted class IArchiveLoader : public virtual IReferenceCounted IFileSystem.h Changed parameters to use io::path (instead of C strings/stringc) virtual IReadFile* createAndOpenFile(const path& filename) =0; virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const path& fileName, bool deleteMemoryWhenDropped=false) =0; virtual IWriteFile* createAndWriteFile(const path& filename, bool append=false) =0; virtual const path& getWorkingDirectory() =0; virtual bool changeWorkingDirectoryTo(const path& newDirectory) =0; virtual path getAbsolutePath(const path& filename) const =0; virtual path getFileDir(const path& filename) const =0; virtual path getFileBasename(const path& filename, bool keepExtension=true) const =0; virtual bool existFile(const path& filename) const =0; virtual IXMLReader* createXMLReader(const path& filename) =0; virtual IXMLReaderUTF8* createXMLReaderUTF8(const path& filename) =0; virtual IXMLWriter* createXMLWriter(const path& filename) =0; New methods virtual IReadFile* createLimitReadFile(const path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize) =0; virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const path& fileName, bool deleteMemoryWhenDropped=false) =0; virtual bool addFileArchive(const path& filename, bool ignoreCase=true, bool ignorePaths=true, E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN) =0; virtual void addArchiveLoader(IArchiveLoader* loader) =0; virtual u32 getFileArchiveCount() const =0; virtual bool removeFileArchive(u32 index) =0; virtual bool removeFileArchive(const path& filename) =0; virtual bool moveFileArchive(u32 sourceIndex, s32 relative) =0; virtual IFileArchive* getFileArchive(u32 index) =0; virtual path& flattenFilename(path& directory, const path& root="/") const =0; virtual EFileSystemType setFileListSystem(EFileSystemType listType) =0; Deprecate methods virtual bool addZipFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) virtual bool addFolderFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) virtual bool addPakFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) Constification of method virtual IFileList* createFileList() =0; IrrlichtDevice.h Renamed method (from setResizeAble) virtual void setResizable(bool resize=false) = 0; New methods virtual void minimizeWindow() =0; virtual void maximizeWindow() =0; virtual void restoreWindow() =0; virtual bool setGammaRamp(f32 red, f32 green, f32 blue, f32 relativebrightness, f32 relativecontrast) =0; virtual bool getGammaRamp(f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast) =0; virtual E_DEVICE_TYPE getType() const = 0; irrMath.h Renamed from ROUNDING_ERROR_32 const f32 ROUNDING_ERROR_f32 = 0.000001f; Renamed from ROUNDING_ERROR_64 const f64 ROUNDING_ERROR_f64 = 0.00000001; New constant const s32 ROUNDING_ERROR_S32 = 1; New methods bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32) u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b ) f32 squareroot(const f32 f) f64 squareroot(const f64 f) s32 squareroot(const s32 f) f64 reciprocal_squareroot(const f64 x) s32 reciprocal_squareroot(const s32 x) f64 reciprocal ( const f64 f ) IGPUProgrammingServices.h Changed parameters to use io::path virtual s32 addHighLevelShaderMaterialFromFiles( const io::path& vertexShaderProgramFileName, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, const io::path& pixelShaderProgramFileName = "", const c8* pixelShaderEntryPointName = "main", E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, IShaderConstantSetCallBack* callback = 0, virtual s32 addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName, const io::path& pixelShaderProgramFileName, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0) = 0; ISceneNode.h New method virtual bool isTrulyVisible() const IEventReceiver.h New enum values EMIE_MOUSE_DOUBLE_CLICK, EMIE_MOUSE_TRIPLE_CLICK, EGET_DIRECTORY_SELECTED, EGET_EDITBOX_CHANGED, EGET_EDITBOX_MARKING_CHANGED, EGET_TREEVIEW_NODE_DESELECT, EGET_TREEVIEW_NODE_SELECT, EGET_TREEVIEW_NODE_EXPAND, EGET_TREEVIEW_NODE_COLLAPS, EGET_COUNT New enum enum E_MOUSE_BUTTON_STATE_MASK New members bool Shift:1; bool Control:1; u32 ButtonStates; New methods bool isLeftPressed() const { return 0 != ( ButtonStates & EMBSM_LEFT ); } bool isRightPressed() const { return 0 != ( ButtonStates & EMBSM_RIGHT ); } bool isMiddlePressed() const { return 0 != ( ButtonStates & EMBSM_MIDDLE ); } Types changed bool PressedDown:1; bool Shift:1; bool Control:1; IGUISpriteBank.h New method virtual void draw2DSpriteBatch(const core::array& indices, const core::array& pos, const core::rect* clip=0, const video::SColor& color= video::SColor(255,255,255,255), u32 starttime=0, u32 currenttime=0, bool loop=true, bool center=false) = 0; SMaterial.h New enums enum E_COMPARISON_FUNC enum E_COLOR_PLANE enum E_ALPHA_SOURCE enum E_ANTI_ALIASING_MODE enum E_COLOR_MATERIAL New parameters inline f32 pack_texureBlendFunc ( const E_BLEND_FACTOR srcFact, const E_BLEND_FACTOR dstFact, const E_MODULATE_FUNC modulate=EMFN_MODULATE_1X, const u32 alphaSource=EAS_TEXTURE ) inline void unpack_texureBlendFunc ( E_BLEND_FACTOR &srcFact, E_BLEND_FACTOR &dstFact, E_MODULATE_FUNC &modulo, u32& alphaSource, const f32 param ) New methods inline bool textureBlendFunc_hasAlpha ( const E_BLEND_FACTOR factor ) Default value set elsewhere now (see IrrCompileConfig.h) const u32 MATERIAL_MAX_TEXTURES = _IRR_MATERIAL_MAX_TEXTURES_; Types changed u8 ZBuffer; bool Wireframe:1; bool PointCloud:1; bool GouraudShading:1; bool Lighting:1; bool ZWriteEnable:1; bool BackfaceCulling:1; bool FrontfaceCulling:1; bool FogEnable:1; bool NormalizeNormals:1; New members u8 AntiAliasing; u8 ColorMask:4; u8 ColorMaterial:3; New constant IRRLICHT_API extern SMaterial IdentityMaterial; IGUISkin.h New enum values EGDS_TITLEBARTEXT_DISTANCE_X, EGDS_TITLEBARTEXT_DISTANCE_Y, quaternion.h New parameters void getMatrix( matrix4 &dest, const vector3df &translation ) const; New method void getMatrixCenter( matrix4 &dest, const vector3df ¢er, const vector3df &translation ) const; ISceneNodeAnimatorCameraFPS.h New method virtual void setInvertMouse(bool invert) = 0; IImage.h New enum values /** Floating Point formats. The following formats may only be used for render target textures. */ ECF_R16F, ECF_G16R16F, ECF_A16B16G16R16F, ECF_R32F, ECF_G32R32F, ECF_A32B32G32R32F, ECF_UNKNOWN Signedness change virtual const core::dimension2d& getDimension() const = 0; virtual void copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format=ECF_A8R8G8B8, u32 pitch=0) =0; New parameter virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ) = 0; New method virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) = 0; static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format) static bool isRenderTargetOnlyFormat(const ECOLOR_FORMAT format) IVideoDriver.h New enum values (only existing if _IRR_MATERIAL_MAX_TEXTURES_ large enough) ETS_TEXTURE_4 ETS_TEXTURE_5 ETS_TEXTURE_6 ETS_TEXTURE_7 New enums enum E_RENDER_TARGET enum E_FOG_TYPE New type struct SOverrideMaterial New methods virtual u32 getImageLoaderCount() const = 0; virtual IImageLoader* getImageLoader(u32 n) = 0; virtual u32 getImageWriterCount() const = 0; virtual IImageWriter* getImageWriter(u32 n) = 0; virtual bool setRenderTarget(E_RENDER_TARGET target, bool clearTarget=true, bool clearZBuffer=true, SColor color=video::SColor(0,0,0,0)) =0; virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primCount, E_VERTEX_TYPE vType=EVT_STANDARD, scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, E_INDEX_TYPE iType=EIT_16BIT) =0; virtual void draw2DImageBatch(const video::ITexture* texture, const core::array >& positions, const core::array >& sourceRects, const core::rect* clipRect=0, SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) =0; virtual void turnLightOn(s32 lightIndex, bool turnOn) =0; virtual bool writeImageToFile(IImage* image, io::IWriteFile* file, u32 param =0) =0; virtual IImage* createImage(ITexture* texture, const core::position2d& pos, const core::dimension2d& size) =0; virtual void setMinHardwareBufferVertexCount(u32 count) =0; virtual SOverrideMaterial& getOverrideMaterial() =0; Changed parameters to use io::path virtual ITexture* getTexture(const io::path& filename) = 0; virtual void renameTexture(ITexture* texture, const io::path& newName) = 0; virtual ITexture* addTexture(const io::path& name, IImage* image) = 0; virtual IImage* createImageFromFile(const io::path& filename) = 0; virtual bool writeImageToFile(IImage* image, const io::path& filename, u32 param = 0) = 0; virtual video::ITexture* findTexture(const io::path& filename) = 0; Changed signedness virtual ITexture* addTexture(const core::dimension2d& size, const io::path& name, ECOLOR_FORMAT format = ECF_A8R8G8B8) = 0; virtual const core::dimension2d& getScreenSize() const =0; virtual const core::dimension2d& getCurrentRenderTargetSize() const =0; virtual IImage* createImageFromData(ECOLOR_FORMAT format, const core::dimension2d& size, void *data, bool ownForeignMemory=false, bool deleteMemory = true) =0; virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d& size) =0; virtual IImage* createImage(IImage* imageToCopy, const core::position2d& pos, const core::dimension2d& size) =0; virtual void OnResize(const core::dimension2d& size) =0; Changed signedness and usage of io::path virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const io::path& name = "rt", const ECOLOR_FORMAT format = ECF_UNKNOWN) =0; Removed deprecated method virtual ITexture* createRenderTargetTexture(const core::dimension2d& size, const c8* name=0) =0; New parameter virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor color, bool zeroTexels = false) const =0; virtual void makeColorKeyTexture(video::ITexture* texture, core::position2d colorKeyPixelPos, bool zeroTexels = false) const =0; Changed parameters virtual void setFog(SColor color=SColor(0,255,255,255), E_FOG_TYPE fogType=EFT_FOG_LINEAR, f32 start=50.0f, f32 end=100.0f, f32 density=0.01f, bool pixelFog=false, bool rangeFog=false) =0; Changed return types virtual s32 addDynamicLight(const SLight& light) =0; EDriverFeatures.h New enum values EVDF_ALPHA_TO_COVERAGE, EVDF_COLOR_MASK, IGUIScrollBar.h New methods virtual void setMin(s32 max) = 0; virtual s32 getMin() const = 0; IQ3LevelMesh.h Removed method virtual void releaseMesh(s32 index) = 0; Made return value non-const virtual quake3::tQ3EntityList& getEntityList() = 0; ISceneCollisionManager.h New parameter virtual bool getCollisionPoint(const core::line3d& ray, ITriangleSelector* selector, core::vector3df& outCollisionPoint, core::triangle3df& outTriangle, const ISceneNode*& outNode) =0; virtual core::vector3df getCollisionResultPosition( ITriangleSelector* selector, const core::vector3df &ellipsoidPosition, const core::vector3df& ellipsoidRadius, const core::vector3df& ellipsoidDirectionAndSpeed, core::triangle3df& triout, core::vector3df& hitPosition, bool& outFalling, const ISceneNode*& outNode, f32 slidingSpeed = 0.0005f, const core::vector3df& gravityDirectionAndSpeed = core::vector3df(0.0f, 0.0f, 0.0f)) = 0; Made parameter const& virtual core::line3d getRayFromScreenCoordinates( const core::position2d & pos, ICameraSceneNode* camera = 0) = 0; virtual core::position2d getScreenCoordinatesFrom3DPosition( const core::vector3df & pos, ICameraSceneNode* camera=0) = 0; Made parameter const& and added new parameter virtual ISceneNode* getSceneNodeFromScreenCoordinatesBB(const core::position2d& pos, s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0) =0; virtual ISceneNode* getSceneNodeFromRayBB(const core::line3d& ray, s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0) =0; New method virtual ISceneNode* getSceneNodeAndCollisionPointFromRay( core::line3df ray, core::vector3df & outCollisionPoint, core::triangle3df & outTriangle, s32 idBitMask = 0, ISceneNode * collisionRootNode = 0, bool noDebugObjects = false) = 0; irrlicht.h Changed interface of method (qualifiers and signedness) extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDevice( video::E_DRIVER_TYPE deviceType = video::EDT_SOFTWARE, // parantheses are necessary for some compilers const core::dimension2d& windowSize = (core::dimension2d(640,480)), u32 bits = 16, bool fullscreen = false, bool stencilbuffer = false, bool vsync = false, IEventReceiver* receiver = 0); extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx( const SIrrlichtCreationParameters& parameters); IImageLoader.h Changed parameters to use io::path virtual bool isALoadableFileExtension(const io::path& filename) const = 0; IGUIWindow.h New methods virtual bool isDraggable() const = 0; virtual void setDraggable(bool draggable) = 0; virtual void setDrawBackground(bool draw) = 0; virtual bool getDrawBackground() const = 0; virtual void setDrawTitlebar(bool draw) = 0; virtual bool getDrawTitlebar() const = 0; ICameraSceneNode.h New methods virtual void setViewMatrixAffector(const core::matrix4& affector) =0; virtual const core::matrix4& getViewMatrixAffector() const =0; EGUIElementTypes.h New enum value EGUIET_TREE_VIEW, IImageWriter.h Changed parameters to use io::path virtual bool isAWriteableFileExtension(const io::path& filename) const = 0; SIrrCreationParameters.h Added members E_DEVICE_TYPE DeviceType; bool Doublebuffer; bool Stereobuffer; Changed signedness core::dimension2d WindowSize; Changed type (from bool) u8 AntiAlias; matrix4.h New methods bool isOrthogonal() const; CMatrix4& buildRotateFromTo(const core::vector3df& from, const core::vector3df& to); void setRotationCenter(const core::vector3df& center, const core::vector3df& translate); void buildAxisAlignedBillboard( const core::vector3df& camPos, const core::vector3df& center, const core::vector3df& translation, const core::vector3df& axis, const core::vector3df& from); IWriteFile.h Changed parameters to use io::path virtual const path& getFileName() const = 0; IGUITable.h New methods virtual void setSelected( s32 index ) = 0; Changed type (from wide c string) virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text) = 0; virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color) = 0; SKeyMap.h New enum value EKA_CROUCH, IGUIFont.h Changed type (from wide c string) virtual void draw(const core::stringw& text, const core::rect& position, video::SColor color, bool hcenter=false, bool vcenter=false, const core::rect* clip=0) = 0; Changed signedness virtual core::dimension2d getDimension(const wchar_t* text) const = 0; New method virtual void setInvisibleCharacters( const wchar_t *s ) = 0; IMeshCache.h Changed parameters to use io::path virtual void addMesh(const io::path& filename, IAnimatedMesh* mesh) = 0; virtual IAnimatedMesh* getMeshByFilename(const io::path& filename) = 0; virtual const io::path& getMeshFilename(u32 index) const = 0; virtual const io::path& getMeshFilename(const IAnimatedMesh* const mesh) const = 0; virtual const io::path& getMeshFilename(const IMesh* const mesh) const = 0; virtual bool setMeshFilename(u32 index, const io::path& filename) = 0; virtual bool setMeshFilename(const IAnimatedMesh* const mesh, const io::path& filename) = 0; virtual bool setMeshFilename(const IMesh* const mesh, const io::path& filename) = 0; virtual bool isMeshLoaded(const io::path& filename) = 0; IGUIButton.h Added default value virtual void setImage(video::ITexture* image=0) = 0; virtual void setPressedImage(video::ITexture* image=0) = 0; virtual void setSpriteBank(IGUISpriteBank* bank=0) = 0; virtual void setIsPushButton(bool isPushButton=true) = 0; virtual void setPressed(bool pressed=true) = 0; virtual void setUseAlphaChannel(bool useAlphaChannel=true) = 0; virtual void setDrawBorder(bool border=true) = 0; New methods virtual void setScaleImage(bool scaleImage=true) = 0; virtual bool isScalingImage() const = 0; position2d.h Replaced by vector2d IGUIImageList.h New interface class IGUIImageList : public virtual IReferenceCounted rect.h Added second template parameter to allow mismatched signedness template rect(const position2d& pos, const dimension2d& size) IParticleEmitter.h Removed wrong overrides virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const {} virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { return 0; } IOSOperator.h Return const string virtual const c8* getTextFromClipboard() const = 0; IGUIElement.h Signedness change void setMaxSize(core::dimension2du size) void setMinSize(core::dimension2du size) IReadFile.h Changed parameters to use io::path virtual const io::path& getFileName() const = 0; IReadFile* createReadFile(const io::path& fileName); IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize); IReadFile* createMemoryReadFile(void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped); IGUITabControl.h New methods virtual void setTabMaxWidth(s32 width ) = 0; virtual s32 getTabMaxWidth() const = 0; IParticleAffector.h Removed wrong overrides virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const {} virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { return 0; } ILogger.h New method virtual void log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION) = 0; vector2d.h New methods vector2d(const dimension2d& other) : X(other.Width), Y(other.Height) {} vector2d& operator=(const dimension2d& other) { X = other.Width; Y = other.Height; return *this; } vector2d operator+(const dimension2d& other) const { return vector2d(X + other.Width, Y + other.Height); } vector2d& operator+=(const dimension2d& other) { X += other.Width; Y += other.Height; return *this; } vector2d operator-(const dimension2d& other) const { return vector2d(X - other.Width, Y - other.Height); } vector2d& operator-=(const dimension2d& other) { X -= other.Width; Y -= other.Height; return *this; } // These methods are declared in dimension2d, but need definitions of vector2d template dimension2d::dimension2d(const vector2d& other) : Width(other.X), Height(other.Y) { } template bool dimension2d::operator==(const vector2d& other) const { return Width == other.X && Height == other.Y; } Changes for Version 1.6.1 ------------------------- This is again just a bugfix release. However, some minor API changes have happened. The most important one is the removal of lins anti-aliasing from SMaterial's default values. Please add that line smoothing flag to the materials you want to be smoothed. But note that this may lead to drastically reduced performance, if no multi-sampling is active. IFileList.h new methods virtual u32 getID(u32 index) const = 0; virtual u32 addItem(const io::path& fullPath, u32 size, bool isDirectory, u32 id=0) = 0; virtual void sort() = 0; IrrCompileConfig.h Removed auto recognition of Solaris OS, please define the setting on your own if you need it _IRR_SOLARIS_PLATFORM_ IGUITreeView.h removed methods (use automatically generated versions) IGUITreeViewNode() {} virtual ~IGUITreeViewNode() {} virtual ~IGUITreeView() {} IFileSystem.h new method virtual IFileList* createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths) =0; SMaterial.h Removed default value (EAAM_LINE_SMOOTH from AntiAliasing) ZBuffer(ECFN_LESSEQUAL), AntiAliasing(EAAM_SIMPLE), ColorMask(ECP_ALL), IGUISkin.h new enum value EGST_COUNT Changes for Version 1.7 ------------------------- This version has less API-breaking changes than the previous major changes. It has many new features, which simply add methods. All those changes, which affect old methods or structures are mostly put in parallel to the old (and now deprecated) methods. Only a few things are changed without backward compatibility: The texture wrap mode is split into separate U and V modes. The beginScene void* parameter has been replaced by an SExposedVideoData. Simply wrap the pointer with this struct and it should work again. EMIE_LMOUSE_DOUBLE_CLICK replaces EMIE_MOUSE_DOUBLE_CLICK and EMIE_LMOUSE_TRIPLE_CLICK replaces EMIE_MOUSE_TRIPLE_CLICK Elements used in the array container need now to have an operator= Here comes the full list: path.h New type struct SNamedPath triangle3d.h New method bool isTotalOutsideBox(const aabbox3d& box) const ESceneNodeTypes.h Changed enum value (from octt) ESNT_OCTREE = MAKE_IRR_ID('o','c','t','r'), SColor.h New method f32 getLightness() const driverChoice.h New method static irr::video::E_DRIVER_TYPE driverChoiceConsole(bool allDrivers=true) ITexture.h New parameter virtual void regenerateMipMapLevels(void* mipmapData=0) = 0; Changed return value (from io:path) const io::SNamedPath& getName() const { return NamedPath; } SceneParameters.h New scene parameters const c8* const OBJ_TEXTURE_PATH = "OBJ_TexturePath"; const c8* const B3D_TEXTURE_PATH = "B3D_TexturePath"; IMeshManipulator.h Not virtual anymore void setVertexColorAlpha(IMesh* mesh, s32 alpha) const void setVertexColors(IMesh* mesh, video::SColor color) const void scale(IMeshBuffer* buffer, const core::vector3df& factor) const void scaleMesh(IMesh* mesh, const core::vector3df& factor) const void scaleTCoords(scene::IMesh* mesh, const core::vector2df& factor, u32 level=1) const void scaleTCoords(scene::IMeshBuffer* buffer, const core::vector2df& factor, u32 level=1) const void transform(IMesh* mesh, const core::matrix4& m) const void transform(IMeshBuffer* buffer, const core::matrix4& m) const New method template bool apply(const Functor& func, IMeshBuffer* buffer, bool boundingBoxUpdate=false) const template bool apply(const Functor& func, IMesh* mesh, bool boundingBoxUpdate=false) const virtual void recalculateTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false) const=0; void scale(IMesh* mesh, const core::vector3df& factor) const New parameter virtual IMesh* createMeshWithTangents(IMesh* mesh, bool recalculateNormals=false, bool smooth=false, bool angleWeighted=false, bool recalculateTangents=true) const = 0; coreutil.h Changed return type and parameters (from stringc/w) inline io::path& cutFilenameExtension ( io::path &dest, const io::path &source ) inline io::path& getFileNameExtension ( io::path &dest, const io::path &source ) inline io::path& deletePathFromFilename(io::path& filename) Fixed behavior inline io::path& deletePathFromPath(io::path& filename, s32 pathCount) ICursorControl.h Return const-ref virtual const core::position2d& getPosition() = 0; irrArray.h Fixed allocator template usage array(const array& other) : data(0) const array& operator=(const array& other) bool operator == (const array& other) const bool operator != (const array& other) const Changed behavior for free_when_destroyed void set_pointer(T* newPointer, u32 size, bool _is_sorted=false, bool _free_when_destroyed=true) void set_free_when_destroyed(bool f) irrMap.h Renamed method (from isEmpty) bool empty() const New method void swap(map& other) IAnimatedMesh.h virtual f32 getAnimationSpeed() const =0; IAttributes.h Made parameters const-ref virtual void addArray(const c8* attributeName, const core::array& value) = 0; virtual void setAttribute(const c8* attributeName, const core::array& value) = 0; virtual void setAttribute(s32 index, const core::array& value) = 0; ISceneManager.h Renamed method (from OctTree) virtual IMeshSceneNode* addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) = 0; virtual IMeshSceneNode* addOctreeSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; virtual ITriangleSelector* createOctreeTriangleSelector(IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode=32) = 0; New parameter (makeActive) virtual ICameraSceneNode* addCameraSceneNode(ISceneNode* parent = 0, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& lookat = core::vector3df(0,0,100), s32 id=-1, bool makeActive=true) = 0; virtual ICameraSceneNode* addCameraSceneNodeMaya(ISceneNode* parent = 0, f32 rotateSpeed = -1500.0f, f32 zoomSpeed = 200.0f, f32 translationSpeed = 1500.0f, s32 id=-1, bool makeActive=true) = 0; virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, f32 rotateSpeed = 100.0f, f32 moveSpeed = 0.5f, s32 id=-1, SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, f32 jumpSpeed = 0.f, bool invertMouse=false, bool makeActive=true) = 0; Make parameter const virtual IMeshSceneNode* addQuake3SceneNode(const IMeshBuffer* meshBuffer, const quake3::IShader * shader, ISceneNode* parent=0, s32 id=-1) = 0; New parameter (loop, pingpong) virtual ISceneNodeAnimator* createFollowSplineAnimator(s32 startTime, const core::array< core::vector3df >& points, f32 speed = 1.0f, f32 tightness = 0.5f, bool loop=true, bool pingpong=false) = 0; SMaterialLayer.h New clamp modes ETC_MIRROR_CLAMP, ETC_MIRROR_CLAMP_TO_EDGE, ETC_MIRROR_CLAMP_TO_BORDER New material layer modes (replaces TextureWrap) TextureWrapU(ETC_REPEAT), TextureWrapV(ETC_REPEAT) vector3d.h Use tolerance to compare, changed order function to total order bool operator<=(const vector3d&other) const bool operator>=(const vector3d&other) const bool operator<(const vector3d&other) const bool operator>(const vector3d&other) const New method vector3d getSphericalCoordinateAngles() New method specializations template <> inline vector3d vector3d::operator /(s32 val) const {return core::vector3d(X/val,Y/val,Z/val);} template <> inline vector3d& vector3d::operator /=(s32 val) {X/=val;Y/=val;Z/=val; return *this;} SExposedVideoData.h New constructors SExposedVideoData() {OpenGLWin32.HDc=0; OpenGLWin32.HRc=0; OpenGLWin32.HWnd=0;} explicit SExposedVideoData(void* Window) {OpenGLWin32.HDc=0; OpenGLWin32.HRc=0; OpenGLWin32.HWnd=Window;} IGUIEnvironment.h New method virtual IGUIFont* addFont(const io::path& name, IGUIFont* font) = 0; New parameter (image) virtual IGUIWindow* addMessageBox(const wchar_t* caption, const wchar_t* text=0, bool modal = true, s32 flags = EMBF_OK, IGUIElement* parent=0, s32 id=-1, video::ITexture* image=0) = 0; IGeometryCreator.h New method IMesh* createPlaneMesh(const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material, const core::dimension2d& textureRepeatCount) const IFileArchive.h New archive type EFAT_NPK = MAKE_IRR_ID('N','P','K', 0), New member for storing the password of AES-encrypted archives core::stringc Password; IFileSystem.h New parameter (password) virtual bool addFileArchive(const path& filename, bool ignoreCase=true, bool ignorePaths=true, E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN, const core::stringc& password="") =0; IrrlichtDevice.h New method virtual void clearSystemMessages() = 0; irrMath.h Changed constant (from 1) const s32 ROUNDING_ERROR_S32 = 0; New method template inline void swap(T& a, T& b) IGPUProgrammingServices.h New parameters (for geometry shaders) virtual s32 addHighLevelShaderMaterial virtual s32 addHighLevelShaderMaterialFromFiles virtual s32 addHighLevelShaderMaterialFromFiles New overload (for calling with geometry shaders) s32 addHighLevelShaderMaterial s32 addHighLevelShaderMaterialFromFiles s32 addHighLevelShaderMaterialFromFiles ISceneNode.h New types typedef core::list ISceneNodeList; typedef core::list ISceneNodeAnimatorList; IEventReceiver.h Renamed events (split from EMIE_MOUSE_*) EMIE_LMOUSE_DOUBLE_CLICK, EMIE_RMOUSE_DOUBLE_CLICK, EMIE_MMOUSE_DOUBLE_CLICK, EMIE_LMOUSE_TRIPLE_CLICK, EMIE_RMOUSE_TRIPLE_CLICK, EMIE_MMOUSE_TRIPLE_CLICK, IGUISpriteBank.h New method virtual s32 addTextureAsSprite(video::ITexture* texture) = 0; virtual void clear() = 0; SMaterial.h Changed binary packing (non-visible from user calls) inline f32 pack_texureBlendFunc ( const E_BLEND_FACTOR srcFact, const E_BLEND_FACTOR dstFact, const E_MODULATE_FUNC modulate=EMFN_MODULATE_1X, const u32 alphaSource=EAS_TEXTURE ) IGUISkin.h New values EGDS_MESSAGE_BOX_GAP_SPACE, EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH, EGDS_MESSAGE_BOX_MAX_TEST_WIDTH, EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT, EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT, New parameter (checkClientArea) virtual core::rect draw3DWindowBackground(IGUIElement* element, bool drawTitleBar, video::SColor titleBarColor, const core::rect& rect, const core::rect* clip=0, core::rect* checkClientArea=0) = 0; quaternion.h New operator bool operator!=(const quaternion& other) const; New method inline quaternion& set(const core::quaternion& quat); inline bool equals(const quaternion& other, const f32 tolerance = ROUNDING_ERROR_f32 ) const; irrList.h New method u32 size() const void swap(list& other) IVideoDriver.h New render targets ERT_MULTI_RENDER_TEXTURES New class struct IRenderTarget Changed parameter (from void*) virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0) =0; New parameter (mipmapData) virtual ITexture* addTexture(const io::path& name, IImage* image, void* mipmapData=0) = 0; New method virtual bool setRenderTarget(const core::array& texture, bool clearBackBuffer=true, bool clearZBuffer=true, SColor color=video::SColor(0,0,0,0)) =0; void drawIndexedTriangleFan(const S3DVertexTangents* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) virtual void getFog(SColor& color, E_FOG_TYPE& fogType, f32& start, f32& end, f32& density, bool& pixelFog, bool& rangeFog) = 0; virtual SMaterial& getMaterial2D() =0; virtual void enableMaterial2D(bool enable=true) =0; virtual core::dimension2du getMaxTextureSize() const =0; Made non-virtual void drawIndexedTriangleList(const S3DVertex* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) void drawIndexedTriangleList(const S3DVertex2TCoords* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) void drawIndexedTriangleList(const S3DVertexTangents* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) void drawIndexedTriangleFan(const S3DVertex* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) void drawIndexedTriangleFan(const S3DVertex2TCoords* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount) EDriverFeatures.h New driver feature enums EVDF_MULTIPLE_RENDER_TARGETS, EVDF_MRT_BLEND, EVDF_MRT_COLOR_MASK, EVDF_MRT_BLEND_FUNC, EVDF_GEOMETRY_SHADER, IGUIWindow.h New method virtual core::rect getClientRect() const = 0; IGUIContextMenu.h New enum enum ECONTEXT_MENU_CLOSE New method virtual void setCloseHandling(ECONTEXT_MENU_CLOSE onClose) = 0; virtual ECONTEXT_MENU_CLOSE getCloseHandling() const = 0; virtual u32 insertItem(u32 idx, const wchar_t* text, s32 commandId=-1, bool enabled=true, bool hasSubMenu=false, bool checked=false, bool autoChecking=false) = 0; virtual s32 findItemWithCommandId(s32 commandId, u32 idxStartSearch=0) const = 0; virtual void setItemAutoChecking(u32 idx, bool autoChecking) = 0; virtual bool getItemAutoChecking(u32 idx) const = 0; virtual void setEventParent(IGUIElement *parent) = 0; New parameter virtual u32 addItem(const wchar_t* text, s32 commandId=-1, bool enabled=true, bool hasSubMenu=false, bool checked=false, bool autoChecking=false) = 0; SIrrCreationParameters.h New parameter (LoggingLevel) createDevice matrix4.h New method bool equals(const core::CMatrix4& other, const T tolerance=(T)ROUNDING_ERROR_f64) const; SSkinMeshBuffer.h Renamed method (from MoveTo_2TCoords) virtual void convertTo2TCoords() Renamed method (from MoveTo_Tangents) virtual void convertToTangents() SVertexManipulator.h New classes (for vertex manipulation) class SVertexColorSetManipulator : public IVertexManipulator class SVertexColorSetAlphaManipulator : public IVertexManipulator class SVertexColorInvertManipulator : public IVertexManipulator class SVertexColorThresholdManipulator : public IVertexManipulator class SVertexColorBrightnessManipulator : public IVertexManipulator class SVertexColorContrastManipulator : public IVertexManipulator class SVertexColorContrastBrightnessManipulator : public IVertexManipulator class SVertexColorGammaManipulator : public IVertexManipulator ; class SVertexColorScaleManipulator : public IVertexManipulator class SVertexColorDesaturateToLightnessManipulator : public IVertexManipulator class SVertexColorDesaturateToAverageManipulator : public IVertexManipulator class SVertexColorDesaturateToLuminanceManipulator : public IVertexManipulator class SVertexColorInterpolateLinearManipulator : public IVertexManipulator class SVertexColorInterpolateQuadraticManipulator : public IVertexManipulator class SVertexPositionScaleManipulator : public IVertexManipulator ; class SVertexPositionScaleAlongNormalsManipulator : public IVertexManipulator class SVertexPositionTransformManipulator : public IVertexManipulator class SVertexTCoordsScaleManipulator : public IVertexManipulator IMeshCache.h Renamed method (from getMeshByFilename) virtual IAnimatedMesh* getMeshByName(const io::path& name) = 0; Renamed method and changed return type (from getMeshFilename/io::path) virtual const io::SNamedPath& getMeshName(u32 index) const = 0; virtual const io::SNamedPath& getMeshName(const IAnimatedMesh* const mesh) const = 0; virtual const io::SNamedPath& getMeshName(const IMesh* const mesh) const = 0; Renamed method (from setMeshFilename) virtual bool renameMesh(u32 index, const io::path& name) = 0; virtual bool renameMesh(const IAnimatedMesh* const mesh, const io::path& name) = 0; virtual bool renameMesh(const IMesh* const mesh, const io::path& name) = 0; IGUIElement.h Changed parameter (to const-ref) IGUIElement(EGUI_ELEMENT_TYPE type, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle) New method virtual bool hasType(EGUI_ELEMENT_TYPE type) const irrString.h Changed parameter (to template with allocator) in all methods with templates Made destructor non-virtual ~string() Added parameter s32 find(const B* const str, const u32 start = 0) const New method void remove(T c) void remove(const string toRemove) void removeChars(const string & characters) template u32 split(container& ret, const T* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const vector2d.h Use tolerance to compare, changed order function to total order bool operator<=(const vector2d&other) const bool operator>=(const vector2d&other) const bool operator<(const vector2d&other) const bool operator>(const vector2d&other) const irrlicht-1.8.3/doc/readme.txt0000644000000000000000000000031512574354552014617 0ustar rootrootLinux Users: There are some tools at the web for reading .chm files (try http://xchm.sourceforge.net/). You can find a html version of this documentation at http://irrlicht.sourceforge.net/docu/index.htmlirrlicht-1.8.3/doc/libpng-license.txt0000644000000000000000000001033112574354552016254 0ustar rootroot This copy of the libpng notices is provided for your convenience. In case of any discrepancy between this copy and the notices in the file png.h that is included in the libpng distribution, the latter shall prevail. COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: If you modify libpng you may insert additional notices immediately following this sentence. This code is released under the libpng license. libpng versions 1.2.6, August 15, 2004, through 1.5.9, February 18, 2012, are Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.2.5 with the following individual added to the list of Contributing Authors Cosmin Truta libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.0.6 with the following individuals added to the list of Contributing Authors Simon-Pierre Cadieux Eric S. Raymond Gilles Vollant and with the following additions to the disclaimer: There is no warranty against interference with your enjoyment of the library or against infringement. There is no warranty that our efforts or the library will fulfill any of your particular purposes or needs. This library is provided with all faults, and the entire risk of satisfactory quality, performance, accuracy, and effort is with the user. libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-0.96, with the following individuals added to the list of Contributing Authors: Tom Lane Glenn Randers-Pehrson Willem van Schaik libpng versions 0.89, June 1996, through 0.96, May 1997, are Copyright (c) 1996, 1997 Andreas Dilger Distributed according to the same disclaimer and license as libpng-0.88, with the following individuals added to the list of Contributing Authors: John Bowler Kevin Bracey Sam Bushell Magnus Holmgren Greg Roelofs Tom Tanner libpng versions 0.5, May 1995, through 0.88, January 1996, are Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. For the purposes of this copyright and license, "Contributing Authors" is defined as the following set of individuals: Andreas Dilger Dave Martindale Guy Eric Schalnat Paul Schmidt Tim Wegner The PNG Reference Library is supplied "AS IS". The Contributing Authors and Group 42, Inc. disclaim all warranties, expressed or implied, including, without limitation, the warranties of merchantability and of fitness for any purpose. The Contributing Authors and Group 42, Inc. assume no liability for direct, indirect, incidental, special, exemplary, or consequential damages, which may result from the use of the PNG Reference Library, even if advised of the possibility of such damage. Permission is hereby granted to use, copy, modify, and distribute this source code, or portions hereof, for any purpose, without fee, subject to the following restrictions: 1. The origin of this source code must not be misrepresented. 2. Altered versions must be plainly marked as such and must not be misrepresented as being the original source. 3. This Copyright notice may not be removed or altered from any source or altered source distribution. The Contributing Authors and Group 42, Inc. specifically permit, without fee, and encourage the use of this source code as a component to supporting the PNG file format in commercial products. If you use this source code in a product, acknowledgment is not required but would be appreciated. A "png_get_copyright" function is available, for convenient use in "about" boxes and the like: printf("%s",png_get_copyright(NULL)); Also, the PNG logo (in PNG format, of course) is supplied in the files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a certification mark of the Open Source Initiative. Glenn Randers-Pehrson glennrp at users.sourceforge.net February 18, 2012 irrlicht-1.8.3/doc/jpglib-license.txt0000644000000000000000000004226312574354552016261 0ustar rootrootThe Independent JPEG Group's JPEG software ========================================== README for release 8d of 15-Jan-2012 ==================================== This distribution contains the eighth public release of the Independent JPEG Group's free JPEG software. You are welcome to redistribute this software and to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. This software is the work of Tom Lane, Guido Vollbeding, Philip Gladstone, Bill Allombert, Jim Boucher, Lee Crocker, Bob Friesenhahn, Ben Jackson, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, Ge' Weijers, and other members of the Independent JPEG Group. IJG is not affiliated with the ISO/IEC JTC1/SC29/WG1 standards committee (also known as JPEG, together with ITU-T SG16). DOCUMENTATION ROADMAP ===================== This file contains the following sections: OVERVIEW General description of JPEG and the IJG software. LEGAL ISSUES Copyright, lack of warranty, terms of distribution. REFERENCES Where to learn more about JPEG. ARCHIVE LOCATIONS Where to find newer versions of this software. ACKNOWLEDGMENTS Special thanks. FILE FORMAT WARS Software *not* to get. TO DO Plans for future IJG releases. Other documentation files in the distribution are: User documentation: install.txt How to configure and install the IJG software. usage.txt Usage instructions for cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom. *.1 Unix-style man pages for programs (same info as usage.txt). wizard.txt Advanced usage instructions for JPEG wizards only. change.log Version-to-version change highlights. Programmer and internal documentation: libjpeg.txt How to use the JPEG library in your own programs. example.c Sample code for calling the JPEG library. structure.txt Overview of the JPEG library's internal structure. filelist.txt Road map of IJG files. coderules.txt Coding style rules --- please read if you contribute code. Please read at least the files install.txt and usage.txt. Some information can also be found in the JPEG FAQ (Frequently Asked Questions) article. See ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. If you want to understand how the JPEG code works, we suggest reading one or more of the REFERENCES, then looking at the documentation files (in roughly the order listed) before diving into the code. OVERVIEW ======== This package contains C software to implement JPEG image encoding, decoding, and transcoding. JPEG (pronounced "jay-peg") is a standardized compression method for full-color and gray-scale images. This software implements JPEG baseline, extended-sequential, and progressive compression processes. Provision is made for supporting all variants of these processes, although some uncommon parameter settings aren't implemented yet. We have made no provision for supporting the hierarchical or lossless processes defined in the standard. We provide a set of library routines for reading and writing JPEG image files, plus two sample applications "cjpeg" and "djpeg", which use the library to perform conversion between JPEG and some other popular image file formats. The library is intended to be reused in other applications. In order to support file conversion and viewing software, we have included considerable functionality beyond the bare JPEG coding/decoding capability; for example, the color quantization modules are not strictly part of JPEG decoding, but they are essential for output to colormapped file formats or colormapped displays. These extra functions can be compiled out of the library if not required for a particular application. We have also included "jpegtran", a utility for lossless transcoding between different JPEG processes, and "rdjpgcom" and "wrjpgcom", two simple applications for inserting and extracting textual comments in JFIF files. The emphasis in designing this software has been on achieving portability and flexibility, while also making it fast enough to be useful. In particular, the software is not intended to be read as a tutorial on JPEG. (See the REFERENCES section for introductory material.) Rather, it is intended to be reliable, portable, industrial-strength code. We do not claim to have achieved that goal in every aspect of the software, but we strive for it. We welcome the use of this software as a component of commercial products. No royalty is required, but we do ask for an acknowledgement in product documentation, as described under LEGAL ISSUES. LEGAL ISSUES ============ In plain English: 1. We don't promise that this software works. (But if you find any bugs, please let us know!) 2. You can use this software for whatever you want. You don't have to pay us. 3. You may not pretend that you wrote this software. If you use it in a program, you must acknowledge somewhere in your documentation that you've used the IJG code. In legalese: The authors make NO WARRANTY or representation, either express or implied, with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you, its user, assume the entire risk as to its quality and accuracy. This software is copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding. All Rights Reserved except as specified below. Permission is hereby granted to use, copy, modify, and distribute this software (or portions thereof) for any purpose, without fee, subject to these conditions: (1) If any part of the source code for this software is distributed, then this README file must be included, with this copyright and no-warranty notice unaltered; and any additions, deletions, or changes to the original files must be clearly indicated in accompanying documentation. (2) If only executable code is distributed, then the accompanying documentation must state that "this software is based in part on the work of the Independent JPEG Group". (3) Permission for use of this software is granted only if the user accepts full responsibility for any undesirable consequences; the authors accept NO LIABILITY for damages of any kind. These conditions apply to any software derived from or based on the IJG code, not just to the unmodified library. If you use our work, you ought to acknowledge us. Permission is NOT granted for the use of any IJG author's name or company name in advertising or publicity relating to this software or products derived from it. This software may be referred to only as "the Independent JPEG Group's software". We specifically permit and encourage the use of this software as the basis of commercial products, provided that all warranty or liability claims are assumed by the product vendor. ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. ansi2knr.c is NOT covered by the above copyright and conditions, but instead by the usual distribution terms of the Free Software Foundation; principally, that you must include source code if you redistribute it. (See the file ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part of any program generated from the IJG code, this does not limit you more than the foregoing paragraphs do. The Unix configuration script "configure" was produced with GNU Autoconf. It is copyright by the Free Software Foundation but is freely distributable. The same holds for its supporting scripts (config.guess, config.sub, ltmain.sh). Another support script, install-sh, is copyright by X Consortium but is also freely distributable. The IJG distribution formerly included code to read and write GIF files. To avoid entanglement with the Unisys LZW patent, GIF reading support has been removed altogether, and the GIF writer has been simplified to produce "uncompressed GIFs". This technique does not use the LZW algorithm; the resulting GIF files are larger than usual, but are readable by all standard GIF decoders. We are required to state that "The Graphics Interchange Format(c) is the Copyright property of CompuServe Incorporated. GIF(sm) is a Service Mark property of CompuServe Incorporated." REFERENCES ========== We recommend reading one or more of these references before trying to understand the innards of the JPEG software. The best short technical introduction to the JPEG compression algorithm is Wallace, Gregory K. "The JPEG Still Picture Compression Standard", Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. (Adjacent articles in that issue discuss MPEG motion picture compression, applications of JPEG, and related topics.) If you don't have the CACM issue handy, a PostScript file containing a revised version of Wallace's article is available at http://www.ijg.org/files/wallace.ps.gz. The file (actually a preprint for an article that appeared in IEEE Trans. Consumer Electronics) omits the sample images that appeared in CACM, but it includes corrections and some added material. Note: the Wallace article is copyright ACM and IEEE, and it may not be used for commercial purposes. A somewhat less technical, more leisurely introduction to JPEG can be found in "The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides good explanations and example C code for a multitude of compression methods including JPEG. It is an excellent source if you are comfortable reading C code but don't know much about data compression in general. The book's JPEG sample code is far from industrial-strength, but when you are ready to look at a full implementation, you've got one here... The best currently available description of JPEG is the textbook "JPEG Still Image Data Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. The book includes the complete text of the ISO JPEG standards (DIS 10918-1 and draft DIS 10918-2). Although this is by far the most detailed and comprehensive exposition of JPEG publicly available, we point out that it is still missing an explanation of the most essential properties and algorithms of the underlying DCT technology. If you think that you know about DCT-based JPEG after reading this book, then you are in delusion. The real fundamentals and corresponding potential of DCT-based JPEG are not publicly known so far, and that is the reason for all the mistaken developments taking place in the image coding domain. The original JPEG standard is divided into two parts, Part 1 being the actual specification, while Part 2 covers compliance testing methods. Part 1 is titled "Digital Compression and Coding of Continuous-tone Still Images, Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS 10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of Continuous-tone Still Images, Part 2: Compliance testing" and has document numbers ISO/IEC IS 10918-2, ITU-T T.83. IJG JPEG 8 introduces an implementation of the JPEG SmartScale extension which is specified in two documents: A contributed document at ITU and ISO with title "ITU-T JPEG-Plus Proposal for Extending ITU-T T.81 for Advanced Image Coding", April 2006, Geneva, Switzerland. The latest version of this document is Revision 3. And a contributed document ISO/IEC JTC1/SC29/WG1 N 5799 with title "Evolution of JPEG", June/July 2011, Berlin, Germany. The JPEG standard does not specify all details of an interchangeable file format. For the omitted details we follow the "JFIF" conventions, revision 1.02. JFIF 1.02 has been adopted as an Ecma International Technical Report and thus received a formal publication status. It is available as a free download in PDF format from http://www.ecma-international.org/publications/techreports/E-TR-098.htm. A PostScript version of the JFIF document is available at http://www.ijg.org/files/jfif.ps.gz. There is also a plain text version at http://www.ijg.org/files/jfif.txt.gz, but it is missing the figures. The TIFF 6.0 file format specification can be obtained by FTP from ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 (Compression tag 7). Copies of this Note can be obtained from http://www.ijg.org/files/. It is expected that the next revision of the TIFF spec will replace the 6.0 JPEG design with the Note's design. Although IJG's own code does not support TIFF/JPEG, the free libtiff library uses our library to implement TIFF/JPEG per the Note. ARCHIVE LOCATIONS ================= The "official" archive site for this software is www.ijg.org. The most recent released version can always be found there in directory "files". This particular version will be archived as http://www.ijg.org/files/jpegsrc.v8d.tar.gz, and in Windows-compatible "zip" archive format as http://www.ijg.org/files/jpegsr8d.zip. The JPEG FAQ (Frequently Asked Questions) article is a source of some general information about JPEG. It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ and other news.answers archive sites, including the official news.answers archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu with body send usenet/news.answers/jpeg-faq/part1 send usenet/news.answers/jpeg-faq/part2 ACKNOWLEDGMENTS =============== Thank to Juergen Bruder for providing me with a copy of the common DCT algorithm article, only to find out that I had come to the same result in a more direct and comprehensible way with a more generative approach. Thank to Istvan Sebestyen and Joan L. Mitchell for inviting me to the ITU JPEG (Study Group 16) meeting in Geneva, Switzerland. Thank to Thomas Wiegand and Gary Sullivan for inviting me to the Joint Video Team (MPEG & ITU) meeting in Geneva, Switzerland. Thank to Thomas Richter and Daniel Lee for inviting me to the ISO/IEC JTC1/SC29/WG1 (also known as JPEG, together with ITU-T SG16) meeting in Berlin, Germany. Thank to John Korejwa and Massimo Ballerini for inviting me to fruitful consultations in Boston, MA and Milan, Italy. Thank to Hendrik Elstner, Roland Fassauer, Simone Zuck, Guenther Maier-Gerber, Walter Stoeber, Fred Schmitz, and Norbert Braunagel for corresponding business development. Thank to Nico Zschach and Dirk Stelling of the technical support team at the Digital Images company in Halle for providing me with extra equipment for configuration tests. Thank to Richard F. Lyon (then of Foveon Inc.) for fruitful communication about JPEG configuration in Sigma Photo Pro software. Thank to Andrew Finkenstadt for hosting the ijg.org site. Last but not least special thank to Thomas G. Lane for the original design and development of this singular software package. FILE FORMAT WARS ================ The ISO/IEC JTC1/SC29/WG1 standards committee (also known as JPEG, together with ITU-T SG16) currently promotes different formats containing the name "JPEG" which is misleading because these formats are incompatible with original DCT-based JPEG and are based on faulty technologies. IJG therefore does not and will not support such momentary mistakes (see REFERENCES). There exist also distributions under the name "OpenJPEG" promoting such kind of formats which is misleading because they don't support original JPEG images. We have no sympathy for the promotion of inferior formats. Indeed, one of the original reasons for developing this free software was to help force convergence on common, interoperable format standards for JPEG files. Don't use an incompatible file format! (In any case, our decoder will remain capable of reading existing JPEG image files indefinitely.) Furthermore, the ISO committee pretends to be "responsible for the popular JPEG" in their public reports which is not true because they don't respond to actual requirements for the maintenance of the original JPEG specification. There are currently distributions in circulation containing the name "libjpeg" which claim to be a "derivative" or "fork" of the original libjpeg, but don't have the features and are incompatible with formats supported by actual IJG libjpeg distributions. Furthermore, they violate the license conditions as described under LEGAL ISSUES above. We have no sympathy for the release of misleading and illegal distributions derived from obsolete code bases. Don't use an obsolete code base! TO DO ===== Version 8 is the first release of a new generation JPEG standard to overcome the limitations of the original JPEG specification. More features are being prepared for coming releases... Please send bug reports, offers of help, etc. to jpeg-info@jpegclub.org. irrlicht-1.8.3/doc/irrlicht-license.txt0000644000000000000000000000275112574354552016630 0ustar rootrootCopyright (C) 2002-2012 Nikolaus Gebhardt This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Please note that the Irrlicht Engine is based in part on the work of the Independent JPEG Group, the zlib, libPng and aesGladman. This means that if you use the Irrlicht Engine in your product, you must acknowledge somewhere in your documentation that you've used the IJPG code. It would also be nice to mention that you use the Irrlicht Engine, the zlib, libPng and aesGladman. See the corresponding license files for further informations. It is also possible to disable usage of those additional libraries by defines in the IrrCompileConfig.h header and recompiling the engine. irrlicht-1.8.3/doc/bzip2-license.txt0000644000000000000000000000355512574354552016041 0ustar rootroot -------------------------------------------------------------------------- This program, "bzip2", the associated library "libbzip2", and all documentation, are copyright (C) 1996-2007 Julian R Seward. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 4. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Julian Seward, jseward@bzip.org bzip2/libbzip2 version 1.0.5 of 10 December 2007 -------------------------------------------------------------------------- irrlicht-1.8.3/doc/aesGladman.txt0000644000000000000000000000304312574354552015417 0ustar rootrootThe Irrlicht Engine may be compiled to provide support for AES encrypted files. The implementation used by Irrlicht is provided by Dr Brian Gladman. The license for these files (including AES, a PRNG, SHA, and other algorithms) is as follows /* --------------------------------------------------------------------------- Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software in both source and binary form is allowed (with or without changes) provided that: 1. distributions of this source code include the above copyright notice, this list of conditions and the following disclaimer; 2. distributions in binary form include the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other associated materials; 3. the copyright holder's name is not used to endorse products built using this software without specific written permission. ALTERNATIVELY, provided that this notice is retained in full, this product may be distributed under the terms of the GNU General Public License (GPL), in which case the provisions of the GPL apply INSTEAD OF those given above. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- */ irrlicht-1.8.3/changes.txt0000644000000000000000000073211312574354552014235 0ustar rootroot-------------------------- Changes in 1.8.3 (13.9.2015) - Fix the fix for compiling on GCC5 (thanks to est31 for report and patch) -------------------------- Changes in 1.8.2 (30.8.2015) - Add VS2013 project files - Fix compiling with IRR_LINUX_XCURSOR_ - Fix compiling with NO_IRR_COMPILE_WITH_LIBJPEG_ (thx to anontypist for report and patch). - Fix compiling on GCC5 on MinGW (thanks to Slipxy for finding the bug and to osense for reporting it). - Fix loading of .X and .B3D models with non-normalized quaternion rotations (thanks to JLouisB for a test-model). - Fix compiling on Free BSD (thanks to leper for reporting and patch) - Fix bug with multiple SetPixelFormat calls. (reported and fixed by anontypist) - Fix bug related to memory release in PNG image loader. Thanks elephoenix for it. - Fix crash in CGUIListBox when users pressed end key folled by any other key in an empty, focused list box (thanks at porcus for report and patch). - Fix use of enabling defines for wal2 (halflife) image loader. Thanks to hendu for noticing. - Fix userClipPlane test by inserting the stabilizeScreenBackground call - Demo enables antialiasing now correct (thanks to Mel for noticing). - Update glext.h (bug #429) - Example 22 no longer select a random texture after loading a new texture (thanks at mongoose7 for reporting). - Fix bug in IGUISkin serialization which messed up serialization of the button-pressed offsets (thanks at Midnight for reporting). - IGUIStaticText::getTextHeight returns now the correct height for texts with newlines even WordWrap is not set. - Crashfix for CGUIEditBox. CGUIEditBox::setMultiLine must break text when changed or other functions like getTextDimension can crash afterward for strings with newline characters. - CGUIEditBox and the GUI-Editor now convert pasted text correctly using mbstowcs. - C::B project files work again on newer Linux-distributions which have cleaned up their dev-lib dependencies. - Makefile for the new IrrFontTool links now correctly to libfontconfig -------------------------- Changes in 1.8.1 (17.11.2013) - Improved OpenGL performance under OSX (Thanks devonsoft for reporting). - Fixed OSX compilation issues. - [KNOWN BUG] Software driver doesn't work properly under OSX 10.9. - For speed improvement the following attributes accessible by ISceneManager::getParameters() are no longer updated in release: "culled", "calls", "drawn_solid", "drawn_transparent", "drawn_transparent_effect". They can be enabled by compiling Irrlicht with the define _IRR_SCENEMANAGER_DEBUG. Thanks @hendu for reporting, see http://irrlicht.sourceforge.net/forum/viewtopic.php?f=2&t=48211 for the discussion. - Fix compile problem with CIrrDeviceSDL on VS2008 (and maybe other systems). Thanks @HellFlip for reporting. - Fix quaternion::rotationFromTo() (Thanks @takamoto for reporting) - Fix iszero for s64 (Thanks @chronologicaldot for reporting) - Fix crash in SoftwareDriver2 when Material was EMT_DETAIL_MAP but texture[1] was not set (Thanks for fix by chronologicaldot) - Fix buffer overrun in x-loader (Thanks for fix by Otaka) - Fix cursor visibility update problem under Windows 8 (Thanks @luthyr for reporting) - Fix irredit links in loadScene/saveScene docs. - Fix issue in CAnimatedMeshSceneNode::clone which caused a crash. (reported and fixed by luthyr) - Fix compiling errors for c++ builder (thx @Greatwolf for many patches and @cfanderek for reminding) - Initialized IColladaMeshWriter::GeometryWriting which was uninitialized. - Fix linker trouble with irr::core::equalsByUl when compiling Irrlicht as managed code (thx @ Memorial76 for a report + testcase) - Fix crashes in CCubeSceneNode::clone and CSphereSceneNode::clone (reported by marsupial) - Fix the clipping in the listbox drawing which was only showing the right line of the sunken pane (reported by Mloren and Abraxas). - Initialize slider in example 05 correct (reported by Zerochen) - Fix crash in CMeshSceneNode::clone when the mesh had no shadow (reported by christianclavet, bug-fix found by Nadro) -------------------------- Changes in 1.8 (7.11.2012) - Let sphere mesh use full opaque color, just as all the other ones do - Gcc on Win32 (MinGW) now also works with the _w file access functions when compiled with _IRR_WCHAR_FILESYSTEM. (thx @ alexzk for reporting compile troubles) - Fix a bunch of off-by one errors in irr::core::string in functions equals_substring_ignore_case, findFirst, findFirstChar, findNext, findLast, findLastChar, replace, remove and removeChars. This prevents some potential memory access errors, find functions no longer try to find the \0, replace no longer replaces the \0 and remove no longer tries to remove it (which did remove the last character instead). - matrix4::setRotationAxisRadians added - user clipplanes fixed - Skip rendering of lines, points, and polygons, as these lead to crahses due to wrong access to the vertex lists. A fix would need major rewrite of the vertex cache, or at least some other render methods. - Add mipmap generation for makeColorKeyTexture - Add another saveScene overload which allows to pass in a user-created XMLWriter. Patch suggested by eversilver. - quaternion conversions to and from matrix4 no longer invert rotations. To test if your code was affected by this you can set IRR_TEST_BROKEN_QUATERNION_USE in quaternion.h and try to compile your application. Then on all compile-errors when you pass the matrix to the quaternion you can replace the matrix transposed matrix. For all errors you get on getMatrix() you can use quaternion::getMatrix_transposed instead. - CGUIEnvironment::loadGui - loading a gui into a target-element no longer messes up when the gui-file contained guienvironment serialization. - Colladawriter now exports materials per node when those are used in Irrlicht - Colladawriter now writing matrices for node transformations as old solution did not work with CDummyTransformationSceneNode's. - Colladawriter no longer create an extra node for the scenemanger as has that job in Collada. - Colladwriter no longer makes all Scenenodes children of ambient-light as that can be parallel on the same layer instead. - Colladareader now creates the ambient-light correct instead of creating a point-light for it. - Add new parameter to array reallocate function. This prevents a reallocation in case the array would become smaller. As the reallocation operation is quite time consuming, this can be avoided on request now, on the expense of more memory consumption. - Add IAnimatedMeshSceneNode::getLoopMode (asked for by JLouisB) - CSceneNodeAnimatorCameraFPS now resets the key-input when it was disabled (thx @ gerdb for reporting and patch-proposal) - Properly destroy OpenGL resources on linux (thx @curaga for the patch) - Fix diplay bux in the attribute-panel of the GUIEditor. Fixes bug 3517314 (thx @Darkcoder for reporting). - Allow caching cursor position on X11 to work around slow XQueryPointer calls (thx @Hendu for reporting+patch proposal) - Make sure after EGET_EDITBOX_ENTER and EGET_COMBO_BOX_CHANGED event processing no more code is executed for the corresponding editbox or combobox objects to allow clearing the environment on those actions (see comments on bug-id 2995838). - Fix string::replace which failed replacing substrings at the end when the replacement was longer - Struct packing works now with gcc 4.7 changes on MinGW (thx @Sudi for reporting). - Struct packing uses now same solution throughout (by including headers in corresponding places) - User can now set characters used for decimal point in fast_atof for localisation. - Add parameter useAlphaChannel to second IGUIEnvironment::addImage function. - Get rid of unnecessary warning "Could not load sprite bank because the file does not exist" for "#defaultfont". - Fix MRT disabling. Bug found and fixed by hendu. - core:::array::reallocate returning now immediately when it has nothing to do. Should reduce a lot of memory thrashing on irrArrays. - Start mesh animations at first OnAnimate , before start-frame was rather random. Thx @Auria for reporting and patch proposal. - renderTargetTexture now working with ECF_R5G6B5 - add -fPic in c::b linux fast math shared build. - Fix by Auria for starting the animated meshes only at first OnAnimate instead of at random times and animation frames. - Add support for MAX_COMBINED_TEXTURES, which allows more texture support than with the original fixed pipeline texture check under OpenGL. Now, more than 4 textures should also work with newer gfx cards and drivers, which often only support 4 fixed pipeline textures. - triangle3d::isPointInsideFast now using some epsilon to catch all points on the borders. - triangle3d::getIntersectionOfPlaneWithLine calculates now with higher precision for more exact results. - triangle3d::isOnSameSide (used by isPointInside) calculates now with higher precision and uses some epsilon to make it work with larger integers and less floating point troubles. Slightly slower now. - new function equalsByUlp to test for spacing between floating point numbers. - speedup for collada writing. - speedup for xml-writing. - Fix 8bit grey image TGAs, which were not working due to missing palette. Also switched to RGB8 format, as otherwise a loss in precision would occur. Thanks to Klunk for the error report and a test image. - fixed issues with a D3D driver and Aero effects. - Fix font-drawing in CGUIButton to use EGDF_BUTTON again (thx @DJLinux for reporting). - Add texture cache with proper reference handling. This avoids deletion of textures while still being active on the GPU. Test case and fix by m(att)giuca - CFileSystem::removeFileArchive now checking for normalized path - Fix zip's with passwords on 64-bit systems (thx @ Dr. Gladman for writing the bugfix) - replace asserts in tests with macro assert_log to allow running all tests through on problems. - added IGUIElement::setName and IGUIElement::getName (similar to ISceneNode) - irr::s64 support - line2d::getClosestPoint can now also get the closest point on the line additional to only checking for closest point on the line-segment. - avoid division by zero in line2d::getClosestPoint when start- and endpoint are identical - Support for sw drivers under OSX - Fix font-loading which got broken by fixed xml-loading. Thanks @ pc0de for finding and providing a test and patch. - Don't crash draw2DSpriteBatch when it get's no textures. - Add support for int passing in setShaderConstant - Support for better collada texture wrapping support on loading. - Fix for render context change where only the window id is given. We now try to change only the window ID, keeping context and display unchanged. Suggestion by vovo4ka from the forum. - XML-reader now ignores all whitespace-only EXN_TEXT elements as old way didn't work in cross-platform way (and arguably also not well on Windows). - CXMLReader initializes IsEmptyElement now. - line2d::intersectWith and and line2d::getClosestPoint work now also with integers. - line2d::getMiddle and line3d::getMiddle work now also with integers. But can be slower for compilers which are not optimizing division by 2 to multiplication by 0.5 for floats. - Add Nadro's initial Cg support. Example 10 is enhanced to allow also Cg shaders. - Add mipmap support from FBO extension, patch by Nadro. - Add vertex optimization algorithm submitted by curaga - rename texureBlend functions to textureBlend - Add threshold for slerp calculation, switching between linear and slerp at this point. - Fix for bug 3401933 - vertex color interpolation with shadow volumes in the scene - Fixed bug in button sprites reported by RdR - Fixed button state sprite animations for pressed, focused and hovered. - Added serialization for terrain smooth factor, patch by RdR - Implemented more button states for sprite banks, patch submitted by RdR - Add IGUIEnvironment::getHovered to get the element most recently known to be under the mouse cursor - Add FPS settings for animated meshes, which allows to push animation speed from files to Irrlicht animation system - Maya camera updates - Add support for bsp brush entities. Written by Hendu. - weighted normals recalculation fixed - Billboard improvements - API docs updates - triangle selector improvements - OSX improvements by Auria - Add new methods for adding and removing file archives based on ifilearchive pointers. - Add getBackgroundColor, isDrawBackgroundEnabled and isDrawBorderEnabled to IGUIStaticText (thx 4 patch from Nalin). - Reduction of multiple skinning the same mesh and frame in one render cycle - Added ISceneNodeAnimatorCameraFPS::getKeyMap and a new ISceneNodeAnimatorCameraFPS::setKeyMap. - CSceneNodeAnimatorCameraFPS uses now SKeyMap instead of SCamKeyMap (structs were identical which was confusing and there wasn't any explanation in comments, so I decided to simplify it). - Add some workaround to MeshViewer to show how we can currently fix the FPS-cam when users to alt-tab while moving. We can improve that some day when we have focus-events, but this works for now. - Fix LZMA decompression - Ply normal fixes - HW buffers only support rendering with both vertex and index buffers - Enables VBOs for water node - Octree support for non-standard vertex meshes - Fix rotationFromTo - Added ConstIterator - Fix for getScreenCoordinatesFrom3DPosition to use proper RTT sizes - Add IGUIComboBox::setMaxSelectionRows and IGUIComboBox::getMaxSelectionRows - Scenemanager switches from type ESNT_UNKNOWN to type ESNT_SCENE_MANAGER. - Add getActiveFont to all elements which have setOverrideFont for cleaner code - Add getOverrideFont to all elements which have setOverrideFont to have a consistent interface - IGUIEditBox: added missing serialization for Border - IGUIEditBox: remove bug that added spaces to the end of each line - IGUIEditBox: fix crash that happened when wordwrapping was enabled, spaces were entered beyond the border and then cursor-key was pressed. - IGUIEditBox::setDrawBackground added. - CGUISkin::draw3DSunkenPane no longer ignores fillBackGround in non-flat mode. Also borderlines are no longer drawn overlapping to avoid ugly corners. - CDummyTransformationSceneNode::clone() added. - IParticleSystemSceneNode::doParticleSystem now public to allow rendering outside scenegraph. - getRelativeFilenames updates and fixes - Renamed IOSOperator::getOperationSystemVersion to getOperatingSystemVersion. Changed return type from wchar_t to core::stringc, as that's the internal representation the name is built on. - Added IGUITabControl::insertTab, IGUITabControl::removeTab, IGUITabControl::clear and IGUITabControl::getTabAt - Add 32bit support to some mesh manipulator methods - Fix mipmap locking under OpenGL - Improvement of screenshot function to support more color formats and targets - getAngle fix to avoid NaNs - Available gfx memory output in log messages - Improved 2d render settings and caching - Initial suppport for sRGB render functions - Improved terrain scene node rendering - Paletted png image support fixed - Gamma settings in image loaders improved - Support for relative filenames in serialization - Access to selectors inside meta selectors implemented - DirectInput joystick support - Support for scaling with draw2dimage with burnings video - More gl extensions have correctly initialised return values - Some fixes for quaternion to euler function - Properly return nullptr if RTT creation fails on low levels - Added IGUIListBox::getItemAt - Add more image formats tried to load by q3 level loader - Add fast_atof improvements from assimp, also strtoul10 method - Add blend equation function for MRTs - Add new material fields for blend operation and polygon offset (depth bias). - Reorder texture stage assignments - Improved VSync handling - Fix Ogre loader for materials with more than one texture - Fix createMeshCopy material handling - Framework target for OSX project added - Terrain scene node fixes - Fix HSL color class - Fix color selection GUI element - Transparency issues in particle system fixed - Particle sphere emitter rand values fixed - Support Unicode SHY dynamic hypen in word wrap - Fix OBJ reader sometimes running over EOF - Added IGUITable::getColumnWidth - Billboard text animates in OnAnimate now - Fix mountpoint reader to properly sync file names and firectories - Added the ability to open an archive from an IReadFile*, added a FileToHeader tool with instructions of how to make a portable app that consists of a single executable file. - Added suppport for right-to-left (RTL) text, supplied by Auria from STK - Added ISceneManager::createSceneNodeAnimator to create animators by name - The Makefile now creates a symlink from the soname to the binary name during install. Binary compatibility is only confirmed between same minor releases. - Added SMF mesh loader, loads meshes from 3D World Studio. Originally written by Joseph Ellis - The loader selection process now consistently checks loader lists in reverse order, so new loaders added to Irrlicht override the internal ones. This applies when adding external mesh, image, scene and archive loaders, image writers, plus node, animator and GUI element factories. - Added getters to retrieve mesh, scene and archive loaders. - Added ISceneLoader interface and .irr loader. Users can now add their own scene loaders to the scene manager and use them by calling loadScene. - Renamed IGUIElement::bringToBack to sendToBack, like in Windows - Send EGET_ELEMENT_CLOSED event when context menus should be closed (thx @ Mloren for reporting). - Added treeview to GUI editor, provided by Armen - Added root type for GUI environment - zip archive fixes: Fix directory tags in file list. Fix loading of stream zip files which have file sizes only in the central directory. - Fixed panel scrollbars in GUI editor, reported by Armen - Fix b3d loading of files with mixed mesh/bone sections. - Fix particle emitters which used integer random numbers so far. The distributions of the particles should be much better (and the code also somewhat faster) now. - Add new random method frand: Returns a random number in the interval [0..1] and gives better distributions than using fmodf on the integer number. - Add node parameter to saveScene and loadScene. saveScene saves the given node and all descendants to the file (if 0, the full scene is saved as before). loadScene loads all elements of the scene as childs of the given node. As before, 0 would load the file on the top level (scenemanager). - Add method to make a filename relative to a given directory. - Fix setMesh to correctly update the joints cache. - Fix setting transition time of skinned meshes back to 0. - Add some getters to IGUIImage: getImage, getColor - Fix OpenGL FBODepthTexture to create less overhead - Fix MRT disabling under OpenGL - API change: Added write only lock mode for textures. The lock method has changed the signature and uses an enum parameter now instead of a bool. The default is still to lock for read/write (previously 'false'). The old 'true' value should be replaced by ETLM_READ_ONLY. - Speedup deleting of particles - Add function IParticleSystemSceneNode::clearParticles - Fix RTT render states under OpenGL - Fix AntiAliasing setup under Windows/OpenGL in case no AA is available - Fix transformation matrices when RTT used - API change: getScreenCoordinatesFrom3DPosition has a new parameter, which needs to be set to true to get the original behavior. Now, the method returns coordinates which would fit as render coordinates of a currently enabled viewport. With the parameter set to true the result would fit only after the viewport is reset to full window rendering. - More checks for Stencilbuffer - Improve render state resets - Fix MRT handling - Fix file search - Add flag and method to disable clipping of the text to the gui element rectangle in GUI static text. - addShadowVolumeSceneNode now replaces an existing shadow. One should avoid to call this method multiple times without changing any parameter, as it is quite time consuming and cannot recognize the duplicate calls. - Add function IGUIEnvironment::removeFont (TODO: Does not remove the texture from cache so far) - Fixed mem leak in mountfilesystem - Update to libjpeg 8b, zlib 1.2.5, bzip2 1.0.6, libpng 1.4.4 and lzma from 9.20 SDK - Functions in IMeshCache expecting IAnimatedMesh* parameters removed as similar functions with IMesh* can be used since a while. Fixes also problems when IAnimatedMesh* got upcasted to IMesh*. (thx @ Greenya for reporting) - Fix blend states for MRTs - 64bit targets for MSVC added - The following functions will now use a "ISceneNode *" instead of a "const ISceneNode *": ITriangleSelector::getSceneNodeForTriangle, ISceneNodeAnimatorCollisionResponse::getCollisionNode, ISceneCollisionManager::getCollisionPoint and ISceneCollisionManager::getCollisionResultPosition. As collision functions often are followed by changing node positions users where so far forced to using const_casts (found by Greenya). - Add vector3d::getAs3Values (patch provided by slavik262) - Add function to SViewFrustum to get corners of the near plane (patch provided by Matt Kline, aka slavik262) - ParticleFadeOutAffector::setFadeOutTime can no longer be set to invalid values - ParticleFadeOutAffector uses now throughout u32 for fadeOutTime (found by greenya) - Add missing access function CParticleSystemSceneNode::getAffectors() (seen by B@z) - Add missing setters/getters for particle emitters (seen by B@z) - Compile-defines can now be disabled from Makefiles/Projectfiles instead of having to change IrrCompileConfig.h each time. - IGUITabControl::setActiveTab should only take IGUITab* and not IGUIElement* (thx to greenya for finding) - Add new skin-colors: EGDC_GRAY_WINDOW_SYMBOL, EGDC_EDITABLE, EGDC_GRAY_EDITABLE, EGDC_FOCUSED_EDITABLE - Disabled state is now extended to sub-elements - Make disabled state for several elements more visible - Bugfix: Icons in tabcontrol get now affected immediately by skin-changes - Proper cleanup if visual not created - XML reader bugfix - Disable mipmaps in 2d mode everywhere - Add xml example written by Yoran Bosman. - Fix cursor cleanup under Linux when using multiple devices - Fix collada parser - Fix MRT reset under D3D - Add a generic attribute interface for querying video driver attributes which are not necessarily of type bool. This interface allows to check certain supported features, such as the number of user clip planes, supported lights and textures, MRTs, and other things. The interface might change in the future, but it's fully functional already. The supported attributes are listed in the API docs of the function: The following names can be queried for the given types: * MaxTextures (int) The maximum number of simultaneous textures supported by the driver. This can be less than the supported number of textures of the driver. Use _IRR_MATERIAL_MAX_TEXTURES_ to adapt the number. * MaxSupportedTextures (int) The maximum number of simultaneous textures supported by the fixed function pipeline of the (hw) driver. The actual supported number of textures supported by the engine can be lower. * MaxLights (int) Number of hardware lights supported in the fixed function pipieline of the driver, typically 6-8. Use light manager or deferred shading for more. * MaxAnisotropy (int) Number of anisotropy levels supported for filtering. At least 1, max is typically at 16 or 32. * MaxUserClipPlanes (int) Number of additional clip planes, which can be set by the user via dedicated driver methods. * MaxAuxBuffers (int) Special render buffers, which are currently not really usable inside Irrlicht. Only supported by OpenGL * MaxMultipleRenderTargets (int) Number of render targets which can be bound simultaneously. Rendering to MRTs is done via shaders. * MaxIndices (int) Number of indices which can be used in one render call (i.e. one mesh buffer). * MaxTextureSize (int) Dimension that a texture may have, both in width and height. * MaxGeometryVerticesOut (int) Number of vertices the geometry shader can output in one pass. Only OpenGL so far. * MaxTextureLODBias (float) Maximum value for LOD bias. Is usually at around 16, but can be lower on some systems. * Version (int) Version of the driver. Should be Major*100+Minor * ShaderLanguageVersion (int) Version of the high level shader language. Should be Major*100+Minor. - Fix getRotationDegrees - Add creation parameter which allows to disable highres timers on Windows upon device creation. - Several transparency setup bugs fixed. Now, alpha_vertex_blend uses proper alpha blending instead of a mixed add/alpha blending. - Added a method to get real time and date in a human readable struct - Fix add folder archives method to support files without trailing slashes. - fix transparent_reflection_2_layers - Add support for MSVC 2010 - Fix "unsupported format" warning on RTT usage - Add IGUIElement::bringToBack (patch written by DtD, although I'm to blame for the function-name) - BurningVideo - add Normalmap Rendering (one light only), pushed Burningvideo to 0.46 - add Stencil Shadow Rendering (one color only and 32 bit only), pushed Burningvideo to 0.47 - internal vertexformat changed - changed fixpoint from 9 to 10 bit fract resolution - renamed createBurningVideoDriver to createBurningVideoDriver and uses SIrrlichtCreationParameters like opengl - internal interfaces for the trianglerenders unified. - Example 11, changed the light billboards to use the light color. allow to disable the bump/parallax on the earth like in the room ( with transparency ) - added DDS Image files, DXT2, DXT3, DXT4, DXT5, based on code from nvidia and Randy Reddig - added Halflife 1 Model Loader (based on code by Fabio Concas) Halflife 1.1.0.8, Counter-Strike 1.6 working -> Load all Textures ( can even optimize it to texture atlas ), all bone animation, all submodels. -> But to make use of the values (named animation, mouth animation) the Interface for IAnimatedMeshSceneNode has to be redone. TODO: ->can handle float frames numbers, the interface for getMesh should be reworked This is my idea of a new getMesh interface for IAnimatedMesh //! Returns the IMesh interface for a frame. /** \param frameA: Frame number as zero based index. The Blend Factor is in the fractional part of frameA The Mesh will be calculated as frame = integer(frameA) * (1-fractional(frameA )) + frameB * fractional(frameA) FrameNr KeyFrameA KeyFrameB 40.0 1 0 40.1 0.9 0.1 40.5 0.5 0.5 40.9 0.1 0.9 41.0 0 1 \param frameB: Frame number as zero based index. The other KeyFrame which is blended with FrameA. \param userParam: for Example Level of detail, or something else */ virtual IMesh* getMesh(f32 frameA, s32 frameB = 0,s32 param = 0) = 0; For now i used the (unused, always 255) detail level parameter and set a blend percentage as s32 frameNr = (s32) getFrameNr(); s32 frameBlend = (s32) (core::fract ( getFrameNr() ) * 1000.f); return Mesh->getMesh(frameNr, frameBlend, StartFrame, EndFrame); So no interface is affected. -> TODO: Quaternion Rotation is done private hand made and should be done with irrlicht quaternions - Included 357kb Yodan.mdl mesh and copyright info file from Doug Hillyer to the media directory, used in example 7. collision as 4th model. - added Halflife 1 Texture Loader Valve uses WAL archive types like quake2. textures are inside model files I reworked the existing ImageloaderWAL and added named Halflife textures to wal2 ( they have no extension ) and an LMP (palette/texture) loader into the same file (all using 32bit now) - added WAD Archive Loader (Quake2 (WAL2) and Halflife (WAL3) are supported) - CFileList added Offset Parameter to SFileListEntry and removed the private array from the archive loaders. CFileList::addItem now uses automatic incremental id if id = 0 - added void splitFilename, splits a path into components - added parameter make_lower to substring ( copy just lower case ) string subString(u32 begin, s32 length, bool make_lower = false ) const - ColorConverter added //! converts a 8 bit palettized or non palettized image (A8) into R8G8B8 static void convert8BitTo24Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad = 0, bool flip=false); //! converts a 8 bit palettized or non palettized image (A8) into A8R8G8B8 static void convert8BitTo32Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad = 0, bool flip=false); - In IGUITreeView "clearChilds" and "hasChilds" deprecated for "clearChildren" and "hasChildren" (thx @Greenya for noticing) - add CGUIEditBox::getOverrideColor and CGUIEditBox::isOverrideColorEnabled - add dimension2d::operator- - Add logging level ELL_DEBUG - Add parameter DisplayAdapter to creation params to allow selecting the card when more than one card is in the system. - Added support for custom cursors - WM_SYSCOMMAND - SC_KEYMENU message is now ignored (F10 and ALT in Win32 windowed mode) - Avoid argument lookup ambiguity in swap when used in combination with stl. Using same trick as boost now and use 2 different template parameters in it. - Add UseMipMap flag in material - Add occlusion query support. Based on code by Nadro - Add support for vertex_array_bgra extension in OpenGL driver. This will speed up OpenGL rendering quite a lot as it skips the silly color conversion thing we have to do otherwise. - Replace raw xml char implementation with template struct in order to decouple the type from POD types. May also help for 64bit problems or changes needed there. - Fixed bug causing memory access violation in string::replace found and patched by Nalin. - Fix windows32 class unregister - Add parameter to line2d::intersectWith to allow getting intersections outside the segments (thx Yoran). - External windows are not destroyed anymore - clamp values in getRotationDegrees to avoid nan values - texture size in terrain mesh fixed - ms3d fixes - Add new matrix methods for infinite projection matrix - Support new OpenGL 2.x shader creation ----------------------------- Changes in 1.7.4 (not yet released) - fixed getDepthFunction in IQ3Shader which always returned ECFN_EQUAL due to missing break (found by the cppcheck tool) - STL loader improved to handle arbitrary file starts - Compiler problem with gcc4.6 and big endian systems fixed - Change include order to get example 21 compiling on MinGW. - Irrlicht.dll has correct name now again (was named libIrrlicht.dll in c::b). This fixes bugreport 3518765 reported by tetho. - Fix linker path in example 16 for C::B project file (linker path was in include path section). - Link with opengl32 and gdi32 in Example 14 in C::B. - Remove --no-export-all-symbols which got recently added to the windows build as that flag is not known by gcc on Windows. - Fix bug in example 23 where Width and Height got mixed up. Thanks @Lazier for reporting. - Fix for R5G6B5 converter submitted by XMight - Fix conversion warning under mingw, found by Randajad - Set EMF_NORMALIZE_NORMALS correct for syndey model in Demo (thanks @ Midnight for reporting). - SceneNodeAnimatorFlyCircle fixes serialization of RadiusEllipsoid (was writing Radius). Thx @ wing64 for reporting. - Yield on Linux now uses nanosleep with 1ns as 0 isn't guaranteed to yield (thx @ hendu for finding + fix) ----------------------------- Changes in 1.7.3 (20.02.2012) - SceneNodeAnimatorFlyCircle fixes serialization of RadiusEllipsoid (was writing Radius). Thx @ wing64 for reporting. - Yield on Linux now uses nanosleep with 1ns as 0 isn't guaranteed to yield (thx @ hendu for finding + fix) - GUIEditor attributes have now scrollbar to be editable - Remove warning when compiling line2d::intersectWith with other types than f32. - Document that triangle3d::isPointInside should not be used with int's. - triangle3d::isPointInsideFast handles 'on-border' cases now consistently. - Some more editbox fixes - Harden Linux joystick usage, in case the driver returns illegal values - Bugfix: vector2d.normalize() and vector3d.normalize() had returned wrong results with very short vectors since Irrlicht 1.5. Thanks to Willem Swart for Bugreport + testcase. - Unknown keymappings now use the X11 keycode instead of 0 to make such keys at least usable in games. - KeyMapping for KeyInput.Key on X11 ignores states like shift&ctrl now like on Windows. - Additional keymappings for X11 (tested with german and us keyboards which seem to work now in all cases). - Fix crash in multiline editbox when pasting several lines into it on Windows (found by Reiko) - example 09.Meshviewer no longer catches keys while a modal dialog is open - Fix SSharedMeshBuffer - Fix right handed ortho matrix - editbox no longer displays cursor when disabled - editbox autoscrolling now at least works good enough to actually show the text which the user is typing in. - editbox no longer moves text into next line when it fails wrapping creating senseless empty lines which mess up scrolling. - Fix crash in editbox when scrolling up with empty first lines caused by textwrapping. - Fix endianess conversions - Changes to isPointInside - Fix focus problem when removing an unfocused modal dialog reported by Reiko here: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=44358 - Fix md2 normals problem again - Add integer template specialization for vector3d::getSphericalCoordinateAngles which rounds angles to nearest integer now. - Recalculate FrameRect and ScrollPos in CGUIEditBox when AbsoluteRect gets changed (thx @ serengeor for report + testcase) - Fix crash in editbox - Fix 'k' in bigfont.png (thx @ Scrappi for reporting) - fix serialization for CBillboardSceneNode, it had missed 2 color (thx for finding + patch from pc0de) - EMIE_MOUSE_WHEEL messages now handled correctly in several gui-element when wheel isn't just 1.0 or -1.0 (thx @ Reiko for reporting) - Fix problems in Textwrapping in CGUIStaticText. Did use wrong size and did ignore last word of the text (thx @ Reiko for bugreport) - Fix crash in collada (.dae) loading - Fix bug handling in case RTT is not properly created - Fix SColorf interpolation - Fix memory-leaks in example 22 MaterialViewer - Fix array::erase which did destroy objects more than once when used with a range (thx @ RedDragCZ for reporting + testcase). - Copy now all membervariables for CCameraSceneNode when cloning. - ICameraSceneNode::IsOrthogonal is correctly serialized and cloned now. - CGUIScrollBar passes unused mousemove-events now to parent element. Fixes focus-bug in ComboBox reported by REDDemon here: http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=43474&highlight= - Fix getAngle and getAngleWith - Fix clipping in CGUITabControl - Fix clipping in CGUITable, reported by ceyron - Skip bone weights and additional information in ms3d file if no joint was defined before. - Fix mem leak in CImage, found by mloren. - Fix tga writing, reported by xirtamatrix - Tab-positions care now about the borders correctly - TabControl now respositions it's tabs when setTabVerticalAlignment is changed (thx @ ceyron for reporting+testcase) - CGUIModalScreen now no longer takes focus itself, but tries to give it first child when possible to fix modal windows losing focus all the time - Modal screens no longer blinks when gui-elements call removeFocus on themself (thx @ yaten for reporting+testcase) - Fix crash in multiline-editbox when selecting with mouse (thx @ ceyron for reporting and testcase) - Fix render context creation for OpenGL under Windows. - Fix the reset problem of d3d9 driver in combination with hardware buffers. - Fix .x loader in case of unused vertices. - Avoid empty line in texts with very large words. Text wrapping would introduce an empty line in earlier versions. - Add a new attribute which assigns hw mapping hint to the whole Mesh. - Allow creation of water scene node without mesh. - Fix regeneration of skydome. - Fix scene node type and factory support for volume light - Q3 maps no longer crash when faces try accessing lightmaps which are not mentioned to be loaded in the file. - Fix crash on null-readfile in texture loading - Get particles saved before 1.7.2 (for example in irrEdit) working again (thx to smashly for problem reporting) - Fix IGUIScrollBar setMax and setMin which had been restricted wrongly (reported by REDDemon) - Fix CNullDriver::createImage - Creating the image from a texture-rectangle which doesn't start at 0,0 works now again (thx @ ceyron for bugreport+testcase) - Menu no longer sets highlight state when clicking disabled menu-item (reported by Mloren) - Treeview can now be disabled ----------------------------- Changes in 1.7.2 (15.11.2010) - Fix in d3d9 driver, which caused a crash when device creation failed. Bug found and fixed by Kostya - Fix a wrong access to Value instead of ValueW. Found and fixed by vroad. - Fix line loop rendering in d3d drivers. Fix submitted by tonic. - Fix tar recognition in tar reader. - Fix blend mode setup in OpenGL driver, when using the material2d override, as pointed out by Auria - Avoid crash due to tcoords2 handling. Might need some more fixing to work correctly. - Fix 2d line intersections. Has had problems with consecutive, but non-overlapping line segments and with overlapping line segments. - Fix image creation from texture, found by dataslayer - Fix crashes when taking Screenhots for DirectX in Windowed mode (thx to agamemnus for reporting) - StaticText does now serialize the background color - Fix gui-elements which didn't care when skin-colors changed. That made it impossible to make the gui slowly transparent (thx to PI for reporting). Note that it couldn't be completely fixed for the SpinBox without breaking the interface, so for that element you have to enforce this by calling for example element->setValue(element->getValue()) once. - Fix CXMLReaderImpl::getAttributeValueAsInt which returned wrong values with large integers (thx to squisher for finding) - Fix compile problem in swap when using irrlicht in combination with stl (backport from trunk r3281) - Add EGET_TREEVIEW_NODE_COLLAPSE and deprecate EGET_TREEVIEW_NODE_COLLAPS (found by greenya) - Fix serialization in CParticleSystemSceneNode (found by B@z) - Prevent crash in BillboardTextSceneNode when a custom font is used. Found and fixed by Nalin (bugtracker id: 3020487) - Fix problem in animation system that currentFrame got messed up after long pauses (especially when not starting at frame 0). See forum thread (http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?p=210537#210537) and bug id 2898876. Also remove BeginFrameTime in CAnimatedMeshSceneNode as it hasn't been used anymore since some time. - Add framerate and current frame information for animations in example 09 and do some minor cleanup. - Added another test for xml-reader. - Fix serialization in several particle emitters and affectors (thx to Ion Dune for reporting). - Fix compile-error on VS for vector2d::getAngleTrig when used with integers. (thx to greenya for reporting) - Fix bug in dimension2d::getInterpolated that caused wrong results when used with integers as template parameter. (thx to Greenya for noticing a warning which made me look over this code). - Remove 2 minor memory leaks in meshloaders (found by tool cppcheck-1.43) - reduce file dependencies for IGUIEventReceiver.h (thx ngc92) - Initialize GUIEvent.Element in several places (found by greenya) - Add EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH and deprecated EGDS_MESSAGE_BOX_MAX_TEST_WIDTH (thx to greenya for reporting). - Fix colors in irr files. - Fix several places where "used" in core::string was used wrongly preventing some memory corruption - Remove additional slash in pathnames in X-Loader - Fix crash in CGUIListBox when environment was cleared on events - Bugfix: Clear up depth-textures which could not be attached in OpenGL to prevent crashes. - Fix arrowMesh boundingbox. - Fix rounding problem in getInterpolated in the color classes - Scrollbar in GUIListbox now uses default id -1 instead of 0 - Fix octree clipping issues. - Fix obj loader. - clone function fixes. - Fix tooltips. - Fix Ogre parser. ----------------------------- Changes in 1.7.1 (17.02.2010) - Fix octree with frustum+parent checks enabled (didn't clip at all before). Now using plane-checks instead of edge-checks for frustum-box intersection. - Prevent that X11 selects larger resolutions in fullscreen even when perfect fits are available. - Ignore setResizable also on X11 when we're fullscreen to avoid messing up the window mode. - Work around a crash when pressing ESC after closing a Messagebox (found by Acki) - Prevent borland compile warnings in SColorHSL::FromRGB and in SVertexColorThresholdManipulator (found by mdeininger) - Improve Windows version detection rules (Patch from brferreira) - Make it compile on Borland compilers (thx to mdeininger) - Make sure that CAnimatedMeshSceneNode::clone calls the virtual updateAbsolutePosition for the new object - Fix that clones got dropped too often when SceneNodes without parent got cloned (found by Ulf) - Make sure TAB is still recognized on X11 when shift+tab is pressed. This does also fix going to the previous tabstop on X11. - Send EGET_ELEMENT_LEFT also when there won't be a new hovered element - Update docs for EGET_ELEMENT_LEFT and EGET_ELEMENT_HOVERED - Fix tooltips: Remove them when the element is hidden or removed (thx to seven for finding) - Fix tooltips: Make (more) sure they don't get confused by gui-subelements - Fix tooltips: Get faster relaunch times working - Fix tooltips: Make sure hovered element is never the tooltip itself - Fix string::remove which got in an endless loop when remove was called with an empty string (found and fixed by Ulf) - Correctly release the GLSL shaders - Make sure we only release an X11 atom when it was actually created - Fix aabbox collision test, which not only broke the collision test routines, but also frustum culling, octree tests, etc. - Fix compilation problem under OSX due to wrong glProgramParameteri usage - mem leak in OBJ loader fixed - Removed some default parameters to reduce ambigious situations --------------------------- Changes in 1.7 (03.02.2010) - Implement minimize and deminimize under OSX. - Define sorting order for vector2d and vector3d in operators <, <=, > and >= to fix bugs 2783509 and 2783510. Operators order now by X,Y,Z and use float tolerances. - Ogre mesh 32bit indices fixed. - Fix tooltips for gui-elements with sub-element like IGUISpinBox (id: 2927079, found by ArakisTheKitsune) - ITimer no longer stops when started twice - wchar_t filesystem updates under Windows. - Joystick POV fixed under Windows, ids fixed under OSX. - Some updates to skinned mesh for better bones support and scaling animations. - OSX supports external window id in creation parameters now. - Fix bbox collision tests. - Updates for win32 key handling - new convenience method for flat plane creation. - Sky dome and other meshes use VBOs by default now. - Speed up b3d loading for files with many frames, material color flags and vertex color support enhanced. - Add hasType to IGUIElement as a dynamic_cast substitute. - Add another parameter to IGUISkin::draw3DWindowBackground to allow getting the client area without actually drawing - Add function getClientRect to IGUIWindow for getting the draw-able area - Fix bug that menus on IGUIWindows with titlebar got drawn too high (id: 2714400) - Renamed OctTree to Octree - Allow getting a ConstIterator from a non-const core:list - Add swap functions to irrMath and to the core classes. - Deprecate map::isEmpty() and replace it with map::empty() to make it similar to other base classes. - Allow to set the logging level already in SIrrlichtCreationParameters. - Add clearSystemMessages to devices (implemented only for Linux and Win32 so far). - Support changing the render window from beginScene also with OpenGL driver. - Add getMaterial2D which allows to alter the 2d render state settings, such as filtering, anti-aliasing, thickness, etc. - Fix incorrect cursorpos for resizable windows on Windows Vista (found and patched by buffer) - Change the beginScene window parameter from void* to SExposedVideoData&. This will allow to manage contexts for OpenGL at some point. - Add bzip2 and LZMA decompression modes for zip loader. - Add OBJ_TEXTURE_PATH and B3D_TEXTURE_PATH to SceneParameters to allow setting texture-paths for obj and b3d. - Irrlicht keeps now filenames additionally to the internally used names, thereby fixing some problems with uppercase-filenames on Linux. - Bugfix: Mousewheel no longer sends EMIE_MOUSE_WHEEL messages twice on Linux. - Use latest jpeglib - refactoring: E_ATTRIBUTE_TYPE and IAttribute have now own headers - CStringWArrayAttribute speedup - SceneNodeAnimatorFollowSpline can now loop and pingpong - Meshviewer.example got some fast-scale buttons. - Support AES-encrypted zip files. Should work with 128, 196, and 256 bit AES. This addition also adds a new PRNG, SHA, and other algorithms to the engine, though no interface is yet added for them. The implementation of the encryption algorithms is provided by Dr Brian Gladman. - flattenFilename and getAbsolutePath fixed and properly added at several places. - Added geometry shaders for OpenGL. A first version of the code was submitted by Matthew Kielan (devsh). - Bugfix: irrArray should no longer crash when using other allocators. - Add MaterialViewer example. - Texture activation now back in setMaterial, which simplifies writing external material renderers (OpenGL only). - Checkbox uses now disabled text color when disabled. - Changed colors for window-title caption to keep them readable when not active. - Draw sub-menus to left side if they would be outside main-window otherwise. - Give ListBox better defaults for the ScrollBar stepsizes. - Double and triple click events now for each mouse-button. Old events for that got removed. - Fix adding archives twice, which caused multiple archives of the same name and type covering each other. This one required a texture name change from using backslashes to slashes under Windows. - Give access to texture mipmaps. You can provide custom mipmap textures upon generation, regeneration, and locking. Make sure the provided data is large enough and covers all miplevels. Also the returned pointer (from lock) will only cover the smaller data of the mipmap level dimension chosen (level 0 is the original texture). - Separate TextureWrap mode into U and V fields - Add mirror texture wrap modes - windows show now active/inactive state - remove unneeded drop/grab calls found by manik_sheeri - fix rounding problem in IGUIElements which have EGUIA_SCALE alignments. - MessageBox supports now automatic resizing and images. Deprecated EGDS_MESSAGE_BOX_WIDTH and EGDS_MESSAGE_BOX_HEIGHT - Let maya-cam animator react on a setTarget call to the camera which happened outside it's own control - New contextmenue features: automatic checking for checked flag. close handling now customizable serialization can handle incomplete xml's setEventParent now in public interface New function findItemWithCommandId New function insertItem - new vector3d::getSphericalCoordinateAngles method. - new triangle3d::isTotalOutsideBox method. - Newly introduced VertexManipulator interface. This allows for very easy creation of vertex manipulation algorithms. Several manipulators, e.g. vertex color changer and transformation algorithms are already available. - createMeshWith1TCoords avoids vertex duplication - getRotation now handles matrices with scaling as well - Ogre format animations now supported. - irrArray: Fixed issues with push_front and reallocation Changed behavior for set_pointer and clear, when free_when_destroyed is false - NPK (Nebula device archive) reader added, it's an uncompressed PAK-like format - SSkinMeshBuffer::MoveTo* methods renamed to convertTo* - Multiple Render Target (MRT) support added, including some enhanced blend features where supported - Directory changing fixed for virtual file systems (Archives etc) - Fix texture matrix init in scene manager and driver - More draw2dimage support in software drivers - Sphere node now properly chooses a good tesselation based on the parameters - Active camera not registered twice anymore - Parallax/normal map shader rotation bug under OpenGL fixed - bump map handling for obj files fixed - Fog serialization added - New context menu features added - Bounding Box updates for skinned meshes fixed - The current FPS for an animated scene node can be queried now, added some variables to serialization - Scrollbars fixed - Fixed 2d vertex primitive method to correctly handle transparency - Fullscreen handling has been enhanced for Windows, now proper resolution is restored on Alt-Tab etc. - Cameras can now be added to the scene node without automatically activating them Clone method added - New video driver method getMaxTextureSize - PAK archive reader fixed - TRANSPARENT_ALPHA_CHANNEL_REF uses modulate to enable lighting - LIGHTMAP_ADD now always uses add operator - Some Unicode file system fixes - destructor of irrString not virtual anymore, please don't derive from irrString Some new methods added, for searching and splitting Assignment operator optimized - new lightness method for SColor - draw3DTriangle now renders filled polygons, old behavior can be achieved by setting EMT_WIREFRAME ----------------------------- Changes in 1.6.1 (13.01.2010) - Fix pingpong for CSceneNodeAnimatorFlyStraight (found by gbox) - Fix bug with IGUIEditBox where the cursor position is reset on text change. - Make sure the window top-left corner on Windows is not negative on start so that Windows sytem-menu is always visible. - Fix problem that the window did sometimes not get the keyboard focus in X11 in fullscreen. Add more debug output in case focus grabbing goes wrong. - Fix screensize in videodriver when we didn't get the requested window size. This also prevents that gui-clicks are no longer synchronized with gui-drawing and elements can't be hit anymore. - Bugfix: Prevent a crash when getTypeName was called for the guienvironment. EGUIET_ELEMENT got changed for this. - Bugfix: Horizontal centered font with linebreaks draw now all lines. For example multiline TextSceneNodes work again. - Bugfix: spinbox can no longer get in an endless loop due to floating point rounding error (found by slavik262) - !!API change!! Disabled AntiAliasing of Lines in material default Please enable this manually per material when sure that it won't lead to SW rendering. - IGUIComboBox: clicking on the statictext displaying the active selection does now close and open listbox correctly. (Bug found by Reiko) - Scrollbuttons in IGUITabControl adapt now to tab-height. - Fix texturing of cylinder mesh - Fix modal dialog position (found by LoneBoco: http://sourceforge.net/tracker/?func=detail&aid=2900266&group_id=74339&atid=540676) - Fix DMF loading - Fixing left+right special keys (ctrl, shift, alt) on Win32 (thanks to pc0de for good patch-ideas). - Make stringarrays for enums in IGUISkin a little safer - Add support for keys KEY_PRINT, KEY_HOME (on numpad) and KEY_NUMLOCK on Linux. - Fix material handling in createMeshWith1TCoords - Fix another (OldValue == NewValue) before drop()/grap(), this time in CTextureAttribute::setTexture. - Fix LIGHTMAP_LIGHTING for D3D drivers. - AntiAliasing disabled for debug render elements. - Bugfix: CGUIToolBar::addButton does no longer mess up when no image is set and does now actually work with the text. - Fix ninja animation range which got messed up a little when b3d animations got fixed (thx gbox for finding) --------------------------- Changes in 1.6 (23.09.2009) - Added IFileSystem::createEmptyFileList, exposed IFileList::sort, addItem and added getID - Fix MAKE_IRR_ID so it can be used from outside the irr namespace (Micha's patch) - Renamed some methods in ISkinnedMesh to match the official Irrlicht naming scheme according to createXXX() - Change debug data to draw using lines instead of arrows, which is much faster. Patch by pc0de - Fix a bug with FPS camera animator causing stutters. Patch by FuzzYspo0N - Fix scrolling controls in CGUITabControl - Fix a bug when getting optimal texture size in D3D drivers, by Jetro Lauha (tonic) - Added EGDS_TITLEBARTEXT_DISTANCE_X and EGDS_TITLEBARTEXT_DISTANCE_Y to GUI, submitted by FuzzYspo0N - Fix for UFT8 filenames displayed in file dialog, patch by MadHyde. - Added const method for array::binary_search, potentially slow as it doesn't sort the list! - Add support for scaling button images. - Irrlicht can now come with multiple device types compiled in, the device to use is selected by SIrrlichtCreationParameters.DeviceType. This defaults to EIDT_BEST which automatically select the best device available starting with native, then X11, SDL and finally the console. - Added support for EXP2 fog distribution. This required a change in the setFog parameters where now an enum value instead of the bool linear is given. - IFileSystem changes: - Renamed the following functions- IFileArchive::getArchiveType to getType IFileSystem::registerFileArchive to addFileArchive IFileSystem::unregisterFileArchive to removeFileArchive IFileArchive::openFile to createAndOpenFile - New enum, E_FILE_ARCHIVE_TYPE. getType on IArchiveLoader and IFileArchive now both return this. - IFileSystem::addFileArchive takes a parameter to specify the archive type rather always using the file extension. IFileSystem::addZipFileArchive, addFolderFileArchive and addPakFileArchive now use this but these functions are now marked as deprecated. Users should now use addFileArchive instead. - Added TAR archive loader. - The ZIP archive loader can now load gzip files, combined with the TAR loader this means Irrlicht now has native support for .tar.gz Currently this must be done in two calls, for example: fileSystem->addFileArchive("path/to/myArchive.tar.gz"); fileSystem->addFileArchive("myArchive.tar"); - Fix highlighting in IGUIEditBox where kerning pairs are used in the font. For example in future italic, OS or other custom fonts. - IOSOperator::getTextFromClipboard returns now const c8* instead of c8* - Support for copy&paste on linux (X11) added (fixing bug 2804014 found by Pan) - bugfix for 2795321 found by egrath: Don't rely anymore on broken XkbSetDetectableAutoRepeat. - bugfix: CMountPointReader::openFile no longer returns true for empty files. Corresponding test added. - Direct3D now also uses screen coordinates in 2d mode, just like OpenGL. This means that screen coords are going from 0..ScreenWidth and 0..ScreenHeight instead of -1..1. - ALT+F4 keypress now closes Windows SDL device - Allow Direct3D drivers in SDL, patch by Halifax - Added compiler error when attempting to compile with VC6. - Use setWindowTextA in Windows device for WIN64 platform, posted by veegun - ELL_ERROR log events are now created when shaders fail to compile or link, reported by Halan - irrList now uses irrAllocator, fixed by Nox - Added IGUIWindow::setDraggable and IGUIWindow::isDraggable, by Nox - Added SGI RGB file reader by Gary Conway, for loading Silicon Graphics .rgb, .rgba, .sgi, .int and .inta textures - Renamed setResizeAble to setResizable - Added new device method minimizeWindow which minimizes the window (just as if the minimize button has been clicked). - SkyDome is now serialized correctly - Added PLY mesh reader and writer - Ensure ListBox on combo box doesn't hang off the bottom of the GUI root, by Matthias Specht - Made IGUIElements recalculate clipping rectangle after setNotClipped, reported by Aelis440 - Bug fix for the combo box where it showed white text instead of skin color before being focused, fix posted by drewbacca - EGDS_MESSAGE_BOX_HEIGHT is now honoured, bug reported by Spkka - Fixed a bug in the edit box where events are sometimes sent to a null parent, reported by Sudi. - Coordinate system fix for OpenGL in SDL device - Added generic console device. You can now use Irrlicht to create and manipuate graphics on a shell where no graphics hardware or windowing system is available. To enable it uncomment #define _IRR_USE_CONSOLE_DEVICE_ in IrrCompileConfig.h - The console device can now present images from the software drivers and display them as ASCII art in the console - By default it replaces the default font in the skin, to prevent fonts from being huge. - Fixed problems with changing cursor visibility while mouse is pressed on windows - Allow control of background drawing in listbox - Allow control of drawing background and titlebar in windows - Improved window serialization - Add mouse events EMIE_MOUSE_DOUBLE_CLICK and EMIE_MOUSE_TRIPLE_CLICK (thx to Ulf for patch proposal) - Set "ButtonStates" for mouse events also on Linux (was only for Windows formerly) - Add Shift+Control states to mouse event - bugfix (2003238): serialize modal screens - allow stacking modal screens - allowing hiding modals - replace many IsVisible checks with virtual isVisible() checks in IGUIElement - bugfix: reset selected row when clearing CGUITable - adding events EGET_EDITBOX_CHANGED and EGET_EDITBOX_MARKING_CHANGED - prevent editbox from recalculating its textbreaking each frame - let spinbox react on each textchange without waiting for enter to prevent getting value changes without corresponding EGET_SPINBOX_CHANGED events. - new test for zipreader - prevent dropping objects accidentally in many set functions - Reversed change in vector3d::normalize. Works now again as documented and a corresponding test has been added. Does fix bug 2770709 (https://sourceforge.net/tracker/?func=detail&aid=2770709&group_id=74339&atid=540676) - Animations can now be paused by setting the fps to 0. - Avoid fp-precision problem in getPickedNodeBB (see also http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=33838&highlight=). This change might also fix the problem with picking nodes found by aanderse (http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=32890&highlight=) - implemented isALoadableFileFormat ( File *file ) for the Archive Loader - PixelBlend16 and PixelBlend16_simd are working for the new rules. - bugfix. CLightSceneNode didn't correctly update it's attributes - vector template and equals tests also set the equal test for s32 to behave like the f32 routine. The function equals always implements a weak test. that means a tolerance MUST always be used if you use the equal function. default is 1. - VideoDriver drawPixel The HW renderes are using the alpha components for blending. The Software Renderes and image loaders are using CImage::setPixel copy. so setPixel is engaged to either blends or copy the pixel default: false - Burningvideo added RenderMaterial EMT_SPHERE_MAP pushed burningsvideo to 0.43 added RenderMaterial EMT_REFLECTION_2_LAYER pushed burningsvideo to 0.44 set EMT_TRANSPARENT_ALPHA_CHANNEL_REF to use AlphaRef 0.5 like Direct3D One Note: in OpenGL there is know difference between sphere_map and reflection layer both using GL_TEXTURE_GEN_MODE GL_SPHERE_MAP, whereas in d3d one time using camera_normal on sphere and reflection on refletcion_layer. The visual difference is that on sphere map the "image is not moving" when you rotate the viewer. For Burning i took the opengl visual. always moving - rename quake3 SEntity to IEntity to be confom with IShader - fixed createMeshWith2TCoords, normals were missing during copy. - added //! Creates a copy of the mesh, which will only consist of S3DVertex vertices. IMesh* CMeshManipulator::createMeshWith1TCoords(IMesh* mesh) const - added io::IFileSystem* CSceneManager::getFileSystem() - added virtual const c8* ISceneManager::getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type); - added CSceneNodeAnimatorFlyCircle::radiusEllipsoid. if radiusEllipsoid == 0 the default circle animation is done else radiusEllipsoid forms the b-axe of the ellipsoid. -> gummiball bouncing - added ISceneManager::createFlyStraightAnimator variable bool ping-pong used in loop mode to device if start from beginning ( default ) or make ping-pong -> straight bouncing - changed IFileSystem::registerFileArchive remove the index of the hierarchy and added a new interface method //! move the hirarchy of the filesystem. moves sourceIndex relative up or down virtual bool moveFileArchive( u32 sourceIndex, s32 relative ) = 0; - bugfix and changes in SViewFrustum::SViewFrustum wrong size of Matrices copy. renamed E_TRANSFORMATION_STATE_2 to E_TRANSFORMATION_STATE_FRUSTUM therefore also changed SViewFrustum::setTransformState to not tap in the pitfall again of wrong memory... - moved //! EMT_ONETEXTURE_BLEND: has BlendFactor Alphablending inline bool textureBlendFunc_hasAlpha ( E_BLEND_FACTOR factor ) const from the material renderes ( 3x declared ) to SMaterial.h - updated managed light example to use standard driver selection - BurningsVideo - LightModel reworked. Point Light & Direction Light works for Diffuse Color as expected Specular and Fog still have problems ( needs new pixel shader ) pushed burningsvideo to 0.42 for this major step - removed obsolete matrix transformations renamed E_TRANSFORMATION_STATE_2 to E_TRANSFORMATION_STATE_BURNING - cleaned line3d.h vector3d.h template behavior. many mixed f32/f64 implementations are here. i'm not sure if this should be the default behavior to use f64 for example for 1.0/x value, because they benefit from more precisions, but in my point of view the user is responsible of choosing a vector3d or vector3d. - added core::squareroot to irrmath.h -> for having candidates for faster math in the same file - added AllowZWriteOnTransparent from SceneManager to burningsvideo -added hasAlpha() to ITexture This info can be used for e.q to downgrade a transparent alpha channel blit to add if the texture has no alpha channel. - FileSystem 2.0 SUPER MASTER MAJOR API CHANGE !!! The FileSystem is now build internally like for e.g. the image- and meshloaders. There exists a known list of ArchiveLoaders, which know how to produce a Archive. The Loaders and the Archives can be attached/detached on runtime. The FileNames are now stored as io::path. where c16 is toggled between char/wchar with the #define flag _IRR_WCHAR_FILESYSTEM, to supported unicode backends (default:off) Replaced most (const c8* filename) to string references. Basically the FileSystem is divided into two regions. Native and Virtual. Native means using the backend OS. Virtual means only use currently attached IArchives. Browsing each FileSystem has it's own workdirectory and it's own methods to - create a FileTree - add/remove files & directory ( to be done ) Hint: store a savegame in a zip archive... basic browsing for all archives is implemented. Example 21. Quake3Explorer shows this TODO: - a file filter should be implemented. - The IArchive should have a function to create a filetree for now CFileList is used. Class Hierarchy: IArchiveLoader: is able to produce a IFileArchive - ZipLoader - PakLoader - MountPointReader ( formaly known as CUnzipReader ) IFileArchive: -ZipArchive -PakArchive -MountPoint (known as FolderFile) IFileSystem - addArchiveLoader - changed implementation of isALoadableFileExtension in all loaders to have consistent behavior - added a parameter to IFileList * createFileList setFileListSystem allows to query files in any of the game archives standard behavior listtype = SYSTEM ( default) - CLimitReadFile added multiple file random-access support. solved problems with mixed compressed & uncompressed files in a zip - IrrlichtDevice added: virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) = 0; virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue ) = 0; and calculating methods to DeviceStub. - irrlicht.h changed exported irrlicht.dll routines createDevice, createDeviceEx, IdentityMatrix to extern "C" name mangling. - ParticleSystem removed the private (old?,wrong?) interface from the ParticleEffectors to match the parent class irr::io::IAttributeExchangingObject::deserializeAttributes - Generic - vector3d& normalize() optimized added reciprocal_squareroot for f64 - dimension2d added operator dimension2d& operator=(const dimension2d& other) to cast between different types - vector2d bugfix operator+= - C3DSMeshLoader renamed chunks const u16 to a enum removing "variable declared but never used warning" - added a global const identity Material changed all references *((video::SMaterial*)0) to point to IdentityMaterial removed warning: "a NULL reference is not allowed" - modified IRRLICHT_MATH to not support reciprocal stuff but to use faster float-to-int conversion. - core::matrix4 USE_MATRIX_TEST i tried to optimize the identity-check ( w.r.t. performance) i didn't succeed so well, so i made a define for the matrix isIdentity -check for now it's sometimes faster to always calculate versus identity-check but if there are a lot of scenenodes/ particles one can profit from the fast_inverse matrix, when no scaling is used. further approvement could be done on inverse for just translation! ( many static scenenodes are not rotated, they are just placed somewhere in the world) one thing to take in account is that sizeof(matrix) is 64 byte and with the additional bool/u32 makes it 66 byte which is not really cache-friendly.. - added buildRotateFromTo Builds a matrix that rotates from one vector to another - irr::array. changed allocating routine in push_back added a new method setAllocStrategy, safe ( used + 1 ), double ( used * 2 + 1) better default strategies will be implemented - removed binary_search_const i added it quite a long time ago, but it doesnt make real sense a call to a sort method should happen always. i just wanted to safe a few cycles.. - added binary_search_multi searches for a multi-set ( more than 1 entry in the sorted array) returns start and end-index - changed some identity matrix settings to use core::IdentityMatrix - added deletePathFromFilename to generic string functions in coreutil.h and removed from CZipReader and CPakReader - s32 deserializeAttributes used instead of virtual void deserializeAttributes in ParticleSystem ( wrong virtual was used) - strings & Locale - started to add locale support - added verify to string - added some helper functions - XBOX i have access to a XBOX development machine now. I started to compile for the XBOX. Question: Who did the previous implementation?. There is no XBOX-Device inhere. maybe it's forbidden because of using the offical Microsoft XDK. I will implement a native or sdl device based on opendk. irrlicht compiles without errors on the xbox but can't be used. - Windows Mobile reworked a little. added the mobile example to the windows solution for cross development. added maximal 128x128 texture size for windows mobile ( memory issues ) - Collision Speed Up The Collision Speed Up greatly improves with many small static child-nodes - added COctTreeTriangleSelector::getTriangles for 3dline from user Piraaate - modified createOctTreeTriangleSelector and createTriangleSelector to allow node == 0, to be added to a meta selector - CSceneNodeAnimatorCollisionResponse has the same problem as CSceneNodeAnimatorFPS on first update: Problem. you start setting the map. (setWorld). First update cames 4000 ms later. The Animator applies the missing force... big problem... changed to react on first update like camera. - add Variable FirstUpdate. if set to true ( on all changes ) then position, lasttime, and falling are initialized -added #define OCTTREE_USE_HARDWARE in Octree.h if defined octtree uses internally a derived scene::MeshBuffer which has the possibility to use the Hardware Vertex Buffer for static vertices and dirty indices;-) if defined OCTTREE_USE_HARDWARE octree uses internally a derived scene::CMeshBuffer so it's not just a replacement inside the octree. It also in the OctTreeSceneNode. #define OCTTREE_PARENTTEST is also used. It's skip testing on fully outside and takes everything on fully inside - virtual void ISceneNode::updateAbsolutePosition() - changed inline CMatrix4 CMatrix4::operator*(const CMatrix4& m2) const - changed inline bool CMatrix4::isIdentity() const to look first on Translation, because this is the most challenging element - virtual core::matrix4 getRelativeTransformation() const Hierarchy on Identity-Check 1) ->getRelativeTransform -> 9 floating point checks to be passed as Identity 2) ->isIdentity () -> 16 floating point checks to be passed as Identity - inline void CMatrix4::transformBoxEx(core::aabbox3d& box) const added isIdentity() check - changed CSceneNodeAnimatorCollisionResponse - added CSceneNodeAnimatorCollisionResponse::setGravity needed to set the differents Forces for the Animator. for eq. water.. - added CSceneNodeAnimatorCollisionResponse::setAnimateTarget - added CSceneNodeAnimatorCollisionResponse::getAnimateTarget - changed CSceneNodeAnimatorCollisionResponse::animateNode to react on FirstUpdate - TODO: set Gravity to Physically frame independent values.. current response uses an frame depdended acceleration vector. ~9.81 m/s^2 was achieved at around 50 fps with a setting of -0.03 may effect existing application.. - SceneNodes - CSkyDomeSceneNode moved radius ( default 1000 ) to constructor added Normals added DebugInfo added Material.ZBuffer, added SceneManager - CVolumeLightSceneNode: changed default blending OneTextureBlendgl_src_color gl_src_alpha to EMT_TRANSPARENT_ADD_COLOR ( gl_src_color gl_one ) which gives the same effect on non-transparent-materials. Following the unspoken guide-line, lowest effect as default - changed SceneNode Skydome from f64 to f32 - AnimatedMesh Debug Data: mesh normals didn't rotate with the scenenode fixed ( matrix-multiplication order) - Camera SceneNode setPosition Camera now finally allow to change position and target and updates all effected animators.. - Device: added the current mousebutton state to the Mouse Event so i need to get the current mouse state from the OS - GUI - CGUIFont: - added virtual void setInvisibleCharacters( const wchar_t *s ) = 0; define which characters should not be drawn ( send to driver) by the font. default: setInvisibleCharacters ( L" " ); - added MultiLine rendering should avoid to us CStaticText breaking text in future - CGUIListBox - changed Scrollbar LargeStepSize to ItemHeight which easy enables to scroll line by line - CGUIScrollBar - bug: event lost when moving outside the window - bug: Scrollbar notifyListBox notify when the scrollbar is clicked. - changed timed event in draw to OnPostRender - added GUI Image List from Reinhard Ostermeier, modified to work - FileOpenDialog changed the static text for the filename to an edit box. - changed the interface for addEditBox to match with addStaticText - changed the interface for addSpinBox to match with addEditBox - added MouseWheel to Spinbox - changed CGUITable CLICK_AREA from 3 to 12 to enable clicking on the visible marker - CGUISpritebank removed some crashes with empty Sprite banks - IGUIScrollBar added SetMin before min was always 0 changed ScrollWheel Direction on horizontal to move right on wheel up, left on wheel down - IComboBox: added ItemData - optimized IsVisible check in IGUIElement::draw - Image Loaders - added TGA file type 2 ( grayscale uncompressed ) - added TGA file type (1) 8 Bit indexed color uncompressed ColorConverter: - added convert_B8G8R8toA8R8G8B8 - added convert_B8G8R8A8toA8R8G8B8 - Media Files - added missing shaders and textures to map-20kdm2. Taken from free implementation - ball.wav. adjusted DC-Offset, amplified to -4dB, trim cross-zero - impact.wav clip-restoration, trim cross-zero - added gun.md2, gun.pcx to media-files - added new irrlicht logo irrlicht3.png - OctTree -added #define OCTTREE_PARENTTEST ( default: disabled ) used to leave-out children test if the parent passed a complete frustum. plus: leaves out children test minus: all edges have to be checked - added MeshBuffer Hardware Hint Vertex to octtree - CQuake3ShaderSceneNode: - removed function releaseMesh Shader doesn't copy the original mesh anymore ( saving memory ) so therefore this (for others often misleading ) function was removed - changed constructor to take a (shared) destination meshbuffer for rendering reducing vertex-memory to a half - don't copy the original vertices anymore - added deformvertexes autosprite - added deformvertexes move - added support for RTCW and Raven BSPs ( qmap2 ) - added polygonoffset (TODO: not perfect) - added added nomipmaps - added rgbgen const - added alphagen - added MesBuffer Hardware Hint Vertex/Index to Quake3: static geometry, dynamic indices - added Quake3Explorer examples - added wave noise - added tcmod transform - added whiteimage - added collision to Quake3Explorer - renamed SMD3QuaterionTag* to SMD3QuaternionTag* ( typo ) - updated quake3:blendfunc - added crouch to Quake3Explorer (modifying the ellipsiodRadius of the camera animator ) added crouch to CSceneNodeAnimatorCameraFPS still problems with stand up and collision - Quake3MapLoader modified memory allocation for faster loading - Quake3LoadParam added Parameter to the Mesh-Loader - added The still existing missing caulking of curved surfaces. using round in the coordinates doesn't solve the problem. but for the demo bsp mesh it solves the problem... (luck) so for now it's switchable. TJUNCTION_SOLVER_ROUND default:off - BurningVideo - pushed BurningsVideo to 0.40 - added blendfunc gl_one_minus_dst_alpha gl_one - added blendfunc gl_dst_color gl_zero - added blendfunc gl_dst_color src_alpha - modified AlphaChannel_Ref renderer to support alpha test lessequal - addded 32 Bit Index Buffer - added sourceRect/destRect check to 2D-Blitter ( slower, but resolves crash ) - added setTextureCreationFlag video::ETCF_ALLOW_NON_POWER_2 Burning checks this flag and when set, it bypasses the power2 size check, which is necessary on 3D but can be avoided on 2D. used on fonts automatically. - added Support for Destination Alpha - Direct3D8 - added 32 Bit Index Buffer - compile for XBOX - Direct3D9 - fixed crash on RTT Textures DepthBuffer freed twice. added deleteAllTextures to destructor - NullDriver - removeallTextures. added setMaterial ( SMaterial() ) to clean pointers for freed textures - ISceneCollisionManager::getSceneNodeAndCollisionPointFromRay() allows selection by BB and triangle on a heirarchy of scene nodes. - Triangle selectors created from animated mesh scene nodes will update themselves as required to stay in sync with the node. - IVideoDriver has methods to enumerate the available image loaders and writers. - Octtree scene nodes are now IMeshSceneNodes rather than ISceneNodes, and so you can call getMesh() on them. - New scene parameter B3D_LOADER_IGNORE_MIPMAP_FLAG to ignore the often missing mipmap flag in b3d files. If this parameter is true, the old pre Irrlicht-1.5 behavior is restored. - Added Mipmap LOD Bias attribute to MaterialLayer. - Added ColorMask support to selectively disable color planes on rendering. - Added support for all available depth test functions. - Add an outNode to getCollisionPoint() that returns the scene node that was hit, as well as the triangle. - Initial support for Alpha To Coverage, needs some more fixing until it works on all supported platforms. - Added support for Anti-Aliasing modes per material - Added an ICollisionCallback to ISceneNodeAnimatorCollisionResponse, to inform the application that a collision has occured. Thanks to garrittg for this. - Added an startPosition parameter to createFlyCircleAnimator() to allow starting the animator at any position on the circle. - Many uses of dimension2d changed to dimension2d, including IImage, ITexture and screen dimensions. You will have to change (at least) createDevice() calls to use dimension2d - Added Doublebuffer flag to SIrrCreationParameters, for better finetuning - Added Stereo-Framebuffer support for professional OpenGL cards - Added IFileSystem::createMemoryWriteFile() to allow creation of an IWriteFile interface that uses an application supplied memory buffer. - Added an IVideoDriver::writeImageToFile() overload that can take an IWriteFile interface. - (Internal) Replaced CMemoryReadFile with CMemoryFile, that also implements an IWriteFile interface. - Added an optional light manager to the scene manager to allow the user application to turn lights on and off during scene rendering. This can be used to produce "zoned" lighting. See example 20.ManagedLights. - Added a method to flip the Y movement of the FPS camera. - The Anisotropy filter can now be set to the AF value per texture layer. So no forced MAX_ANISOTROPY anymore. .irr files will probably fail, though. - AntiAlias parameter in SIrrCreationParameters is now an u8 value specifying the multisampling level (0 for disabled, 4,6,8, and others for anti-aliasing) - D3D devices use DISCARD for windowed renderbuffers now, can be faster. - Changed behavior of PixelBlend16() / PixelBlend16_simd() so that they treat the 1 bit alpha of the source pixel as boolean, i.e. they draw either the source pixel, or the destination pixel, rather than "blending". (Issue revealed by the fix to IVideoDriver::makeColorKeyTexture()). - IVideoDriver::makeColorKeyTexture() bug fixed so that only alphas, not whole texel colors, are zeroed. An optional parameter allows using the old (buggy) behavior for backwards compatibility. - position2d is now a synonym for vector2d. position2d is therefore marked as deprecated, although it's unlikely to be removed. - ISceneNodeAnimator now has a hasFinished() method. - ISceneNodeAnimatorCollisionResponse exposes the target node. Setting the node again resets the last position, allowing the node to be teleported. - Add a hitPosition out parameter to ISceneCollisionManager::getCollisionResultPosition() - this is a (small) API breaking change. ------------------------------------- Changes in version 1.5.2 (16.12.2009) - Properly check boundaries in getFont and setFont. - Reinit values in the driver when scene manager is cleared. - Normals handling fixed in createMeshWithTangents, existing normals are not always destroyed now. - Fix terrain smoothing, bug found by loverlinfish - SOLARIS recognition removed. Please specify the platform define manually. This allows for compilation under sparc/Linux and sparc/Solaris - Some uninitialized variables fixed - FreeBSD joystick support added (for Debian package) - Fix cursor problems found by buffer and by rvl2 as described in http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=34823&highlight= - OSX/XCode updates - MS3D loader bug fixed - Float parse bug fixed ------------------------------------- Changes in version 1.5.1 (05.08.2009) - Make sure a missing font does not corrupt the skin. - Fix getAngle in vector2d as suggested by xray. This has only a minor impact on s32 vectors. - bugfix: CGUIFont::getCharacterFromPos regards now kerning (found by Arras) - Add support for range fog in some OpenGL versions. - Fix for shadow volume removal, submitted by vitek. - Avoid using X11 autorepeat to deal with broken X11 versions. - Speculars are properly exported into mtl files now, instead of corrupting them. - Binary type loading in attributes fixed. - bugfix: Use make_lower throughout for spritebank filenames (found and patched by Ion Dune) - STL loader fixed: Right-handedness corrected, normals and bboxes are correctly added now. - bugfix: CUnZipReader::openFile no longer returns true for empty files. Corresponding test added. - Big endian issues in .x loader fixed. - HSLColor methods repaired. - copyToScaling fixed. - Fixed problem with highlighting menus when mouse was outside sub-menu area. - bugfix (2796207): menu acted (wrongly) on left-click down instead of left-click up. - bswap16 fallback macro fixed - getBaseName fixed to work correct with dots in filenames. - static method isDriverSupported allows for simple check of available drivers. - Some defines added to check for the Irrlicht version of the library. - Make sure all renderstates are properly initialized - Wrong size for main depth buffer fixed. - Fix 3ds shininess to the allowed range. - Fix loading of Collada files from irrEdit 1.2 - Remove texture pointers after texture clear. - WindowsCE pathnames fixed. - Some virtuals are now overridden as expected. - Incomplete FBOs are properly signalled now - Update to libpng 1.2.35, fixed issues on 64bit machines with system's libpng. - Fixed wrong grab/drop in setOverrideFont - Added draw2dRectOutline - rectf and recti added. - Fix ALPHA_CHANNEL_REF to a fixed check for alpha==127 as expected. - Fixed OSX device bug where screen size was not set in fullscreen mode. - cursor setVisible changed to be called less often. - OpenGL version calculation fixed. - OSX device now supports shift and ctrl keys. - Fixed ambient light issues in burningsvideo. - device reset for d3d fixed when using VBOs. - Fix dimension2d += - MD2 mesh loader: Now uses much less memory, reduced number of allocations when loading meshes. - OpenGL render state (texture wrongly cached) fixed. - Fixed animator removal. - Checnged collision checks for children of invisible elements to also be ignored (as they're actually invisible due to inheritance). - Fix terrain to use 32bit only when necessary, make terrain use hw buffers. Heightmap loading and height calculation fixed. Visibility and LOD calculations updated. - Some mem leaks fixed - FPS camera resets the cursor better ----------------------------------- Changes in version 1.5 (15.12.2008) - Construction calls for FPS camera changed to take speed in units/milliseconds, just as the setSpeed method does. - Code::Blocks workspaces added. C::B projects (using gcc) now output to /lib/gcc and /bin/gcc, when built on either Windows or Linux. - Added a test suite in the /tests directory. This can be used to perform regression tests, and should be updated with new tests to verify fixes or validate new features. - Changed the preferred way of altering light node's radius: Use the new member methods of ILightSceneNode instead of directly modifying the SLight structure. - Changed the initial attenuation back to (0,1/radius,0). To override this value simply change the attenuation in the SLight (lightnode->getLightData().Attenuation.set(x,y,z)) - Dirty fix for OSX device setResizable and a bug fix to do with resizing the device. - Terrain heightmap and texture were flipped in order to draw them as expected (looking onto the terrain from high above will just look like the actual texture/heightmap). - Significant internal change to the way that FPS camera jump speed and collision response animator gravity interact. The behavior is now much more realistic, but it will require you to adjust your jump speed and gravity. - Skybox won't be culled anymore by nearplane or farplane. - BBoxes of animated meshes (skinned meshes) are updated again. - Lost devices (as found with D3D) are properly handled now. So the screen can be resized or minimized without crashing the app. - Renamed IGUIElement::setRelativePosition(const core::rect& r) to IGUIElement::setRelativePositionProportional(), as it has radically different functionality from setRelativePosition(const core::rect& r) - Added IGUIElement::setRelativePosition(const core::position2di & position) to set a new position while retaining the existing height and width. - Many Collada fixes. z_up coords are supported now, texture coords are properly loaded. Transparency is supported. - Camera scene node rotation and target can now be bound together so that changing one automatically changes the other (as the FPS camera has always done). See ICameraSceneNode::bindTargetAndRotation() - Removed the extra libpng files for OSX. OSX now also uses the default libpng. - Enhanced PCX support with some more color formats and write support. - Fixed LMTS problems with extra data in files. - Removed VS6 .dsw / .dsp project files - VS6 is no longer supported. - Particles can be scaled during animations. Particle scaling needs to happen in the emitter now, instead of in the Particle system scene node. Deprecation methods will guide the user. - ISceneNode::setParent and addChild now updates node SceneManager pointers if the node was from another SceneManager. - Basic support for joystick input events on Windows, Linux, SDL and OSX. Tested with wired Logitech and Thrustmaster wired controllers and XBox 360 wireless controller ( http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/OsxDriver ) - Fixed scaled octree nodes being incorrectly frustum culled. - FSAA under OpenGL and Win32 added. Now all hw drivers and platforms should support it. - Unlimited RTT fix for D3D systems. Depth buffers are now shared if possible, otherwise a new depth buffer is generated. In order to save VidMem one should create RTTs starting with the largest one. - Avoid RTTs with nonFBO-support under OpenGL which are larger than the screen. Since we rely on rendering into textures in this case we need to clamp the size by the screensize. - Fixes for getAbsoluteFilename under Linux in order to return a filename instead of en empty string in case the file doesn't exist. - Use absolute path names when creating / finding textures. - Font tool implementation for Linux with xft, by Neil Burlock. - Support for normals and UV coords from DeclData in .x files. - Modified line2d::intersectWith() to cover more cases. - Added IVideoDriver::drawPixel(). - Moved the window pointer from endScene to beginScene, as this is required for OpenGL support of external window pointers. - Fix for terrain culling. - Added minimize button to win32 window (if resizable) - Major API change: RTTs are now created via addRenderTargetTexture instead of createRenderTargetTexture, which allows to retrieve them from the texture cache, but also changes the way of removing the RTTs, and especially one must not drop the pointer anymore. - WindowsCE-Bugfix - disableFeature can be used to override feature support of the video driver. - draw2DImage can now also handle RTTs under OpenGL (which were flipped before). - Ogre mesh format fixes for proper texture support. - Added .obj mesh writer. - Some core::string constructors made explicit to avoid unintended conversions. Just add core::stringc() or core::stringw() around the old code to avoid warnings. - IdentityMatrix is now a properly defined global, with external visibility on all platforms. - Bugfix for context releases with glx 1.3 on error. - Removed constraints for sizes of the terrain scene node. - Support for 32bit indices in a special MeshBuffer class. - isBetweenPoints return true now even for the begin and end points, i.e. line segments are now including their start and end. - Fix XML reader creation for non-existing files and invalid callbacks. - Changed interpretation of MaterialTypeParam==0 in transparent materials. Now it's consistent with all other values, but one has to set the value to 0.5 to get the old behavior (slightly faster rendering, but no smooth borders) - Replaced transformBox by transformBoxEx in some internal methods to avoid major malfunction of the transformations. - Fix use of zip file inside zip files. - Avoid loading textures which are not used by the mesh in b3d loader. - Added scaleTCoords methods to MeshManipulator - Enable use of other meshes for shadow mesh generation, can be used to speed up shadow generation and rendering for complex meshes. Patch based on a version by tonic. - Fixed usage of SIrrCreationParameters struct, which dind't have copy constructor and assignment operator anymore, since the Irrlicht version string was made const. - New glext.h (version 41) and glxext.h (version 20) supporting OpenGL 3.0 - Added support for read-only locking of textures. Can speed up those calls. - Added support for locking RTTs under OpenGL. - Implementation of UserData events from system events. - ICameraSceneNode::setIsOrthogonal replaced by a parameter to setProjectionMatrix. - All meshbuffers are now dynamically allocated to avoid problems with grabbed buffers, which may be deleted before the last drop happens (due to static memory allocation). - Enhanced scene graph traversal with example from rogerborg. - FPS camera disabling of event receiver works better now. - scene deserialization allows for a user defined callback after a new scene node is created. - Fixed tangent mesh loading from .irrmesh files. - OpenGL clamp modes are now properly set. - IMeshManipulator::transformMesh renamed to transform, also supports meshbuffers now. scaleMesh renamed to scale, supports meshbuffers as well. - vector3d::rotationToDirection added. - New mesh generators for cone and cylinder. - Hardware accelerated Vertex and Index Buffer support finally integrated into Irrlicht. Thanks to a resource handling idea by Klasker and the almost immediate implementation by Luke, Irrlicht now supports VBOs under OpenGL and D3D. Hardware buffers make rendering the same vertices much faster. To use this feature with a mesh, simply set a usage type via MeshBuffer->setHardwareMappingHint(scene::EHM_STATIC). The driver will upload the vertices and indices on the next draw and reuse this information without the need to upload it each frame. Vertex and Index buffers can also be updated separately, which is e.g. useful for the terrain node's LOD. - Changed FBO creation according to Nadro's patch. Seems to have zbuffer problems currently. - Update to libpng 1.2.29 - Compiler flag for PerfHUD support added. - recalculateNormals and tangent space creation enhancements by ryanclark. - Added getColorFormat methods for device and driver, returning the color format of the device's window and the driver's framebuffer. - Added isFullscreen method. - Added isWindowFocused and isWindowMinimized methods. - Screenshots are now always made from the frontbuffer, so always the last completely rendered image is captured. However, overlapping windows may corrupt those parts of the screenshot (as was previously happening with d3d already). - New device creation parameter to disable Irrlicht's system event handling. - New device creation parameter to specify depth bits. - New device creation parameter to request alpha channel in framebuffer. - Draw2DImage methods under OpenGL now also handle RTTs correctly. - Fixed RTT bug which lead to strangely clamped textures. - Speed improvement for screenshots on some Intel cards under OpenGL. - My3D file loader fixed. - Terrain mesh performance increased. - Fixed mem leak in cube node. - Compiler errors in shaders won't corrupt the material renderer list anymore. - Quake3 shader files now have properly working texture matrices again. - FPS and Maya style cameras are now standard cameras with a special animator. - ISceneNodeAnimator now inherits IEventReceiver - New method ISceneNodeAnimator::isEventReceiverEnabled, returns false by default - CCameraSceneNode::OnEvent passes events to animators with enabled event receivers - ISceneNodeAnimatorCameraFPS and ISceneNodeAnimatorCameraMaya interfaces for changing camera settings at run-time. - Changed SExposedVideoData to use void* instead of s32. Fixed 64bit portability. - Added support for front face culling. - Fix for HLSL shaders in one file. - Billboard::setColor bug fix by rogerborg. - Scene node sorting uses squared distances now. - Enhanced API for hte math functions. Many of them will now return a reference to *this for chained method invocations. - prevent .x loader to load .xml files. - AntiAlias support for OSX device. - Period character handling bug fixed. - New filesystem methods for filename handling. - added getVideoModeList and getDesktopResolution support for OSX - Octree supports tangent meshes now. Some performance improvements for the generation. - Fix mouse pointer and fullscreen mode problems in OSX. - Make cube and sphere scene node a mesh scene node (for access to the cube/sphere mesh). - Support for normal maps in 3ds files. Mem leak fixed. Loading for files with keyframe data fixed. - BillboardTextSceneNode is now an IBillboardSceneNode and an ITextSceneNode. - Support for external windows under Linux. - .X loader bug fixes. - Better debug visualization for MeshSceneNodes. - Fixed bug in material serialization when using the NullDriver. - Fix for Win32 CursorControl::setVisible - Support for LWO files. - Support for Collada 1.4 files. - Better and faster terrain smoothing by Frosty Topaz. - Fixed a performance bug in ISceneNode constructor reported by izhbq412 - Win32 device now makes the cursor invisible immediately when setVisible(false) is called. - Command line tool for mesh conversion added. - Added volume light scene node - .obj files now won't duplicate vertices unnecessarily. This allows recalculation of smooth normals and other things, and is also faster when rendering. The loading is a little slower now. They also support normal maps and texture clamping now. Group support added, can be ignored via scene manager attribute scene::OBJ_LOADER_IGNORE_GROUPS. Normals will be calculated if the file doesn't provide them. - Better fix for hires timers on dual core machines by RogerBorg - added Initial Windows Mobile 6 Version. - Windows Mobile 6 SDK - Visual Studio 2005 - Added checks to avoid buffer overrun in b3d loader. Enabled normals calculation in all cases, previously it was not done for lightmapped meshes. Fixed transparency support. Added mipmap creation flag support which might disable mipmap creation too often. Should be checked. - Burningvideo: MipMap Selection repaired - renamed private Driver function getTextureSizeFromImageSize to getTextureSizeFromSurfaceSize - Added collision manager speedup patch by RogerBorg. - D3D drivers now releases the IImage member from initialization, thus freeing lots of memory. The image is accessible via the driver anyway. - SDL device character handling enhanced. - MeshBuffers can now access the elements of the S3DVertex base class in all vertex types directly, instead of using the getVertices() pointer access. This simplifies simple mesh manipulations as it does not require a switch statement over all vertex types. - More OpenGL renderstate bugs fixed - GLSL changes for setting arrays. Also allow for only pixel or vertex shader to be set. - Bugfix for removeChild in AnimatedMeshSceneNode. - Some bugfixes for Joint handling and skinned meshes. Added getJointCount in IAnimatedMeshSceneNode and isStatic in ISkinnedMesh. - Added WAL image format support based on the original loader by Murphy McCauley, written for Irrlicht around version 0.7. - OpenGL RTTs now also support alpha values. - New method driver->getVendorInfo() to query information about the actual hardware driver. - Fixed somed CQuake3ShaderSceneNode problems. - Changed BurningsVideo internal Vertex Format. version changed to 0.39 - SceneManager: Removed the seperate rendering states for quake3 Shader Scene Nodes. Nodes are now solid or transparent. ( but still more states are needed ) - GUI: - Editbox didn't draw children - Checking IsEnabled is now consistent across all GUI elements - Move window to front bug fixed. - Disabling the BMP loader now compiles without the built-in font - Added setTextAlignment to IGUIComboBox - Avoid dropping skin pointer which is in use. - Better warning for fonts without regions (sometimes wrong file is loaded by the user). - Fixed a bug in CGUISpriteBank which caused a crash when a non-looping animated sprite reached the end of its animation. - Modal screens no longer flash invisible children when rejecting a focus change. - Finally added StarSonata patch with table element and TabControl additions. Table is based on MultiColor listbox by Acki, and has loads of changes by CuteAlien. ------------------------------------------- Changes in version 1.4.2 (22.9.2008) - Unified the handling of zwrite enable with transparent materials on all hw accelerated drivers. This means that all transparent materials will now disable ZWrite, ignoring the material flag. There is a scene manager attribute, though, which will revert this behavior to the usual SMaterial driven way. Simply call SceneManager->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true) and set the SMaterial flag as desired. - Some changes for texture matrices in q3 shaders. - Added BlindSide's irrAllocator patch for proper TextureMatrix release under Win32 with any CRT library. - Added VC9 project files. - Added getEmitter for particle system scene nodes. - Fixed rounding problem in getScreenCoordinatesFrom3DPosition - Fixed Software renderer color flicker, was a shift bug I believe. - irrMap fix to make root node always black, by rogerborg. - Possible core dump fixed in particle system node, by CuteAlien. - Mem leak fixed in b3d loader. - Avoid double rendering of child nodes of joints. - Support for d3d draw2dimage clipping by CuteAlien. - Fixed an animation transition bug, pointed out by wuallen. - Fixed the major problem with OpenGL drivers, that claim to be 2.x compatible, but don't offer NPOT support (well, they do, but only in sw rendering...). Now we check for the extension string only. - Fixed .obj loader bug which inserted vertices in wrong buffers. - Fixed minor mem leak in Linux device. ------------------------------------------- Changes in version 1.4.1 (04 Jun 2008) - MD3 meshes are movable again. - New JPG image writer version by Vitek. - Texture matrix fixes, all methods should now work as expected. - Some container methods now return the this pointer after member functions have been called on them, in order to allow call chains. - Some new methods for SColorf access, for uniform API of all colors. - bug fix for SMaterialLayer equality check. Did only check the TextureMatrix pointers, instead of the matrices. - New getMesh method for the SceneManager, which takes an IReadFile instead of a filename. - Support for flags _WIN32 and _WIN64 in addition to WIN32 and WIN64 added, this simplifies usage of Irrlicht headers under MSVC. - Fixed a crash in GUIMeshViewer - new string method findLastChar by Halifax - GUIEditBox got the 1 pixel shift after click fixed. - Some debug visualization has been fixed for skinned meshes - Undef PI symbol before declaring core::PI to avoid compilation problems - SAnimatedMesh now properly returns properties of Meshes[0] if those exist, such that it should be usable in place of an SMesh again. - Fixed 2d initialisation in opengl and d3d9 driver. This should fix problems with render states mixing up and distrubing, e.g. skin effects. - Avoid a crash when passing setSkin the current skin - Fixed current frame calculation for non-looped animations. Bug reported by greenya. - Fixed bug in CBillboardSceneNode::setColor, reported by rogerborg - Fixed clipping of menu, toolbar and combo box GUI elements, reported by greenya - setNotClipped now applies all the way up to the root of the GUI environment, rather than just to the next parent - Made new scene managers use the original manager's GUIEnvironment, reported by MasterGod - Fixed IGUICheckBox::setEnabled, reported by Dorth - Fixed the FollowSpline animator to avoid crashes when only one waypoint is given. - OpenGL VolumeShadow now uses glPolygonOffset to avoid zbuffer artifacts. - Fixed meshbuffer corruption in append methods. - Fixed mem leaks in irrArray. - Fixed minor bugs in ISceneNode and ISceneManager. - Fixed the MeshCache handling of GeometryCreator meshes. - Terrain LOD bugfix. - Some Collada 1.3 loader enhancements and bug fixes. - Fixed a bug in CGUISpriteBank which caused a crash when a non-looping animated sprite reached the end of its animation. - Enhanced the .obj loader with the patch from ryanclark. This allows for recalculation of smoothed normals of the mesh, also should decrease the tri count on some meshes. - Avoid the global Logger to be destroyed too early. - Function setbit was renamed to setbit_cond to avoid name clashes. - Fixed .x animations with multiple references to the same joint from different meshes. Fixed texture path problems. - Support for Milkshape 1.8 files, also with multiple weights per joint. - The config file now also supports _IRR_OSX_PLATFORM_ and _IRR_USE_OSX_DEVICE_. This allows to use the Linux device (X11 support) on OSX. - Avoid terrain scene node crash when heightmap cannot be loaded. - Speed improvements for WaterSceneNode. - FlyCircle animator now also works for upvectors (Direction parameter) which are not (0,1,0). Is also faster now, since most calculations are done on init. Thanks to Dorth for working on this. - The 3ds loader correctly creates a texture matrix when texture tiling properties are found in the file. - Fix for S3DVertex comparison operators. Used some wrong logic. - Bugfix getCurrentRenderTargetSize in D3D drivers. Due to signature differences a wrong virtual method was chosen. Thanks to Jiang for finding it. ------------------------------------------- Changes in version 1.4 (30 Nov 2007) - Major API change: All material properties which are available per texture layer (curently texture, texture matrix, texture filters, and texture wrap mode) are separated into a new struct SMaterialLayer. You can access them via the array TextureLayer[] in SMaterial. The texture matrix methods in SMaterial are still alive, and also textures can be accessed via methods in SMaterial now. But still, many places in user code need some update (usually changing material.Textures[i] to material.TextureLayer[i].Texture etc.) - Major API rewriting for proper const usage. Now, most getter methods are const and so are the larger parameters and return values. Moreover, many methods taking only unsigned numbers now use u32 instead of s32 in order to recognize this limitation from the method's signature. - the base class for nearly all Irrlicht classes has been renamed from IUnknown to IReferenceCounted - Fixed Skybox texture orientations. They are now displayed non-flipped. Existing skyboxes have to be changed, though: Exchange left and right texture. Textures from Terragen and other tools can be used directly, now. Quake maps will also need the right/left exchange. - Added ITexture::isRenderTarget() - Added STL mesh file format reader and writer. - Added IMeshManipulator::createMeshWelded which creates a copy of the mesh with similar vertices welded together. - Irrlicht now has its own file format for static meshes. It is based on xml and has the extension .irrmesh. Irrlicht is able to write every IMesh to this file format, and of course to read it back again. - Irrlicht is now able to write Meshes out into files. Use ISceneManager::createMeshWriter() to obtain an interface with which you can write out meshes. Currently, an own .irrmesh file format is supported as well as the COLLADA file format. - fixed the keyboard autorepeat difference betwenn Linux and Windows. Thanks to denton we now have only KeyPressed events on both systems in case of autorepeat. - Added several new particle emitters and affectors from IrrSpintz. Also some new getter and setter methods were added. - D3D transparent materials do not disable zbuffer writing automatically anymore. This has to be done by the user to keep those settings configurable. - OpenGL texture now also require a regenerateMipmapLevels() after unlocking. This is the same as for d3d devices now. - Point sprite support in the driver. Point sprites use just one 3d vertex and a size to create a textured billboard on the GPU. This can provide fast particle systems, especially in combination with shaders. The proper particle extension will follow later on as it needs some more refactoring. - OpenGL 2D drawing accuracy fix by tuXXX - Added OnResize and getCurrentRenderTargetSize to the software video drivers. - Added Spot light type for dynamic lights. Note that both position and direction for all dynamic lights are now determined by the LightSceneNode, the SLight attributes are only used for internal purposes. API change! One can easily work around this change by setting the LightSceneNode's Position and Rotation instead of the SLight's. This change won't provoke a compile error, though, and can hence go unrecognized besides the visual problems. The lights use a default direction (0,0,-1) which is rotated by the usual scene node transformations and can hence be modified by scene node animators. A change in the Radius usage can lead to strange artifacts. Just increase the Radius in this case. further handling of Radius is to be discussed. - Added per pixel fog support for OpenGL. - Added driver support for user defined clip planes, based on mandrav's patch. The OpenGL version is more picky about ModelView matrices, so it's best to set the projection plane at the time it is used. - .obj files now load relative indices correctly. Collada files load textures. - A new MeshBuffer implementation is publicly available. It supports a shared vertex list for all MeshBuffers, used for MS3D meshes. - MeshBuffers can recalculate their BoundingBoxes on their own now, no need for MeshManipulators. New append methods help to merge MeshBuffers. take care that the types match! - The new texture generation mode is working. With ETCF_NO_ALPHA_CHANNEL textures are generated without ALPHA bits reserved. - D3D9 hardware mipmap updates are re-enabled, problems should be reported. - In some cases fullscreeen modes under win32 should have a better frame rate now. - Fixed the hillplane mesh to work with non-quadratic dimensions as well. Changed the interface also, so use a u32 dimension to specify the tilecount now. - Hires timers are disabled on windows systems with more than one CPU, due to bugs in the BIOS of many multi-core motherboards. To enable hires timers in your project, use SetProcessAffinityMask to set to use only one CPU before creating the device. - OpenGL render targets now the same way up as the other drivers. If you have written opengl shaders that use render targets then you'll need to change your texture coordinates accordingly. - Fixed some OpenGL renderstate stuff. setBasicRenderstate returns with active texture layer 0. The material renderer must return from OnUnset with the same active texture layer. The alpha test is disabled and the texture mode should be GL_MODULATE. - Fixed CSoftwareTexture2::getOriginalSize, reported by CaptainPants. Added a new method CSoftwareTexture2::getMaxMipMapSize to return the size of the largest mipmap, which is used by texelarea instead of getOriginalSize. - Changed parameter order of addArrowMesh and added default parameters such that it's enough to set the color (or even just the name). - Fixed bugs in MY3D and OBJ loader. - Added IMeshCache::clearUnusedMeshes(). This allows the user to remove meshes that are sitting in the mesh cache but aren't used by any scene nodes. This is useful for example when changing levels. - Added IUnknown::getReferenceCount() - createDevice now reports errors if the driverType is unknown, previously it created a window but populated it with a null driver without any warning. - Fixed a bug in CBillboardTextSceneNode::setText where the old text was not cleared. - Changed irrArray::linear_search to use the == operator rather than < This may be slower in some cases, but it no longer returns false positives when searching arrays of classes that override the < operator but !(x for relative positioning within their parents - getFileSystem added to the GUI environment - New IGUISpriteBank, used to hold 2d image data like fonts and GUI icons. Icons provided by the built-in font are now accessed through the skin's sprite bank. Users can override the icons by setting a different sprite bank and setting new sprites. - Skins are now serializable and are loaded/saved with the GUI. - IGUIStaticText getter/setter functions patch by rogerborg. - added 3d TextSceneNode2. to view a Text in real 3D Space in fact it is a combination of Billboard & TextSceneNode - Burning Video (the second but only complete software renderer) - New Compile Config BURNINGVIDEO_RENDERER_ULTRA_FAST - New Compile Config BURNINGVIDEO_RENDERER_FAST touching the 20fps border in the demo ( P4 mobile 2Ghz ). 15fps average. ( Compile config Release Fast-FPU ) - VertexCache for Tansformed & Light Vertices boost small drawPrimitive Calls ( 2DRectangle, Billboard ) and Real Index Triangles - Bilinear Dither - clipping test ( compare instead of generic plane normal ) - support for NOT using vertexcolor #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR - added vertex to color to billboard. shade top & shade down. to support some static lighting effect on billboards - Implemented line rendering for SoftwareDriver - XMLWriter fix for 32bit wchar_t (esp. for big endian) - updated to latest PNG library - implemented CImagerWriterJpeg::writeImage - The ISceneManager::addCameraSceneNodeFPS() has a new parameter named 'jumpSpeed' and a Key Map Entry. - added param to IIImageWriteFile::writeImage control Parameter for the backend ( e.g. jpeg compression level ) - addContextMenu: CGUIEnvironment::addContextMenu set the focus on the submenu. - Added IFileSystem::createMemoryReadFile for accessing memory like a file. - Added core::map class submitted by Nastase Catalin (Kat'Oun) - Fix vertex colors for .x and .ms3d, alpha bug in .obj - Fixed 16bit depth screens under Windows. - Implemented getMeshBuffer(SMaterial) for all AnimatedMeshes. It was returning 0 for all implementations previously. User defined IMesh derivates will also have to implement it now due to the removed empty implementation. - Added yield() method to IrrlichtDevice which allows to pause the Irrlicht process for a very short time. This allows other processes to execute without a major penalty for the Irrlicht application. - Added sleep() methd to IrrlichtDevice, for pausing the Irrlicht process for a longer amount of time. - Auto-split mesh to 16bit buffers in 3ds loader - 8bit RGB332 image format support - isActive() under Linux now behaves like the Windows variant: True iff window has focus - Fixed(?) the glXGetProcAddress problems with different drivers - B3D changes by Luke: Texture scaling bugfix, support for alpha blending, new option to normalise weights, animation code optimization, fixed memory leak - ROUNDING_ERROR is now ROUNDING_ERROR_f32 or ROUNDING_ERROR_f64 - Material ZBuffer flag changed to a u32 value Reason: change ( off or on ) to , off, lequal, equal Necessary for multi-pass if previous stage has had transparency - DebugDataVisible is now an enum of flags show normals is supported ( uses the new build in arrowmesh ) - New Function: GeometryCreator addArrowMesh. build a closed cylinder and a cone used to show normals as debug feature - New Function: CMeshManipulator::transformMesh(scene::IMesh* mesh, const core::matrix4& m) const transforms VertexPosition and VertexNormal - BUGFIX: CGUIButton notified Pressed when Mouse was clicked Inside ( correct ) but also left up outside rectangle ( incorrect) - BUGFIX: Octree:getPolys(const scene::SViewFrustum& frustum, SIndexData* idxdata) was recursive calling invisible children - CFileList: Changed FileListEntry sorting to a) Directory comes first b) sorting ignores case so it feel's more like common browers - added a Texture transform to IVideoDriver::setTransform - quaternion::getmatrix in fact the getmatrix version is returning the transposed. i'm quite sure that this is the wrong implementation. so this should be verified to remove the getmatrix_transposed version... - Quake3 Map Loader: new loading method - Bezier Patches with LOD more than 3 - Multiple Meshes, stay compatible with the previous version - Indexed Triangle List - initial support for quake3 Shaders and Entities - Shaders are parsed. When it's possible to resolve a 2 Texture Scheme it's taken Shaders exist in namespace scene::quake3 - The Example Quake3Map shows how to continue applying the Q3Shaders with SceneNodes ( for example animmap converts to TextureAnimator.) TODO: use the Irrlicht Variable Syntax to remove redundant code.. - added getVertexPitch() to IMeshBuffer interface - added generic isupper, isspace.. functions to coreutil.h to remove dependencies for ctype.h ( future: it's possibly to use binary comparison test..) removed 1000's include of string.h and moved one to irrstring.h in preparing of complete removing the MSVC. - moved fast_atof.h to the public include added strtol10 to remove dependencies for stdlib.h anyway math.h is needed for powf - core::vector3d added getInterpolated_quadratic. vector3d getInterpolated_quadratic(const vector3d& v2, const vector3d& v3, const T d) const // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d; - irrstring: added param start to findLast(T c, s32 start = -1 ) reason: to continue searching reverse on a specific position (parameter is checked against boundaries ) - added operation reciprocal_squareroot to irrmath. core::reciprocal_squareroot = 1.f / sqrtf ( x ) changed the core::vector3df normalize vector. specialized templates are not allowed in irrlicht currently, so it's only for f32 for now. a C function and a NVidia Version are in irrmath.h - add Primitives to CFPSCounter and changed interpolation to 1500ms instead of 2000ms and rounding to ceiling.. - added Interface setAmbientLight to ISceneManager it was a Bug, because SceneManager always calls Driver therefore AmbientLight has to be set in SceneManager. - changed GUIFont & FontTool to support kerning ( on a global basis ) very basic mode.. apply an offset for position useful for example if you want to apply an outline stroke in your favorite and therefore let the texture grow. and to correct the border back on drawing, specify the parameter in IGUIFont. this is quite useful if you want to use more artistic fonts. default = 0 better kerning would need a seperate coordinate set for each symbol. - changed MD2_FRAME_SHIFT to lower framerate -> lower IPol problems can occur if somebody uses hardcoded frame-numbers instead of Animation name... - changed spelling "frustrum" to "frustum" -> changed also SViewFrustrum.h to SViewFrustum.h - changed Parameter AutomaticCulling from bool to enum E_CULLING_TYPE to support more than two culling modes. added Frustum culling ( it's a copy & paste from the octree ) added initial bounding sphere used for culling point lights.. - Added getSystemMemory and getProcessorSpeedMHz for Windows and Linux to the OSOperator, submitted by Vitek. ------------------------------------------- Changes in version 1.2 (29 Nov 2006) - Added Solaris/Sparc port (basically some compiler define statements). Irrlicht and the examples should compile out-of-the-box on Suns with the usual Makefiles and gnumake. - Added texture matrix support for hardware accelerated drivers. This allows for efficient texture coord manipulations for complete meshes at once. - Multisampling with OpenGL under Linux added - Non-power-of-two textures are left unscaled if the driver supports such textures. - new draw2DImage method that speeds up drawing many quads from the same texture. Font drawing is improved by this under OpenGL. - TGA files are now always correctly flipped and loaded if compressed. All PNG color formats are now supported, including correct alpha handling. - 3ds mesh loader fix in texture loading, now loads some textures that were not loaded before, but might introduce problems with very recent files. OGRE mesh loader bugfixes and lightmap support. Several B3d mesh loader updates. Obj and mtl loader enhancements. - A new compile flag (IRR_OPENGL_USE_EXTPOINTER) allows Irrlicht to either use OpenGL extension function pointers or direct OpenGL calls. - OpenGL now uses frame buffer objects for render targets larger than the screen, supplied by Mandrav - Split ESNRP_LIGHT_AND_CAMERA passes into ESNRP_LIGHT and ESNRP_CAMERA to fix a problem with lights being rendered before cameras in OpenGL (thanks again to Vitek for finding this). ESNRP_LIGHT_AND_CAMERA is now deprecated. - Fixed many OpenGL render state problems which were related to wrong texture states. The textures are now enabled and disabled by the material renderers in OnSetMaterial. Also enabled the texture state cache which helps preventing texture changes just as the one for D3Dx. Thanks to hey_i_am_real for some good hints on where the problem was located. - Added compile flag _IRR_COMPILE_WITH_X11_ which is by default enabled. Disabling the flag removes all X11 dependencies from Irrlicht and allows for a headless Linux Irrlicht server - added by request :-) - Win32 OpenGL driver tries to use the requested bpp size. - Default texture format is now A8R8G8B8 if not explicitly specified. This fixes some color artifacts with lightmaps. Bugfix submitted by hey_i_am_real. - In OnPostRender all transformations were taken as relative and multiplied with the root transformation matrix every time due to a wrong check for the real root node. This shoudl increase render performance for scenes with lots of (invisible) nodes. - Added correct list copy constructor. - Color selection dialog added. - New GUI skin "Burning Skin". it's a black & white skin. look elegant on true-color. and looks ok on 1-Bit ( e.g. no vertex color in burnings video ) - GUIStatic text is correctly grayed out if disabled. - Added getHeight method for terrain node submitted by Spintz. It calculates the height from the base mesh instead of requiring ray casts and collision detection and is much faster. - New methods core::lerp to linearly interpolate two floats and SColor.getLuminance to calculate luminance of RGB color. - MAJOR API CHANGE: Fixed matrix access methods mat(x,y). These were previously said to be (row,column) but actually were (column, row). This lead to some confusion and made their use quite tricky. Irrlicht code is updated for the new method, but applications will silently fail now (i.e. compile without errors, but not working as expected). - Update to zlib-1.2.3 - Fixed vertex alpha handling in DirectX drivers. - Image writers fixed and working (at least for little endian systems). - VSync under Linux fixed and correctly working. - New os::Byteswap::byteswap methods which can be used for byteswapping (endianess correction) in mesh loaders and image loaders. - New video driver feature to check for multitexture feature. - Direct3D drivers update the devicelost variable if reseeting failed with this return code. - VideoModeList under Linux is correctly filled now. No glX calls are made if GLX extension is not found - only software drivers are available then. RandR extension can be enabled with a new compile flag in IrrCompileConfig.h, either instead of XF86VidMode or in addition. - Big Endian support for MS3D loader. - Apfelbaum software renderer: basic mipmap support (per triangle), switch for using w-buffer instad z-buffer ( default on ) - Better FPU support: Changed various fpu-call's in whole project (main reason to use faster float to int conversion on x86. ( fistp )) - changed Visual Studio 7.1 vcproj project config "Release Fast FPU" to __fastcall in /QIfist - CGUIFont added True Alpha Font Support. (currently it's a little hack, but it'a good starting point. Fonts are back compatible. To use the new feature make first pixel half transparent in the font file.) - Scolor: replaced s16 color with u16 color, replaced s32 color with u32 color to get rid of unnecessary arithmetic shift - Colorconverter: X8R8G8B8toA1R5G5B5, set Alpha High, minor: A1R5G5B5toA8R8G8B8 changed if (a) to conditional set - CImage: added boxfilter (weigthed average), (generic, slow) - The scene manager now sets an ambient light color when calling ISceneManager::drawAll(). You can influence this by calling ISceneManager::setAmbientLight(). That light color is also stored when saving .irr files via ISceneManager::saveScene(). - Loaded COLLADA files which contained only one single mesh now behave like all the other loaded meshes, and the #meshname workaround has been removed. - File lists are now sorted. - Dynamically checking the OpenGL version now instead of at compile time to call the supported methods of the executing machine, not that one of the compile host. This should fix the extension check and the automatic mipmap update. - Fixed vertex alpha handling of 2D images with OpenGL. - Default depth buffer under Windows now 24bit to avoid zbuffer fighting. - Fixed light count in OpenGL. - Particle emitters can now be enabled/disabled via a new method. - Sky dome is rotatable just like the sky box. - Rotation animator can be applied to several nodes now, before it only rotated the first one it was applied to. - Support for drawing other vertex primitive lists such as triangle strips. - Default specular color is white again, thus simply enabling shininess is enough to get speculars. - Some .x loader and animator improvements. Vertex color support. - isActive now also work under Linux. ------------------------------------------- Changes in version 1.1 (06 Aug 2006) - New example to show some features of the .irr format - Added support for making screenshots in all video drivers and a general possibility to save any IImage to several file formats. Some image writers are not yet implemented. As a testcase screenshots are now available in the demo by pressing F9. This code was contributed by Travis Vitek. - Changed EAMTS_OCT to EAMT_OCT. - Improved .3ds and .obj file importers. - Added support for .b3d (Blitz Basic) submitted by Luke Hoschke and .pak (Quake archive) files submitted by skreamz. - Added sky dome implementation contributed by Anders la Cour-Harbo (alc). - In addition to the Cube scene node (formerly test scene node) there is now also a sphere scene node available, with an adjustable amount of polygons. Use ISceneManager::addSphereSceneNode to create it. Thx to Alfaz93 for making available his code on which this node is based on. Note that both nodes now use default material settings, e.g. lighting is enabled by default. - Fixed Linux keyhandling for many keys. - The aspect ratio has been inverted in the matrix, which means when setting a new aspect ratio for cameras, set it to screen.width/screen.height now instead of screen.height/screen.width as previously. - added support for reading/importing binary .x files. - .ms3d and .x normals are now correctly transformed in animations, bounding boxes are slightly better transformed, but not yet correct. - Added possibility to load and save Irrlicht scenes to and from xml files via ISceneManager::saveScene and ISceneManager::loadScene. Note that not all scene nodes are supported yet, but most features should already work. - Bounding box of the Skybox corrected (set to null) - The SMaterial structure now supports 4 textures. (Currently ignored by the renderers and their materials.) - Test scene node renamed to CubeSceneNode. - Added scene node animator factories. This is the same as scene node factories, but for scene node animators. - Added scene node factories. This is an interface making it possible to dynamicly create scene nodes. To be able to add custom scene nodes to Irrlicht and to make it possible for the scene manager to save and load those external scene nodes, simply implement this interface and register it in you scene manager via ISceneManager:: registerSceneNodeFactory - Introduced IMeshSceneNode interface with the possibility to set readonly materials to make it possible to use the mesh materials directly instead of overriding them. In this way it is possible to change the materials of a mesh causing all mesh scene nodes referencing this mesh to change, too. - Added possibility to load OGRE .mesh files directly, thanks to Christian Stehno who contributed a loader for this. - Merged with Irrlicht 1.0 for MacOS - Added a method getType() to ISceneNodeAnimator. - There is now a system to serialize and deserialize attributes of scene nodes. In this way it should be quite simple to to expose the attributes of your scene node for scripting languages, editors, debuggers or xml serialization purposes. - Irrlicht containers and strings now have allocators, making it possible to use them across .dll boundaries. - Changed the name of scene nodes from wide character to to char* for speed and memory reasons. - Renamed IStringParameter class to IAttributes and enhanced it to be able to serialize its content into and from xml. - Textures now have a method getName(). - Added the methods getTextureCount() and getTextureByIndex() to IVideoDriver. - Most classes now derive virtually from IUnknown. ------------------------------------------- Changes in version 1.0 (19 Apr 2006) - Irrlicht now will load d3d 9 dlls (like d3dx9_27.dll) manually if needed. If you compile irrlicht with an SDK which needs one of these dlls, irrlicht will now also start up on a pc without these Dlls installed. Note that now these dlls will also only be loaded if your application uses shaders. If the dlls are missing, shader support will be disabled. - The Apfelbaum Software Software Renderer now works in 32 bit and is capable of rendering dynamic lighting as well as doing alpha channel blending. - Added support for the Code::Blocks IDE (http://www.codeblocks.org) - It is now possible to draw temporarily to foreign windows, by specifying a window handle when calling IVideoDriver::endScene(). Note: This does not work in fullscreen mode and is not implemented for all devices (only for D3D8, D3D9, Software1 and Software2, and only for Windows). In addition, you can also specify the source rectangle to present. - Picking is now more accurate and also works with view ports and better with orthogonal cameras. - Scene Nodes now have an additional flag, IsDebugObject. This denotes if a scene node is a debug object. Debug objects have some special properties, for example they can be easily excluded from collision detection, picking or from serialization, etc. - Scene Nodes now have the possibility to return their type using virtual ESCENE_NODE_TYPE getType(). - Improved support for orthogonal rendering: Skyboxes and billboards can be used with orthogonal cameras now, too. - Fixed a bug in collision - Fixed some marshalling bugs in Irrlicht.NET - Some fixes to make gcc 4 happy. - Fixed a bug which caused the engine to crash when trying to use the apfelbaum software rasterizer with linux - Several improvements to Irrlicht.NET, for example string output for vectors, viewfrustrum access for cameras, drawing of bounding boxes, support for orthogonal cameras. - Updated DMF importer to support new DeleD functionalities, solid materials will now be shown correctly again in Irrlicht. Thanks to Salvatore "Il Buzzo". - Added a method to change the return value of ICameraSceneNode::isOrthogonal - Improved md2 animation playback - Fixed the REFLECTION_2_LAYER materials. Now also works for OpenGL. Had to change the parameters of this material (for all drivers), the reflection is now at texture 2 and the diffuse map at texture 1. This was the other way round before. - Added examples for csharp, visualbasic, delphi.net and boo. - Several other small bug fixes. ------------------------------------------------------------------------------------- Changes in version 0.14.0 (30 November 2005) - Irrlicht now includes another video driver type. Together with D3D8, D3D9, OpenGL, the NULL driver and the Software Renderer, an Irrlicht user now has the decision between 6 renderers: The new included renderer is The Apfelbaum Software Renderer, an alternative software renderer for Irrlicht. Basically it can be described as the Irrlicht Software renderer on steroids. It rasterizes 3D geometry perfectly: It is able to perform correct 3d clipping, perspective correct texture mapping, perspective correct color mapping, and renders sub pixel correct, sub texel correct primitives. In addition, it does bilinear texel filtering and supports more materials than the EDT_SOFTWARE driver. In short: It looks a lot like the already available hardware accelerated drivers, but without hardware. :) This renderer has been written entirely by Thomas Alten, thanks a lot for this huge contribution. - Irrlicht now supports anisotropic filtering. Use the SMaterial::AnisotropicFilter member or EMF_ANISOTROPIC_FILTER flag to enable it. I implemented this for all 3 hardware accelerated drivers: D3D8, D3D9 and OpenGL. - Irrlicht now supports the recently released new microsoft compiler. Irrlicht versions compiled with older verions of this compiler can now also be used with the new one, which wasn't possible previously because of a name mangeling issue. - All 2D drawing functions can now be used to draw into textures (render targets). This also means for example that the whole GUI environment can be rendered into textures. - Irrlicht.NET now supports shaders. - Irrlicht now loads all textures in 32 bit mode by default. (Previously this was 16bit). To change this behavior back again, use device->getVideoDriver()->setTextureCreationFlag(ETCF_ALWAYS_16_BIT, true); - Irrlicht.NET now supports Particlesystems and Shaders. Thanks to a code contribution by Delight. - Fixed a bug in the mipmap generation. Now mipmaps are not that blurry anymore and the rendering quality has been improved a lot. - It is now possible to assign a userData int to callback functions of shaders. In this way it it easily possible to use the same callback method for multiple materials and distinguish between them during the call. - Directional lights are now supported in the OpenGL and D3D drivers. To switch on directional lighting, set the light type to ELT_DIRECTIONAL in the SLight structure. - Fixed several bugs in the GLSL implementation. Thanks to Michael Zoech for sending in his improvements. - For the windows version of Irrlicht, the engine now displays an icon in the program window, if there is one available in the start path with the name "irr.ico". - It is now possible to use images with alpha channels on buttons. Use the new IGUIButton::setUseAlphaChannel() method to enable this feature. - The scene manager has a new method getSceneNodeFromName() which finds a scene node by its name. - It is now also possible to attach scene nodes to joints/bones of sceletal animated .x files. (Using IAnimatedMesh->getXJointNode() ). This was previously only possible with milkshape models. - Billboards now draw their bounding box when debugdata is set to visible for them. - Lights now draw their bounding box and radius when debugdata is set to visible for them. - Upgraded to irrXML 1.2. Thanks to some hints by Patrik Mller, irrXML, the XML parser used by the Irrlicht Engine now has CDATA support and some other useful new features. - Support for VisualC++ (Express) 2005. Added a project file and a IrrlichtPropsVC2005.vsprops file which sets the no deprecate define and adds needed libraries. - Fixed size of the bounding box of billboards. - Billboards are now also culled by default, increasing rendering speed a bit. - Fixed a bug which caused the .ms3d loader to crash when loading .ms3d files without materials. Thanks to sdi2000 for posting this. - Fixed a bug causing the possibility to crash when destructing the scene graph or a scene node with children. - Fixed some bugs which caused invalid RTT operations, when for example the render target texture was smaller than the screen. - Fixed a heavy bug in Irrlicht.NET causing lots of memory leaks when drawing text. - Fixed a bug in the attachement of scene nodes to animated X files. - Fixed a bug in the .NET Vector3D addition operator. - Updated to Salvatore Russo's DMF loader version 1.3. Notes by him: This version just adds some new functionalities. First of all Alpha Blended Textures are now supported by DeleD as well as loader. Because of some trouble with Irrlicht 0.12.0 TGA loading, TGA textures are always flipped so I've added a parameter so that you can choose to flip or not all TGA textures coords, this way: SceneManager->getParameters()->setParameter(scene::DMF_FLIP_ALPHA_TEXTURES, true); you can also set material transparent reference value by setting: SceneManager->getParameters()->setParameter(scene::DMF_ALPHA_CHANNEL_REF, 0.01); you can use every value beetween 0 and 1, but to respect DeleD rapresentation 0.01 is OK, just a note, if you set 0, it's just like you set 0.5, this means that each pixel found corresponding to a position in alpha map that has a value<127 won't be drawn. - Fixed a small bug in the line breaking algorithm. - Fixed a bug which caused the engine to display strange artifact pixels when drawing 2D images like text in screens which odd resolutions. - Slightly changed the interface of createDevice and createDeviceEx(): the version parameter now is a char* instead of wchar_t*. Also, IrrlichtDevice::getVersion() now returns char* instead of wchar_t*. - Fixed some parts in the source to make Irrlicht compile in Linux 64. - Renamed the EDT_DIRECTX8, EDT_DIRECTX9, _IRR_COMPILE_WITH_DIRECTX_8_ and _IRR_COMPILE_WITH_DIRECTX_8_ enumeration literals to EDT_DIRECT3D8, EDT_DIRECT3D9, _IRR_COMPILE_WITH_DIRECT3D_8_ and _IRR_COMPILE_WITH_DIRECT3D_9_. You might need to update your code and compilation settings with these new names. - Added the remaining '..' directory in the linux version of the file list - Updated to a faster version of the TerrainSceneNode by Spintz. Much thanks again! - Fixed a bug causing billboards to be displayed upside down. - The D3D drivers now won't crash anymore when they get feeded with nullpointers as shader constants. - Irrlicht now identifies the Linux platform it runs on and returns a more detailed string when calling getOperationSystemVersion(). - Fixed some bugs in several collision test methods thanks to Spintz. - Updated font tool - Made the list::iterator constructor which took a sklistnode as parameter private, to make Irrlicht compatible with the Errlicht interface. ------------------------------------------------------------------------------------- Changes in version 0.12.0 (24 August 2005) - It is now possible to have multiple scene managers. Use ISceneManager::createNewSceneManager() to create a new one. This can be used to easily draw and/or store two independent scenes at the same time. - Irrlicht now supports GLSL, the OpenGL Shading Language, which means Irrlicht now supports 14 shading modes/languages: ARB Vertex Programs, ARB Pixel Programs, HLSL, GLSL 100, GLSL 110VS1.1, VS2.0, VS3.0, PS1.1, PS1.2, PS1.3, PS1.4, PS2.0, PS3.0. Lots of thanks go to William Finlayson for implementing this and making available his code to be used in Irrlicht. - Added support for pixel shader 3.0 and vertex shader 3.0. - Irrlicht now supports detail maps, use EMT_DETAIL_MAP for this. The new terrain scene node tutorial shows how to use detail maps. - Again some changes have been made in Irrlicht.NET. For example it is now a little bit more memory friendly, I removed several bugs and made the terrain scene node, realtime shadows and key codes available. In addition, I extended the .net example application a lot, just try it out. - I've worked around a heavy bug in the microsoft compiler which caused lots of bugs in Irrlicht.NET. They are all fixed now. See http://support.microsoft.com/default.aspx?kbid=823071 for details. - The timer of the engine has been enhanced a lot, which maybe needs a little change in your project if you are upgrading from an older version of Irrlicht. It is now possible to set the speed of the timer, a new time value, and to start and stop it. Also, all calls to getTime() will now return the same value within the same drawing frame. The timer will only advance when ITimer::tick() is called. IrrlichtDevice::run() will call this method automaticly, but if you aren't using this method, and you are wondering why your scene is not animating anymore, just call Device->getTimer()->tick() before drawing your scene. If you need the system time, not the new virtual time, use ITimer::getRealTime(). - The material EMT_TRANSPARENT_ALPHA_CHANNEL now is using a configurable alpha ref value. The default value is 127, which means people who are using this material for drawing things like grass, trees etc will get nice results automaticly when changing to 0.12.0. To change to a different alpha ref value, just change SMaterial::MaterialTypeParam value. See EMT_TRANSPARENT_ALPHA_CHANNEL for details. Also, this fixes two bugs: - A bug causing the D3D versions not looking like the OpenGL version. - A second bug which caused the texture to look like disappearing when looking at from far away. - Upgraded to a new dmf loader version by Salvatore Russo which is able to use a texture path and material directories. Set DMF_USE_MATERIALS_DIRS and DMF_TEXTURE_PATH using the ISceneManager::getParameters() method. - It is now possible to set a separate scale for the second texture coordinate set in the terrain scene node when calling ITerrainSceneNode::scaleTexture(). This is useful when using detail maps on the terrain. - Added a new material flag named EMF_NORMALIZE_NORMALS. You can enable this if you need to scale a dynamic lighted model. Usually, its normals will get scaled too then and it will get darker. If you enable the EMF_NORMALIZE_NORMALS flag, the normals will be normalized again. - When loading Milkshape .ms3d files, Irrlicht also loads materials and tries to apply the textures. Thanks to atomice for this patch. - The ISceneManager::addCameraSceneNodeFPS() has a new parameter named 'noVerticalMovement' with which it is possible to disable vertical movement of the FPS camera and make the camera behave just like in most ego shooters today. - Made Irrlicht 64 bit compatible, removing some 32 bit only constructs. However, I wasn't able to test it out extensively. If you are compiling Irrlicht for a 64 bit windows environment and get a linker problem, try playerdark's solution: "The linker settings are so that no machine is specified in the drop down field, instead, the command line option /MACHINE:x86 is set manually which interferes with the 64 bit linker of course. Removing that from the 64 bit version (and replacing it with the drop down selection in the 32 bit version for that matter) fixed the linker problem." - There is now a IrrlichtDevice::postEventFromUser() method available, to make it possible to post key or mouse input events to the engine if you are using an own input library for example for doing joystick input. - The GUI Environment now has an own basic RTTI system, and all IGUIElement derived classes have a method named getType(). This is needed for the .NET wrapper but will be used later for serializing and deserializing. If you wrote your own GUIElements, you need to set the type for your element as first parameter in the constructor of IGUIElement. For own (=unknown) elements, simply use EGUIET_ELEMENT. - Thanks to William Finlayson, Irrlicht now also supports RTT (render to texture) when rendering using OpenGL. - Thanks to William Finlayson, the EMT_REFLECTION_2_LAYER is now implemented in the OpenGL version of Irrlicht, too. - There is now a mesh cache interface available. With this, is is possible to get access to all loaded meshes, and to remove them to free memory. You can get access to the cache using ISceneManager::getMeshCache(). Please note that the addMesh() method of ISceneManager now is now longer available, you can find it now in the IMeshCache interface. - The VideoDriver now has a method for clearing the zbuffer at any time: IVideoDriver::clearZBuffer(). With this, it is for example easily possible to overlay two scenes. - Fixed a bug which caused Irrlicht to crash when loading grayscale jpeg files. - Somebody sent me an .x file (tank_human1_crashes_irrlicht.zip) which caused Irrlicht to crash. It seems I've lost that mail, but maybe you are reading this: It's fixed now. :) - Fixed a bug which caused the diffuse maps of lightmaps to disappear under certain circumstances in OpenGL. - Its now possible to make IGUIStaticText draw its background. - Removed the first two default parameters from IGPUProgrammingServices::addShaderMaterialFromFiles() to prevent SWIG to create non compilable wrapper code. - Fixed a small bug which caused the terrain scene node to be culled incorrectly. - Changed the names the driver return (now "OpenGL 1.5", "Direct3D 9.0" and "Direct3D 8.1") - Added a new macro _IRR_DEBUG_BREAK_IF which is now used instead of the _asm int 3 break points in debug mode. - Fixed a bug were the software renderer didn't clip 2d rectangles. This effect was visible for example when using list boxes, selecting an entry at the end an scrolling up so that it wasn't visible anymore. - There is now a new gui event available (named EGET_COMBO_BOX_CHANGED) which will be sent when the selected item in a combo box has been changed. Finally. - Fixed a Problem which caused an empty window to be created when a rendering device could not be initialized under special circumstances. Thanks to Sascha Plumhoff for the bug report. - Fixed a bug with the FileList in Linux, reported by DrAnonymous and fixed by William Finlayson. - Fixed some bad documentation bugs. - The XWindow handle is now exposed too, via IVideoDriver::getExposedVideoData(). ------------------------------------------------------------------------------------- Changes in version 0.11.0 (08 July 2005) - Antialiasing is now supported by Irrlicht in the D3D8 and D3D9 renderer. To switch it on, use createDeviceEx() and set SIrrlichtCreationParameters::AntiAlias to true. - Irrlicht.NET can now run inside a pre created Windows.Form window. - I'm no longer providing a Visual Studio 7.0 project/solution file for the Irrlicht Engine sourcecode, only 7.1 and 6.0 are supported. If you are using Visual Studio 7.0, just open the .dsp file for Visual Studio 6.0, it will be converted automaticly. - Irrlicht.NET includes now all basic GUI Elements and can capture GUI events. There are still some features missing, but it is already enough to do simple things like showing message boxes, displaying images, getting input strings, etc. - Improved the .NET documentation a bit. - There is a full implemented ISceneCollisionManager now available in Irrlicht.NET. - The Linux OpenGL renderer now supports mip mapping. - It is now possible to compile Irrlicht as shared lib in Linux. To do this, go into the source folder and run 'make sharedlib'. This should create a libIrrlicht.so.0.11.0 file in lib/Linux. To install it in /usr/local/lib, you can run 'make install'. - The drawing of the GUI system has been refactored and a lot of redundant code has been removed. - The new method IVideoDriver::draw2DRectangle() is able to draw rectangles not only filled with a single color, but with a gradient from four colors. This is implemented in all drivers except the Software driver which still uses one color for this method. - It is now possible to customize the GUI system's skin a lot more: Simply implement your own IGUISkin interface and implement the draw..() methods. - There are now two build-in skins available: Windows Classic and Windows Metallic. The default skin is now Windows Metallic, if you want to change back to the old skin, use the following code: gui::IGUISkin* newskin = environment->createSkin(gui::EGST_WINDOWS_CLASSIC); environment->setSkin(newskin); newskin->drop(); - Added improved keyboard input handling for the Linux version of Irrlicht, thanks to Fabien Coutant for the fix. - Fixed a bug in the Linux OpenGLDriver which caused to load a wrong OpenGL extension and made multitexturing look quite strange. Thanks to hybrid for spotting out that bug. - COLLADA file loading now works the same like the loading of other meshes: Just call ISceneManager::getMesh("yourfile") and display it using for example ISceneManager::addAnimatedMesh(yourLoadedMesh); To make it possible to create instances from meshes, lights and cameras in COLLADA files again as in irrlicht 0.10, just enable the collada instance creating mode: SceneManager->getParameters()->setParameter(COLLADA_CREATE_SCENE_INSTANCES, true); - Added lots of useful methods to the IStringParameters class. It is now possible to set not only strings but also boolean, integer and float values as parameters. - Fixed a bug with the TRANSPARENT_ALPHA_CHANNEL materials in all renderers to make them work more as expected: They didn't write to the zbuffer. If you are using this material and you don't want the new setting, just set the ZWriteEnable flag in the SMaterial structure of your transparent material to false. Thanks to Fabien to point this out. - There are now some new defines making it possible to use system installed libs instead of the ones which come with Irrlicht: _IRR_USE_NON_SYSTEM_JPEG_LIB_, _IRR_USE_NON_SYSTEM_LIB_PNG_ and _IRR_USE_NON_SYSTEM_ZLIB_, which are defined by default in the file IrrCompileConfig.h - Renamed ISceneManager::getStringParameters() to ISceneManager::getParameters() - Changed the define _IRR_D3D_SHADER_DEBUGGING to _IRR_D3D_NO_SHADER_DEBUGGING to be able to make it defined by default and to let it be included in the doxygen documentation. - The SceneManager now does not do any culling tests for cameras, lights and skyboxes. - Added a transformBoxEx() method to matrix4 which transforms a bounding box more accurate. - Small edit box copy & paste bug fixed thanks to Fish HF - Fixed a bug which caused the engine to read windows messages when embedded in a custom win32 control when called IrrlichtDevice::setResizeAble(). Thanks for Duncan Mac Leod to find that bug. - Fixed a bug in the HLSL renderer which caused Irrlicht to crash, if no vertex shader was specified. Thanks to mightypanda for reporting this. - Fixed a bug in the normal map generation thanks to jox. Parallax mapping and normalmapping now even look a lot better because of this. ;) - Updated to irrXML 1.1: - The XML parser is now also able to parse embedded text correctly when it is shorter than 2 characters. - The XML parser now treats whitespace quite smart and doesn't report it when it is obviously used for formatting the xml file. (Text won't be reported when it only contains whitespace and is shorter than 3 characters) - The XML parser won't crash anymore when the xml file is malformed and an attribute has an opening but no closing attribute. - Removed a documentation which claimed that the xml parser doesn't work as the xml standard when replacing special characters, which wasn't true. ------------------------------------------------------------------------------------- Changes in version 0.10.0 (26 May 2005) - The engine is now able to use parallax mapping. It's implemented for D3D9, D3D8 and OpenGL. The perPixelLighing tutorial shows how to use it. Thanks go to Terry Welsh who wrote the 'Parallax Mapping with Offset Limiting'-paper on which the Irrlicht implementation is based and who allowed me to use his texture for use in the example. - Added render to texture support. Currently, only the D3D9, D3D8 and the software renderer are able to use this feature. There is a new example, showing how to render scenes into a texture. - Irrlicht now can load .png textures. There is also a new compile configuration define to exclude the png loading option: _IRR_COMPILE_WITH_LIBPNG_. Thanks to rt who originally wrote the png loader and who allowed me to use and modify his code and place it under the Irrlicht Engine license. - Added support for COLLADA files. COLLADA is an open Digital Asset Exchange Schema for the interactive 3D industry. There are exporters and importers for this format available for most of the big 3d packages at http://collada.org. Irrlicht can import COLLADA files by using the ISceneManager::getMesh() method. As COLLADA need not contain only one single mesh but multiple meshes and a whole scene setup with lights, cameras and mesh instances, this loader sets up a scene as described by the COLLADA file instead of loading and returning one mesh. The returned mesh is just a dummy object. However, if the COLLADA file does not include any tags, only meshes will be loaded by the engine and no scene nodes should be created. Meshes included in the scene will be added into the scene manager with the following naming scheme: path/to/file/file.dea#meshname. The loading of such meshes is logged. Currently, this loader is able to create meshes (made of only polygons), lights, and cameras. Materials and animations are currently not supported but this will change with future releases. - Added Delgine DeleD .dmf mesh loading support. I simply added Salvatore Russo's .dmf loader to Irrlicht, and changed some parts of it. Thanks to Salvatore for his work and for allowing me to use his code in Irrlicht and put it under Irrlicht's license. - Specular highlights are now finally usable the engine. To activate, simply set the shininess of a scene node to a value other than 0: sceneNode->getMaterial(0).Shininess = 20.0f; You can also change the color of the highlights using sceneNode->getMaterial(0).SpecularColor.set(255,255,255,255);. The specular color of the dynamic lights will influence the highlight color, too, but they are set to a useful value by default when creating the light. This feature is currently only available in the D3D drivers. - Added a new material type: EMT_TRANSPARENT_ALPHA_CHANNEL_REF. This draws a pixel of the material only when the alpha channel has a value greater than 128. It is ideal for drawing for example leafes of plants and does not use alpha blending, so it is a lot faster than EMT_TRANSPARENT_ALPHA_CHANNEL. - There is now a createDeviceEx() method with which it is possible to create an Irrlicht Engine device into an already existing window. This currently only works in Windows. This method will be extended in the future with other options. - Irrlicht.NET has been extended with ports of the SceneNodeAnimators, TriangleSelectors the FileSystem and Font drawing. Also the documentation of it has been improved a lot. - There are two new tutorials/examples available. One demonstrates how to use render to texture feature, the other one shows how to run Irrlicht inside a precreated Win32 window/widget. This means there are now 17 examples available in the SDK. - The software renderer now renders 3d geometry transparent when its material is somewhat transparent. - The XML Parser has been enhanced. Several small bugs have been fixed and there are some new features: The parser can now read ASCII, UTF-8, UTF-16 and UTF-32 (both little and big endian) files, and return the parsed string data in one selectable format from the same list. In addition, it is now completely independent from Irrlicht. If you wish to use the parser without the engine, take a look at the newly created project at http://irrxml.sourceforge.net. - Upgraded to DirectX Exporter Mod 1.3.1 - Upgraded dev-cpp project file to Dev-C++ 4.9.9.2. Removed dependency to zlib and jpeglib for devcpp, the necessary .c files are now simply included in the project. - Renamed the VisualStudio and DevCpp sub directories in the SDK to Win32-gcc, Win32-VisualStudio. - Fixed a bug in irrXML causing it to replace xml characters wrongly sometimes. - The C++ decorations at createDevice() have been added again, because lots of people started to mix the gcc and the microsoft .DLL and got confused why the thing crashed at random positions. - Moved heapsink and heapsort into the core namespace. - Updated to My3D version 3.15 - Fixed the wrongly drawn alpha channel material in OpenGL driver and a problem with the VertexAlpha material in the same driver. - Implemented multipass rendering in the OCTTree scene node now too. This means that octtrees can now contain transparent materials as well. - Improved string comparison speed, especially when comparing with pointer to char or w_char, no more temporary strings are being constructed now. In addition, there are some new string comparison methods in this class. - Added string::replace() method. - Added string::trim() method. - Addes string::erase() method. - Fixed a bug in array which caused data corruption if an element which already inside the the array was pushed_back. Thanks to vox for reporting this and to provide a solutin - Added ISceneManager::addMesh() method. - Added IMeshManipulator::recalculateNormals(IMeshBuffer*) method. - The file array.h has been renamed to irrArray.h - Due to a bug, Irrlicht 0.9 didn't cull the scene nodes anymore which resulted in a huge performance loss. This is fixed now. - After lots releases ignoring the 'make the fps camera smoother request', it is now finally integrated. - Removed audiere dependency and the mp3 file, reeducing SDK download size. - A bug was fixed causing the binding of the wrong fragment program sometimes in OpenGL. - Lots of internal filenames have been renamed. All CVideo* files have been renamed to fit the other name conventions, CD3D9Driver.h into CD3D9Driver.h for example. - The IMaterialRenderer interface now has the new method getRenderCapability() which returns if the material is able to be rendererd with all settings on current hardware. - Added IMeshManipulator::setVertexColors(); - Added float color reading support in the 3DS loader. - video::EVDF_BILINEAR_FILER renamed to EVDF_BILINEAR_FILTER - core::equals function added. - fixed a small bug in fast_atof thanks to jox - Added a method ICamera::isOrthogonal() which is being used by ISceneCollisionManager::getRayFromScreenCoordinates(), thanks to a bug report and fix by jox in this thread: http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=6243 - Added some fixes to the GUI environment to make the parent and child pointers be more consistent as suggested by jox in this thread: http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=6220 - Fixed a bug which caused the ambient light not to be reset after a window resize in D3D8 and 9. Thanks to jox for this bug report and fix. - vector3df equals method added. - added SColorf::getInterpolated() method - Moved ITextSceneNode interface to include folder. - Fixed a small bug in the My3DLoader which failed sometimes finding the right textures. - Fixed bounding box problem with meshes without joints in .X file loader, thanks to jox. (http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=6669) - Fixed IFileSystem::getWorkingDirectory in Linux version. (http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=6678) ------------------------------------------------------------------------------------- Changes in version 0.9 (28 Mar 2005) - There is now a 100% working terrain renderer available. The old buggy and unfinished terrain scene node has been replaced by a new TerrainSceneNode which is based on Spintz's GeoMipMapSceneNode and Soconnes terrain renderer. Lots of thanks for their work on this and that they allowed it to be modified and integrated into Irrlicht. - It is now possible for a scene node to draw itself in multiple passes. This means it can register itself for multiple render passes (E_SCENE_NODE_RENDER_PASS) and during rendering it can query the current render pass using ISceneManager::getSceneNodeRenderPass(). With this, SceneNodes can contain solid and transparent materials at the same time and will be rendered in the correct order from now on. The IAnimatedMeshSceneNode and the IMeshSceneNode implement this feature, so it is now possible to create for example cars with transparent windows without the need of a separate scene node. Because of this change, all render time enumeration values have been renamed. - Irrlicht is now able to load OCT files directly. OCT files can be created with Paul Nette's Radiosity Processor from http://www.fluidstudios.com or exported from Blender with Murphy McCauley's exporter. This exporter can be found in the directory \exporters\OCTTools of the Irrlicht SDK or from his homepage http://www.constantthought.com/project/OCTTools. A lot of thanks go to Murphy McCauley for this work on this and his permission to include his OCTTools into Irrlicht. - Irrlicht is now able to load Cartography shop 4 (.csm) files directly. A lot of thanks go to Saurav Mohapatra for this work on this and his permission to adapt and include his IrrCSM library into Irrlicht. If you are using .csm files, please note that you'll have to set the path of the textures before loading meshes. You can do this using SceneManager->getStringParameters()->setParameter(scene::CSM_TEXTURE_PATH, "path/to/your/textures");. The original loader can be obtained from http://www.geocities.com/standard_template/index.html - Irrlicht is now able to load Pulsar LMTools (.lmts) files directly because it now integrates a modified version of Jonas Petersen's lmts loader in version 1.5 (from http://development.mindfloaters.de/). Lots of thanks go to him for creating this loader and giving his permission to add it to Irrlicht. If you are using this loader, please note that you can set the path of the textures before loading .lmts files. You can do this using SceneManager->getStringParameters()->setParameter( scene::LMTS_TEXTURE_PATH, "path/to/your/textures"); - Irrlicht is now able to load my3D files directly. The My3DTools 3.12 loader by Zhuck Dimitry was (a bit modified and) integrated into the engine. Lots of thanks go to him for his work and for giving his permission to do that. Newer versions of this loader can be found at http://my3dproject.nm.ru. The exporters for this file format have also been added into the \exporters directory of the SDK. - To be able to replace built-in meshloaders with newer external versions without the need of recompiling the engine, now mesh loaders which are added to the engine using ISceneManager::addExternalMeshLoader() are prefered over built-in mesh loaders. Thanks to for his suggestion of this. - D3D8 and D3D9 support for dev-cpp has been improved. If you are using Dev-Cpp and a DirectX-Devpack for recompiling the engine, just add -DIRR_COMPILE_WITH_DX9_DEV_PACK to your compiler settings and something like -ld3dx9 -ld3dx8 to the linker settings and press 'compile'. - The SceneManager now contains an interface for storing and exchanging parameters. ISceneManager::getStringParameters() returns IStringParameters, which can be used for example by extensions like external mesh loaders to set and read independent parameters. This is also currently used by the newly built in CMS, LMTS and MY3D loader: It is possible to set a value 'CSM_TexturePath', 'LMTS_TexturePath' or 'MY3D_TexturePath' to let them know the path of the textures. - IAnimatedMeshSceneNode now has two new methods for being able to have more influcence on the animation playback: It is now possible to set the playback mode to looped or non looped with IAnimatedMeshSceneNode::setLoopMode() and it is possible to set a callback interface which will be called when animation playback has finished using IAnimatedMeshSceneNode::setAnimationEndCallback(). Thanks to Electron for his suggestion for this addition. - The software renderer has a new triangle renderer specialized on disabled zread and write. This means that skyboxes are now rendered in the correct order when using the software renderer. - Multitexturing and other extensions in Linux are now turned on by default. There is a new #define in the file IrrCompileConfig.h for disabling this again: LINUX_OPENGL_USE_EXTENSIONS - There is now a EET_USER_EVENT user event type for making it possible to send custom events through the system. - The setTarget()-method of the FPSCameraSceneNode now is finally correctly implemented. - Changing parents of scene nodes is now much safer. The parent member of a scene node now is set to 0 in all cases and should never point to invalid data when rearranging the scene node tree. In addition, there is now a getParent() method in the ISceneNode class. - Debug breakpoints using "_asm int 3" are now only being used when in debug mode and using Micosoft's compiler. Now more exotic compilers like BorlandC++ will like Irrlicht better because of this. - Updated zlib version to 1.2.2 - An implementation of 3D triangle clipping in the software renderer has been started. It is not 100% ready, but it is a beginning. This means now for version 0.9, that there are not that much artifact triangles drawn anymore. But this means also that drawing is a lot faster and that triangles clipped at the border of the screen will disappear too fast. If anyone wants to finish the drawClippedIndexedTriangleListT() method in the CSoftwareDriver class, he is welcome :) - There is a new parameter in the IVideoDriver::createImageFromData() which causes the image to be able to own foreign memory. - A renderstate setting has been fixed which caused to disable mip maps on wrong geometry when there was other geometry which had no mip maps. At least this bug doesn't appear on my hardware any more, I hope this means the problem it is now fixed. - A bug in the D3D version of the stencil shadows has been fixed thanks to Murphy. Sometimes you could see a small shadow similar to the the real shadow in the scene. This should now be fixed. - Irrlicht can now draw non filled concyclic reqular 2d polyons like triangles, tetragons, pentagons, hexagons, heptagons, octagons, enneagons, decagons, hendecagons, dodecagon and triskaidecagons. And circles. Yes, I was a little bit bored. Christian Lins made a suggestion to add 2D circle drawing support to Irrlicht, and I did this, but also added support for drawing these figures using the same method. Check out IVideoDriver::draw2DPolygon(). - Removed a memory leak when creating hlsl pixel shaders. - I've made varoius updates to the documentation and moved to doxygen 1.4 - Fixed a bug in the xml reader which caused it to crash when reading empty xml files. - Removed the buggy bsp tree scene node from the engine. - Tweaked some settings with some GUI elements. - ISceneNode::getAbsolutePosition now should be way faster. - Applied a fix by William Finlayson to the opengl stencil shadow drawing code which fixes several bugs. - There is now a min_ and max_ template function available in the core namespace. - Added some bugfixes to MayaCameraSceneNode by jox. An even more improved version can be found at http://development.mindfloaters.de/Downloads.12.0.html. - core::array now has a push_front method. - core::array now has an insert method. (Thanks to jox) - IrrlichtDevice now has a getEventReceiver() method. - Fixed a mouse wheel - mouse coordinates bug thanks to a bug report and fix by jox. - Changed the first parameter in IGUIContextMenu::addItem(wchar_t* text, ...) to const. Thanks to jox.. again. :) - Fixed ignore path bug in zip file reader thanks to Pr3t3nd3r. It is now possible to use zip files with the complete path to the files from the archive. - Fixed matrix4::rotateVect method after a suggestion by several users. (I think Electron, Pr3t3nd3r, Jox) Thanks all :) - Fixed a bug in CGUIEditbox that enables you to write more characters than the max set limit, thanks to Rush for the bug report and fix. - Added getAngleTrig() method to vector2d as suggested by Pr3t3nd3r, thanks! - After a suggestion by schick, plane3d now stores the normal vector first, and then the distance to the origin. - A bug was fixed which caused 2D elements to be drawn with a second texture set in OpenGL mode when 3D geometry with >1 textures has been rendered before. This effect has often been reported as darkened 2D gui in the forum. - A bug in IrrCompileConfig prevented users to be able to recompile irrlicht with D3D9 with gcc. This is now fixed, thanks to Jedive. - The project setup for Dev-C++ is now nicer. Added lots of folders and cleaned up the whole setup a little bit with this. - Fixed a small bug in CGUIScrollbar reported by Klaus Niederkrueger. - The Checkbox rect is now clipped correctly, thanks to jox for that bug report. - The debug names of all scene nodes and GUI elements are now set correctly. - Applied a patch making it possible to compile Irrlicht without OpenGL in Linux. - core::rect::clipAgainst was fixed thanks to a bug report and correction by Jox. ------------------------------------------------------------------------------------- Changes in version 0.8 (19 Feb 2005) - Irrlicht now supports HLSL. This is possible using the new IGPUProgrammingServices::addHighLevelShaderMaterial() methods. Also, methods for setting high level shader constants have been added. - Irrlicht.NET now supports events and cursor control. This means now you can read mouse and keyboard input from .NET projects like C# and VB.net too. - There are three new built in materials for doing normal/bump mapping available: EMT_NORMAL_MAP_SOLID, EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR and EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA. If the hardware does not support these, the materials will fall back to their base materials. To be able to use these materials, there is the new vertex type 'S3DVertexTangents', the material does not work with any other vertex types. There are some new methods to create meshes with this vertex type (IMeshManipulator::createMeshWithTangents()). - A new example/tutorial (11.PerPixelLighting) shows how to use per pixel lighting in your applications. - The software renderer now works in Linux, too. - Irrlicht now has a built-in normal map generator. It creates on the fly 32 and 16 bit normal maps from height maps (IVideoDriver::makeNormalMapTexture). As most other things in Irrlicht, the generator does not depend on D3D, D3DX or OpenGL. - Added shader debugging capabilities to Irrlicht. If _IRR_D3D_SHADER_DEBUGGING is defined in IrrCompileConfig.h (commented out by default), it is now possible to debug all D3D9 shaders in VisualStudio. All shaders (which have been generated in memory or read from archives for example) will be emitted into a temporary file for this purpose. To debug your shaders, choose Debug->Direct3D->StartWithDirect3DDebugging in Visual Studio, and for every shader a file named 'irr_dbg_shader_%%.vsh' or 'irr_dbg_shader_%%.psh' will be created. Drag'n'drop the file you want to debug into visual studio. That's it. You can now set breakpoints and watch registers etc. This works both with ASM, HLSL, pixel and vertex shaders. Note that the engine will run in D3D REF for this, which is a lot slower than HAL. - Support for compressed .tga texture loading added. (Support from 0.4.1 was buggy) Thanks to neojzs for posting his improvement. - Support for 32 bit .bmp texture loading added. - Global particles are now possible. Use IParticleSystem::setParticlesAreGlobal() to switch between global and local particles. A demonstration of this can be seen in the new tutorial (11.SpecialFX2). - It is now possible to let IGUIImages draw themselves using the alpha channel of the texture they show. Use IGUIImage::setUseAlphaChannel() for this. - ITexture now has a method for rebuilding the mip map levels: regenerateMipMapLevels(). This is useful for example after locking and modifying the texture. - Gravity acceleration speed in CollisionResponseAnimator was changed thanks to a suggestion by Morrog. The accelerationPerSecond value has been removed beacause of this, you can now control everything just with the gravity vector. Note that the gravity value must now be a little bit smaller to achieve the same effect as before. - Fixed a problem with several material renderers which weren't able to update their states at the right time sometimes. A new method OnRender() will be called every time the material is actually used. - Adjusted all tutorials to fit some interface changes. - Changed the opengl shader of tutorial 10 to fit the d3d shaders. The now look the same. - The MeshManipulator has a new method createMeshWithTangents() which creates a mesh with normals, tangents and binormals from any mesh. - Wrong 2D alpha channel renderstates have been set when using D3D9 and 8. This has been fixed now. - When loading 32 bit images with an alpha channel and storing them internally as 16 bit, the alpha channel got lost. This is now fixed, the remaining one bit alpha channel is now stored correctly. - There is a new overloaded IGUIEnvironment::addImage method, which creates an image directly with a texture as parameter, adjusting its size to the original size of the texture. - A small bug in rect::isValid() has been fixed, thanks to jox. - Fixed a bug in D3D8, D3D9 and OpenGL, which caused Materials be set and unset with an unequal amount when mixing 3d with 2d grafics or stencil buffer shadows. - If you are recompiling the whole engine with Visual Studio 6 (which means Irrlicht.dll, NOT the application which is using Irrlicht), DirectX9 support is disabled now by default, because Microsoft stopped support for DX9 on VS6 in December 2004. You can reenable this by uncommenting the new define at the bottom of IrrCompileConfig.h, if you have an old SDK for example. - The mixed fvf and vertex shader system in D3D8 caused a slight issue in Irrlicht ending up in really messed up render states sometimes. This is now fixed. - A major bug with the OpenGL renderer which occured on some OpenGL implementations has been removed thanks to a bugfix by Murphy and a great report and some investigations by ElectroDruid. - Sorting transparent scene nodes was broken in all previous versions of Irrlicht. This didn't attract a lot attention because most users used the ADD_COLOR transparencies for which the sorting is not relevant. Thanks to Morrog and mmm76, sorting now is right. - After the application window is resized, getViewport() no longer returns viewport as the first time the window has been created. - The draw primitive functions are no longer wrongly checking the maximum primitive count with the vertex amount value. Thanks to Spintz for the bug report. - Template materials in X files just like exported in the panda exporter are now supported, thanks to JoeWright. - Changed the stringc typedef slightly to make it work with people not using namespace irr. Thanks to schick. - Refactored the MeshManipulator code, which in some cases now uses template methods for performing calculations on different vertex types. - Fixed an interface problem with newer versions of libJPEG. Thanks to Fabien Coutant and Simon Barner for some help and clues into the right direction. Was not able to add system specific zlib/jpeglib support due to issues on some strange systems/users and a lack of time, sorry. - Typo in plane3d and triangle3d: method isFrontFacting renamed to isFrontFacing. ------------------------------------------------------------------------------------- Changes in version 0.7.1: (26 Sep 2004) - Fixed some bugs which prevented the engine to compile with gcc 3.4.1. - Fixed a problem with the OpenGL driver, which caused the renderstates not to be reset correctly when drawing scene nodes with reflective materials. - Fixed error in Irrlicht's software mip map generation, which caused that some mipmap levels looked strange. This fix was found by jox, the hardcore bug fixer, so many thanks go to him. Again. :) - Disabled hardware mip map generation in D3D9 again, because it seems to cause problems on some hardware. I don't have any hardware where this problem occurs, but I hope this helps. - Fixed a small bug in fast_atof submitted in the forum by da_dude. - Fixed string operator + after a bug report by osre and a fix suggestion by jox. - IEventReceiver now has a virtual destructor for the people who needed it. - 3DS-Loader patched due to some suggestions of Daniel Azkona Coya. ------------------------------------------------------------------------------------- Changes in version 0.7: (11 Sep 2004) - The first version of Irrlicht.NET is included in this release. It is a managed C++ wrapper .DLL which makes the most important features of the engine available for all .NET languages. The wrapper is incomplete, but it can already be used. You can find the documentation for this .DLL in the compiled help file doc\IrrlichtNET.chm. There are also two very basic examples available, which show how to use Irrlicht.NET from C# and VisualBasic. - Low level vertex and pixel shader programming is now possible. There are now some methods with wich you can write GPU programs in vertex/pixel shader assembler using Direct3D 8 and 9 and in ARB vertex and fragment program assembler for OpenGL. You can use the IGPUProgrammingServices interface which can be reached by IVideoDriver->getGPUProgrammingServices() for this. The new material types you can create with this can be combined with all other already existing material types. For example, it is possible to create a new material which uses a vertex shader to calculate texture coordinates and diffuse colors, and let this be rendered by the built in material video::EMT_TRANSPARENT_ADD_COLOR. Support for high level programming languages like GLSL or HLSL is planned for the following releases. Also note that you won't be able to use all techniques shaders offer with Irrlicht, due to its current high level abstraction of the 3D APIs. For example, the engine does not expose vertex streams or vertex buffers currently. - There is a new tutorial showing how to use shaders with the engine. In addition, all old tutorials have been rewritten and adapted. For example, the hello world tutorial now also shows how to set up visual studio .NET to use it with the engine. - Hardware mip map level generation of textures is now supported when using D3D9. - Internal pointers and data of the video drivers can now be exposed for experienced users with VideoDriver::getExposedVideoData(). For example, you can get a pointer to the IDirect3DDevice9 interface and the HWND window handle, if the engine is running with D3D9. - The createDevice() function has a new additional parameter: bool vsync. With this, it is now possible to enable or disable the waiting for the vertical retrace period. This is implemented in D3D9, D3D8, and the Windows OpenGL driver only, the software driver will ignore this flag. - The engine now behaves like in the documentation: irr::createDevice() returns 0, if the desired driver could not be initialized. - There is a new SceneNode available: The ITextSceneNode is able to display 2D text at a position in 3D space. Use ISceneManager::addTextSceneNode() to create one. - Finally now all VideoDrivers have a draw2DLine() implementation, thanks to some additions sent in by Vash TheStampede. - Applied some changes to the compilation configuration, so that it should now be easier to use the engine with XBOX projects. Thanks to MattyBoy for sending in some clues for this. - Some improvements for the linux version of the engine: The NULL device is finally fully operational with Linux too, and also all examples and even the techdemo compile and run with this OS. - The default field of view in the cameras of the irrlicht engine was a little bit extreme, so I changed it now from core::PI / 3.5f to core::PI / 2.5f. - Added a new draw2DImage method for partially draw a 2d Texture, as sent in by zola with implementations for OpenGL, D3D8 and D3D9. Software implementation is missing. - The string class is now able to convert integer values into a string or append it as string to itself. - Added a getDriverType() method to the IVideoDriver interface. - Added a getTransform() method to the IVideoDriver interface. - The EMT_TRANSPARENT_ALPHA_CHANNEL material in OpenGL is now implemented. - The integrated XML Parser now works better with different text file formats. (ASCII, UFT-16,..) - IGUIEdit Box now feels more like a windows editbox, thanks to some changes by Jox - Added a new method to IVideoDriver: createImageFromData as suggested by Oliver Klems. - Fixed a the EMT_TRANSPARENT_ALPHA_CHANNEL problem in D3D8 and D3D9 due to a suggestion by Jox. - Added 3 methods created by zola to the quaternion class: fromAngleAxis(), toEuler() and operator*(vector3df&). - A bug in a matrix multiplication operator was fixed. - Changed visual studio project files to version 7.1, but provided 7.0 project files for people with that version. - Added SceneNodeAnimatorRotation rotation fix as posted by warui - Added normalization fix to vector2d and 3d. Warui suggested a fix like that in the forum. The one I made has the same result, but is a little bit faster. - Fixed some problems with the drawStencilShadow() method in the OpenGL implementation of the IVideoDriver interface after some suggestions by Nicholas Bray. - Added IGUIButton::setPressed() and isPressed(). - Fixed checkPrimitiveCount() bug in NullDevice. - Applied jox's matrix4::getRotationDegrees() fix, many thanks for posting this! - Changed aabbox3d::getExtend() to getExtent(). - Changed IXMLReader::isEmtpyElement() to isEmptyElement() - Fixed a bug in CSceneManager::getSceneNodeFromId() which caused the engine to crash sometimes. - Fixed a bug in CGUISkin::setSize reported by REAPER. This method never worked before. - Improved texture mapping and normals of the TestSceneNode, thanks go again to Jox. - ScrollBar is now posting mousewheel events, thanks go to REAPER to post this bug and a fix for it. - Added - operator to vector2d and vector3d, thanks to calimero - Fixed a bug in vector2d::getAngle() and vector2d::rotateBy() thanks to Jox. - Fixed a bug in quaternion::set(f32 x, f32 y, f32 z) thanks again to Jox. - Fixed a bug in list::insert_before and list::insert_after, reported by Haddock. - Fixed a bug in XML Parser which caused a seqfault on linux. Thanks for G.o.D reporting this problem. - EDriverType enumeration renamed to E_DRIVER_TYPE - SceneNodeRenderTime enumeration renamed to E_SCENE_NODE_RENDER_PASS ------------------------------------------------------------------------------------- Changes in version 0.6: (09 Mar 2004) - Irrlicht now includes its own XML parser. It provides forward-only, read-only access to a stream of non validated XML data. It can read everywhere Irrlicht can, also in compressed .zip-Files for example. Use IFileSystem::createXMLReader() to use it. - Like the new XMLReader, there is also a IXMLWriter available for making it easier to write xml files. - There is a new tutorial available in the SDK. It is for more advanced users, and shows how to create a 3d model viewer with the engine easily. It shows how to use menus, tabcontrols, edit-, message- and sky boxes. The resulting program can also be used as tool, to check if the engine loads exported 3d models correctly. - Again, there are some new GUI widgets available: A ComboBox, a ToolBar, a PushButton and an ImageButton. The last two are simply the old IGUIButton, but it is now able to display additional images and behave like a PushButton. - It is now possible to make the drawing window resizeable, if it is in windowed mode. Use IVideoDriver::setResizeAble(true) to do this. - The .x file reader and animation player now should work with 99% of all text .x files. This is achieved by most of the following bug fixes. - Fixed a huge bug in the .x file reader, which caused that negative coordinates were interpreted as positive ones sometimes. This caused that sometimes .x animations were played wrong. - Slerp interpolation of the quaternion class fixed. This means that also some bugs in the animation of .x files are removed now. - Added virtual joints to not weighted vertices to improve .x file animations. - The FileSystem is now 100% implemented. Finally it is now possible to write files too. There is a new Class IWriteFile and the corresponding IFileSystem::createAndWriteFile() - Added lots of text and sample code to the documentation. In most parts documentation should be clearer now. - The ISceneManager has a clear() method, which clears the whole scene, all scene nodes are removed. - All ISceneNodes now own a new method called removeAll(), which deletes all children of the node. - Fixed a bug which prevented the possibility to compile directx8 without having installed directx9. - Fixed a bug in 3d line dawing in D3D 8 and 9. - All video drivers now print out the gfx adapter type, vendor and driver version into the log strings. - The D3D9 device is now as fast as the D3D8 device. - The string class has an additional new constructor for creating a string from character data with a specific length. - Bug fixed in string class assignment operator which might cause a crash in very special circumstances. - Added a findNext() method to the string class. - The ISceneNode class now has a isDebugDataVisible() method. - Some lines were changed to make the source of the engine compatible to VS.NET 2003. - Some functionality of the IFileList and IFileSystem was missing in the Linux version of the engine. This caused the FileOpen-Dialog not to work. I fixed this problem. - The Middle and Right mouse button were swapped in the Linux version. This is now fixed. - Multitexturing should now work with most linux systems too, thanks to a bug report by Martin Piskernig. - The logger now has an additional log() method which accepts another combination of strings. - Fixed a bug which caused fonts to be displayed very transparent in OpenGL. - Removed one of the redundant overloaded IGUIEnvironment::updateAbsolutePosition() methods. - Fixed lots of clipping problems in all GUI Widgets. - core::rect has the new methods getCenter() and isValid(). - Scrollbar buttons are now disabled if it is not possible to scroll. ------------------------------------------------------------------------------------- Changes in version 0.5: (17 Feb 2004) ------------------------------------- / Highlights in short: / * DirectX 9 support / * .x file support in all render devices including opengl and software / * new materials like lightmaps with dynamic lighting / * fog / * stencil buffer shadows now also work in OpenGL device / * more gui widgets: tab controls, edit boxes, menus / * spline animation support / * mouse wheel support / * triangle fan drawing / * quaternions / * improved keyboard input control / * lots of bugfixes including improved quake 3 map support ------------------------------------- - DirectX 9 is now supported by Irrlicht. This does not mean that it replaces DirectX 8. The engine now supports both. You can now select between OpenGL, DirectX8, DirectX9, Software and the Null device. - The engine now is able to read and display .x files. Using Microsoft's excellent .x file exporter for Maya or MAX which comes with the DX8 and DX9 SDK, it is now possible to create content for the engine easily. Using .X files with Irrlicht is independent of D3D, they can be used with OpenGL and with Linux for example too. Currently only text file .x files are supported, and some animated .x files may be displayed not 100% correctly, because the animation player may still have some small bugs. It works perfectly with most .x files which come with the DX9-SDK. Some skinned mesh .x files which use quaternions for animating joints have some problems, there might be a bug somewhere. I commented the lines with a possible bug in CXAnimationPlayer.cpp. - The GUI Environment now supports edit boxes. They should support unicode input from every keyboard around the world, scrolling, copying and pasting (exchanging data with the clipboard directly), maximum character amount, marking and all shortcuts like ctrl+X, ctrl+V, ctrg+C, shift+Left, shift+Right, Home, End, and so on. Wow, I never programmed an edit box, its much more work than it seems to be. - Tabcontrols are now available in the GUI environment. It is also possible to create tabs without tabcontrols, to be able to create invisible gui elements for grouping other elements together. - Another new supported GUI Element are context menus. They support ordinary text menu items, separators and sub menus. In Addition, a standard menu as seen at the top of most windows can be created easily with them. - Rewrote all tutorials to fit the new API. - Spline animations are now supported thanks to a spline scene node animator written by Matthias Gall. - Taskswitching now works with Direct3D 8 and 9 devices in fullscreen mode. - Added Material types EMT_LIGHTMAP_LIGHTING, EMT_LIGHTMAP_LIGHTING_M2, EMT_LIGHTMAP_LIGHTING_M4 and EMT_LIGHTMAP_ADD. - The engine now supports drawing of trianglefans. To do this, use IVideoDriver::drawIndexedTriangleFan(). Mario Gruber sent in code for this, so lots of thanks go to him! - It is now possible to draw 3d objects with fog. Simply switch on the fog flag in the objects material. To change to way fog is drawn (per pixel/vertex, color, linear/expontential) use IVideoDriver::setFog(); - With IrrlichtDevice::getOSOperator() a pointer to an interface is returned, with wich it is possible to do some operation system specific operations. Currently there are only 3 methods supported, but more will be added in the future. - Mouse wheel input is now supported. - The Key Event structure of SEvent now contains a Char entry, describing the corresponding character of the pressed key. Also two bools were added, specifying if shift or ctrl was pressed too. - The version of the Operating System is now printed out into the log at startup. - There is now a non-const getBoundingBox() method in IMeshBuffer and IMesh available. - IGUIElement now has a method getElementFromId(), which searches children (and its children if wanted) for an element with a specific id. If you want to search all items, just do IGUIEnvironment::getRootGUIElement::getElementFromId(). - ISceneNode::updateAbsolutePosition() is now public - Small bug fixed in CMeshManipulator::scaleMesh(). - The engine now supports Quaternions. - A bug was fixed causing the windows caption not to be displayed in Windows 95/98/ME. - IGUIEnvironment::getBuildInFont() was renamed to getBuiltInFont(). - IGUIElement::bringToFront() is able to brint a child to the front. Windows for example are now using this new feature. - Changed the texture mapping of the test scene node a little bit based on code sent in by Dr Andros C Bragianos. - Added code to fix some bug in some ATI drivers. Thanks to ariaci for posting this code. - Stencil buffer shadows now also work with the OpenGL device, they worked only in D3D in earlier versions. Lots of thanks go to Philipp Dortmann, who sent in a modification to the opengl driver! - IGUIStaticText::setWordWarp() renamed to setWordWrap(), IGUIStaticText::enableOverrrideColor() renamed to enableOverrideColor() [thanks to saigumi] - A bug was fixed, causing that the window was not able to be closed with Alt+F4 in Win95/98. - Optimized the Octree-Scene node a little bit for getting more rendering speed. Culling is now done with the real frustum, not the bounding box around it. Speed increase is about 5%, it's not much but ok. - Bug fixed in the Quake 3 .bsp file loader, which caused holes to appear in some maps. - Combination of 3D displaying and drawing GUI elements was improved, and the priority of input receiving of 3d cameras and gui elements swapped. - A bug in the static text was fixed, which caused it to draw itself outside of its clipping rectangle. - KeyFocus and MouseFocus methods in GUIEnvironment are now merged into one method. - The Clamptexturecoordinates flag in the material was removed. - IVideoDriver::draw3DLine in all devices was improved. - The devcpp-version of the binary DLL which comes with the SDK is now faster. I'll compile this version from now on always with optimization switched on. - Other, Minor New/Changed methods in public interfaces: * buildShadowMatrix in matrix4 * getRotationDegrees in matrix4 (sent in by Chev) * rotateVect in matrix4 * linear_search in array * recalculateBoundingBox in MeshManipulator * ISceneManager::addStaticText() now has a parameter for word wrapping * getCharacterFromPos() in IGUIFont * drawMeshBuffer() in IVideoDriver; * interpolate() in matrix4 * getLast in array ------------------------------------------------------------------------------------- Changes in version 0.4.2: (13 Dec 2003) - The engine does no more use only 16 bit textures internaly. Now all other texture formats are supported too. This means higher precision and better quality images. In this context, the ISurface interface has been replaced by IImage, and the ISurfaceLoader by IImageLoader. - By changing the texture creation mode of the IVideoDriver, it is now possible to influence how textures are created: You can choose between 'optimized for speed', 'optimized for quality' or simply set constant bit depth like 'always 32 bit'. Also, you can now enable and disable Mip map generation with these flags. Take a look at IVideoDriver::setTextureCreationFlag() for details. - There is now some support for outdoor or terrain rendering available. You can create a static mesh from a heightmap and a texture using ISceneManager::addTerrainMesh(). You can specify a huge texture if you like, even bigger as your hardware allows to render, because the texture will be splitted up if necessary. Another possibility for doing terrain rendering is the new Terrain Scene node. But it is only in a very early alpha stage, I disabled for example the use of different level of details. - It is now possible to load software images into memory from files on disk, without creating a hardware texture. You can do this by calling IVideoDriver::createImageFromFile(). This is very useful for example for loading heighmaps for terrain renderers. - The Quake 3 Map Loader now supports curved surfaces, thanks to by Dean P. Macri who sent in his code. (He also sent in lots of other cool stuff, which I will merge with the code of next releases, lots of thanks to him!) - It is now possible to control what text is printed out to the console and the debug window of Visual Studio. By getting a pointer to the ILogger interface, is is possible to adjust if Warning, Error or Informational texts should be printed out. In addition, now every text can be catched by the event receiver. - The engine is now capable of loading .PCX files. Only a few PCX formats are supported currently, but at least the common used formats of most textures of the quake 2 models. Thanks go to Dean P. Macri who sent in the code for the new PCXLoader! - A new Scene node is available, which simply does nothing. It is useful for doing advanced transformations or for structuring the scene graph. - The ISceneManager::addOctTreeSceneNode() now takes AnimatedMeshes as parameter. If this new method is called, the first frame in the animated mesh is taken as mesh to construct the octree. This means that you won't have to write addOctTreeSceneNode(yourMesh->getMesh(0)) anymore, but can use addOctTreeSceneNode(yourMesh), which is a little bit more intuitive. - The Driver type enumeration have been adapted to the Irrlicht naming conventions. For example instead of writing DT_OPENGL, now write EDT_OPENGL. - The ITexture interface has two new methods for getting the size of the texture: ITexture::getSize() and ITexture::getOriginalSize(). This replaces the old getDimension()-method and allows to disable bugs which are generated by the automatic scaling to optimal sizes of textures. - There are some new keycodes available: KEY_COMMA, KEY_PLUS, KEY_MINUS, KEY_PERIOD. - There are now 3 lightmap Material types: EMT_LIGHTMAP, EMT_LIGHTMAP_M2 and EMT_LIGHTMAP_M4, which are making the lightmaps 2 or 4 times brighter. If you used the Material EMT_LIGHTMAP in your code, you should replace it now with EMT_LIGHTMAP_M4. - The transformation enumeration names have been adapted to the irrlicht naming conventions. For example instead of writing TS_VIEW, now write ETS_VIEW. - Video driver feature enumeration names have been changed from EK3DVDF_... to EVDF_... - The GUIEnvironment now has a new method: getRootGUIElement(). With this it is possible now to add external created custom GUI Elements to the gui environment, without an existing internal GUI element as parent. - The setViewPort()-Method of the OpenGL-device now works, too. Nothing stands now in the way of creating splitscreen applications using the OpenGL device. Oliver Klems sent code for this, I slightly modified it. Thank you! - Corrected a bug, which made the EMT_REFLECTION_2_LAYER Material disappear on some hardware. - Sirshane sent in a bug fix: It is now possible to make the mouse cursor invisible in the Linux version of the engine. Thanx sirshane! - getFrameNr() of IAnimatedMeshSceneNode is now public. - Again a small bug in the 3ds file loader was fixed. - A small bug causing light positions being transformed in the OpenGL driver differently compared to D3D. Thanx to Matthias Gall for reporting this! - Typing error fixed: ISceneCollisionMananger::getRayFromScreenCoordiantes renamed to getRayFromScreenCoordinates. - Linux support with multitexturing and mipmap generation has been improved. - A bug was fixed wich caused the Engine not to run when compiled as dynamic library under linux. Thanks to Shane Parker who pointed out the problem. - A bug was fixed in position2d.h in the operator +=, and the list iterator now has per and postfix operators. Thanks to Isometric God for spotting this out. - A bug was fixed in the Metatriangleselector, causing it to detect only collisions with the last TriangleSelector in it. ------------------------------------------------------------------------------------- Changes in version 0.4.1: (18 Sep 2003) - Input events are now processed faster than repaint and window events. This means that input commands now effect things directly, in earlier versions there could be a delay when there were low frames per second. Some people noticed this when moving with the fps camera in large levels: The camera sometimes stopped seconds after the button was released. This is now fixed. - A Message Box is now available in the GUI Environment. It looks like the windows message boxes and supports OK, Cancel, Yes and No buttons, which can be combined freely. Also, it shows multiline text and adjusts its size based on the amount of text it shows, so it should be very useful for displaying (debug) messages during runtime. - It is now possible to make all windows (message boxes, file open dialogs, simple windows) modal. - IGUIStaticText now supports multiline text via automatic word warp and manual line breaking with '\n'. You only need to switch it on with yourText->setWordWrap(true); - Non default MD2 animations are now supported. Which means simply that you can enumerate the names of all md2 animations and the AnimatedMeshSceneNode now supports a setMD2Animation() with a character string as parameter instead of a constant. - You do not need an event receiver anymore for sending user events to the active camera, this is now done autmaticly. In addition, it is now possible to set a new event receiver during runtime of the engine using IrrlichtDevice:: setEventReceiver(). - It is now possible to disable and enable the input receiver of a camera. This is useful for example for removing the users control of the camera. To do this, call camera->setInputReceiverEnabled(false); - The first person shooter camera now supports a keymap: You can define your own key mapping to control the camera when you create it with ISceneManager:: addCameraSceneNodeFPS(). - Thanks to Jon Pry, the engine now also loads compressed TGA texture files. Now only 8 bit palette using TGAs are missing. :) - There are methods for converting 3d coordinates in 2d coordinates and the other way round. You can find them as two new methods of the ISceneCollisionManager: getRayFromScreenCoordiantes() and getScreenCoordinatesFrom3DPosition(). - There are now access methods in IGUIWindow for getting pointers to the maximize, minimize and close buttons, to be able to remove them for example. - Before starting up the engine, a version check now is performed and a warning is written, if Irrlicht.DLL version and header version of your application do not match. - A bug with the skybox has been fixed: In OpenGL, it was possible to see the borders of the skybox. In addition, when a skybox was visible, there were errors in the texture coordinates of other meshes. This is all fixed now. - A bug has been fixed causing the engine to crash when removing gui childs which where created inside the .dll but are removed from outside. - A bug was fixed causing the engine to crash when drawing debug data of octtree scene nodes with geometry data with vertices with one texture coordiante. - Multitexturing now works with linux, too. Thanx to Jon Pry again, for showing me where the problem was. - The bug (reported by saigumi) preventing scene nodes attached to a camera from moving correctly is now fixed. - The "Climb-Walls" bug (reported first by Matthias Gall) is fixed. Gravity acceleration is now quadratic instead of linear. - A warning is now printed out, if more vertices are rendererd with one call than the hardware supports. - Other, Minor New/Changed methods in public interfaces: * get and setText() in IGUISkin * += operators are now available in the string class. * setRelativePosition() in IGUIElement * enumeration EKEY_CODES renamed to EKEY_CODE * getMaximalPrimitiveCount() in IVideoDriver * getAnimationCount() in IAnimatedMeshMD2 * getAnimationName() in IAnimatedMeshMD2 ------------------------------------------------------------------------------------- Changes in version 0.4: (04 Sep 2003) - Collision detection and reponse based on ellipsoids in now implemented. There is a new method available in the ISceneCollisionMananger, which returns a collision response point. In addition, a new SceneNodeAnimator is available, which causes a scene node, to which it is attached to, not to move through walls, to climb stairs and to be affected by gravity. This scene node animator can be attached to any scene node. For example adding it to the FPSCamera, it makes the user possible to walk through the 3d world as in first person shooters. - There is now a full featured Particle System included in the engine for creating fire, explosions, snow, smoke and so on. It is customizeable and extensible. There is a ParticleSystemScene node available in the SceneManager and some standard particle emitters and affectors are already implemented. - Realistic water: The engine now features an IWaterSurfaceScene node, which animates a static mesh with water waves. In combination with the new EMT_REFLECTION or EMT_TRANSPARENT_REFLECTION material type, you can easily create realistic animated water surfaces. - Triangle base picking is now possible using the ISceneCollisionMananager. If a collision happened, the intersection point and the triangle causing the intersection is returned. - Stencil shadows are now drawn using the ZFail method by default, but it is possible to choose ZPass, if wished. This means that the camera may now move inside the shadow volumes and no errors will occur. In addition a stencil shadow bug is now fixed: In 0.3 there where no shadows visible in the TechDemo. - The interface of ISceneNode has changed: There is no more a RelativeTransformation and AnimatedRelativeTransformation matrix. They have been replaced by 3 vectors: RelativeTranslation, RelativeRotation and RelativeScale, which can be accessed by the corresponing get() and set() methods. This simplifies the interface a lot. Also, the set/getRelativePosition was renamed to set/getPosition. - The new IAnimatedMeshMD2 interface now returns start, begin time and fps of every MD2 animation type. In this context, IAnimatedMeshSceneNode got a new method called setMD2Animation(), which accepts a single constant like EMAT_ATTACK, which starts and plays the fitting animation (attack animation in this case), simplifying the interface a lot. - Some scene nodes can now draw debug data like their bounding boxes. This feature is switched on for a single node by calling ISceneNode::setDebugDataVisible(true). Looks really interesting for animated scene nodes like particle systems or animated meshes. - There is now a IGUIInOutFader avaiable, which is able to fade in or out the whole screen or parts of it. - The new IVideoModeList is a list with all available video modes. It can be retrieved with IrrlichtDevice::getVideoModeList(). If you are confused now, because you think you have to create an Irrlicht Device with a video mode before being able to get the video mode list, let me tell you that there is no need to start up an Irrlicht Device with DT_DIRECTX8, DT_OPENGL or DT_SOFTWARE: For this (and for lots of other reasons) the null device, DT_NULL exists. - With the new IMeshManipulator interface accessible with ISceneManager::getMeshManipulator() it is possible to perform some basic operations on meshes: Flipping all surfaces, recalculating all normals, scaling the mesh, creating a new texture mapping and so on. - A new material for creating water surfaces or glass with reflections on it is available: EMT_REFLECTION_2_LAYER and EMT_TRANSPARENT_REFLECTION_2_LAYER. It has uses a reflection map, and an additional optional texture. The transparency of this material is set by the alpha color value in the vertices. - Another new material is EMT_SOLID_2_LAYER. It is a material with 2 textures, blended together with the alpha value of the vertex color. This material is currently only available in DirectX. - Trilinear Filtering is now supported by the engine. There is a new option in SMaterial: TrilinearFilter and EMF_TRILINEAR_FILTER. - The addChild() method of the IAnimatedMeshSceneNode for adding SceneNodes to joints of skeletal animated meshes was removed. Instead there is now a new method: getMS3DJointNode(). This returns a pointer to a child node, wich has the same transformation as the corrsesponding joint. In this way it is possible to do more advanced operations with joints and attaching scene nodes to joints. Also, the IAnimatedMeshMS3D interface now gives access to all joints. In this way, you can easily enumerate all names of all joints in the mesh. - Font and color of every IGUIStaticText can now be set separately, without modifying the IGUISkin. - There is now a ELEMENT_LEFT gui event, which all hovered elements receive when they are left. - All features of the FileOpenDialog are now working. - Debug informations are now printed out to the console window also on the win32 platform. - FPSCamera now supports setTarget(). Its not precise but working. - Textures of 3ds files are now loaded from the same directory in which the 3ds file is. If the texture is not found there, the texture is tried to be loaded from the current working directory. - A small bug in the 3ds file loader has been fixed. There were 3ds files exported by anim8or, where the reading of the 3ds file never stopped. - It is now possible to configure the minimal amount of polygons contained in every node in an OctTree via addOctTreeSceneNode(). - There is a new template class in the core namespace: triangle3d. With this, it is easy to find intersections between lines and triangles, find out if a point is within a triangle and so on. - A small bug in ISceneManager::addHillPlaneMesh() was fixed: Now the right tile amount is created. - There is a new SceneNode available: IDummyTransformationSceneNode. It exists for making it possible to insert matrix transformations anywhere into the scene graph. - Added a new SceneNode animator for deleting Scene nodes automaticly after some time. Create it with ISceneManager::createDeleteAnimator(). - The techdemo now is interactive. After a short non-interactive flight over the quake 3 level, you are placed as player inside the level, may move around, shoot fire balls and take a look at some animated characters which are placed on the map. - I fixed a bug which caused the screen get black when choosing shadows and fullscreen on some special 3d adapters. - I fixed some bugs in the linux port: The timer returned an incorrect time, causing wrong animations everywhere and the releasing of keys and mouse buttons was not sent as event. In addition, I placed a copy of the zlib.a and jpeglib.a into the /lib/Linux directory and changed the Makefiles of the examples and the source of the engine for doing this automaticly in the future, so I hope there will be no problems with other versions of zlib and jpeglib anymore. - There are 2 new tutorials: One showing how to do collision detection and for special effects. - Other, Minor New/Changed methods in public interfaces: * getVersion() in IrrlichtDevice * getLengthSQ() in vector3d * getInterpolated() in vector3d * getInterpolated() in SColor * getAngle() in vector2d * getAngleWith() in vector2d * getPrimitiveCountDrawed() in IVideoDriver renamed to getPrimitiveCountDrawn() * getSceneNodeFromSceenCoordinates() renamed to getSceneNodeFromScreenCoordinates() * getMeshType() in IAnimatedMesh * getInterpolated() in aabbox * setMD2Animation() in IAnimatedMeshSceneNode * getFullFileName() in IFileList * addShadowVolumeSceneNode() in IAnimatedMeshSceneNode extended with zfail parameter * drawStencilShadowVolume() in IVideoDriver extended with zfail parameter * getDistanceFromSQ() in vector3d * subString() in string * findFirst() in string * findLast() in string * getTriangleSelector() in ISceneNode * setTriangleSelector() in ISceneNode * draw3DTriangle() in IVideoDriver * setShadowColor() in ISceneManager * getShadowColor() in ISceneManager * addToDeletionQueue() in ISceneManager * getSceneNodeFromId() in ISceneManager ------------------------------------------------------------------------------------- Changes in version 0.3: (18 Jul 2003) - Linux port: The Irrlicht Engine now compiles and runs on Linux. Currently only the OpenGL driver is available. The Software driver would be there too, if somebody could tell me a fast way to blit a A1R5G5B5 surface to the screen using X. All examples do compile and run, but there are some things missing: * It is not yet possible to make the mouse cursor invisibe. * The timer seems not to return the currect time. * Multitexturing does not work correctly on all gfx adapters. - Ms3D Animations: The engine is now able to play skeletal animations directy from Milkshape 3D (.ms3d) files. It is also possible to attach objects to parts of the animated mesh. For example a weapon to the left hand of the animated model. - Because the swprintf function in Windows32 does not match the ISO C standard, and it does in linux and all other platforms, there is now a define in Irrlicht.h, to make the code be the same on all platforms: #define swprintf _snwprintf This simply means that you need to add a parameter to your swprintf calls if you used this function in your win32 irrlicht engine projects. For example instead of writing wchar_t tmp[255]; swprint(tmp, "FPS: %d", fps); you now write wchar_t tmp[255]; swprint(tmp, 255, "FPS: %d", fps); - Automatic culling has changed a little bit: It is now done by the SceneManager. Scene nodes now only need to return a valid, non transformed bounding box to be culled automaticly. It is explaned in the CustomSceneNode Tutorial how this works. - It is now possible to use the engine easily for 2D graphics: There are now to new methods in the IVideoDriver, which create an 1bit alpha channel for textures using an color key. The methods are both named makeColorKeyTexture. There is a tutorial '2d graphics' which explains how this works. - The rect template class was removed and replaced by the rectEx class. There is now only one rectangle template available, called 'rect' for simplifying the interface. - The texture coordinate bug in Milkshape 3d models with lots of shared vertices was fixed. - Bugfix with GUI environment hovering invisible elements. - There are two new tutorials: One for 2d graphics, and one for user interface. - Tutorial changes: * All backslashes replaced by slashes in file names in all tutorials for linux compatibility. * RectEx replaces with rect in 1.HelloWorld * Added second parameter to swprintf in 2.Quake3Map * Added bounding box creation to 3.CustomSceneNode * Added second parameter to swprintf in 4.Movement - New/Changed methods in public interfaces: * getClosestPoint in line3d * getMatrixOfMeshPart in IAnimatedMesh * removeChild in ISceneNode now returns true or false * addChild in IAnimatedMeshSceneNode * setParent in ISceneNode ------------------------------------------------------------------------------------- Changes in version 0.2.5: (22 Jun 2003) - A new material type is available: EMT_TRANSPARENT_VERTEX_ALPHA, which realizes transparency based on the vertex alpha color. It currently is only implemented in the DirectX device. - There is now an ISceneCollisionManager available. Get it with getSceneCollisionManager() from the ISceneManager. It currently only implements picking, but more is coming soon. - Automatic Culling based on Bounding Boxes is implemented now. It can be switched on or off for every SceneNode seperately using ISceneNode::setAutomaticCulling(). It is on by default. - It is now possible to remove loaded textures for freeing memory or reloading them. Use IVideoDriver::removeTexture() or removeAllTextures(). - New drawing methods in the IVideoDriver interface: * Draw3dLine(), drawing a 3d line. * Draw3dBox(), which draws an axis aligned bounding box. * Draw2dLine(), currently only supported by the Software device. - MD2 bugfixes: * There was a small bug with texture coordinates. * Frames are now correctly interpolated when playing animations. - Bugfix in the 3ds file format loader: Single objects in the 3ds file with multiple materials attached are now loaded correctly. - list.h renamed to irrlist.h due to compatibility issues. - Now works with Dev-C++ 5 Beta 8. (4.9.8.0) - New/Changed methods in public interfaces: * 'getInverse' in matrix4. * 'transformBox' in matrix4. * 'repair' in aabbox. * 'intersectsWithLine' in aabbox. * 'getVector' in line3d. * 'getMiddle' in line3d. * 'normalize' method in vector3d and vector2d now returns reference to vector. * 'getTransformedBoundingBox' in ISceneNode. * 'getChildren' in ISceneNode * 'setRotation' in ISceneNode * 'addHillPlaneMesh' in ISceneManager now accepts a texture repeat count parameter. ------------------------------------------------------------------------------------- Changes in version 0.2: (19 May 2003) - The engine is now able to load .3ds files, with their materials and textures. - There are some new SceneNodeAnimators: A fly straight animator and a texture animator. - Texture coordinates can now be set to clamp or wrap mode with a flag in the SMaterial struct. - Skyboxes are implemented. - Billboards now work 100% correctly. - The IAnimatedMeshSceneNode is now able to draw shadows of itself. To enable this, just call addShadowVolumeSceneNode(). Please note that shadows are currently just experimental, there are some bugs, and they only only in Direct3D mode. - A small bug in the view frustum and the octree fixed. - The default aspect ratio in all camera scene nodes was changed. - Some changes and extenstions to the core::matrix4, SViewFrustum, plane3d and aabbox were made. The plane3dex was removed, there is now only one plane implementation available. Implemented some ideas and suggestions by Mark Jeacocke. Thanx a lot! - The interface for adding dynamic lights has been enhanced. There are some new methods for handling dynamic light in the IVideoDriver interface. For example, it is now possible to change the ambient light. - There is a new parameter in the createDevice() function, which specifies if the stencil buffer should be activated. Also, now all parameters have default parameters. - There is now a timer object to get the current timer. It can be received using the getTimer() method from the IrrlichtDevice. - The first person shooter camera is now able to be moved by external using setRelativePosition() and the sceneNodeAnimators. In addition, it now supports multiple FPS cameras. - Mesh format loading extenstions are now possible. To extend the engine with a mesh format it currently does not support (e.g. .cob), just implement a IMeshLoader interface and add it to the engine calling ISceneManager::addExternalMeshLoader(). - It is now possible to extend the Irrlicht Engine easily with new texture file format loaders. If there is an image file format the engine does not support (for example .gif files) the IImageLoader interface can be implemented to load .gif files and added to the engine via IVideoDriver::addExternalSurfaceLoader(). ------------------------------------------------------------------------------------- Changes in version 0.1.5: (03 Apr 2003) - The zlib and libjpeg are now included in the SDK. - It is now possible to let the scene manager generate a hilly plane on the fly. - The Interface for handling dynamic lights was simplified. - The OpenGL 2D and 3D device is now full implemented. - There is now a way to access to root scene node from the scene manager, and so it is possible to add external created custom scene nodes to the scene. - There is a new Camera control scene node available in the engine: First Person Shooter Camera Control. Look with mouse movement, move and strafe with the cursor keys. - The engine now compiles with g++ and the Microsoft compilers, which enables it to develop applications for the engine with VisualC++6.0, VisualC++.NET and Dev-C++. - There is now a ICursorControl available in the engine, which is able to modify the mouse cursor: Get/Set the position of the cursor, make it invisible or visible. - video::Color was renamed to video::SColor to fit the Irrlicht Engine naming conventions and for g++ compatibility issues in the Vertices. ------------------------------------------------------------------------------------- Release notes of version 0.1: (14 Mar 2003) This is an alpha version of the SDK. So please note that there are features missing in the engine and maybe also some bugs. The following list is a complete list of parts of this alpha SDK which do not work 100% correct. All other parts which can be found in the documentation and accessed with the Irrlicht header files work and can already be used. - OpenGL Device The OpenGL Device is currently only able to load textures and draw basic 3D primitives. No 2D functions, complex materials and dynamic light are implemented. Please use the DirectX8 or the Software Device instead. In the next release (0.2) the OpenGL device will be complete. - Software Device Dynamic lighting, multitexturing, 3d clipping and bilinear filtering are not implemented because the Software Device was intented to to only 2d functions, the primitive 3d functions are only an addition. Until the first non beta release (1.0) of the Engine, some more 3d functionality will be added. - BspTree The binary space partition scene node does not work correctly and has some bugs in it, which might lead to crashes. Please use the OctTree scene node instead. There is nearly no difference between the interface of them. - MeshViewerGUIElement The camera control of this element is currently disabled. - FileOpenDialog Not all functions are implemented. - Render to Texture support Is not implemented yet. - MS3D Skeletal Animation A loaded mesh is currently not animated and only drawn static. - Quake 3 maps No support for curved surfaces yet. - Linux Support The engine currently only runs with Windows platforms. A linux version will be available somewhere between the versions 0.2 and 0.5, it depends on the need of the users. -------------------------------------------------------------------------------------